iptables防火墙详解
1. iptables介绍及工作原理
1.1 防火墙概述
-
防火墙分类:
-
从逻辑上讲,防火墙可以大体分为主机防火墙和网络防火墙。
- 主机防火墙:针对于单个主机进行防护,比如Windows。
- 网络防火墙:往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的服务器集群。
-
从物理上讲,防火墙可以分为硬件防火墙和软件防火墙。
- 硬件防火墙:在硬件级别实现部分防火墙功能,另一部分功能基于软件实现,性能高,成本高。
- 软件防火墙:以软件的方式模拟防火墙功能,运行在操作系统上,性能不高,成本较低。
-
1.2 iptables概述
iptables 其实不是真正的防火墙,我们可以把它理解成是一个代理程序,用户通过 iptables 这个代理程序,将安全规则执行到对应的"安全框架"中,这个"安全框架"才是真正的防火墙;这个安全框架叫 netfilter 。
netfilter 位于操作系统的内核空间。 iptables 位于操作系统的用户空间,我们是通过 iptables 命令工具操作 netfilter 内核框架。
iptables是一种包过滤防火墙。
-
包过滤防火墙
包过滤防火墙它在网络层截获网络数据包的包头 (header) ,它针对数据包的包头,根据预先定义好的防火墙过滤规则进行比对,与规则相匹配的包会被放行,与规则不匹配的包则可能会被丢弃、也可能执行更复杂的动作。
包过滤防火墙一般作用在网络层,故也称”网络层防火墙“,通过检查数据流中每一个数据包的源IP地址、目的IP地址、源端口、目的端口、协议类型 (TCP、 UDP、ICMP) 、状态等信息来判断是否符合规则。
-
包过滤防火墙是由 Netfilter 来实现的,它是内核的一部分,所以,如果我们想要防火墙能够达到"防火"的目的,则需要在内核中设置关卡,所有进出的报文都要经过这些关卡,进行检查,将符合条件的放行,不符合条件的阻止,而这些关卡在iptables中不被称为"关卡",而被称为"链"。
1.3 iptables链的概念
我们知道,防火墙的作用就在于对经过的数据报文进行"规则"匹配,然后执行规则对应的"动作",所以当报文经过这些关卡的时候,则必须匹配这个关卡上的规则,但是,这个关卡上可能不止有一条规则,而是有很多条规则,当我们把这些规则串到一起的时候,就形成了"链"。
当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据 该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定义的默认策略来处理数据包。
Netfilter在内核中数据流经的五个地方设置了规则链,即5个钩子函数(hook functions):
- INPUT链:进入本机的数据包应用此规则链中的策略;
- OUTPUT链:外出本机的数据包应用此规则链中的策略;
- FORWARD链:经本机转发数据包时应用此规则链中的策略;
- PREROUTING链:对数据包作路由选择前应用此链中的规则,所有的数据包进来的时侯都先由这个链处理;
- POSTROUTING链:对数据包作路由选择后应用此链中的规则 ,所有的数据包出来的时侯都先由这个链处理;
不同流向的数据包经过的链并不一样:
-
进入本机的报文经过的链有:(PREROUTING-->INPUT-->Local Process);
-
经过本机的报文经过的链有:(PREROUTING-->FORWARD-->POSTROUTING);
-
从本机流出的报文经过的链有:(Local Process-->OUTPU-->POSTROUTING);
1.4 iptables表的概念
我们对每个"链"上都放置了一串规则,但是这些规则有些很相似,比如,A类规则都是对IP或者端口的过滤,B类规则是修改报文,那么这个时候,我们是不是能把实现相同功能的规则放在一起呢?
我们把具有相同功能规则的集合叫做"表",所以说,不同功能的规则,我们可以放置在不同的表中进行管理,而 iptables 已经为我们定义了4种表,每种表对应了不同的功能。
iptables内置了四种表,分别用于实现不同的功能,每种表只能作用在特定的链上,具体对应关系如下:
表名 | 作用 | 可以作用的链 |
---|---|---|
filter表 | 过滤数据包 ,使用内核模块:iptables_filter | INPUT、OUTPUT、FORWARD |
Nat表 | 用于网络地址转换(IP、端口),使用内核模块:iptable_nat | PREROUTING、POSTROUTING、OUTPUT |
Mangle表 | 修改数据包的字段,例如服务类型、TTL、并且可以配置路由实现QOS,使用内核模块:iptable_mangle | PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD |
Raw表 | 决定数据包是否被状态跟踪机制处理 ,使用内核模块:iptable_raw | OUTPUT、PREROUTING |
- iptables四张表处理的先后顺序依次为:raw --> mangle --> nat --> filter。
1.5 iptables表和链的关系
数据的处理流程如下图:
-
问题1:来自于 10.0.0.1 的地址,访问本机的 web 服务请求都不允许,应该在哪个表的哪个链上设定规则?
答案1:很多人会觉得是 PREROUTING 链,但其实是INPUT链。因为我们要做的是过滤,而 PREROUTING 不能做过滤,所以是 INPUT 。
-
问题2:所有由本机发往 10.0.0.0/24 网段的 TCP 服务都不允许?
答案2:由本地发出会经过 OUTPUT、POSTROUTING 、但由于 POSTROUTING 不支持做过滤,所以应该在 OUTPUT 规则链上配置。
-
问题3:所有来自己本地内部网络的主机,像互联网发送 web 服务器请求都允许?
答案3:本地内部主机发送互联网经过 PREROUTING、FORWARD、POSTROUTING 而能做过滤的只有 FORWARD 。
2. iptables规则管理
2.1 iptables规则
规则的组成部分:根据规则匹配条件来尝试匹配报文,一旦匹配成功,就由规则定义的处理动作作出处理;
- 匹配条件:
- 基本匹配条件:内建
- 扩展匹配条件:由扩展模块定义;
- 处理动作:
- 基本处理动作:内建
- 扩展处理动作:由扩展模块定义;
- 自定义处理机制:自定义链
iptables的链:内置链和自定义链
- 内置链:对应于hook function
- 自定义链接:用于内置链的扩展和补充,可实现更灵活的规则管理机制,自己定义的链,必须是跟某种特定的链关联起来的。在一个关卡设定,指定当有数据的时候专门去找某个特定的链来处理,当那个链处理完之后,再返回。接着在特定的链中继续检查。
编写规则时的考量点:
- (1) 要实现哪种功能:判断添加到哪个表上;
- (2) 报文流经的路径:判断添加到哪个链上;
2.1.1 iptables规则安排的基本原则
任何不允许的访问,应该在请求到达时给予拒绝
规则在链接上的次序即为其检查时的生效次序
基于上述,规则优化
- 1.安全放行所有入站和出站的状态为ESTABLISHED状态连接
- 2.谨慎放行入站的新请求
- 3.有特殊目的限制访问功能,要在放行规则之前加以拒绝
- 3.同类规则(访问同一应用),匹配范围小的放在前面,用于特殊处理
- 4.不同类的规则(访问不同应用),匹配范围大的放在前面
- 5.应该将那些可由一条规则能够描述的多个规则合并为一条
- 6.设置默认策略,建议白名单(只放行特定连接)
- 7.修改默认策略时不建议iptables -P,建议在规则的最后定义规则做为默认策略
2.2 iptables命令详解
iptables的基本语法如下:
iptables [-t table] COMMAND chain [-m matchname [per-match-options]] -j targetname [per-target-options]
说明:
-t:指定要操作的表,不指定则默认为filter;
COMMAND:用于实现规则的增删查改插入等功能;
chain:指明操作的链名;
[-m matchname [per-match-options]]:表示具体的规则,匹配条件等;
-j targetname:表示处理的动作;
规则操作相关的命令如下:
命令 | 意义 | 示例 |
---|---|---|
-A, --append | 追加一条规则至链的末尾 | iptables -t filter -A INPUT |
-I, --insert | 插入一条规则至链的顶部 | iptables -t filter -I INPUT |
-D, --delete | 删除指定一条规则,需要指明规则的编号或规则本身 | iptables -t filter -D INPUT 1 |
-R, --replace | 替换选定链中的规则 | iptables -t filter -R INPUT |
-S, --list-rules | 打印选定链中的所有规则 | iptables -t filter -S |
-F, --flush | 清空链中的所有规则 | iptables -t filter -F |
-Z, --zero | 将所有链中的数据包和字节计数器归零 | iptables -t filter -Z |
-P, --policy | 给链设定默认策略 | iptables -t filter -P DROP |
-L | 列出指定鏈上的所有规则 | iptables -t filter -L |
链操作相关的命令如下:
命令 | 意义 | 示例 |
---|---|---|
-N, --new-chain | 创建自定义名称规则链 | iptables -N New_Rules |
-E, --rename-chain | 给自定义链修改名称,引用计数不为0的自定义链不能够被重命名,也不能被删除; | iptables -E Old_Rules New_Rules |
-X, --delete-chain | 删除自定义链,仅能删除用户自定义的引用计数为0 (0 references)的 空的无规则链; | iptables -X Rules_Name |
2.2.1 查看规则
查看规则相关的选项如下:
选项 | 说明 |
---|---|
-n:numberic | 以数字格式显示地址和端口号,如果不加-n,则会将ip反向解析成主机名; |
-v:verbose | 显示详细信息; |
-x:exactly | 显示计数器结果的精确值; |
--line-numbers | 显示规则的序号,每种规则单独计数; |
示例如下:
#1.查看规则:
[root@iptables ~]# iptables -vnL
Chain INPUT (policy ACCEPT 122 packets, 10494 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.8
0 0 REJECT udp -- * * 172.16.0.0/16 0.0.0.0/0 udp dpt:53 reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 45 packets, 6969 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 192.168.20.8 0.0.0.0/0
#2. 显示规则编号:
[root@iptables ~]# iptables -vnL --line-numbers
Chain INPUT (policy ACCEPT 186 packets, 14884 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.8
2 0 0 REJECT udp -- * * 172.16.0.0/16 0.0.0.0/0 udp dpt:53 reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 75 packets, 11649 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- * * 192.168.20.8 0.0.0.0/0
2.2.2 添加规则
-
允许其他任何主机 ping 通本机。
[root@iptables ~]# iptables -t filter -A INPUT -p icmp -j ACCEPT root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 4011 packets, 440K bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 239 packets, 14202 bytes) num pkts bytes target prot opt in out source destination
-
在策略最前面增加规则,允许192.168.20.0/24地址段访问本机的22端口。
[root@iptables ~]# iptables -t filter -I INPUT -s 192.168.20.0/24 -p tcp --dport 22 -j ACCEPT [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 8 576 ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 5 packets, 780 bytes) num pkts bytes target prot opt in out source destination
-
在第二条策略前增加一个策略,允许192.168.20.0/24地址段访问本机的23端口。
[root@iptables ~]# iptables -t filter -I INPUT 2 -s 192.168.20.0/24 -p tcp --dport 23 -j ACCEPT [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 237 21668 ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 2 0 0 ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:23 3 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 5 packets, 988 bytes) num pkts bytes target prot opt in out source destination
2.2.3 修改规则
-
修改上述INPUT策略中的第二条规则,拒绝192.168.20.0/24地址段访问本机的23端口。
[root@iptables ~]# iptables -t filter -R INPUT 2 -s 192.168.20.0/24 -p tcp --dport 23 -j REJECT [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 336 28360 ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 2 0 0 REJECT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:23 reject-with icmp-port-unreachable 3 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 4 packets, 608 bytes) num pkts bytes target prot opt in out source destination
2.2.4 删除规则
-
删除上面INPUT链中的第二条规则
[root@iptables ~]# iptables -t filter -D INPUT 2 [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 466 37424 ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 7 packets, 996 bytes) num pkts bytes target prot opt in out source destination
2.2.5 增加默认规则
-
把filter表中的forward默认规则设置为拒绝。
[root@iptables ~]# iptables -t filter -P FORWARD REJECT iptables: Bad policy name. Run `dmesg' for more information. [root@iptables ~]# iptables -t filter -P FORWARD DROP [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 606 47012 ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 6 packets, 728 bytes) num pkts bytes target prot opt in out source destination
2.2.6 保存和恢复规则
iptables规则为临时生效,需要进行保存。
-
CentOS6环境
#将规覆盖保存至/etc/sysconfig/iptables文件中 service iptables save #自动从/etc/sysconfig/iptables重新载入规则 service iptables restart
-
CentOS7环境
#1.保存规则: [root@iptables ~]# iptables-save > /etc/iptable.rules [root@iptables ~]# cat /etc/iptable.rules # Generated by iptables-save v1.4.21 on Sun Jul 18 16:13:05 2021 *filter :INPUT ACCEPT [66:5601] :FORWARD DROP [0:0] :OUTPUT ACCEPT [44:4700] -A INPUT -s 192.168.20.0/24 -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p icmp -j ACCEPT COMMIT # Completed on Sun Jul 18 16:13:05 2021 #2.清空规则 [root@iptables ~]# iptables -F [root@iptables ~]# iptables -vnL Chain INPUT (policy ACCEPT 61 packets, 4708 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 44 packets, 4528 bytes) pkts bytes target prot opt in out source destination #3.恢复规则: [root@iptables ~]# iptables-restore < /etc/iptable.rules [root@iptables ~]# iptables -vnL Chain INPUT (policy ACCEPT 3 packets, 234 bytes) pkts bytes target prot opt in out source destination 6 428 ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 4 packets, 560 bytes) pkts bytes target prot opt in out source destination [root@iptables ~]#
2.2.7 设置规则开启自动加载
-
Centos 6:设置iptables开机启动
chkconfig --list iptables
-
Centos 7,8:
-
方法一:在/etc/rc.d/rc.local文件中添加规则恢复命令
vim /etc/rc.local iptables -restore < /PATH/FROM/SOME_RULES_FILE
-
方法二:定义Unit File, CentOS 7,8 可以安装 iptables-services 实现iptables.service
#安装包: [root@iptables ~]# yum install iptables-services #保存iptables规则 [root@iptables ~]# iptables-save > /etc/sysconfig/iptables #重启服务iptables规则自动恢复 [root@iptables ~]# systemctl restart iptables.service # 开机启动 [root@iptables ~]# systemctl enable iptables.service
-
2.3 iptables基本匹配条件
基本匹配条件无需加载任何模块,由iptables/netfilter自行提供。
2.3.1 基本匹配参数
匹配参数 | 说明 |
---|---|
[!] -p, --protocol protocol | 指明需要匹配的协议,如icmp、udp、tcp |
[!] -s, --source address[/mask][,...] | 指定匹配源地址,如有多个可以逗号分隔,所有地址:0.0.0.0/0 |
[!] -d, --destination address[/mask][,...] | 指定匹配目标地址,如有多个可以逗号分隔 |
[!] --source-port,--sport port[:port] | 指定源端口,可以匹配范围,例如22:29,表示22到29端口 |
[!] --destination-port,--dport port[:port] | 指定目标端口,可以匹配范围 |
[!] -i, --in-interface name | 接收数据包的接口名称 |
[!] -o, --out-interface name | 发送数据包的接口名称 |
-j, --jump target | 执行匹配规则后的动作、ACCEPT、DROP、REJECT等 |
2.3.2 基本匹配示例
-
示例一:允许192.168.20.0/24网段和192.168.50.0/24网点访问本机的22端口,其他业务全部拒绝。
因为数据报文有一来一回,因此需要在INPUT和OUTPUT链中都增加规则。
[root@iptables ~]# iptables -I INPUT -s 192.168.20.0/24,192.168.50.0/24 -p tcp --dport 22 -j ACCEPT [root@iptables ~]# iptables -I OUTPUT -d 192.168.20.0/24,192.168.50.0/24 -p tcp --sport 22 -j ACCEPT [root@iptables ~]# iptables -A INPUT -j REJECT [root@iptables ~]# iptables -A OUTPUT -j REJECT [root@iptables ~]# iptables -vnL Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- * * 192.168.50.0/24 0.0.0.0/0 tcp dpt:22 315 21360 ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 9 702 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.50.0/24 tcp spt:22 78 7488 ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.0/24 tcp spt:22 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
-
示例二:仅允许192.168.20.0/24网段中的192.168.20.1访问本机的tcp/80-90端口,网段其他地址均拒绝。
[root@iptables ~]# iptables -I INPUT 3 -s 192.168.20.0/24 -p tcp --dport 80:90 -j DROP [root@iptables ~]# iptables -I OUTPUT 3 -d 192.168.20.0/24 -p tcp --sport 80:90 -j DROP [root@iptables ~]# iptables -I INPUT 3 -s 192.168.20.1 -p tcp --dport 80:90 -j ACCEPT [root@iptables ~]# iptables -I OUTPUT 3 -d 192.168.20.1 -p tcp --dport 80:90 -j ACCEPT [root@iptables ~]# iptables -vnL Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- * * 192.168.50.0/24 0.0.0.0/0 tcp dpt:22 1340 107K ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 0 0 ACCEPT tcp -- * * 192.168.20.1 0.0.0.0/0 tcp dpts:80:90 0 0 DROP tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpts:80:90 383 30207 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.50.0/24 tcp spt:22 781 77625 ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.0/24 tcp spt:22 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.1 tcp dpts:80:90 0 0 DROP tcp -- * * 0.0.0.0/0 192.168.20.0/24 tcp spts:80:90 24 1960 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
-
实例三:允许lo接口所有的报文
[root@iptables ~]# iptables -I INPUT 3 -i lo -j ACCEPT [root@iptables ~]# iptables -I OUTPUT 3 -o lo -j ACCEPT [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 192.168.50.0/24 0.0.0.0/0 tcp dpt:22 2 1649 129K ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 3 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT tcp -- * * 192.168.20.1 0.0.0.0/0 tcp dpts:80:90 5 0 0 DROP tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpts:80:90 6 458 36510 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 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 1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.50.0/24 tcp spt:22 2 962 98725 ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.0/24 tcp spt:22 3 0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.1 tcp dpts:80:90 5 0 0 DROP tcp -- * * 0.0.0.0/0 192.168.20.0/24 tcp spts:80:90 6 24 1960 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
-
示例四:允许本机进行DNS查询
[root@iptables ~]# iptables -I OUTPUT 6 -p udp --dport 53 -j ACCEPT [root@iptables ~]# iptables -I INPUT 6 -p udp --sport 53 -j ACCEPT [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 192.168.50.0/24 0.0.0.0/0 tcp dpt:22 2 3469 264K ACCEPT tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpt:22 3 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT tcp -- * * 192.168.20.1 0.0.0.0/0 tcp dpts:80:90 5 0 0 DROP tcp -- * * 192.168.20.0/24 0.0.0.0/0 tcp dpts:80:90 6 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53 7 1693 156K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 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 1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.50.0/24 tcp spt:22 2 2083 220K ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.0/24 tcp spt:22 3 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.20.1 tcp dpts:80:90 5 0 0 DROP tcp -- * * 0.0.0.0/0 192.168.20.0/24 tcp spts:80:90 6 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 7 43 3444 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
2.4 iptables扩展匹配条件
扩展匹配需要特定模块的支持,查看iptables支持的模块如下:
[root@iptables ~]# rpm -ql iptables | grep -i tcp
/usr/lib64/xtables/libxt_TCPMSS.so
/usr/lib64/xtables/libxt_TCPOPTSTRIP.so
/usr/lib64/xtables/libxt_tcp.so
/usr/lib64/xtables/libxt_tcpmss.so
其中.so为扩展模块,小写的表示匹配扩展模块,大写的表示处理动作扩展模块。
扩展命令需要使用-m选项指明扩展模块的名称。
下面对常用的扩展命令进行详细说明。
2.4.1 multiport模块
使用 multiport 模块可以同时添加多个不连续的端口,可以指定源端口或目的端口:
- [!] --source-ports,--sports port[,port|,port:port]...:指定多个源端口;
- [!] --destination-ports,--dports port[,port|,port:port]...:指定多个目标端口;
示例:开放本机的ftp,samba,http,ssh服务,即开放tcp的21,22,139,445,80和udp的137,138端口:
[root@iptables ~]# iptables -I INPUT -p tcp -m multiport --dports 21,22,139,445,80 -j ACCEPT
[root@iptables ~]# iptables -I INPUT -p udp -m multiport --dports 137,138 -j ACCEPT
[root@iptables ~]# iptables -I OUTPUT -p udp -m multiport --sports 137,138 -j ACCEPT
[root@iptables ~]# iptables -I OUTPUT -p tcp -m multiport --sports 21,22,139,445,80 -j ACCEPT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 36 2808 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138
2 572 46416 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80
3 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53
5 1869 170K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 110 16384 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80
2 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138
3 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
5 43 3444 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
2.4.2 iprange模块
使用 iprange 模块可以指定 "一段连续的IP地址范围",用于匹配报文的源地址或者目标地址, iprange 扩展模块中有两个扩展匹配条件可以使用。
- [!] --src-range from[-to]: 原地址范围
- [!] --dst-range from[-to]: 目标地址范围
示例:允许100.0.0.1-100.0.0.100的主机访问本机的tcp43端口
[root@iptables ~]# iptables -I INPUT 5 -m iprange --src-range 100.0.0.1-100.0.0.100 -p tcp --dport 443 -j ACCEPT
[root@iptables ~]# iptables -I OUTPUT 5 -m iprange --dst-range 100.0.0.1-100.0.0.100 -p tcp --sport 443 -j ACCEPT
[root@iptables ~]# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
120 9360 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138
973 76040 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80
11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 100.0.0.1-100.0.0.100 tcp dpt:443
1869 170K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
352 40480 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138
11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 100.0.0.1-100.0.0.100 tcp spt:443
43 3444 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
2.4.3 string模块
使用 string 扩展模块,可以指定要匹配的字符串,如果报文中包含对应的字符串,则符合匹配条件。
注意:仅对非加密报文有效,对ssh,https报文无法检测。
- --algo {bm|kmp} :字符匹配的查询算法,bm:Boyer-Moore, kmp:Knuth-Pratt-Morris;
- [!] --string pattern :字符匹配的字符串;
- --from offset 开始偏移;
- --to offset 结束偏移;
示例:应用返回的报文中包含字符 "hello" ,我们就丢弃当前报文,其余正常通过。
[root@iptables ~]# iptables -t filter -I OUTPUT 6 -p tcp -m string --string "hello" --algo kmp -j DROP
[root@iptables ~]# iptables -t filter -I INPUT 6 -p tcp --sport 80 -j ACCEPT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 204 16365 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138
2 1365 108K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80
3 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53
5 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 100.0.0.1-100.0.0.100 tcp dpt:443
6 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp spt:80
7 1869 170K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 617 68688 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80
2 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138
3 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
5 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 100.0.0.1-100.0.0.100 tcp spt:443
6 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "hello" ALGO name kmp TO 65535
7 43 3444 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
2.4.4 time模块
使用time扩展模块,根据时间段区匹配报文,如果报文到达的时间在指定的时间范围以内,则符合匹配条件。
- --timestart hh:mm[:ss] :开始时间
- --timestop hh:mm[:ss] :结束时间
- [!] --monthdays day[,day...] :指定一个月的某一天
- [!] --weekdays day[,day...] :指定周一到周天
- --kerneltz :使用内核时区而不是 UTC 时间,centos6 不支持kerneltz ,--localtz指定本地时区(默认)
- --datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
- --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
示例一:放行192.168.20.10-192.168.20.20的工作日的上午10点到下午18点对本机的telnet服务:
[root@iptables ~]# iptables -I INPUT 7 -m iprange --src-range 192.168.20.10-192.168.20.20 -m time --timestart 10:00 --timestop 18:00 --weekdays 1,2,3,4,5 --kerneltz -p tcp --dport 23 -j ACCEPT
[root@iptables ~]# iptables -I OUTPUT 7 -m iprange --dst-range 192.168.20.10-192.168.20.20 -m time --timestart 10:00 --timestop 18:00 --weekdays 1,2,3,4,5 --kerneltz -p tcp --sport 23 -j ACCEPT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 2500 201K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138
2 2361 188K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80
3 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
4 12 1194 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53
5 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 100.0.0.1-100.0.0.100 tcp dpt:443
6 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
7 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp dpt:23
8 2078 245K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 1316 136K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80
2 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138
3 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
4 12 756 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
5 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 100.0.0.1-100.0.0.100 tcp spt:443
6 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "hello" ALGO name kmp TO 65535
7 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp spt:23
8 61 5062 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
示例二:限制用户在上班时间段访问淘宝、爱奇艺等资源,其他时间可以正常放行;
[root@iptables ~]# iptables -t filter -I OUTPUT -p tcp -m string -- string "taobao.com" --algo kmp -m time --timestart 01:00 -- timestop 04:00 -j DROP
[root@iptables ~]# iptables -t filter -I OUTPUT -p tcp -m string -- string "taobao.com" --algo kmp -m time --timestart 06:00 -- timestop 10:30 -j DROP
[root@iptables ~]# iptables -t filter -I OUTPUT -p tcp -m string -- string "aqiyi.com" --algo kmp -m time --timestart 01:00 -- timestop 04:00 -j DROP
[root@iptables ~]# iptables -t filter -I OUTPUT -p tcp -m string -- string "aqiyi.com" --algo kmp -m time --timestart 06:00 -- timestop 10:30 -j DROP
2.4.5 ICMP模块
icmp 扩展模块:默认情况当禁止 ping 后,其他主机无法 ping 通本主机,本主机也无法 ping 通其他主机。
-
[!] --icmp-type
指定 ICMP 类型, echo-request(8请求) 、 echo-reply(0回应)
-
示例四:允许192.168.20.0/24网段和192.168.50.0/24网段能够ping通本机。
ping使用的是icmp报文的type为0和8的报文:type=0:这个是ICMP的ping回复包,type=8:这个是ICMP的ping的请求包。
[root@iptables ~]# iptables -I INPUT -s 192.168.20.0/24,192.168.50.0/24 -p icmp --icmp-type 8 -j ACCEPT [root@iptables ~]# iptables -I OUTPUT -d 192.168.20.0/24,192.168.50.0/24 -p icmp --icmp-type 0 -j ACCEPT [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT icmp -- * * 192.168.50.0/24 0.0.0.0/0 icmptype 8 2 0 0 ACCEPT icmp -- * * 192.168.20.0/24 0.0.0.0/0 icmptype 8 3 2596 208K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138 4 2487 198K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80 5 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 6 12 1194 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53 7 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 100.0.0.1-100.0.0.100 tcp dpt:443 8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 9 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp dpt:23 10 2098 250K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 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 1 0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.50.0/24 icmptype 0 2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.20.0/24 icmptype 0 3 1402 148K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80 4 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138 5 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0 6 12 756 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 7 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 100.0.0.1-100.0.0.100 tcp spt:443 8 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "hello" ALGO name kmp TO 65535 9 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp spt:23 10 69 5790 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable #测试192.168.20.17可以ping通本机 [root@xuzhichao ~]# ping -c 1 192.168.20.71 PING 192.168.20.71 (192.168.20.71) 56(84) bytes of data. 64 bytes from 192.168.20.71: icmp_seq=1 ttl=64 time=0.249 ms --- 192.168.20.71 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.249/0.249/0.249/0.000 ms #但是本机无法ping通192.168.20.1 [root@iptables ~]# ping 192.168.20.1 PING 192.168.20.1 (192.168.20.1) 56(84) bytes of data. From 192.168.20.71 icmp_seq=1 Destination Port Unreachable ping: sendmsg: Operation not permitted From 192.168.20.71 icmp_seq=2 Destination Port Unreachable ping: sendmsg: Operation not permitted
-
示例五:允许本机可以ping通任何主机
[root@iptables ~]# iptables -I INPUT 3 -p icmp --icmp-type 0 -j ACCEPT [root@iptables ~]# iptables -I OUTPUT 3 -p icmp --icmp-type 8 -j ACCEPT [root@iptables ~]# iptables -vnL --line-number Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT icmp -- * * 192.168.50.0/24 0.0.0.0/0 icmptype 8 2 0 0 ACCEPT icmp -- * * 192.168.20.0/24 0.0.0.0/0 icmptype 8 3 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0 4 2596 208K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138 5 2504 199K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80 6 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 7 12 1194 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53 8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 100.0.0.1-100.0.0.100 tcp dpt:443 9 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 10 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp dpt:23 11 2098 250K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 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 1 0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.50.0/24 icmptype 0 2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.20.0/24 icmptype 0 3 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8 4 1416 153K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80 5 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138 6 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0 7 12 756 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 100.0.0.1-100.0.0.100 tcp spt:443 9 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "hello" ALGO name kmp TO 65535 10 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp spt:23 11 69 5790 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable #可以ping通192.168.20.17 [root@iptables ~]# ping 192.168.20.17 -c 1 PING 192.168.20.17 (192.168.20.17) 56(84) bytes of data. 64 bytes from 192.168.20.17: icmp_seq=1 ttl=64 time=0.184 ms --- 192.168.20.17 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.184/0.184/0.184/0.000 ms
2.4.6 connlimit模块
限制每个客户端IP地址到服务器的并行连接数,可防止Dos(Denial of Service,拒绝服务)攻击。
- --connlimit-upto n :如果现有连接数小于或等于n,则匹配。
- --connlimit-above n :如果现有连接数大于n,则匹配。
示例一:单IP对本机的ssh连接超过2个时拒绝连接。
[root@iptables ~]# iptables -I INPUT 11 -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT icmp -- * * 192.168.50.0/24 0.0.0.0/0 icmptype 8
2 1 84 ACCEPT icmp -- * * 192.168.20.0/24 0.0.0.0/0 icmptype 8
3 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0
4 2761 222K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138
5 3062 239K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80
6 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
7 12 1194 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53
8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 100.0.0.1-100.0.0.100 tcp dpt:443
9 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
10 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp dpt:23
11 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 #conn src/32 > 2 reject-with icmp-port-unreachable
12 2122 259K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.50.0/24 icmptype 0
2 1 84 ACCEPT icmp -- * * 0.0.0.0/0 192.168.20.0/24 icmptype 0
3 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
4 1763 196K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80
5 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138
6 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
7 12 756 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 100.0.0.1-100.0.0.100 tcp spt:443
9 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "hello" ALGO name kmp TO 65535
10 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp spt:23
11 69 5790 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
示例二:限制每个客户端主机对本机的http服务允许100个并发连接:
[root@iptables ~]# iptables -I INPUT 12 -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 -j REJECT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT icmp -- * * 192.168.50.0/24 0.0.0.0/0 icmptype 8
2 1 84 ACCEPT icmp -- * * 192.168.20.0/24 0.0.0.0/0 icmptype 8
3 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0
4 2911 234K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138
5 3256 252K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80
6 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
7 12 1194 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53
8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 100.0.0.1-100.0.0.100 tcp dpt:443
9 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
10 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp dpt:23
11 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 #conn src/32 > 2 reject-with icmp-port-unreachable
12 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 flags:0x17/0x02 #conn src/32 > 100 reject-with icmp-port-unreachable
13 2122 259K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.50.0/24 icmptype 0
2 1 84 ACCEPT icmp -- * * 0.0.0.0/0 192.168.20.0/24 icmptype 0
3 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
4 1870 209K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80
5 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138
6 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
7 12 756 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 100.0.0.1-100.0.0.100 tcp spt:443
9 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "hello" ALGO name kmp TO 65535
10 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp spt:23
11 69 5790 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
2.4.7 limit模块
limit扩展模块: 针对"报文速率"进行限制。限制单位时间内流入包的数量,我们可以以秒为单位进行限制,也可以以分钟、小时、天作为单位进行限制。
- --limit rate[second|minute|hour|day] :平均匹配的速率
- --limit-burst number :超过限制速率的包,允许超过 burst 所设定值,默认可超出5个
示例一:限制对方ping本机,每秒钟限制只能ping一个包,开始可以一次性接收5个包。
[root@iptables ~]# iptables -I INPUT -p icmp --icmp-type 8 -m limit --limit 1/s --limit-burst 5 -j ACCEPT
[root@iptables ~]# iptables -I INPUT 2 -p icmp --icmp-type 8 -j DROP
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8 limit: avg 1/sec burst 5
2 0 0 DROP icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
3 0 0 ACCEPT icmp -- * * 192.168.50.0/24 0.0.0.0/0 icmptype 8
4 1 84 ACCEPT icmp -- * * 192.168.20.0/24 0.0.0.0/0 icmptype 8
5 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 0
6 3013 242K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 137,138
7 3811 298K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 21,22,139,445,80
8 11 1064 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
9 12 1194 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:53
10 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 100.0.0.1-100.0.0.100 tcp dpt:443
11 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
12 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 source IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp dpt:23
13 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 #conn src/32 > 2 reject-with icmp-port-unreachable
14 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 flags:0x17/0x02 #conn src/32 > 100 reject-with icmp-port-unreachable
15 2122 259K REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.50.0/24 icmptype 0
2 1 84 ACCEPT icmp -- * * 0.0.0.0/0 192.168.20.0/24 icmptype 0
3 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
4 2259 250K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 21,22,139,445,80
5 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 137,138
6 11 1064 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
7 12 756 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
8 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 100.0.0.1-100.0.0.100 tcp spt:443
9 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "hello" ALGO name kmp TO 65535
10 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 destination IP range 192.168.20.10-192.168.20.20 TIME from 10:00:00 to 18:00:00 on Mon,Tue,Wed,Thu,Fri tcp spt:23
11 69 5790 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
#测试效果:
[root@xuzhichao ~]# ping -i 0.1 192.168.20.71 <==发包间隔为0.1秒发一个包;
PING 192.168.20.71 (192.168.20.71) 56(84) bytes of data.
64 bytes from 192.168.20.71: icmp_seq=1 ttl=64 time=0.676 ms
64 bytes from 192.168.20.71: icmp_seq=2 ttl=64 time=1.73 ms
64 bytes from 192.168.20.71: icmp_seq=3 ttl=64 time=1.04 ms
64 bytes from 192.168.20.71: icmp_seq=4 ttl=64 time=1.48 ms
64 bytes from 192.168.20.71: icmp_seq=5 ttl=64 time=0.927 ms
64 bytes from 192.168.20.71: icmp_seq=11 ttl=64 time=1.53 ms <==注意seq号,中间丢了几个包
64 bytes from 192.168.20.71: icmp_seq=20 ttl=64 time=1.59 ms
64 bytes from 192.168.20.71: icmp_seq=29 ttl=64 time=0.797 ms
64 bytes from 192.168.20.71: icmp_seq=38 ttl=64 time=1.28 ms
64 bytes from 192.168.20.71: icmp_seq=47 ttl=64 time=0.569 ms
示例二:限制主机传输时的带宽每秒不超过 500k ; (500k * 1000=500000字节/1500=333 个包)
[root@iptables ~]# iptables -t filter -I OUTPUT -p tcp -m limit -- limit 300/second -j ACCEPT
[root@iptables ~]# iptables -t filter -A OUTPUT -p tcp -j DROP
2.4.8 tcp-flags模块
使用 tcp 扩展模块的 "--tcp-flags" 选项,即可对 TCP 的标志位进行匹配,匹配指定标志位的值是否为"1",在tcp协议建立连接的过程中,需要先进行三次握手,而三次握手就要依靠tcp头中的标志位进行。
我们可以通过 --tcp-flag 指明需要匹配哪些标志位,然后再指明这些标志位中,哪些必须为1,剩余的都必须为0。
所以当服务器接收新请求时,SYN标志位必须1,其他的标志位为0,而服务端响应这个连接时, SYN、ACK 标志位必须为1,其他的标志位为0。(这样可以避免木马程序通过端口主动向外发送新连接。)
--tcp-flags SYN,RST,ACK,FIN SYN表示:匹配SYN,RST,ACK,FIN这些位,其中SYN为1,其余位为0。
使用"--syn"选项相当于使用"--tcp-flags SYN,RST,ACK,FIN SYN"。
示例:客户端连接服务端22端口第一次握手必须是客户端发起的,所以SYN必须为1,剩下全部为0。然后服务端可以通过22端口返回对应的报文。
[root@xuzhichao ~]# iptables -F
#匹配客户端第一次握手:
[root@iptables ~]# iptables -I INPUT -p tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST SYN -j ACCEPT
#匹配客户端第三次握手:
[root@iptables ~]# iptables -A INPUT -p tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST ACK -j ACCEPT
#禁止其他的ssh连接
[root@iptables ~]# iptables -A INPUT -p tcp --dport 22 -j REJECT
#匹配第二次握手
[root@iptables ~]# iptables -I OUTPUT -p tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST SYN,ACK -j ACCEPT
#允许ACK报文
[root@iptables ~]# iptables -A OUTPUT -p tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST ACK -j ACCEPT
#禁止其他ssh连接
[root@iptables ~]# iptables -A OUTPUT -p tcp --dport 22 -j REJECT
[root@iptables ~]# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x02
589 39124 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x10
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 22 packets, 2168 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x12
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x10
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 reject-with icmp-port-unreachable
2.4.9 state模块
2.4.9.1 state实现原理
state扩展模块,可以根据”连接追踪机制“去检查连接的状态,较耗资源,可以追踪TCP,UDP,ICMP状态。
连接跟踪所做的事情就是发现并跟踪这些连接的状态,但这个追踪状态与TCP协议没有关系。它是由内核nefilter在IP层实现,可IP层是无连接、无追踪的,那是如何知道这个IP此前到底有没有来过?
当用户发送请求时,会将用户的请求存储在内核开辟的内存空间中,记录源IP、目标IP、协议、时间,当下次在有用户发起请求,就可以通过内存空间中获取该用户是否来过,以此来实现连接追踪机制。
-
查询连接追踪信息
-
已经追踪到的并记录下来的连接信息库
/proc/net/nf_conntrack
-
调整连接追踪功能所能够容纳的最大连接数量
/proc/sys/net/nf_conntrack_max
-
查看连接跟踪有多少条目
/proc/sys/net/netfilter/nf_conntrack_count
-
不同的协议的连接追踪时长
/proc/sys/net/netfilter/
-
-
连接跟踪,需要加载模块: modprobe nf_conntrack_ipv4
-
iptables的链接跟踪表最大容量为/proc/sys/net/nf_conntrack_max
-
当服务器连接多于最大连接数时会出现kernel: ip_conntrack: table full, dropping packet错误,因此此时新连接会丢弃,生产中需要根据实际情况增大连接数或关闭连接追踪功能。各种状态的超时后,链接会从表中删除。
连接过多的解决方法两个:
-
1.加大nf_conntrack_max 值
vi /etc/sysctl.conf net.nf_conntrack_max = 393216 net.netfilter.nf_conntrack_max = 393216
-
2.降低 nf_conntrack timeout时间
vi /etc/sysctl.conf net.netfilter.nf_conntrack_tcp_timeout_established = 300 net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120 net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60 net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
2.4.9.2 state模块实现
state模块的语法格式为:
[!] --state state
state:INVALID, ESTABLISHED, NEW, RELATED or UNTRACKED.
常用的状态如下:
- NEW:新发出请求;连接追踪信息库中不存在此连接的相关信息条目,因此,将其识别为第一次发出的请求;
- ESTABLISHED:NEW状态之后,连接追踪信息库中为其建立的条目失效之前期间内所进行的通信状态,即为除第一次连接外的其他连接;
- RELATED:新发起的但与已有连接相关联的连接。比如ftp有两个连接,命令连接和数据连接。命令连接有来有往是一个独立的循环,数据连接有来有往又是另外一个独立的循环,但是两者之间有关系,如果没有命令连接就不可能有数据连接,所以我们将这种称为”相关联的连接“;
- INVALID:无效的连接,如flag标记不正确;
- UNTRACKED:未进行追踪的连接,如raw表中关闭追踪;
- SNAT:当通过NAT操作更改了源地址时设置的虚拟状态。连接跟踪系统使用它,以便它知道将源地址改回答复数据包。
- DNAT:当通过NAT操作更改了目标地址时设置的虚拟状态。连接跟踪系统使用它,以便在路由答复数据包时知道将目标地址改回。
sate模块的作用:
- 使用state模块可以大大减少规则条目,对出本机出去和进入的流量,只要状态为ESTABLISHED的即可直接放行。
- 安全功能:正常情况下服务器的80等服务端口不会主动连接其他服务器,如果出现了80端口连接其他服务器,那么说明出现了异常行为,或者可以理解为中了木马程序病毒。如果关闭80端口的响应报文,但那样就会造成请求进来无法响应;如果开放80端口则又会出现异常行为。所以我们需要从80端口做连接追踪限制,凡事从80端口出去的就必须是对某个请求的响应,也就是说通过80端口出去的状态必须是ESTABLISHED,不能是NEW。
示例一:放行本机的ssh,http,mysql服务,但是不允许本机的这些服务端口主动向外发起访问:
#状态为ESTABLISHED的连接全部放行
[root@iptables ~]# iptables -I INPUT -m state --state ESTABLISHED -j ACCEPT
[root@iptables ~]# iptables -I OUTPUT -m state --state ESTABLISHED -j ACCEPT
#放行从外部发起访问的连接,状态为NEW
[root@iptables ~]# iptables -A INPUT -p tcp -m multiport --dports 22,80,3306 -m state --state NEW -j ACCEPT
#拒绝其他连接
[root@iptables ~]# iptables -A INPUT -j REJECT
[root@iptables ~]# iptables -A OUTPUT -j REJECT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 488 34940 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
2 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 22,80,3306 state NEW
3 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 238 22376 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
2 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
示例二:放行icmp连接
#放行外部主机ping本机的流量,回包被ESTABLISHED策略匹配放行
[root@iptables ~]# iptables -I INPUT 3 -p icmp --icmp-type 8 -j ACCEPT
#放行本机ping外部主机的流量,回包被ESTABLISHED策略匹配放行
[root@iptables ~]# iptables -I OUTPUT 3 -p icmp --icmp-type 8 -j ACCEPT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 964 70868 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
2 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 22,80,3306 state NEW
3 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
4 54 4212 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 543 55396 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
3 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
示例三:允许本机可以ssh其他主机
[root@iptables ~]# iptables -I OUTPUT 3 -p tcp --dport 22 -m state --state NEW -j ACCEPT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 1223 88184 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
2 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 22,80,3306 state NEW
3 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
4 124 13713 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 685 70372 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
2 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
3 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW
4 1 106 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
示例四:放行本机的FTP服务(被动模式)
装载ftp连接追踪的专用模块:
跟踪模块路径:/lib/modules/kernelversion/kernel/net/netfilter
vim /etc/sysconfig/iptables-config
IPTABLES_MODULES=“nf_conntrack_ftp"
modproble nf_conntrack_ftp #命令行加载模块
配置实现:
[root@iptables ~]# modprobe nf_conntrack_ftp
#命令连接:NEW, ESTABLISHED
#数据连接:RELATED, ESTABLISHED
[root@iptables ~]# iptables -I INPUT -p tcp --dport 21:22 -m state --state NEW -j ACCEPT
[root@iptables ~]# iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@iptables ~]# iptables -I OUTPUT -m state --state ESTABLISHED -j ACCEPT
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 94 8248 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpts:21:22 state NEW
3 1462 111K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
4 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 22,80,3306 state NEW
5 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
6 178 17925 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 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
1 952 98176 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
2 1 84 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8
3 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW
4 1 106 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
2.4.10 mac模块
指明源MAC地址
适用于:PREROUTING, FORWARD,INPUT chains
[!] --mac-source XX:XX:XX:XX:XX:XX
示例:
[root@iptables ~]# iptables -A INPUT -s 172.16.0.100 -m mac --mac-source 00:50:56:12:34:56 -j ACCEPT
[root@iptables ~]# iptables -A INPUT -s 172.16.0.100 -j REJECT
2.5 iptables日志功能
iptables的日志功能通过动作模块LOG实现。
- --log-level 日志级别
- --log-prefix 日志前缀
默认日志保存于/var/log/messages
注意:LOG动作应该在ACCEPT,DROP,REJECT
等动作之前处理才能记录日志。
示例:记录telnet服务的登录日志,日志前缀为“telnet access”
#1.安装telnet服务
[root@iptables ~]# yum install telnet-server -y
#2.启动telnet服务
[root@iptables ~]# systemctl start telnet.socket
#3.修改pam模块,允许root用户远程登录
[root@iptables ~]# echo "pts/1" >> /etc/securetty
[root@iptables ~]# echo "pts/2" >> /etc/securetty
#4.添加iptables规则
[root@iptables ~]# iptables -I INPUT -p tcp --dport 23 -j LOG --log-prefix "telnet access : "
[root@iptables ~]# iptables -vnL
Chain INPUT (policy ACCEPT 19 packets, 1312 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:23 LOG flags 0 level 4 prefix "telnet server : "
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 12 packets, 1480 bytes)
pkts bytes target prot opt in out source destination
#5.客户端telnet登录本机,查看本机日志:
[root@iptables ~]# grep "telnet access" /var/log/messages
Jul 23 12:40:23 iptables kernel: telnet access : IN=eth1 OUT= MAC=00:0c:29:23:6e:ac:00:0c:29:2f:d0:da:08:00 SRC=192.168.20.17 DST=192.168.20.71 LEN=52 TOS=0x10 PREC=0x00 TTL=64 ID=17770 DF PROTO=TCP SPT=41858 DPT=23 WINDOW=229 RES=0x00 ACK URGP=0
3. iptables自定义链
3.1 自定义链的作用
- 当默认链中的规则非常多时,不便于管理。假设INPUT链中存放了200条规则,这200条规则有针对80端口的,有针对22端口的,有针对私网IP的,等等。
- 假如想修改针对80端口的规则,可能需要从头到尾看一遍200条规则,找出哪些规则是针对80端口。这显然不合理。所以,我们需要使用自定义链,通过自定义链即可解决上述问题。
- 假设,我们自定义一条链,链名叫 IN_HTTP ,我们可以将所有针对80端口入站规则都写入到这条自定义链中,当以后想要修改针对80端口入站规则时,就直接修改IN_HTTP 链中的规则就可以了。
- 即使默认链中有再多的规则,也没有关系,因为所有针对80端口的入站规则都存放在 IN_HTTP 链中。同理,我们可以将针对22端口的出站规则放入到OUT_SSH自定义链中,这样,我们就能快速定位到想修改的规则在哪里。
3.2 自定义链的处理顺序
- 自定义链的处理顺序:主链规则自上而下处理,遇到自定义链时开始处理自定义链中的规则,当自定义链中的规则匹配到时执行相应动作,当自定义链没有匹配到规则,则返回主链继续向下匹配规则,如果在自定义链中需要提前返回主链时需要使用RETUEN动作返回调用者。
3.3 自定义链配置示例
-
定义一个icmp链,允许除192.168.20.17以外的192.168.20.0/24网段ping192.168.20.71
#1.自定义链: [root@iptables ~]# iptables -N icmp_rules #2.自定义链中添加规则: [root@iptables ~]# iptables -t filter -I icmp_rules -s 192.168.20.17 -p icmp --icmp-type 8 -m state --state NEW -j DROP [root@iptables ~]# iptables -t filter -A icmp_rules -s 192.168.20.0/24 -p icmp --icmp-type 8 -m state --state NEW -j ACCEPT #3.查看自定义链中的规则: [root@iptables ~]# iptables -vnL Chain INPUT (policy ACCEPT 8 packets, 576 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 5 packets, 1020 bytes) pkts bytes target prot opt in out source destination Chain icmp_rules (0 references) pkts bytes target prot opt in out source destination 0 0 DROP icmp -- * * 192.168.20.17 0.0.0.0/0 icmptype 8 state NEW 0 0 ACCEPT icmp -- * * 192.168.20.0/24 0.0.0.0/0 icmptype 8 state NEW
-
在INPUT链中引用自定义链
#引用自定义链 [root@iptables ~]# iptables -I INPUT -p icmp -j icmp_rules [root@iptables ~]# iptables -vnL Chain INPUT (policy ACCEPT 6 packets, 428 bytes) pkts bytes target prot opt in out source destination 0 0 icmp_rules icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 4 packets, 512 bytes) pkts bytes target prot opt in out source destination Chain icmp_rules (1 references) pkts bytes target prot opt in out source destination 0 0 DROP icmp -- * * 192.168.20.17 0.0.0.0/0 icmptype 8 state NEW 0 0 ACCEPT icmp -- * * 192.168.20.0/24 0.0.0.0/0 icmptype 8 state NEW
-
自定义链修改名称
#把icmp_rules改名为icmp_rule,INPUT链会自动 [root@iptables ~]# iptables -E icmp_rules icmp_rule [root@iptables ~]# iptables -vnL Chain INPUT (policy ACCEPT 6 packets, 428 bytes) pkts bytes target prot opt in out source destination 0 0 icmp_rule icmp -- * * 0.0.0.0/0 0.0.0.0/0 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 4 packets, 480 bytes) pkts bytes target prot opt in out source destination Chain icmp_rule (1 references) pkts bytes target prot opt in out source destination 0 0 DROP icmp -- * * 192.168.20.17 0.0.0.0/0 icmptype 8 state NEW 0 0 ACCEPT icmp -- * * 192.168.20.0/24 0.0.0.0/0 icmptype 8 state NEW
-
删除自定义链
删除自定义链需要满足两个条件:
-
1.自定义链没有被引用
-
2.自定义链中没有任何规则
#不满足以上任意一个条件,自定义链都无法删除 [root@iptables ~]# iptables -X icmp_rule iptables: Too many links. #删除自定义链中的规则 [root@iptables ~]# iptables -t filter -D icmp_rule 1 [root@iptables ~]# iptables -t filter -D icmp_rule 1 #删除INPUT链中引用自定义链 [root@iptables ~]# iptables -t filter -D INPUT 1 #成功删除自定义链 [root@iptables ~]# iptables -X icmp_rule
-
4. iptables的forward链
faorward链一般用于实现网络防火墙的功能。
请求-响应报文均会经由FORWARD链,要注意规则的方向性
实验环境如下,允许客户端访问nginx主机的web服务,但是不允许客户能ping通nginx主机:
-
防火墙规则设置如下:
#1.开启ip_forward转发功能 [root@iptables ~]# sysctl -w net.ipv4.ip_forward=1 net.ipv4.ip_forward = 1 #2.设置iptables规则: [root@iptables ~]# iptables -I FORWARD -s 192.168.50.17 -d 192.168.20.22 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT [root@iptables ~]# iptables -I FORWARD -m state --state ESTABLISHED -j ACCEPT [root@iptables ~]# iptables -A FORWARD -p icmp --icmp-type 8 -m state --state NEW -j DROP [root@iptables ~]# iptables -vnL Chain INPUT (policy ACCEPT 22 packets, 1452 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED 0 0 ACCEPT tcp -- * * 192.168.50.17 192.168.20.22 tcp dpt:80 state NEW,ESTABLISHED 0 0 DROP icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmptype 8 state NEW Chain OUTPUT (policy ACCEPT 12 packets, 1168 bytes) pkts bytes target prot opt in out source destination
-
nginx和客户端的网关都指向防火墙,在客户端上测试。
#1.测试访问nginx: [root@xuzhichao ~]# curl -k -Hhost:www.xuzhichao.com https://192.168.20.22 node1.xuzhichao.com page #2.测试pingnginx主机,无法ping通: [root@xuzhichao ~]# ping -c 1 192.168.20.22 PING 192.168.20.22 (192.168.20.22) 56(84) bytes of data. --- 192.168.20.22 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms
5. iptables的NAT表
网络地址转换 (NAT) :对数据包的网络地址 (IP + Port) 进行转换,用于实现用户上网以及ip和端口映射。
NAT有以下几种模式:
- SNAT:源地址转换,用于实现内部用户多对一上网;作用于POSTROUTING链;
- DNAT:目的地址转换,用于实现把内部主机映射到外部互联网,隐藏主机;作用于PREROUTING链;
- PNAT:端口转换;
5.1 SNAT场景示例
-
SNAT场景如下:
公司内部员工需要多台主机需要访问互联网,网段地址为192.168.50.0/24,出口为一个防火墙,ETH1口为外网口,ETH2口为内网口,需要在防火墙上开启SNAT转换,实现内部主机上网。
-
防火墙需要开启ip_forward转发:
#开启防火墙的ip_forward转发: [root@iptables ~]# sysctl -w net.ipv4.ip_forward=1 net.ipv4.ip_forward = 1
-
防火墙配置SNAT规则,此处分为两种情况:
-
当防火墙互联网出接口为固定IP地址时,可以直接写转换的公网接口地址;
[root@iptables ~]# iptables -t nat -I POSTROUTING -s 192.168.50.0/24 -j SNAT --to 192.168.20.71 [root@iptables ~]# iptables -t nat -nvL Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 SNAT all -- * * 192.168.50.0/24 0.0.0.0/0 to:192.168.20.71
-
当防火墙互联网出接口为非固定地址时,例如PPPOE或DHCP,可以使用
MASQUERADE
自行判断要转换为的外网地址;注意:需要用路由指明防火墙外网出接口。
[root@iptables ~]# iptables -t nat -A POSTROUTING -s 192.168.50.0/24 -j MASQUERADE [root@iptables ~]# iptables -t nat -nvL Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 MASQUERADE all -- * * 192.168.50.0/24 0.0.0.0/0
-
5.2 DNAT场景示例
-
DNAT场景说明:
公司内部有一台nginx服务器,需要通过防火墙映射到防火墙的公网地址192.168.50.71上,让客户端可以通过公网地址192.168.50.71访问内部nginx服务器。
-
防火墙配置规则如下:
#1.开启防火墙的ip_forward转发: [root@iptables ~]# sysctl -w net.ipv4.ip_forward=1 net.ipv4.ip_forward = 1 #2.配置iptables规则: #方式一:端口映射: [root@iptables ~]# iptables -t nat -I PREROUTING -d 192.168.50.71 -p tcp --dport 80 -j DNAT --to 192.168.20.22:80 [root@iptables ~]# iptables -t nat -vnL Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 DNAT tcp -- * * 0.0.0.0/0 192.168.50.71 tcp dpt:80 to:192.168.20.22:80 Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination #方式二:地址映射: [root@iptables ~]# iptables -t nat -I PREROUTING -d 192.168.50.71 -j DNAT --to 192.168.20.22
-
客户端无需配置网关地址,nginx服务器把网关指向防火墙的ETH1口192.168.20.71,客户端测试访问nginx服务器:
[root@xuzhichao ~]# curl -Hhost:www.xuzhichao.com http://192.168.50.71 node1.xuzhichao.com page
5.3 REDIRECT动作示例
REDIRECT动作用于把访问本机的某个端口重定向到另外一个端口。
-
--to-ports port[-port] 指定把端口重定向到哪个端口上。
-
在上述DNAT实现中,如果客户端需要访问nginx的web服务,需要访问nginx的8080端口,此时可以在nginx服务器上配置策略,把访问本机的80端口重定向到本机8080端口,此时客户端就可以通过80端口访问nginx服务器的web服务。
-
在nginx服务器上做的策略如下:
[root@nginx02 ~]# iptables -t nat -A PREROUTING -d 192.168.20.22 -p tcp --dport 80 -j REDIRECT --to-ports 8080 [root@nginx02 ~]# iptables -t nat -vnL Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 REDIRECT tcp -- * * 0.0.0.0/0 192.168.20.22 tcp dpt:80 redir ports 8080 Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 1 packets, 140 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 1 packets, 140 bytes) pkts bytes target prot opt in out source destination