16、iptables的使用
一、iptables是啥
iptables是一个linux下的防火墙工具,它能帮助我们基于规则进行网络流量控制。它可以做到,但不限于以下功能:
- 允许/拒绝某种协议的链接建立,比如TCP,UDP
- 允许/拒绝 来自某个ip的访问
- 允许/拒绝某个端口被访问
二、表、链、规则
规则(rule)
来自192.168.2.31的访问,就要将其拒绝,这即是一条规则
链(chain)
往往我们的安全策略不只一条规则,除了
来自192.168.2.31的访问,就要将其拒绝 这条规则之外,我们还有其它规则,比如:
来自192.168.43.22的访问,也要将其拒绝
甚至,我们可能还有多个互斥的规则,这多个规则,哪个规则先执行? 这就涉及到链这个概念。简单来讲,链就是将多个规则从上大小串起来的一个集合单位。规则按从上倒下依次进行匹配。
总览
在iptables中,有四张表:
filter:这里面的链条,规则,可以决定一个数据包是否可以到达目标进程端口
mangle: 这里面的链条,规则,可以修改数据包的内容,比如ttl
nat:这里面的链条,规则,可以修改源和目标的ip地址,从而进行包路由。
raw:这里面的链条,规则,能基于数据包的状态进行规则设定
上述四张表中,会内置一些链,且每个链,都有默认包处理策略,默认策略一般在链中的所有规则都没匹配时生效。
filter表中的链有:
- INPUT:对路由策略分派过来的包到达目标进程端口之前进行匹配并处理,后续会讲到细节 - FORWARD:对路由策略分派过来的包进行路由转发,后续会讲到细节 - OUTPUT:判断,从本地的目标进程端口处理好的包如何返回/要不要返回给请求方
mangle表中的链有:
PREROUTING:包在到达网口时,进行规则匹配
INPUT:含义同filter
FORWARD: 含义同filter
OUTPUT: 含义同filter
POSTROUTING: 包离开网口的时候匹配
nat表中的链有:
PREROUTING:含义同mangle
OUTPUT:含义同filter
POSTROUTING:含义同mangle
raw表中的链有:
PREROUTING:含义同mangle
OUTPUT:含义同filter
注意,虽然不同的表中有同名的链,但他们并不是同一个链,并且一个链只能引用同一个表中的链,不能跨表引用。,平时我们的防火墙策略配置,即是在上述各个表的各个链中配置具体的规则
规则生效顺序
虽然一个链中的规则是从上到下依次匹配,但多个表中的多个链,甚至同名链的之间的匹配优先顺序是啥?这就要看下图了
PREROUTING 链
PREROUTING 链是最先生效的,当数据包到达网口时,即开始工作。同时由于其在raw, mangle, nat表中都存在,其执行的优先顺序是:raw(PREROUTING) ----> mangle(PREROUTING)----> mangle(nat)
PREROUTING 一般用作对包进行目标地址修改。比如将该包的目标地址,修改为非本机的另外的网络ip,一般通过DNAT规则进行修改。
路由决策(Routing Decision)
决定一个包该走哪个链。如果上述PREROUTING 链对包进行了目标网络ip更改。那么决策会觉得这个是一个需要转发的数据包,于是会将该包转发给 FORWARD 链。
否则, 该包会走INPUT链
FORWARD 链
FORWARD在各表中生效的优先顺序是:mangle(FORWARD) ----> filter(FORWARD)
处理路由决策派发发过来的包,到这里的包一般目标网络地址在PREROUTING链被修改过
INPUT 链
其生效顺序是: mangle(INPUT) ----> filter(INPUT)
处理路由决策派发发过来的包,到这里的包一般目标网络地址在PREROUTING链没有被修改过。
OUTPUT 链
在目标进程端口接收到输入数据包后,输出的数据包,将在这里进行规则应用。OUTPUT链在各表中生效的先后顺序是:
raw(OUTPUT) ----> mangle(OUTPUT) ----> nat(OUTPUT) ----> filter(OUTPUT)
规则详解
前面铺垫了那么多,主要讲解了链的复杂生效时机,毕竟如果包最终都到不了这个链,那其中的规则配置也就没有意义。接下来,我们需要讲解,链中具体规则的设置和使用。
一个规则一般分为两大部分:
匹配: 即哪些数据包会命中这个规则,比如一个指定的ip,即是一个匹配规则
动作: 匹配到规则之后,需要做什么动作,是放行,还是拒绝。
动作分为以下几种:
ACCEPT: 直接接受该数据包,不会再走其他链条和规则。比如filter中的input表中的某个规则命中后,动作是ACCEPT,那么该数据包将被直接送达目标进程端口。
DROP: 直接抛弃该数据包,并且没有任何返回。且不会再走其他链和规则
REJECT: 跟DROP类似,但好歹还是会跟请求方返回一些拒绝信息,比如我们拒绝掉ICMP协议后,ping该主机,会返回“destination host unreachable”
RETURN: 当前规则不做任何处理,返回。让给下一个规则处理
LOG : 同RETURN类似,但只是会将请求信息记录到系统日志中,记录路径为:/var/log/syslog or /var/log/messages
如何看某个表中有哪些链和规则:
iptables -t nat -nvL --line-numbers
-t 表示想要查看那个表,这里查看的是nat表。iptables的所有命令,如果不指定-t,如果不写默认是filter表。
-L 表示列出该表所有链和所有规则
-v 详细显示,会将规则匹配的进出网口也列出来
--line-numbers 表示给规则进行编号处理。编号能方便我们后续对规则进行修改、删除等操作
如图所示,表头有以下信息:
num 表示当前规则编号,从1开始
in 表示该规则会匹配那些的输入网口,如果包是由该网口输入,则会被匹配
out 表示该规则会匹配的目标网口,如果包的目标网口是该网口,则会被匹配
source 表示该规则匹配的具体源ip范围
destination 表示该规则匹配的具体目标ip范围
总结来看,其实一个数据包本身就有源、目标的一些信息,而规则就是基于数据包本身属性的特点进行规则设定。
在已知链末尾添加规则(举例,拒绝某个ip的访问)
iptables -t filter -A INPUT -s 59.45.175.62 -j REJECT
-A 表示Append,其后紧跟的是链的名称,表示该条规则要被添加到哪个链中。
-s 表示包的来源ip即source。除了指定固定的ip外,我们还可以指定ip范围,比如59.45.175.0/24
-j 表示jump 也即是我们最终的动作,这里的动作是拒绝
在已知链链首插入规则
链尾的规则匹配优先级最低,如果前面有规则被匹配后,并将数据包进行了终态处理(比如:ACCEPT, DROP, REJECT),那么链尾的规则将永远不会被使用。
如果我们想要该规则优先匹配,可以选择将其放入链首,使用-I参数,表示insert。举例:
iptables -t filter -I INPUT -s 59.45.175.62 -j REJECT
拒绝掉对某个ip的回应
iptables -A OUTPUT -d 31.13.78.35 -j DROP
-d
表示destination,即所有返回给ip 31.13.78.35的数据包都直接丢掉,不回应。
清空某个链中的所有规则
iptables -t filter -F INPUT
所有TCP协议的数据包,都丢弃
iptables -A INPUT -p tcp -j DROP
-p
表示protocol
丢弃掉某个ip对端口22的访问
iptables -A INPUT -p tcp -m tcp --dport 22 -s 59.45.175.0/24 -j DROP
由于要对端口进行精准匹配,所以先-m tcp
进行tcp module加载。
如何对多个端口进行匹配
iptables -A INPUT -p tcp -m multiport --dports 22,5901 -s 59.45.175.0/24 -j DROP
匹配指定链接状态的数据包
链接状态有以下几种:
NEW:新创建的连接
ESTABLISHED 已经建立的连接
RELATED:跟已经创建的连接相关的连接
INVALID:非正常状态
DNAT:如果一个连接其目标地址被nat表PREROUTING链中的规则修改了,即是这个状态
SNAT:如果一个连接其源地址被nat表中的规则修改了,即是这个状态
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
即只对已经建立的连接和由此产生的相关连接进行放行
有些版本的linux,对应的module不是conntrack,而是state。 对应指定状态的参数不是ctstate 而是--state
。所以,上述写法在有些linux版本中需要替换成
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
一般来讲,这些规则不可能单独出现,如果都不允许任何NEW状态连接建立,那哪来的已建立连接和相关连接?所以正确的做法一般是:
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT //这条规则允许已经建立的连接和相关连接 iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT //新建链接如果是访问22号端口,则允许访问
改变某个链的默认规则
一般每个链都有默认规则,即该链没有任何规则或者没有任何一条规则被匹配的情况下,对数据的放行策略是怎么样的。
Chain INPUT (policy ACCEPT)
...
Chain FORWARD (policy ACCEPT)
...
Chain OUTPUT (policy ACCEPT)
..
以filter表的三个链为例,默认是ACCEPT。 但是我们可以改变这个模型规则,比如默认规则就是DROP
iptables -t filter -P INPUT DROP
回环地址的访问始终允许
iptables -t filter -A INPUT -i lo -j ACCEPT //在本地网络通信的所有包,都放行
-i 表示input 输入网口。lo表示本地的网络接口。这里没有指定-s 或 -d地址 ,表示在回环网络上通信的所有端口,都放行,这样我们本机的web service,访问本机的mysql数据库才不会有问题。当然一般INPUT的默认规则是ACCEPT,你不用配置上述的规则,只要没有其它规则去限制,那么本机回环地址之间的端口通信也是放行的,除非你对INPUT链默认开启了拒绝策略
在使用某个网络时,不响应请求
iptables -A OUTPUT -o wlan0 -d 121.18.238.0/29 -j DROP
上述配置含义:所有发给目标网口是wlan0 且 目标ip是121.18.238.0/29 地址的包,都会被丢弃。-o
表示 数据包的目标网口。
在linux命令行中,使用ifconfig
,就能看见当前已连接的所有网络接口
规则的取反配置
上述规则配置,一般都是满足某某条件,做什么动作。除此之外,我们还可以配置,如果不满足某某条件,则做某个动作。
iptables -A INPUT -p tcp -m multiport ! --dports 22,80,443 -j DROP
这个不满足则
的取动作,是通过感叹号来实现的。
上述命令的含义是:非22,80,443的端口,我们直接丢弃。
当然这条命令之前,应该要配置一条规则:
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
因为通过22或80建立的连接,可能会衍生出一些RELATED的连接,他们的端口可能不是22或80,那样也就被拒掉了。会导致通信出问题。
如何将规则持久化
上述命令对iptable的操作,并不是永久生效的,机器重启后,对应配置会丢失。如果需要持久化,则需要以下命令进行保存
centos
第一步,在修改iptables配置后,将其导出到某个文件,比如: /etc/iptables.conf 。命令为:iptables-save > /etc/iptables.conf 这一步,每次修改后都要做
第二步,在/etc/rc.local中添加命令iptables-restore < /etc/iptables.conf。从此之后,每次重启,系统会自动从/etc/iptables.conf恢复对应的iptables配置。这一步只需要做一次
ubuntu
安装iptables-persistent,它会在系统启动时,从/etc/iptables/rules.v4 和 /etc/iptables/rules.v6分别加载ipv4 和ipv6的iptables 规则
sudo apt install iptables-persistent
所以,每次我们对iptables进行了任何改动,使用下面的命令,将当前生效的iptables配置,导出到/etc/iptables/rules.v4
和 /etc/iptables/rules.v6
即可
sudo iptables-save > /etc/iptables/rules.v4 //如果添加了ipv4 规则,执行这步 sudo ip6tables-save > /etc/iptables/rules.v6 //如果添加了ipv6规则,执行这步
自定义链
除了在现有的链中添加规则,我们也可以自定义链,自定义链可以帮助我们将一组规则收纳在一起,方便我们管理。比如:
- 我们可以定义一个名为
ssh-rules
的链来管理ssh登录的一些规则