分类: LINUX
2014-08-01 13:57:39
原文地址:netfilter/iptables 简介 作者:luoyan_xy
Linux 的防火墙技术经历了若干代的沿革,一步步的发展而来。最开始的 ipfwadm 是 Alan Cox 在 Linux kernel 发展的初期,从 FreeBSD 的内核代码中移植过来的。后来经历了 ipchains,再经由 Paul Russell 在 Linux kernel 2.3 系列的开发过程中发展了 netfilter 这个架构。而用户空间的防火墙管理工具,也相应的发展为 iptables。netfilter/iptables 这个组合目前相当的令人满意。在经历了 Linux kernel 2.4 和 2.5 的发展以后,的确可以说,netfilter/iptables 经受住了大量用户广泛使用的考验。
netfilter/iptables IP 信息包过滤系统是一种功能强大的工具,可用于添加、编辑和除去规则,这些规则是在做信息包过滤决定时,防火墙所遵循和组成的规则。这些规则存储在专用的信息包过滤表中,而这些表集成在 Linux 内核中。在信息包过滤表中,规则被分组放在我们所谓的 链(chain)中。我马上会详细讨论这些规则以及如何建立这些规则并将它们分组在链中。
虽然 netfilter/iptables IP 信息包过滤系统被称为单个实体,但它实际上由两个组件 netfilter和 iptables 组成。
netfilter 组件也称为 内核空间(kernelspace),是内核的一部分,由一些信息包过滤表组成,这些表包含内核用来控制信息包过滤处理的规则集。
iptables 组件是一种工具,也称为 用户空间(userspace),它使插入、修改和除去信息包过滤表中的规则变得容易。除非您正在使用 Red Hat Linux 7.1 或更高版本,否则需要从 netfilter.org 下载该工具并安装使用它。
通过使用用户空间,可以构建自己的定制规则,这些规则存储在内核空间的信息包过滤表中。这些规则具有 目标,它们告诉内核对来自某些源、前往某些目的地或具有某些协议类型的信息包做些什么。如果某个信息包与规则匹配,那么使用目标 ACCEPT
允许该信息包通过。还可以使用目标 DROP
或 REJECT
来阻塞并杀死信息包。对于可对信息包执行的其它操作,还有许多其它目标。
根据规则所处理的信息包的类型,可以将规则分组在链中。处理入站信息包的规则被添加到 INPUT
链中。处理出站信息包的规则被添加到 OUTPUT
链中。处理正在转发的信息包的规则被添加到 FORWARD
链中。这三个链是基本信息包过滤表中内置的缺省主链。另外,还有其它许多可用的链的类型(如 PREROUTING
和 POSTROUTING
),以及提供用户定义的链。每个链都可以有一个 策略,它定义“缺省目标”,也就是要执行的缺省操作,当信息包与链中的任何规则都不匹配时,执行此操作。
建立规则并将链放在适当的位置之后,就可以开始进行真正的信息包过滤工作了。这时内核空间从用户空间接管工作。当信息包到达防火墙时,内核先检查信息包的头信息,尤其是信息包的目的地。我们将这个过程称为 路由。
如果信息包源自外界并前往系统,而且防火墙是打开的,那么内核将它传递到内核空间信息包过滤表的 INPUT
链。如果信息包源自系统内部或系统所连接的内部网上的其它源,并且此信息包要前往另一个外部系统,那么信息包被传递到 OUTPUT
链。类似的,源自外部系统并前往外部系统的信息包被传递到 FORWARD
链。
接下来,将信息包的头信息与它所传递到的链中的每条规则进行比较,看它是否与某条规则完全匹配。如果信息包与某条规则匹配,那么内核就对该信息包执行由该规则的目标指定的操作。但是,如果信息包与这条规则不匹配,那么它将与链中的下一条规则进行比较。最后,如果信息包与链中的任何规则都不匹配,那么内核将参考该链的策略来决定如何处理该信息包。理想的策略应该告诉内核 DROP
该信息包。 用下图中的图形说明了这个信息包过滤过程。
HOOK点 | 说 明 | 函数位置 | 应用举例 |
NF_IP_PRE_ROUTING | 由网卡传入主机的数据包,在没有经过IP层路由之前,会先经过这个点 | ip_rcv() | 过滤拒绝服务攻击\NAT\计算 |
NF_IP_LOCAL_IN | 经过路由选择,要进入本机的数据包,会经过这个点 | ip_local_deliver() 在此处可进行碎片重组 |
防火墙过滤进入本机的包 |
NF_IP_FORWARD | 经过路由,不是发往本机的包,需要向外发送,会经过这个点 | ip_forward() 之后进入ip_send() |
|
NF_IP_LOCAL_OUT | 本机发往外部的数据包在经过路由之前会经过这个点 | ip_build_and_send_pkt() ip_queue_xmit() ip_build_xmit_slow() ip_buid_xmit() 不同的上层协议会走不同的流程 |
防火墙过滤外发的数据包 |
NF_IP_POST_ROUTING 所有外出包都必须经过的钩子点 |
本机发送出去的包,在路由后会经过此点 | ip_finish_output() | 包计数功能实现 |
数据流描述:
简单的校验
|
NF_IP_PRE_ROUTING->
|
路由
|
发往本机—>发往外部 ->NF_IP_FORWARD—->NF_IP_POST_ROUTING
|
NF_IP_LOCAL_IN
|
高层的协议及进程
|
发包
|
NF_IP_LOCAL_OUT
|
路由
|
NF_IP_POST_ROUTING
HOOK函数的返回值
通过向防火墙提供有关对来自某个源、到某个目的地或具有特定协议类型的信息包要做些什么的指令,规则控制信息包的过滤。通过使用 netfilter/iptables 系统提供的特殊命令 iptables
,建立这些规则,并将其添加到内核空间的特定信息包过滤表内的链中。关于添加/除去/编辑规则的命令的一般语法如下:
$ iptables [-t table] command [match] [target]
[-t table]
选项允许使用标准表之外的任何表。表是包含仅处理特定类型信息包的规则和链的信息包过滤表。有三种可用的表选项: filter
、 nat
和 mangle
。该选项不是必需的,如果未指定,则 filter
用作缺省表。
filter 表用于一般的信息包过滤,它包含 INPUT
、 OUTPUT
和 FORWARD
链。nat 表用于要转发的信息包,它包含 PREROUTING
、 OUTPUT
和 POSTROUTING
链。如果信息包及其头内进行了任何更改,则使用 mangle 表。该表包含一些规则来标记用于高级路由的信息包,该表包含 PREROUTING
和 OUTPUT
链。
注: PREROUTING
链由指定信息包一到达防火墙就改变它们的规则所组成,而 POSTROUTING
链由指定正当信息包打算离开防火墙时改变它们的规则所组成。
上面这条命令中具有强制性的 command 部分是 iptables
命令的最重要部分。它告诉 iptables
命令要做什么,例如,插入规则、将规则添加到链的末尾或删除规则。以下是最常用的一些命令:
-A
或 --append
: 该命令将一条规则附加到链的末尾。 $ iptables -A INPUT -s 205.168.0.1 -j ACCEPT
INPUT
链的末尾,确定来自源地址 205.168.0.1 的信息包可以 ACCEPT
。
-D
或 --delete
: 通过用 -D
指定要匹配的规则或者指定规则在链中的位置编号,该命令从链中删除该规则。下面的示例显示了这两种方法。 $ iptables -D INPUT --dport 80 -j DROP
$ iptables -D OUTPUT 3
INPUT
链删除规则,它指定 DROP
前往端口 80 的信息包。第二条命令只是从 OUTPUT
链删除编号为 3 的规则。
-P
或 --policy
: 该命令设置链的缺省目标,即策略。所有与链中任何规则都不匹配的信息包都将被强制使用此链的策略。 $ iptables -P INPUT DROP
INPUT
链的缺省目标指定为 DROP
。这意味着,将丢弃所有与 INPUT
链中任何规则都不匹配的信息包。
-N
或 --new-chain
: 用命令中所指定的名称创建一个新链。 $ iptables -N allowed-chain
-F
或 --flush
: 如果指定链名,该命令删除链中的所有规则,如果未指定链名,该命令删除所有链中的所有规则。此参数用于快速清除。 $ iptables -F FORWARD
$ iptables -F
-L
或 --list
: 列出指定链中的所有规则。 $ iptables -L allowed-chain
iptables 命令的可选 match 部分指定信息包与规则匹配所应具有的特征(如源和目的地地址、协议等)。匹配分为两大类: 通用匹配和 特定于协议的匹配。这里,我将研究可用于采用任何协议的信息包的通用匹配。下面是一些重要的且常用的通用匹配及其示例和说明:
-p
或 --protocol
: 该通用协议匹配用于检查某些特定协议。协议示例有 TCP
、 UDP
、 ICMP
、用逗号分隔的任何这三种协议的组合列表以及 ALL
(用于所有协议)。 ALL
是缺省匹配。可以使用 !
符号,它表示不与该项匹配。 $ iptables -A INPUT -p TCP, UDP
$ iptables -A INPUT -p ! ICMP
TCP
和 UDP
信息包都将与该规则匹配。通过指定 ! ICMP
,我们打算允许所有其它协议(在这种情况下是 TCP
和 UDP
),而将 ICMP
排除在外。
-s
或 --source
: 该源匹配用于根据信息包的源 IP 地址来与它们匹配。该匹配还允许对某一范围内的 IP 地址进行匹配,可以使用 !
符号,表示不与该项匹配。缺省源匹配与所有 IP 地址匹配。 $ iptables -A OUTPUT -s 192.168.1.1
$ iptables -A OUTPUT -s 192.168.0.0/24
$ iptables -A OUTPUT -s ! 203.16.1.89
-d
或 --destination
: 该目的地匹配用于根据信息包的目的地 IP 地址来与它们匹配。该匹配还允许对某一范围内 IP 地址进行匹配,可以使用 !
符号,表示不与该项匹配。 $ iptables -A INPUT -d 192.168.1.1
$ iptables -A INPUT -d 192.168.0.0/24
$ iptables -A OUTPUT -d ! 203.16.1.89
我们已经知道,目标是由规则指定的操作,对与那些规则匹配的信息包执行这些操作。除了允许用户定义的目标之外,还有许多可用的目标选项。下面是常用的一些目标及其示例和说明:
ACCEPT
: 当信息包与具有 ACCEPT
目标的规则完全匹配时,会被接受(允许它前往目的地),并且它将停止遍历链(虽然该信息包可能遍历另一个表中的其它链,并且有可能在那里被丢弃)。该目标被指定为 -j ACCEPT
。
DROP
: 当信息包与具有 DROP
目标的规则完全匹配时,会阻塞该信息包,并且不对它做进一步处理。该目标被指定为 -j DROP
。
REJECT
: 该目标的工作方式与 DROP
目标相同,但它比 DROP
好。和 DROP
不同, REJECT
不会在服务器和客户机上留下死套接字。另外, REJECT
将错误消息发回给信息包的发送方。该目标被指定为 -j REJECT
。 $ iptables -A FORWARD -p TCP --dport 22 -j REJECT
RETURN
: 在规则中设置的 RETURN
目标让与该规则匹配的信息包停止遍历包含该规则的链。如果链是如 INPUT
之类的主链,则使用该链的缺省策略处理信息包。它被指定为 -jump RETURN
。示例:
$ iptables -A FORWARD -d 203.16.1.89 -jump RETURN
还有许多用于建立高级规则的其它目标,如 LOG
、 REDIRECT
、 MARK
、 MIRROR
和 MASQUERADE
等。
现在,您已经学习了如何建立基本的规则和链以及如何从信息包过滤表中添加或删除它们。但是,您应该记住:用上述方法所建立的规则会被保存到内核中,当重新引导系统时,会丢失这些规则。所以,如果您将没有错误的且有效的规则集添加到信息包过滤表,同时希望在重新引导之后再次使用这些规则,那么必须将该规则集保存在文件中。可以使用 iptables-save命令来做到这一点:
$ iptables-save > iptables-script
现在,信息包过滤表中的所有规则都被保存在文件 iptables-script 中。无论何时再次引导系统,都可以使用 iptables-restore命令将规则集从该脚本文件恢复到信息包过滤表,如下所示:
$ iptables-restore iptables-script
如果您愿意在每次引导系统时自动恢复该规则集,则可以将上面指定的这条命令放到任何一个初始化 shell 脚本中。