iptables配置实例

摘要

本文是一些简单的iptables配置实例,都是日常会有机会碰到的。

一些iptables配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# --line-number 可以显示标记位
# -v 显示规则匹配的包大小,可以看出规则是否匹配到
iptables -L -t nat --line-number -v
#删除某个标记位的记录
iptables -D POSTROUTING 1 -t nat
# DROP
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
# 先清空规则
iptables -F
iptables -t nat -F
iptables -X
iptables -t nat -X
iptables -Z
# 允许icmp
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -p icmp -j ACCEPT
# 通过一台外网机器跳转另一台内网机器ssh
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 2233 -j DNAT --to-destination 172.16.210.12:22
iptables -t nat -A POSTROUTING -d 172.16.210.12/32 -p tcp -m tcp --dport 22 -j SNAT --to-source 172.16.210.11
or
iptables -t nat -A POSTROUTING -d 192.168.100.9 -p tcp --dport 80 -j SNAT --to-source 172.168.100.7
iptables -t nat -A POSTROUTING -d 192.168.100.9 -p tcp --dport 80 -j MASQUERADE
# 开放端口
iptables -A INPUT -m state --state NEW -m tcp -p tcp -s 121.40.177.102 --dport 80 -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp -s 0.0.0.0 --dport 10050 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# DROP
iptables -A INPUT -p tcp -m tcp --dport 22 -j DROP
# nat 需要 net.ipv4.ip_forward = 1 并配置其他机器的下一跳
iptables -t nat -I POSTROUTING 1 -s 172.16.60.0/22 -j RETURN
iptables -t nat -A POSTROUTING -s 172.16.60.0/22 -o eth0 -j SNAT --to-source 172.16.60.75
or
iptables -t nat -A POSTROUTING -s 172.16.60.0/22 -d !172.16.60.0/22 -o eth0 -j SNAT --to-source 172.16.60.75
#temp computer
iptables -A INPUT -s 121.40.202.23/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 123.56.0.101/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 172.21.0.0/16 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 172.22.0.0/16 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 172.23.0.0/16 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 172.23.0.0/16 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 172.16.19.0/24 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 100.0.0.0/8 -p tcp -m tcp --dport 3306 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -p icmp -j ACCEPT
-A INPUT -s 172.16.19.67/32 -p tcp -m tcp --dport 2233 -j ACCEPT
-A INPUT -s 172.16.19.68/32 -p tcp -m tcp --dport 2233 -j ACCEPT
-A INPUT -s 172.16.19.69/32 -p tcp -m tcp --dport 2233 -j ACCEPT
-A INPUT -s 172.16.19.70/32 -p tcp -m tcp --dport 2233 -j ACCEPT
-A INPUT -s 172.16.19.71/32 -p tcp -m tcp --dport 2233 -j ACCEPT
-A INPUT -s 180.169.76.195/32 -p tcp -m tcp --dport 2233 -j ACCEPT
-A INPUT -s 100.0.0.0/8 -p tcp -m tcp --dport 2233 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 2233 -j DROP

iptables四个表与五个链

netfilter和iptables说明

netfilter/iptables IP 信息包过滤系统是一种功能强大的工具,可用于添加、编辑和除去规则,这些规则是在做信息包过滤决定时,防火墙所遵循和组成的规则。这些规则存储在专用的信息包过滤表中,而这些表集成在 Linux 内核中。在信息包过滤表中,规则被分组放在我们所谓的链(chain)中。

虽然 netfilter/iptables IP 信息包过滤系统被称为单个实体,但它实际上由两个组件 netfilter 和 iptables 组成。

  • netfilter 组件也称为内核空间(kernelspace),是内核的一部分,由一些信息包过滤表组成,这些表包含内核用来控制信息包过滤处理的规则集。
  • iptables 组件是一种工具,也称为用户空间(userspace),它使插入、修改和除去信息包过滤表中的规则变得容易。
  • iptables包含4个表,5个链。其中表是按照对数据包的操作区分的,链是按照不同的Hook点来区分的,表和链实际上是netfilter的两个维度。

4个表:filter,nat,mangle,raw,默认表是filter(没有指定表的时候就是filter表)。表的处理优先级:raw>mangle>nat>filter。

1
2
3
4
filter:一般的过滤功能
nat:用于nat功能(端口映射,地址映射等)
mangle:用于对特定数据包的修改
raw:有限级最高,设置raw时一般是为了不再让iptables做数据包的链接跟踪处理,提高性能
  • RAW 表只使用在PREROUTING链和OUTPUT链上,因为优先级最高,从而可以对收到的数据包在连接跟踪前进行处理。一但用户使用了RAW表,在某个链 上,RAW表处理完后,将跳过NAT表和 ip_conntrack处理,即不再做地址转换和数据包的链接跟踪处理了.

  • RAW表可以应用在那些不需要做nat的情况下,以提高性能。如大量访问的web服务器,可以让80端口不再让iptables做数据包的链接跟踪处理,以提高用户的访问速度。

5个链:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING。

1
2
3
4
5
PREROUTING:数据包进入路由表之前
INPUT:通过路由表后目的地为本机
FORWARDING:通过路由表后,目的地不为本机
OUTPUT:由本机产生,向外转发
POSTROUTIONG:发送到网卡接口之前。如下图:

img

iptables中表和链的对应关系如下:

img

iptables的数据包的流程是怎样的?

一个数据包到达时,是怎么依次穿过各个链和表的(图)。

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
基本步骤如下:
1. 数据包到达网络接口,比如 eth0。
2. 进入 raw 表的 PREROUTING 链,这个链的作用是赶在连接跟踪之前处理数据包。
3. 如果进行了连接跟踪,在此处理。
4. 进入 mangle 表的 PREROUTING 链,在此可以修改数据包,比如 TOS 等。
5. 进入 nat 表的 PREROUTING 链,可以在此做DNAT,但不要做过滤。
6. 决定路由,看是交给本地主机还是转发给其它主机。
到了这里我们就得分两种不同的情况进行讨论了,一种情况就是数据包要转发给其它主机,这时候它会依次经过:
7. 进入 mangle 表的 FORWARD 链,这里也比较特殊,这是在第一次路由决定之后,在进行最后的路由决定之前,我们仍然可以对数据包进行某些修改。
8. 进入 filter 表的 FORWARD 链,在这里我们可以对所有转发的数据包进行过滤。需要注意的是:经过这里的数据包是转发的,方向是双向的。
9. 进入 mangle 表的 POSTROUTING 链,到这里已经做完了所有的路由决定,但数据包仍然在本地主机,我们还可以进行某些修改。
10. 进入 nat 表的 POSTROUTING 链,在这里一般都是用来做 SNAT ,不要在这里进行过滤。
11. 进入出去的网络接口。完毕。
另一种情况是,数据包就是发给本地主机的,那么它会依次穿过:
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子系统

1
2
3
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,链接碰到各种状态的超时后就会从表中删除。

解決方法一般有两个:

加大 ip_conntrack_max 值

1
2
3
4
vi /etc/sysctl.conf
net.ipv4.ip_conntrack_max = 393216
net.ipv4.netfilter.ip_conntrack_max = 393216

降低 ip_conntrack timeout时间

1
2
3
4
5
6
vi /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服务器可以这样:

1
2
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