iptables简介
iptables是用户管理netfilter上规则的一个用户空间的工具,真正实现防火墙的功能是netfilter,内核组件netfilter在内核中选取了五个位置放置了五个hook(勾子)函数分别是INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING、用户是没有办法直接使用的,必须通过用户空间的软件去调用才可以使用,这说明了iptables它是一个工具,而不是一个服务
iptables的组成以及数据包的传输过程
iptables的组成
iptables由五个表和五个链以及一些规则组成,五个表分别是filter、nat、mangle、raw、security,这五个表每张表都有不同的作用:
- filter表:这里的链条,规则,可以决定一个数据包是否可以到达目标进程端口
- nat表:这里的链条,规则,可以修改源和目标的ip地址,从而进行包路由
- mangle表:这里的链条,规则,可以修改数据包的内容,比如ttl
- raw表:这里面的链条,规则,能基于数据包的状态进行规则设定
- serurity表:用于强制控制(MAC)网络规则,由Linux安全模块(如selinux)实现;
iptables表优先级顺序
iptables中表的优先级由高到低的顺序为:
security --> raw --> mangle --> nat --> filter
iptables内置的链
上述表中,会内置一些链,且每个链,都有默认包处理策略,默认策略一般在链中的所有规则没匹配时生效。
filter表中的链
- INPUT:对路由策略分配过来的包到达目标进程端口之前进行匹配处理
- FORWARD:对路由策略分配过来的包进行路由转发
- OUTPUT:判断,从本地的目标进程端口处理好的包如何返回/要不要返回给请求方
mangle表中的链
- PREROUTING:包在到达网口时,进行规则匹配
- INPUT:对路由策略分配过来的包到达目标进程端口之前进行匹配处理
- FORWARD:对路由策略分配过来的包进行路由转发
- OUTPUT:判断,从本地的目标进程端口处理好的包如何返回/要不要返回给请求方
- POSTROUTING:包离开网口的时候匹配
nat表中的链
- PREROUTING:包在到达网口时,进行规则匹配
- OUTPUT:判断,从本地的目标进程端口处理好的包如何返回/要不要返回给请求方
- POSTROUTING:包离开网口的时候匹配
raw表中的链
- PREROUTING:包离开网口的时候匹配
- OUTPUT:判断,从本地的目标进程端口处理好的包如何返回/要不要返回给请求方
注意:虽然不同的表中有同名的链,但他们并不是同一个链,并且一个链只能引用同一个表中的链,不能跨表引用。平时我们的防火墙策略配置,即是在上述各个表中的各个链中配置具体的规则
规则生效顺序
虽然一个链中的规则是从上到下依次匹配,在多个表中的多个链,甚至同名链直接的匹配优先级顺序如下图
PREROUTING链
PREROUTING链是最先生效的,当数据包到达网口时,即开始工作。同时由于其在raw,mangle,nat表中都存在,其执行的有限顺序是:raw(PREROUTE)-->managle(PREROUTE)-->mangle(nat)
PREROUTING一般用作对包进行目标地址修改。比如将该包的目标地址,修改为非本机的另外的网络ip,一般通过 DNAT 规则进行修改
路由策略(Routing Decision)
决定一个包该走哪个链。如果上述PERROUTE链对包进行了目标网络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命令使用和选项说明
查看iptables使用说明
一、使用iptables -h查看iptables命令使用格式
[root@master ~]# iptables -h
二、使用 man 8 iptables
除了以上用-h来了解iptables的简要用法和说明外,我们还可以通过 man 8 iptables来了解每个选项的详细说明
- -t 选项表示指定表名,默认是filter表
- -A 表示追加规则到最后
- -s 表示指定源ip地址
- -j 表示处理的动作
- 还可以使用-t 指定具体操作的表,缺省为filter表
iptables命令大概可以分为二段,第一段指明规则位置,第二段是规则本身,规则又需要指明匹配条件和处理动作;
上图命令表示在INPUT链上的filter表上追加一条规则到最后,规则内容为源地址192.168.0.1的报文将丢弃,注意-A后面需要跟链名,链名必须得大写
总结:
命令使用格式:iptables [-t tablesname] COMMAND chain [-m matchname [per-match-options]] -j targetname [per-target-options]
tablesname: raw,mangle,nat,[filter]默认不指定就是filter;
COMMAND子命令,指明对规则的增删查改
链管理
子命令 | 作用 |
-N :new | 自定义一条新的规则链 |
-X :delete | 删除自定义的规则链(前提是,自定义链未被主链引用,也就是引用计数为0,其次是自定义链必须是空链,就是没有任何规则的链) |
-P:policy | 设置默认策略;对filter表中的链而言,其默认策略有:ACCEPT接受,ACCEPT允许。DROP丢弃 |
-E | 重命名自定义链 |
规则管理
子命令 | 作用 |
-A:append | 追加规则到指定表达最后 |
-I:insert | 插入,要指明位置,省略时表示第一条 |
-D:delete | 删除,删除规则需要指明规则序号,或者指明规则本身 |
-R:replace | 替换指定链上的指定规则,需指明替换第几条规则 |
-F:flush | 清空指定的规则链;若为指定链,则表示清空filter表所在的所有链 |
-Z:zero | 置零指定链上的计数器,若为指定则表示,清空filter表所在的所有链上的规则计数器;iptables的每条规则都有两个计数器:(1) 匹配到的报文的个数;(2) 匹配到的所有报文的大小之和; |
查看指定链上的规则
提示:使用查看子命令-L如果有其它修饰子命令的选项和-L合并时,需要把其它修饰该命令的选项放在-L前面,否则会把其选项识别为链名
例:
[root@node1 ~]# iptables -nvL
子命令 | 作用 |
-L:list | 列出指定链上的所有规则 |
-n:numberic | 以数字格式显示地址和端口 |
-v:verbose | 详细信息 支持-vv -vvv来指定详细程度 |
-x:exactly | 显示计数器结果的精确值,而非单位转换后的已读值(bytes字段) |
--line-num: --line-numbers | 显示规则的序号,可缩写为--line-num |
-S selected | 以iptables-save命令格式显示链上规则 |
-S ,以iptables-save命令格式显示链上规则。提示:如果有需要,可以将其输出重定向到一个文件中去,但是导出的内容不能用于规则导入到文件,也就是说导出的文件不能用来重载iptables规则表
规则的导出和导入
iptables规则导出到指定文件
提示:保存规则使用iptables-save命令,它默认是把链上的所有规则打印到标准输出,如果需要保存到指定文件需要用到输出重定向到指定文件即可
导入规则的文件内容必须是iptables-save导出的文件,不能用iptables -S导出的文件还原
[root@node1 ~]# iptables-save > iptables.bak [root@node1 ~]# cat iptables.bak
还原
[root@node1 ~]# iptables -nvLChain INPUT (policy ACCEPT 1984 packets, 181K bytes) pkts bytes target prot opt in out source destination 2 168 REJECT all -- * * 192.168.224.173 192.168.224.237 [root@node1 ~]# iptables -F [root@node1 ~]# iptables -nvL Chain INPUT (policy ACCEPT 2042 packets, 186K bytes) pkts bytes target prot opt in out source destination [root@node1 ~]# iptables-restore < iptables.bak [root@node1 ~]# iptables -nvL Chain INPUT (policy ACCEPT 37 packets, 3208 bytes) pkts bytes target prot opt in out source destination 0 0 REJECT all -- * * 192.168.224.173 192.168.224.237 reject-with icmp-port-unreachable
-n,--noflush:不清楚原有规则导入
提示:-n 选项是不清空原有非自定义链上的规则,对应自定义链不管是否引用都会被清空
-t --test 仅分析生成规则集,但不提交
[root@node1 ~]# iptables-restore -n iptables.bak
iptables使用
如何查看某个表中有哪些链和规则
iptables -t nat -nvl --line-numbers
- -t 表示想要查看哪个表,这里查看的是nat表。iptables的所有命令,如果不指定-t,如果不写默认是filter表
- -L 表示列出该表所有链和所有规则
- -v 详细显示,会将规则匹配的进出网口也列出来
- --line-numbers 表示会给规则进行编号处理。编号能方便我们后续对规则进行修改、删除等操作
[root@node1 ~]# iptables -t nat -nvL --line-numbersChain PREROUTING (policy ACCEPT 1 packets, 229 bytes)num pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination
如上所示,表头有以下信息:
- pkts:匹配到改规则的数据包数量
- bytes:匹配到该规则的数据包的总字节数
- target:规则的目标动作,指定如何处理匹配到的数据包
- port:匹配的协议类型,如TCP、UDP、ICMP等
- opt:规则中的选项,指定其它匹配条件或操作
- num 表示当前规则编号 从1开始
- in 表示该规则会匹配哪些的输入网口,如果包是由该网口输入,则会匹配
- out 表示该规则会匹配的目标网口,如果包的目标网口时该网口,则会匹配
- source 表示该规则匹配的具体源ip范围
- destination 表示该规则匹配的具体目标ip范围
总结来看,其实一个数据包本身就有源、目标的一些信息,而规则是基于数据包本身属性的特点进行规则设定
在已有链末尾添加规则
举例,拒绝某个ip的访问
iptables -t filter -A INPUT -s 192.168.224.173 -j REJECT
- -A 表示Append,其后紧跟的是链的名称,表示该条规则要被添加到哪个链中。
- -s 表示包的来源ip 即source。除了指定固定的ip外,我们还可以指定ip范围,比如192.168.224.0/24
- -j 表示jump 即是我们最终的动作,这里的动作是拒绝
[root@node1 ~]# iptables -t filter -A INPUT -s 192.168.224.137 -d 192.168.224.237 -j REJECT
在已有链链首插入规则
iptables -t filter -I INPUT -s 192.168.224.137 -j REJECT
链尾的规则匹配优先级最低,如果前面有规则被匹配后,并将数据包进行了终态处理(比如:ACCEPT、DROP、REJECT),那么链尾的规则将永远不会被使用。
如果我们想要该规则优先匹配,可以选择将其放入链首,使用-I参数,表示insert
[root@node1 ~]# iptables -t filter -I INPUT -s 192.168.224.137 -j REJECT
删除规则
想要删除已配置的规则,可以使用 -D 参数
iptables -t filter -D INPUT -s 192.168.224.137 -j REJECT
这种删除方法,需要我们明确知道当初添加进去的规则是怎么写的。如果忘了,我们可以通过规则编号进行删除。在查看规则时使用参数 --line-numbers(例如:iptbales -nvL --line-numbers),可以对规则进行编号,然后基于编号进行删除
iptables -t filter -D FORWARD 1
表示删除filter表中的FORWARD链中的第一条规则
拒绝掉对某个ip的回应
iptables -A OUTPUT -d 192.168.224.173 -j DROP
-d 表示destination,即所有返回给ip 192.168.224.173的数据包都直接丢掉,不回应
清空某个链中的所有规则
[root@node1 ~]# iptables -t filter -F INPUT
-p 表示protocol 指定协议
丢弃掉某个ip对端口22的访问
由于要对端口进行精准匹配,所以先 -m tcp 进行tcp module加载
[root@node1 ~]# iptables -t filter -A INPUT -p tcp -m tcp --dport 22 -s 192.168.224.173 -j DROP
如果对多个端口进行匹配
-m multiport --dports 22,5901使用muliport模块匹配多个端口号,这里匹配目标端口号为22和5901的数据包
[root@node1 ~]# iptables -t filter -A INPUT -p tcp -m multiport --dports 22,5901 -s 192.168.224.173 -j DROP
匹配指定链接状态的数据包
链接状态有以下几种:
- NEW:新创建的连接
- ESTABLISHED: 已经建立的连接
- RELATED:跟已经创建的连接相关的连接
- INVALID:非正常状态
- DNAT:如果一个连接其目标地址被nat表PREROUTING链中的规则修改了,即是这个状态
- SNAT:如果一个连接其源地址被nat表中的规则修改了,即是这个状态
一、
-m conntrack --create RELATED,ESTABLISHED 使用 conntrack 模块匹配与已建立连接的连接相关的数据包,包括已建立和相关的连接状态
这条规则的作用是允许已建立的连接和与已建立的连接相关的数据包进入系统。这是一条常见的规则,用于确保系统可用接受与已建立的连接相关的数据包,如相应已建立的连接的数据包或新建立连接的数据包
[root@node1 ~]# iptables -t filter -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
有些版本的Linux,对应的module不是conntrack,而是state。对应指定状态的参数不是ctstate而是有些 --state,所以,上述写法在有些Linux版本中需要替换成
[root@node1 ~]# iptables -t filter -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
二、
一般来讲,这些规则不可能单独出现,如果都不允许任何NEW状态连接建立,那哪来的已建立连接和先关连接?
所以一般正确做法是:
这条规则允许已经建立的连接和相关连接
[root@node1 ~]# iptables -t filter -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
新建连接如果是访问22号端口,则允许访问
[root@node1 ~]# iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
改变某个链的默认规则
一般某个链都有默认规则,即该链没有任何规则或者没有任何一条规则被匹配的情况下,对数据的放行策略是怎么样的
[root@node1 ~]# iptables -S-P INPUT ACCEPT-P FORWARD ACCEPT-P OUTPUT ACCEPT
以filter表的三个链为例,默认是ACCEPT。但是我们可以改变这个模型规则,比如默认规则就是DROP
[root@node1 ~]# iptables -t filter -P INPUT DROP
[root@node1 ssh_config.d]# iptables -t filter -P INPUT DROP[root@node1 ssh_config.d]# [root@node1 ssh_config.d]# iptables -S-P INPUT DROP -P FORWARD ACCEPT -P OUTPUT ACCEPT -A INPUT -s 192.168.224.1/32 -j ACCEPT ## 这条规则是提前配置的 防止远程连接被干掉
回环地址的访问始终允许
INPUT链的默认规则改成了DROP丢弃,所以就连ping回环地址都被丢弃了
[root@node1 ssh_config.d]# ping 127.0.0.0Do you want to ping broadcast? Then -b. If not, check your local firewall rules.[root@node1 ssh_config.d]# ping 127.0.0.1PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. ^C --- 127.0.0.1 ping statistics --- 4 packets transmitted, 0 received, 100% packet loss, time 3086ms
-i 表示INPUT输入网口。lo 表示本地的网络接口。这里没有指定-s 或 -d地址,表示在回环网络上通信的所有端口,都放行。
这样我们本机的web service,访问本机的MySQL数据库才不会有问题。当然一般INPUT的默认规则是ACCEPT,你不用配置上述的规则,只要没有其它规则去限制,那么回环地址之间的端口通信是放行的,除非对INPUT链默认开启了拒绝策略
[root@node1 ssh_config.d]# iptables -t filter -A INPUT -i lo -j ACCEPT[root@node1 ssh_config.d]# ping 127.0.0.1PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.034 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.048 ms ^C --- 127.0.0.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1044ms rtt min/avg/max/mdev = 0.034/0.041/0.048/0.007 ms
在使用某个网络时,不响应请求
说明:所有发给目标网口时ens224,且目标ip是192.168.100.0/24地址的包,都会被丢弃。-o 表示 数据包的目标网口
[root@node1 ~]# iptables -A OUTPUT -o ens224 -d 192.168.100.0/24 -j DROP[root@node1 ~]# ping 192.168.100.100PING 192.168.100.100 (192.168.100.100) 56(84) bytes of data.ping: sendmsg: 不允许的操作 ping: sendmsg: 不允许的操作 ^C --- 192.168.100.100 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1046ms
规则的取反配置
上述规则配置,一般都是满足某某条件,做什么动作。除此之外,我们还可以配置,如果不满足某某条件,则做某个动作。
这个 不满足则 的动作,是通过感叹号来实现的。下面命令的含义是:
非20,80,443的端口,我们直接丢弃
[root@node1 ~]# iptables -t filter -A INPUT -p tcp -m multiport ! --dports 22,80,443 -j DROP
当然这条命令之前,还应该要配置一条规则:因为通过22或80建立的连接,可能会衍生出一些RELATED的连接,他们的端口可能不是22或80,那样也就被拒绝掉了。会导致通信出问题
[root@node1 ~]# iptables -t filter -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
如何将规则持久化
Centos
第一步
在修改iptables配置后,将其导出到某个文件,比如/etc/iptables.conf。命令为
[root@node1 ~]# iptables-save > /etc/iptables.conf
这一步,每次修改后都要做
第二步
在/etc/rc.local中添加命令iptables-restore < /etc/iptables.conf。从此之后,每次重启,系统会自动从/etc/iptables.conf恢复对应的iptables配置。这一步只需要做一次
[root@node1 ~]# echo 'iptables-restore < /etc/iptables.conf' >> /etc/rc.local[root@node1 ~]# tail -3 /etc/rc.localtouch /var/lock/subsys/localiptables-restore < /etc/iptables.conf [root@node1 ~]# chmod a+x /etc/rc.local
Ubuntu
安装 iptables-persistent,它会在系统启动的时候,从/etc/iptables/rules.v4 和 /etc/iptables/rules.v6分别加载ipv4和ipv6的规则
sudo apt install iptables-persistent
所以,每次我们对iptables进行了任何改动,使用下面的命令,将当前生效的iptables配置,导出到/etc/iptables/rules.v4和/etc/iptables/rules.v6即可
# 如果添加了ipv4规则,则执行这一步sudo iptables-save > /etc/iptables/rules.v4# 如果添加了ipv6规则,则执行这一步sudo iptables-save > /etc/iptables/rules.v6
自定义链
管理自定义链
除了在现有链中添加规则,我们也可以自定义链,自定义链可以帮助我们将一组规则收纳在一起,方便我们管理。比如:
1.
定义一个名为ssh-rules的链来管理ssh登录的一些规则
[root@node1 ~]# iptables -t filter -N ssh-rules
2.
在这个链中添加具体的规则
iptables -t filter -A ssh-rules -s 192.168.224.0/24 -j ACCEPTiptables -t filter -I ssh-rules 2 -s 172.16.254.0/24 -j ACCEPTiptables -t filter -A ssh-rules -j DROP
3.
然后将该链作为一个规则出口,挂在iptable内置的链上
[root@node1 ~]# iptables -t filter -A INPUT -p tcp -m tcp --dport 22 -j ssh-rules
以上含义就是在INPUT链中添加一个规则,所有22号端口的访问,都会导向ssh-rules。
删除自定义链
当我们想要删除自定义链时,使用命令
[root@node1 ~]# iptables -X ssh-rulesiptables v1.8.4 (nf_tables): CHAIN_USER_DEL failed (Device or resource busy): chain ssh-rules
删除自定义链前提是,自定义链未被主链引用,也就是引用计数为0,其次是自定义链必须是空链,就是没有任何规则的链
删除ssh-rules中所有的规则[root@node1 ~]# iptables -t filter -D ssh-rules 1删除INPUT链中的ssh-rules规则[root@node1 ~]# iptables -t filter -D INPUT 1
[root@node1 ~]# iptables -X ssh-rules