iptables是Linux系统中最重要的网络管控工具。它与Kernel中的netfilter模块配合工作,
其主要功能是为netfilter设置一些过滤(filter)或网络地址转换(NAT)的规则。当Kernel收到网络数据包后,
将会依据iptables设置的规则进行相应的操作。
iptables原理
iptables的语法比较复杂,但工作原理较易理解。清楚iptables的前提是理解它的表(Table)、链(Chain)和规则(Rule)。
三者关系如下图所示:
iptables内部(其实是Kernel的netfilter模块)维护着四个Table,分别是filter、nat、mangle和raw,它们对应着不同的功能:
- filter,iptables默认使用的表,用于数据包的过滤
- nat,控制网络地址转换的表
- mangle,修改包的信息,例如修改包的TTL值
- raw,根据链接状态进行相关处理,属于iptables的高级用法
Table中定义了Chain。一个Table可以支持多个Chain,Chain实际上是Rule的集合,每个Table都有默认的Chain。例如
filter表默认的Chain有INPUT、OUTPUT、FORWARD。用户可以自定义Chain,也可以修改Chain中的Rule。Rule就是iptables工作的规则。首先,系统将检查要处理的数据包是否满足Rule设置的条件,如果满足则执行Rule中设置的
目标(Target),否则继续执行Chain中的下一条Rule。
iptables Target和常用参数
iptables中的Rule有四个默认定义的Target,如下:
ACCEPT:接收数据包
DROP:直接丢弃数据包。没有任何信息反馈给数据源端
RETURN:返回到调用Chain,略过后续的Rule处理
QUEUE:数据返回到用户空间处理
iptables的扩展Target还支持REJECT。相对于DROP而言,REJECT会反馈信息给数据源端。目前只有INPUT、OUTPUT、FORWARD
以及被这三个链调用的自定义链支持REJECT。
常用参数如下:
- -t:指定table。默认为filter表
- -N:创建一条新的Chain
- -L,–list:显示指定Table的Chain和Rule信息
- -A,–append chain rule-specification:在指定Chain的末尾添加一条Rule
- -D,–delete chain rule-specification:删除指定Chain中满足rule-specification的那条Rule
- -I,–insert chain [rule num] rule-specification:为指定Chain插入一条Rule
Rule-specification描述该Rule的匹配条件以及目标动作,参数如下:
- -i:指定接收数据包的网卡名
- -o:指定发出数据包的网卡名
- -p:指定协议
- -s,–source address[/mask]:指定数据包的源IP地址
- -j,–jump target:跳转到指定目标,如ACCEPT、DROP等
经过iptables的数据包的流程介绍
一个数据包到达时,是怎么依次穿过各个链和表的,见下图:
基本步骤如下:
- 数据包到达网络接口,比如 eth0。
- 进入 raw 表的 PREROUTING 链,这个链的作用是赶在连接跟踪之前处理数据包。
- 如果进行了连接跟踪,在此处理。
- 进入 mangle 表的 PREROUTING 链,在此可以修改数据包,比如 TOS 等。
- 进入 nat 表的 PREROUTING 链,可以在此做DNAT,但不要做过滤。
- 决定路由,看是交给本地主机还是转发给其它主机。
*到了这里我们就得分两种不同的情况进行讨论了,一种情况就是数据包要转发给其它主机,这时候它会依次经过: *
- 进入 mangle 表的 FORWARD 链,这里也比较特殊,这是在第一次路由决定之后,在进行最后的路由决定之前,我们仍然可以对数据包进行某些修改。
- 进入 filter 表的 FORWARD 链,在这里我们可以对所有转发的数据包进行过滤。需要注意的是:经过这里的数据包是转发的,方向是双向的。
- 进入 mangle 表的 POSTROUTING 链,到这里已经做完了所有的路由决定,但数据包仍然在本地主机,我们还可以进行某些修改。
- 进入 nat 表的 POSTROUTING 链,在这里一般都是用来做 SNAT ,不要在这里进行过滤。
- 进入出去的网络接口。完毕。
*另一种情况是,数据包就是发给本地主机的,那么它会依次穿过: *
- 进入 mangle 表的 INPUT 链,这里是在路由之后,交由本地主机之前,我们也可以进行一些相应的修改。
- 进入 filter 表的 INPUT 链,在这里我们可以对流入的所有数据包进行过滤,无论它来自哪个网络接口。
- 交给本地主机的应用程序进行处理。
- 处理完毕后进行路由决定,看该往那里发出。
- 进入 raw 表的 OUTPUT 链,这里是在连接跟踪处理本地的数据包之前。
- 连接跟踪对本地的数据包进行处理。
- 进入 mangle 表的 OUTPUT 链,在这里我们可以修改数据包,但不要做过滤。
- 进入 nat 表的 OUTPUT 链,可以对防火墙自己发出的数据做 NAT 。
- 再次进行路由决定。
- 进入 filter 表的 OUTPUT 链,可以对本地出去的数据包进行过滤。
- 进入 mangle 表的 POSTROUTING 链,同上一种情况的第9步。注意,这里不光对经过防火墙的数据包进行处理,还对防火墙自己产生的数据包进行处理。
- 进入 nat 表的 POSTROUTING 链,同上一种情况的第10步。
- 进入出去的网络接口。完毕。
References
- “Linux Firewall Tutorial: IPTables Tables, Chains, Rules Fundamentals”
- “iptables的相关概念和数据包的流程”,介绍了iptables中各个Table及Chain的处理顺序
- “Iptables 指南 1.1.19”