iptables 指南
iptables 是linux下的流量过滤工具(防火墙),程序员要不要学习?这里举两个例子:
- 程序访问第三方接口,如何模拟接口 超时和挂掉
- 程序启动后需要预热,如何在预热阶段拒绝掉所有请求或者部分请求
如果使用iptables,事情就很简单,注意:模拟结束后用 iptables -F
清除
- 模拟超时
iptables -A OUTPUT -p tcp -d 220.181.57.217 --dport 443 -j DROP
- 模拟挂掉
iptables -A OUTPUT -p tcp -d 220.181.57.217 --dport 443 -j REJECT --reject-with tcp-reset
- 预热时拒绝请求
iptables -A INPUT -p tcp --dport 6379 -j REJECT --reject-with tcp-reset
- 拒绝部分请求(单IP最大5个连接)
iptables -A INPUT -p tcp --dport 6379 -m connlimit --connlimit-above 5 -j REJECT --reject-with tcp-reset
man iptables
洋洋洒洒2000多行,如何开始学习呢?
1 iptables 的运行架构
iptables
由多个 table
组成,每个 table
分多个 chain
,每个 chain
分多个 rule
。 网络packet
按内置的顺序通过 table
和 chain
。 table
有4个, filter nat mangle raw
,默认是 filter
, filter
有 INPUT FORWARD OUTPUT
三个 chain
。可以自定义 chain
,但是这里不讲。看下图理解 网络packet
通过它们的顺序:
table
的顺序其实并不十分重要,特定的功能只能在特定的 table
中完成, chain
通常只关心 INPUT
是进入流量, output
是外出流量即可。 chain
内 rule
的顺序是用户自己控制的。 rule
由两部分组成 match
和 target
, match
指定了匹配条件,例如: -p tcp --dport 6379 -m connlimit --connlimit-above 5
。 target
指定了 packet
匹配时的操作,常用的有 ACCEPT REJECT DROP LOG
等,有的 target
会终止 chain
匹配后面的 rule
,有的则不会。例如目标是 ACCEPT
会终止 , LOG
则不会。
注意 rule
过多,或者使用了某些性能不理想的 match
会导致性能问题。
2 iptables 辅助命令
2.1 查看iptables
iptables -L -v -n --line-number
列出所有的规则。
-v
输出详细信息-n
用IP和端口而不是主机名和服务名--line-number
列出了rule
对应的编号,用于插入、修改、删除rule
。
2.2 清空iptables
iptables -F
2.3 保存和恢复iptables
iptables-save > iptables.cfg
保存iptables-restore < iptables.cfg
恢复
3 增删改 rule
因为 rule
的顺序很重要,所以需要增加时需要关心位置。
-A
在chain
的尾部添加rule
-I
在首部或者指定位置前添加rule
-R
替换指定的rule
-D
删除rule
假设现在的iptables如下, iptables -L INPUT -n -v --line-number
只显示 INPUT
Chain INPUT (policy ACCEPT 10 packets, 570 bytes) num pkts bytes target prot opt in out source destination 1 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:6379
例如:
iptables -A INPUT -p tcp -s 192.168.10.10 --dport 22 -j ACCEPT; iptables -A INPUT -p tcp --dport 222 -j DROP
在链尾添加iptables -R INPUT 3 -p tcp --dport 22 -j DROP
发现1中222端口
写错了,要改成22端口
。3
是rule
的numiptables -I INPUT -p tcp --dport 6378 -j DROP
在链首插入iptables -I INPUT 4 -p tcp --dport 22 -j LOG --log-prefix "DENY
在指定位置4
前插入
此时iptables是
Chain INPUT (policy ACCEPT 121 packets, 38196 bytes) num pkts bytes target prot opt in out source destination 1 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:6378 2 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:6379 3 0 0 ACCEPT tcp -- * * 192.168.10.10 0.0.0.0/0 tcp dpt:22 4 5 320 LOG tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 LOG flags 0 level 4 prefix `DENY 22' 5 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
使用 iptables -D INPUT -p tcp --dport 22 -j DROP
和 iptables -D INPUT 3
删除两条规则。
注意 使用 num
操作 rule
虽然简单,但是 num
并不是和 rule
绑定的,它只是一个序号,随着 chain
的变化, num
也会变,尽量少用。
操作 OUTPUT
FORWARD
等 chain
的方法类似。
4 target
使用 -j
参数指定 target
,以下是常用的 target
4.1 ACCEPT
这是默认的target,通常 ACCEPT
需要和 DROP或REJECT
配合使用,例如:只允许来自192.168.10.10的22请求
iptables -A INPUT -p tcp -s 192.168.10.10 --dport 22 -j ACCEPT
白名单iptables -A INPUT -p tcp --syn --dport 22 -j DROP
拒绝所有22的请求,但是不拒绝本机向外请求22
注意这两条 rule
的顺序非常重要( -A
append),所有非192.168.10.10的请求都会走到 rule 2
被拒绝
4.2 DROP
丢弃掉收到的网络包,没有任何响应(仿佛这个IP不存在),客户端发送的 syn
被丢弃了,客户端会重试,直到超时。
4.3 REJECT
丢掉收到的网络包,但会有响应,模拟网络错误。通过 --reject-with
指定响应的类型,默认是 port-unreachable
4.4 LOG
用于记录日志。先看例子, 这里LOG放到了REJECT的前面,因为放到后面就无法记录,REJECT执行后 chain
就结束了
iptables -I INPUT -p tcp --dport 6379 -m connlimit --connlimit-above 5 -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp --dport 6379 -m connlimit --connlimit-above 5 -j LOG --log-prefix "DENY 6379"
日志记录到了 /var/log/messages
中。
5 match
5.1 常用选项
-s
指定源IP,或者IP段-d
指定目标IP,或者IP段-p
指定协议,常用的有tcp
udp
icmp
等--sport
在指定-p
为tcp/udp
时使用,指定源端口,可以使用6379:7399
指定范围--dport
在指定-p
为tcp/udp
时使用,指定目标端口,可以使用6379:7399
指定范围-m
指定match
的名字,通常-p tcp
隐含了-m tcp
,--sport
和--dport
也是-m tcp
的参数。udp
类似。
下面介绍常用的 match
,用户可以编写自己的 match
。也有第三方 match
不包含在标准 iptables
发行版中,可以自己安装。
5.2 iprange
指定IP的范围,例如:
iptables -A INPUT -m iprange --src-range 192.168.1.10-192.168.1.20 -j DROP
5.3 multiport
指定多个IP或者IP范围
iptables -A INPUT -p tcp -m multiport --dports 21,25,500:1024 -j DROP
5.4 connlimit
限制单个IP(或IP段)的并发请求
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 -j REJECT
5.5 limit
限制系统的并发,最大500每秒,允许10个在排队。
iptables -A INPUT -p tcp --dport 80 -m limit --limit 500/second --limit-burst 10 -j ACCEPT; iptables -A INPUT -p tcp --dport 80 -j DROP
5.6 owner
匹配用户uid,仅用于 OUTPUT POSTROUTING
,因为 INPUT
无法获取 网络packet
的uid。例如:只允许root用户访问某台机器
iptables -A OUTPUT -p tcp -d 192.168.10.5 -m owner ! --uid-owner 0 -j REJECT --reject-with tcp-reset
5.7 string
用于匹配 网络packet
的内容,例如拒绝某些带某些user-agent的请求(可能是攻击)
iptables -I INPUT -p tcp --dport 80 -m string --algo kmp --string "User-Agent: HttpClient/java" -j REJECT --reject-with tcp-reset