参考文档:http://blog.chinaunix.net/uid-10915175-id-3381754.html
iptables
5链:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
4表:优先级由高到低raw-->mangle-->nat-->filter
如果PRROUTING链上既有mangle表也有nat表,那么先由mangle处理后再由nat表处理。
RAW(提供PREROUTING链和OUTPUT链)表优先级最高,可以对收到的数据包在连接跟踪前进行处理。一但用户使用了RAW表,将跳NAT表和 ip_conntrack处理,即不再做地址转换和数据包的链接跟踪。
RAW表可以应用在那些不需要做nat和链接跟踪的情况,如大量迸发的Web服务,可以让80端口不再做数据包的链接跟踪,节省iptables处理开销以提高用户的访问速度。
man iptables
raw:
NOTRACK
简要示例:
Conntrack模块会默认记录所有网络五元组(类型,源IP/Port,目的IP/Port),并标识连接的状态。用户添加的IPtables规则是在Filter表中,在Conntrack的后面,所以用户的规则在有Conntrack记录的情况下无法起作用。
延时的时间我们用的是Conntrack的nf_conntrack_tcp_timeout_established默认值五天。所以如果用户用的是mysql之类的长连接,并且已经有记录的情况下,想禁止外部用户对于mysql的访问,即使加了规则,也要等5天才能生效。
Nginx影响不大。因为Nginx会在keepalive_timeout(默认值65秒)之后发FIN包,让nf_conntrack_tcp_timeout_established不再起作用,转而触发nf_conntrack_tcp_timeout_time_wait这个值起作用,它的默认值是120秒,这个影响一般用户应该能接受。
补救措施:
以Mysql中的3306端口为例,利用VM中的iptables
RAW表,假设源src为101.231.119.202,那么在VM中请加入:
iptables -t raw -I
用此措施的原因:
1.Raw表的引入:
Linux的Netfilter在PREROUTING以及OUTPUT这两个HOOK的conntrack之前安插了一个优先级更高的raw表,通过它就可以分离出不需要被conntrack的流量。
2.Raw表的位置:
VM级别优于VNAT。
为了减少对于宿主机上对别的VM的影响。可以利用VM中的IPtables。
详细的包过滤流程:
1. 数据包到达网络接口,比如 eth0。
2. 进入 raw 表的 PREROUTING
链,这个链的作用是赶在连接跟踪之前处理数据包。
3. 如果进行了连接跟踪,在此处理。
4. 进入 mangle 表的 PREROUTING 链,在此可以修改数据包,比如 TOS
等。
5. 进入 nat 表的 PREROUTING
链,可以在此做DNAT,但不要做过滤。
6. 决定路由,看是交给本地主机还是转发给其它主机。
到了这里我们就得分两种不同的情况进行讨论了
A.数据包要转发给其它主机
7. 进入 mangle 表的 FORWARD
链,这里也比较特殊,这是在第一次路由决定之后,在进行最后的路由决定之前,我们仍然可以对数据包进行某些修改。
8. 进入 filter 表的 FORWARD
链,在这里我们可以对所有转发的数据包进行过滤。需要注意的是:经过这里的数据包是转发的,方向是双向的。
9. 进入 mangle 表的 POSTROUTING
链,到这里已经做完了所有的路由决定,但数据包仍然在本地主机,我们还可以进行某些修改。
10. 进入 nat 表的 POSTROUTING 链,在这里一般都是用来做 SNAT
,不要在这里进行过滤。
11. 进入出去的网络接口。完毕。
B.数据包就是发给本地主机的
7. 进入 mangle 表的 INPUT
链,这里是在路由之后,交由本地主机之前,我们也可以进行一些相应的修改。
8. 进入 filter 表的 INPUT
链,在这里我们可以对流入的所有数据包进行过滤,无论它来自哪个网络接口。
9. 交给本地主机的应用程序进行处理。
10. 处理完毕后进行路由决定,看该往那里发出。
11. 进入 raw 表的 OUTPUT
链,这里是在连接跟踪处理本地的数据包之前。
12. 连接跟踪对本地的数据包进行处理。
13. 进入 mangle 表的 OUTPUT
链,在这里我们可以修改数据包,但不要做过滤。
14. 进入 nat 表的 OUTPUT 链,可以对防火墙自己发出的数据做 NAT
。
15. 再次进行路由决定。
16. 进入 filter 表的 OUTPUT
链,可以对本地出去的数据包进行过滤。
17. 进入 mangle 表的 POSTROUTING
链,同上一种情况的第9步。注意,这里不光对经过防火墙的数据包进行处理,还对防火墙自己产生的数据包进行处理。
18. 进入 nat 表的 POSTROUTING
链,同上一种情况的第10步。
19. 进入出去的网络接口。完毕。
iptables raw表的使用
增加raw表,在其他表处理之前,-j
NOTRACK跳过其它表处理
状态除了以前的四个还增加了一个UNTRACKED
例如:
可以使用 “NOTRACK” target 允许规则指定80端口的包不进入链接跟踪/NAT子系统
iptables -t raw -A PREROUTING -d 1.2.3.4 -p tcp --dport 80 -j
NOTRACK
iptables -t raw -A PREROUTING -s 1.2.3.4 -p tcp --sport 80 -j
NOTRACK
iptables -A FORWARD -m state --state UNTRACKED -j
ACCEPT
解决ip_conntrack: table full, dropping
packet的问题
在启用了iptables web服务器上,流量高的时候经常会出现下面的错误:
ip_conntrack: table full, dropping packet
这个问题的原因是由于web服务器收到了大量的连接,在启用了iptables的情况下,iptables会把所有的连接都做链接跟踪处理,这样iptables就会有一个链接跟踪表,当这个表满的时候,就会出现上面的错误。
iptables的链接跟踪表最大容量为/proc/sys/net/ipv4/ip_conntrack_max,链接碰到各种状态的超时后就会从表中删除。
所以解決方法一般有两个:
(1) 加大 ip_conntrack_max 值
vim /etc/sysctl.conf
net.ipv4.ip_conntrack_max = 393216
net.ipv4.netfilter.ip_conntrack_max = 393216
(2): 降低 ip_conntrack timeout时间
vim /etc/sysctl.conf
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established =
300
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait =
120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait =
60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait =
120
上面两种方法打个比喻就是烧水水开的时候,换一个大锅。一般情况下都可以解决问题,但是在极端情况下,还是不够用,怎么办?
这样就得反其道而行,用釜底抽薪的办法。iptables的raw表是不做数据包的链接跟踪处理的,我们就把那些连接量非常大的链接加入到iptables
raw表。
如一台web服务器可以这样:
iptables -t raw -A PREROUTING -d 1.2.3.4 -p tcp --dport 80 -j
NOTRACK
iptables -A FORWARD -m state --state UNTRACKED -j
ACCEPT
iptables
raw表的效果测试
我们在一台web
server上做测试,先不使用raw表,观察链接跟踪表(/proc/net/ip_conntrack)的大小:
在另一台机器上用ab测试:
ab -c 1000 -n 5000 http://192.168.20.26/index.html
在web server上查看链接跟踪表(/proc/net/ip_conntrack)的大小:
可以看到跟踪表内有5153个链接,再大一些的压力可能就要报ip_conntrack: table full, dropping
packet的错误了。
启用raw表:
cat /etc/sysconfig/iptables
... ...
# Generated by iptables-save v1.3.5 on Wed Aug 18 10:10:52
2010
*raw
:PREROUTING ACCEPT [116163:9327716]
:OUTPUT ACCEPT [104076:12500201]
-A PREROUTING -p tcp -m tcp --dport 80 -j
NOTRACK
-A OUTPUT -p tcp -m tcp --sport 80 -j
NOTRACK
COMMIT
# Completed on Wed Aug 18 10:10:52 2010
重启iptables:service
iptables restart
然后再用ab测试:
ab -c 1000 -n 5000 http://192.168.20.26/index.html
查看链接跟踪表(/proc/net/ip_conntrack)的大小:
wc -l /proc/net/ip_conntrack
1 /proc/net/ip_conntrack
跟踪表内只跟踪了一个链接了。
cat
/proc/net/ip_conntrack
tcp
可以看到iptables已经不跟踪进出端口为80的链接了。
测试结果表明用iptables的raw表可以完美解决ip_conntrack: table full, dropping packet的问题。