1.1. 为什么要写这个指南
我发现目前所有的HOWTO都缺乏Linux 2.4.x 内核中的Iptables和Netfilter 函数的信息,于是我试图回答一些问题,比如状态匹配。我会用插图和例子 rc.firewall.txt 加以说明,此处的例子可以在你的/etc/rc.d/使用。最初这篇文章是以HOWTO文档的形式书写的,因为许多人只接受HOWTO文档。
--------------------------------------------------------------------------------
我请教了Marc Boucher 及netfilter团队的其他核心成员。对他们的工作以及对我在为boingworld.com 书写这个指南时的帮助表示极大的谢意,现在这个指南在我自己的站点frozentux.net上进行维护。这个文档将一步一步教你setup过程,让你对iptables包有更多的了解。这大部分的东西都基于例子rc.firewall 文件,因为我发现这是学习iptables的一个好方法。我决定自顶向下地跟随rc.firewall 文件来学习 iptables。虽然这样会困难一些,但更有逻辑。当你碰到不懂的东西时再来查看这个文件。
--------------------------------------------------------------------------------
文中包含了一些术语,你应该有所了解。这里有一些解释,并说明了本文中如何使用它们。
--------------------------------------------------------------------------------
这一章是学习iptables的开始,它将帮助你理解Netfilter和iptables在Linux中扮演的角色。它会告诉你如何配置、安装防火墙,你的经验也会随之增长。当然,要想达到你的目标,是要花费时间,还要有毅力。( 译者注:听起来很吓人的:) )
--------------------------------------------------------------------------------
iptables 可以从www.netfilter.org 下载,网站中的FAQs也是很好的教程。iptables 也使用一些内核空间,可以在用make configure配置内核的过程中配置,下面会介绍必要的步骤。
--------------------------------------------------------------------------------
为了运行iptables,需要在内核配置期间,选择以下一些选项,不管你用make config或其他命令。
严格地说,iptables并不需要CONFIG_PACKET,但是它有很多用处(译者注:其他程序需要),所以就选上了。当然,你不想要,不选就是了。(译者注:建议还是选的为好)
CONFIG_PACKET
--------------------------------------------------------------------------------
下面,我们来看看如何编译iptables。iptables很多组件的配置、编译是与内核的配置、编译相关联的,了解这一点是很重要的。某些Linux产品预装了iptables,比如Red Hat,但是它的缺省设置是不启用iptables的。后文我们会介绍如何启用它,也会介绍一下其他 Linux产品里的iptables情况。
--------------------------------------------------------------------------------
首先要解压iptables包。这里,我用iptables 1.2.6a做例子(译者注:在我翻译时,最新版本已经是 1.2.9,其中又有了不少改进,修补了一些bug,增添了几个match和target。)。命令 bzip2 -cd iptables-1.2.6a.tar.bz2 | tar -xvf -(当然也可以用tar -xjvf iptables-1.2.6a.tar.bz2,但这个命令可能对一些老版的tar不适用 ) 将压缩包解压至目录iptables-1.2.6a,其中的INSTALL文件有很多对编译、运行有用的信息。
有一些补丁仅仅处在实验阶段,把它们也安装上不是一个好主意。这一步,你会遇到很多十分有趣的匹配和对数据包的操作,但它们还正在实验。
总之,只有某些补丁会被询问是否加入内核,而Netfilter的开发者们有大量的补丁或附件想要加入内核,但还要再实验一阵子才能做到。如果你想安装这些东西,就用下面的命令:
你要是不打算用patch-o-matic修补内核,以上的命令都用不着,它们不是必需的。不过,你可以用这些命令来看看有什么有趣的玩意儿,这不会影响任何东西。
--------------------------------------------------------------------------------
Red Hat 7.1使用2.4.x的内核,支持Netfilter和iptables。Red Hat包含了所有基本的程序和需要的配置文件,但缺省使用的是B class=COMMAND>ipchains。“iptables为什么不能用”是最常见的问题,下面就让我们就来说说如何关闭ipchains而起用iptables 。
Red Hat 7.1预装的iptables版本有些老了,在使用之前,你可能想装个新的,再自己编译一下内核。
用下面的命令以使iptables能在这些层运行:
--------------------------------------------------------------------------------
这一章我们来讨论数据包是以什么顺序、如何穿越不同的链和表的。稍后,在你自己写规则时,就会知道这个顺序是多么的重要。一些组件是iptables与内核共用的,比如,数据包路由的判断。了解到这一点是很重要的,尤其在你用iptables改变数据包的路由时。这会帮助你弄明白数据包是如何以及为什么被那样路由,一个好的例子是DNAT和SNAT,不要忘了TOS的作用。
--------------------------------------------------------------------------------
当数据包到达防火墙时,如果MAC地址符合,就会由内核里相应的驱动程序接收,然后会经过一系列操作,从而决定是发送给本地的程序,还是转发给其他机子,还是其他的什么。
1 在线路上传输(比如,Internet)
2 进入接口 (比如, eth0)
3 mangle PREROUTING 这个链用来mangle数据包,比如改变TOS等
4 nat PREROUTING 这个链主要用来做DNAT。不要在这个链做过虑操作,因为某些情况下包会溜过去。
5 路由判断,比如,包是发往本地的,还是要转发的。
6 mangle INPUT 在路由之后,被送往本地程序之前,mangle数据包。
7 filter INPUT 所有以本地为目的的包都要经过这个链,不管它们从哪儿来,对这些包的过滤条件就设在这里。
8 到达本地程序了(比如,服务程序或客户程序)
1 本地程序(比如,服务程序或客户程序)
2 路由判断,要使用源地址,外出接口,还有其他一些信息。
3 mangle OUTPUT 在这儿可以mangle包。建议不要在这儿做过滤,可能有副作用哦。
4 nat OUTPUT 这个链对从防火墙本身发出的包进行DNAT操作。
5 filter OUTPUT 对本地发出的包过滤。
6 mangle POSTROUTING 这条链主要在包DNAT之后(译者注:作者把这一次DNAT称作实际的路由,虽然在前面有一次路由。对于本地的包,一旦它被生成,就必须经过路由代码的处理,但这个包具体到哪儿去,要由NAT代码处理之后才能确定。所以把这称作实际的路由。),离开本地之前,对包 mangle。有两种包会经过这里,防火墙所在机子本身产生的包,还有被转发的包。
7 nat POSTROUTING 在这里做SNAT。但不要在这里做过滤,因为有副作用,而且有些包是会溜过去的,即使你用了DROP策略。
8 离开接口(比如: eth0)
9 在线路上传输(比如,Internet)
1 在线路上传输(比如,Internet)
2 进入接口(比如, eth0)
3 mangle PREROUTING mangle数据包,,比如改变TOS等。
4 nat PREROUTING 这个链主要用来做DNAT。不要在这个链做过虑操作,因为某些情况下包会溜过去。稍后会做SNAT。
5 路由判断,比如,包是发往本地的,还是要转发的。
6 mangle FORWARD 包继续被发送至mangle表的FORWARD链,这是非常特殊的情况才会用到的。在这里,包被mangle(还记得mangle的意思吗)。这次mangle发生在最初的路由判断之后,在最后一次更改包的目的之前(译者注:就是下面的FORWARD链所做的,因其过滤功能,可能会改变一些包的目的地,如丢弃包)。
7 filter FORWARD 包继续被发送至这条FORWARD链。只有需要转发的包才会走到这里,并且针对这些包的所有过滤也在这里进行。注意,所有要转发的包都要经过这里,不管是外网到内网的还是内网到外网的。在你自己书写规则时,要考虑到这一点。
8 mangle POSTROUTING 这个链也是针对一些特殊类型的包(译者注:参考第6步,我们可以发现,在转发包时,mangle表的两个链都用在特殊的应用上)。这一步mangle是在所有更改包的目的地址的操作完成之后做的,但这时包还在本地上。
9 nat POSTROUTING 这个链就是用来做SNAT的,当然也包括Masquerade(伪装)。但不要在这儿做过滤,因为某些包即使不满足条件也会通过。
10 离开接口(比如: eth0)
11 又在线路上传输了(比如,LAN)
在上面的情况里,不要在INPUT链上做过滤。INPUT是专门用来操作那些以我们的机子为目的地址的包的,它们不会被路由到其它地方的。
想要更多的信息,可以看看rc.test-iptables.txt ,这个脚本包括了一些规则,它们会向你展示包是怎样通过各个表和链的。
--------------------------------------------------------------------------------
这个表主要用来mangle包,你可以使用mangle匹配来改变包的TOS等特性。
强烈建议你不要在这个表里做任何过滤,不管是DANT,SNAT或者Masquerade。
TOS
--------------------------------------------------------------------------------
此表仅用于NAT,也就是转换包的源或目标地址。注意,就象我们前面说过的,只有流的第一个包会被这个链匹配,其后的包会自动被做相同的处理。实际的操作分为以下几类:
DNAT
--------------------------------------------------------------------------------
filter 表用来过滤数据包,我们可以在任何时候匹配包并过滤它们。我们就是在这里根据包的内容对包做DROP或ACCEPT的。当然,我们也可以预先在其他地方做些过滤,但是这个表才是设计用来过滤的。几乎所有的target都可以在这儿使用。大量具体的介绍在后面,现在你只要知道过滤工作主要是在这儿完成的就行了。
--------------------------------------------------------------------------------
本章将详细介绍状态机制。通读本章,你会对状态机制是如何工作的有一个全面的了解。我们用一些例子来进行说明状态机制。实践出真知嘛。
--------------------------------------------------------------------------------
状态机制是iptables中特殊的一部分,其实它不应该叫状态机制,因为它只是一种连接跟踪机制。但是,很多人都认可状态机制这个名字。文中我也或多或或少地用这个名字来表示和连接跟踪相同的意思。这不应该引起什么混乱的。连接跟踪可以让Netfilter知道某个特定连接的状态。运行连接跟踪的防火墙称作带有状态机制的防火墙,以下简称为状态防火墙。状态防火墙比非状态防火墙要安全,因为它允许我们编写更严密的规则。
--------------------------------------------------------------------------------
我们先来看看怎样阅读/proc/net/ip_conntrack里的conntrack记录。这些记录表示的是当前被跟踪的连接。如果安装了ip_conntrack模块,cat /proc/net/ip_conntrack 的显示类似:
dport=22 [UNREPLIED] src=192.168.1.9 dst=192.168.1.6 sport=22 \
dport=32775 use=2
conntrack模块维护的所有信息都包含在这个例子中了,通过它们就可以知道某个特定的连接处于什么状态。首先显示的是协议,这里是tcp,接着是十进制的6(译者注:tcp的协议类型代码是6)。之后的117是这条conntrack记录的生存时间,它会有规律地被消耗,直到收到这个连接的更多的包。那时,这个值就会被设为当时那个状态的缺省值。接下来的是这个连接在当前时间点的状态。上面的例子说明这个包处在状态 SYN_SENT,这个值是iptables显示的,以便我们好理解,而内部用的值稍有不同。SYN_SENT说明我们正在观察的这个连接只在一个方向发送了一TCP SYN包。再下面是源地址、目的地址、源端口和目的端口。其中有个特殊的词UNREPLIED,说明这个连接还没有收到任何回应。最后,是希望接收的应答包的信息,他们的地址和端口和前面是相反的。
最近patch-o-matic里有一个新的补丁,可以把上面提到的超时时间也作为系统变量,这样我们就能够在系统空闲时改变它们的值。以后,我们就不必为了改变这些值而重编译内核了。
--------------------------------------------------------------------------------
就象前面说的,包的状态依据IP所包含的协议不同而不同,但在内核外部,也就是用户空间里,只有4种状态:NEW,ESTABLISHED,RELATED 和INVALID。它们主要是和状态匹配一起使用。下面就简要地介绍以下这几种状态:
NEW NEW说明这个包是我们看到的第一个包。意思就是,这是conntrack模块看到的某个连接第一个包,它即将被匹配了。比如,我们看到一个SYN 包,是我们所留意的连接的第一个包,就要匹配它。第一个包也可能不是SYN包,但它仍会被认为是NEW状态。这样做有时会导致一些问题,但对某些情况是有非常大的帮助的。例如,在我们想恢复某条从其他的防火墙丢失的连接时,或者某个连接已经超时,但实际上并未关闭时。
ESTABLISHED ESTABLISHED已经注意到两个方向上的数据传输,而且会继续匹配这个连接的包。处于ESTABLISHED状态的连接是非常容易理解的。只要发送并接到应答,连接就是ESTABLISHED的了。一个连接要从NEW变为ESTABLISHED,只需要接到应答包即可,不管这个包是发往防火墙的,还是要由防火墙转发的。ICMP的错误和重定向等信息包也被看作是ESTABLISHED,只要它们是我们所发出的信息的应答。
RELATED RELATED是个比较麻烦的状态。当一个连接和某个已处于ESTABLISHED状态的连接有关系时,就被认为是RELATED的了。换句话说,一个连接要想是RELATED的,首先要有一个ESTABLISHED的连接。这个ESTABLISHED连接再产生一个主连接之外的连接,这个新的连接就是RELATED的了,当然前提是conntrack模块要能理解RELATED。ftp是个很好的例子,FTP-data 连接就是和FTP-control有RELATED的。还有其他的例子,比如,通过IRC的DCC连接。有了这个状态,ICMP应答、FTP传输、DCC等才能穿过防火墙正常工作。注意,大部分还有一些UDP协议都依赖这个机制。这些协议是很复杂的,它们把连接信息放在数据包里,并且要求这些信息能被正确理解。
INVALID INVALID说明数据包不能被识别属于哪个连接或没有任何状态。有几个原因可以产生这种情况,比如,内存溢出,收到不知属于哪个连接的ICMP 错误信息。一般地,我们DROP这个状态的任何东西。
--------------------------------------------------------------------------------
本节和下面的几节,我们来详细讨论这些状态,以及在TCP、UDP和ICMP这三种基本的协议里怎样操作它们。当然,也会讨论其他协议的情况。我们还是从TCP入手,因为它本身就是一个带状态的协议,并且具有很多关于iptables状态机制的详细信息。
dport=23 [UNREPLIED] src=192.168.1.35 dst=192.168.1.5 sport=23 \
dport=1031 use=1
从上面的记录可以看出,SYN_SENT状态被设置了,这说明连接已经发出一个SYN包,但应答还没发送过来,这可从[UNREPLIED]标志看出。
dport=23 src=192.168.1.35 dst=192.168.1.5 sport=23 dport=1031 \
use=1
现在我们已经收到了相应的SYN/ACK包,状态也变为SYN_RECV,这说明最初发出的SYN包已正确传输,并且SYN/ACK包也到达了防火墙。 这就意味着在连接的两方都有数据传输,因此可以认为两个方向都有相应的回应。当然,这是假设的。
sport=1031 dport=23 src=192.168.1.35 dst=192.168.1.5 \
sport=23 dport=1031 use=1
现在我们发出了三步握手的最后一个包,即ACK包,连接也就进入ESTABLISHED状态了。再传输几个数据包,连接就是[ASSURED]的了。
NONE 30 minutes
ESTABLISHED 5 days
SYN_SENT 2 minutes
SYN_RECV 60 seconds
FIN_WAIT 2 minutes
TIME_WAIT 2 minutes
CLOSE 10 seconds
CLOSE_WAIT 12 hours
LAST_ACK 30 seconds
LISTEN> 2 minutes
注意状态机制在用户空间里的部分不会查看TCP包的标志位(也就是说TCP标志对它而言是透明的)。如果我们想让NEW状态的包通过防火墙,就要指定NEW状态,我们理解的NEW状态的意思就是指SYN包,可是iptables又不查看这些标志位。这就是问题所在。有些没有设置SYN或ACK的包,也会被看作NEW状态的。这样的包可能会被冗余防火墙用到,但对只有一个防火墙的网络是很不利的(可能会被攻击哦)。那我们怎样才能不受这样的包的影响呢?你可以使用未设置SYN的NEW状态包 里的命令。还有一个办法,就是安装patch-o-matic里的tcp-window-tracking扩展功能,它可以使防火墙能根据TCP的一些标志位来进行状态跟踪。
--------------------------------------------------------------------------------
UDP连接是无状态的,因为它没有任何的连接建立和关闭过程,而且大部分是无序列号的。以某个顺序收到的两个数据包是无法确定它们的发出顺序的。但内核仍然可以对UDP连接设置状态。我们来看看是如何跟踪UDP连接的,以及conntrack的相关记录。
[UNREPLIED] src=192.168.1.5 dst=192.168.1.2 sport=1025 \
dport=137 use=1
从前两个值可知,这是一个UDP包。第一个是协议名称,第二个是协议号,第三个是此状态的生存时间,默认是30秒。接下来是包的源、目地址和端口,还有期待之中回应包的源、目地址和端口。[UNREPLIED]标记说明还未收到回应。
dport=1025 src=192.168.1.5 dst=192.168.1.2 sport=1025 \
dport=137 use=1
一旦收到第一个包的回应,[UNREPLIED]标记就会被删除,连接就被认为是ESTABLISHED的,但在记录里并不显示ESTABLISHED标记。相应地,状态的超时时间也变为180秒了。在本例中,只剩170秒了,10秒后,就会减少为160秒。有个东西是不可少的,虽然它可能会有些变化,就是前面提过的[ASSURED]。要想变为 [ASSURED]状态,连接上必须要再有些流量。
dport=53 src=195.22.79.2 dst=192.168.1.5 sport=53 \
dport=1025 [ASSURED] use=1
可以看出来,[ASSURED]状态的记录和前面的没有多大差别,除了标记由[UNREPLIED]变成[ASSURED]。如果这个连接持续不了180秒,那就要被中断。180秒是短了点儿,但对大部分应用足够了。只要遇到这个连接的包穿过防火墙,超时值就会被重置为默认值,所有的状态都是这样的。
--------------------------------------------------------------------------------
ICMP也是一种无状态协议,它只是用来控制而不是建立连接。ICMP包有很多类型,但只有四种类型有应答包,它们是回显请求和应答(Echo request and reply),时间戳请求和应答(Timestamp request and reply),信息请求和应答(Information request and reply),还有地址掩码请求和应答(Address mask request and reply),这些包有两种状态,NEW和ESTABLISHED 。时间戳请求和信息请求已经废除不用了,回显请求还是常用的,比如ping命令就用的到,地址掩码请求不太常用,但是可能有时很有用并且值得使用。看看下面的图,就可以大致了解ICMP连接的NEW和ESTABLISHED状态了。
id=33029 [UNREPLIED] src=192.168.1.10 dst=192.168.1.6 \
type=0 code=0 id=33029 use=1
可以看到,ICMP的记录和TCP、UDP的有点区别,协议名称、超时时间和源、目地址都一样,不同之处在于没有了端口,而新增了三个新的字段:type,code和id。字段type说明ICMP的类型。code说明ICMP的代码,这些代码在附录ICMP类型里有说明。id是ICMP包的ID。每个ICMP包被发送时都被分配一个ID,接受方把同样的ID 分配给应答包,这样发送方能认出是哪个请求的应答。
注意,应答包必须符合一定的标准,连接才能被认作established的,每个传输类型都是这样。
--------------------------------------------------------------------------------
有时,conntrack机制并不知道如何处理某个特殊的协议,尤其是在它不了解这个协议或不知道协议如何工作时,比如,NETBLT,MUX还有EGP。这种情况下,conntrack使用缺省的操作。这种操作很象对UDP连接的操作,就是第一个包被认作NEW,其后的应答包等等数据都是 ESTABLISHED。
--------------------------------------------------------------------------------
有些协议比其他协议更复杂,这里复杂的意思是指连接跟踪机制很难正确地跟踪它们,比如,ICQ、IRC 和FTP,它们都在数据包的数据域里携带某些信息,这些信息用于建立其他的连接。因此,需要一些特殊的 helper来完成工作。
注意连接跟踪并不处理NAT,因此要对连接做NAT就需要增加相应的模块。比如,你想NAT并跟踪FTP连接,除了FTP的相应模块,还要有NAT的模块。所有的NAT helper名字都是以ip_nat_开头的,这是一个命名习惯:FTP NAT helper叫做ip_nat_ftp,IRC的相应模块就是ip_nat_irc。conntrack helper 的命名也遵循一样的习惯:针对IRC的conntrack helper叫ip_conntrack_irc,FTP的叫作ip_conntrack_ftp。
--------------------------------------------------------------------------------
iptables提供了两个很有用的工具用来处理大规则集: iptables-save和iptables-restore,它们把规则存入一个与标准脚本代码只有细微查别的特殊格式的文件中,或从中恢复规则。
--------------------------------------------------------------------------------
使用iptables-save和iptables-restore的一个最重要的原因是,它们能在相当程度上提高装载、保存规则的速度。使用脚本更改规则的问题是,改动每个规则都要调运命令iptables,而每一次调用iptables,它首先要把Netfilter内核空间中的整个规则集都提取出来,然后再插入或附加,或做其他的改动,最后,再把新的规则集从它的内存空间插入到内核空间中。这会花费很多时间。
--------------------------------------------------------------------------------
iptables-restore能替代所有的脚本来设置规则吗?不,到现在为止不行,很可能永远都不行。iptables-restore的主要不足是不能用来做复杂的规则集。例如,我们想在计算机启动时获取连接的动态分配的IP地址,然后用在脚本里。这一点,用iptables-restore来实现,或多或少是不可能的。
--------------------------------------------------------------------------------
iptables-save用来把当前的规则存入一个文件里以备iptables-restore使用。它的使用很简单,只有两个参数:
iptables-save [-c] [-t table]
参数-c的作用是保存包和字节计数器的值。这可以使我们在重启防火墙后不丢失对包和字节的统计。带-c参数的iptables-save命令使重启防火墙而不中断统计记数程序成为可能。这个参数默认是不使用的。
# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:17 2002
*filter
:INPUT ACCEPT [404:19766]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [530:43376]
COMMIT
# Completed on Wed Apr 24 10:19:17 2002
# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:17 2002
*mangle
:PREROUTING ACCEPT [451:22060]
:INPUT ACCEPT [451:22060]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [594:47151]
:POSTROUTING ACCEPT [594:47151]
COMMIT
# Completed on Wed Apr 24 10:19:17 2002
# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:17 2002
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [3:450]
:OUTPUT ACCEPT [3:450]
COMMIT
# Completed on Wed Apr 24 10:19:17 2002
# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:55 2002
*filter
:INPUT DROP [1:229]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth1 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
COMMIT
# Completed on Wed Apr 24 10:19:55 2002
# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:55 2002
*mangle
:PREROUTING ACCEPT [658:32445]
:INPUT ACCEPT [658:32445]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [891:68234]
:POSTROUTING ACCEPT [891:68234]
COMMIT
# Completed on Wed Apr 24 10:19:55 2002
# Generated by iptables-save v1.2.6a on Wed Apr 24 10:19:55 2002
*nat
:PREROUTING ACCEPT [1:229]
:POSTROUTING ACCEPT [3:450]
:OUTPUT ACCEPT [3:450]
-A POSTROUTING -o eth0 -j SNAT --to-source 195.233.192.1
COMMIT
# Completed on Wed Apr 24 10:19:55 2002
--------------------------------------------------------------------------------
iptables-restore用来装载由iptables-save保存的规则集。不幸的是,它只能从标准输入接受输入,而不能从文件接受。下面是它的事方法:
iptables-restore [-c] [-n]
参数-c要求装入包和字节计数器。如果你用iptables-save保存了计数器,现在想重新装入,就必须用这个参数。它的另一种较长的形式是--counters。
--------------------------------------------------------------------------------
本章将详细地讨论如何构件你自己的规则。规则就是指向标,在一条链上,对不同的连接和数据包阻塞或允许它们去向何处。插入链的每一行都是一条规则。我们也会讨论基本的matche及其用法,还有各种各样的target,以及如何建立我们自己的target(比如,一个新的子链)。
--------------------------------------------------------------------------------
我们已经解释了什么是规则,在内核看来,规则就是决定如何处理一个包的语句。如果一个包符合所有的条件(就是符合matche语句),我们就运行target或jump指令。书写规则的语法格式是:
iptables [-t table] command [match] [target/jump]
对于这个句法没什么可说的,但注意target指令必须在最后。为了易读,我们一般用这种语法。总之,你将见到的大部分规则都是按这种语法写的。因此,如果你看到别人写的规则,你很可能会发现用的也是这种语法,当然就很容易理解那些规则了。
--------------------------------------------------------------------------------
选项-t用来指定使用哪个表,它可以是下面介绍的表中的任何一个,默认的是 filter表。注意,下面的介绍只是章节表和链的摘要。
nat nat表的主要用处是网络地址转换,即Network Address Translation,缩写为NAT。做过NAT操作的数据包的地址就被改变了,当然这种改变是根据我们的规则进行的。属于一个流的包只会经过这个表一次。如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自动地被做相同的操作。也就是说,余下的包不会再通过这个表,一个一个的被NAT,而是自动地完成。这就是我们为什么不应该在这个表中做任何过滤的主要原因,对这一点,后面会有更加详细的讨论。PREROUTING 链的作用是在包刚刚到达防火墙时改变它的目的地址,如果需要的话。OUTPUT链改变本地产生的包的目的地址。POSTROUTING链在包就要离开防火墙之前改变其源地址。
mangle 这个表主要用来mangle数据包。我们可以改变不同的包及包头的内容,比如 TTL,TOS或MARK。注意MARK并没有真正地改动数据包,它只是在内核空间为包设了一个标记。防火墙内的其他的规则或程序(如tc)可以使用这种标记对包进行过滤或高级路由。这个表有五个内建的链: PREROUTING,POSTROUTING, OUTPUT,INPUT和 FORWARD。PREROUTING在包进入防火墙之后、路由判断之前改变包,POSTROUTING是在所有路由判断之后。 OUTPUT在确定包的目的之前更改数据包。INPUT在包被路由到本地之后,但在用户空间的程序看到它之前改变包。FORWARD在最初的路由判断之后、最后一次更改包的目的之前mangle包。注意,mangle表不能做任何NAT,它只是改变数据包的 TTL,TOS或MARK,而不是其源目地址。NAT是在nat表中操作的。
filter filter表是专门过滤包的,内建三个链,可以毫无问题地对包进行DROP、LOG、ACCEPT和REJECT等操作。FORWARD 链过滤所有不是本地产生的并且目的地不是本地(所谓本地就是防火墙了)的包,而 INPUT恰恰针对那些目的地是本地的包。OUTPUT 是用来过滤所有本地生成的包的。
--------------------------------------------------------------------------------
在这一节里,我们将要介绍所有的command以及它们的用途。command指定iptables 对我们提交的规则要做什么样的操作。这些操作可能是在某个表里增加或删除一些东西,或做点儿其他什么。以下是iptables可用的command(要注意,如不做说明,默认表的是 filter表。):
Example iptables -A INPUT ...
Explanation 在所选择的链末添加规则。当源地址或目的地址是以名字而不是ip地址的形式出现时,若这些名字可以被解析为多个地址,则这条规则会和所有可用的地址结合。
Command -D, --delete
Example iptables -D INPUT --dport 80 -j DROP或iptables -D INPUT 1
Explanation 从所选链中删除规则。有两种方法指定要删除的规则:一是把规则完完整整地写出来,再就是指定规则在所选链中的序号(每条链的规则都各自从1被编号)。
Command -R, --replace
Example iptables -R INPUT 1 -s 192.168.0.1 -j DROP
Explanation 在所选中的链里指定的行上(每条链的规则都各自从1被编号)替换规则。它主要的用处是试验不同的规则。当源地址或目的地址是以名字而不是ip地址的形式出现时,若这些名字可以被解析为多个地址,则这条command会失败。
Command -I, --insert
Example iptables -I INPUT 1 --dport 80 -j ACCEPT
Explanation 根据给出的规则序号向所选链中插入规则。如果序号为1,规则会被插入链的头部,其实默认序号就是1。
Command -L, --list
Example iptables -L INPUT
Explanation 显示所选链的所有规则。如果没有指定链,则显示指定表中的所有链。如果什么都没有指定,就显示默认表所有的链。精确输出受其它参数影响,如-n 和-v等参数,下面会介绍。
Command -F, --flush
Example iptables -F INPUT
Explanation 清空所选的链。如果没有指定链,则清空指定表中的所有链。如果什么都没有指定,就清空默认表所有的链。当然,也可以一条一条地删,但用这个command会快些。
Command -Z, --zero
Example iptables -Z INPUT
Explanation 把指定链(如未指定,则认为是所有链)的所有计数器归零。
Command -N, --new-chain
Example iptables -N allowed
Explanation 根据用户指定的名字建立新的链。上面的例子建立了一个名为allowed的链。注意,所用的名字不能和已有的链、target同名。
Command -X, --delete-chain
Example iptables -X allowed
Explanation 删除指定的用户自定义链。这个链必须没有被引用,如果被引用,在删除之前你必须删除或者替换与之有关的规则。如果没有给出参数,这条命令将会删除默认表所有非内建的链。
Command -P, --policy
Example iptables -P INPUT DROP
Explanation 为链设置默认的target(可用的是DROP 和ACCEPT,如果还有其它的可用,请告诉我),这个target称作策略。所有不符合规则的包都被强制使用这个策略。只有内建的链才可以使用规则。但内建的链和用户自定义链都不能被作为策略使用,也就是说不能象这样使用:iptables -P INPUT allowed(或者是内建的链)。
Command -E, --rename-chain
Example iptables -E allowed disallowed
Explanation 对自定义的链进行重命名,原来的名字在前,新名字在后。如上,就是把allowed改为disallowed。这仅仅是改变链的名字,对整个表的结构、工作没有任何影响。
可用此选项的命令 --list, --append, --insert, --delete, --replace
Explanation(说明) 这个选项使输出详细化,常与--list 连用。与--list连用时,输出中包括网络接口的地址、规则的选项、TOS掩码、字节和包计数器,其中计数器是以K、M、G(这里用的是10的幂而不是2的幂哦)为单位的。如果想知道到底有多少个包、多少字节,还要用到选项-x,下面会介绍。如果-v 和--append、--insert、--delete 或--replace连用,iptables会输出详细的信息告诉你规则是如何被解释的、是否正确地插入等等。
Option -x, --exact(精确的)
Commands used with --list
Explanation 使--list输出中的计数器显示准确的数值,而不用K、M、G等估值。注意此选项只能和--list连用。
Option -n, --numeric(数值)
Commands used with --list
Explanation 使输出中的IP地址和端口以数值的形式显示,而不是默认的名字,比如主机名、网络名、程序名等。注意此选项也只能和--list连用。
Option --line-numbers
Commands used with --list
Explanation 又是一个只能和--list连用的选项,作用是显示出每条规则在相应链中的序号。这样你可以知道序号了,这对插入新规则很有用哦。
Option -c, --set-counters
Commands used with --insert, --append, --replace
Explanation 在创建或更改规则时设置计数器,语法如下:--set-counters 20 4000,意思是让内核把包计数器设为20,把字节计数器设为4000。
Option --modprobe
Commands used with All
Explanation 此选项告诉iptables探测并装载要使用的模块。这是非常有用的一个选项,万一modprobe命令不在搜索路径中,就要用到了。有了这个选项,在装载模块时,即使有一个需要用到的模块没装载上,iptables也知道要去搜索。
--------------------------------------------------------------------------------
这一节,我们会详细讨论一些matche,我把它们归为五类。第一类是generic matches(通用的匹配),适用于所有的规则;第二类是TCP matches,顾名思义,这只能用于TCP包;第三类是UDP matches,当然它只能用在UDP包上了;第四类是ICMP matches ,针对ICMP包的;第五类比较特殊,针对的是状态(state),所有者(owner)和访问的频率限制(limit)等,它们已经被分到更多的小类当中,尽管它们并不是完全不同的。我希望这是一种大家都容易理解的分类。
--------------------------------------------------------------------------------
无论我们使用的是何种协议,也不管我们又装入了匹配的何种扩展,通用匹配都使可用的。也就是说,它们可以直接使用,而不需要什么前提条件,在后面你会看到,有很多匹配操作是需要其他的匹配作为前提的。
Example iptables -A INPUT -p tcp
Explanation 匹配指定的协议。指定协议的形式有以下几种:
1、名字,不分大小写,但必须是在/etc/protocols中定义的。
Match -s, --src, --source
Example iptables -A INPUT -s 192.168.1.1
Explanation 以IP源地址匹配包。地址的形式如下:
1、单个地址,如192.168.1.1,也可写成 192.168.1.1/255.255.255.255或192.168.1.1/32
Match -d, --dst, --destination
Example iptables -A INPUT -d 192.168.1.1
Explanation 以IP目的地址匹配包。地址的形式和 -- source完全一样。
Match -i, --in-interface
Example iptables -A INPUT -i eth0
Explanation 以包进入本地所使用的网络接口来匹配包。要注意这个匹配操作只能用于INPUT,FORWARD和 PREROUTING这三个链,用在其他任何地方都会提示错误信息。指定接口有一下方法:
1、指定接口名称,如:eth0、ppp0等
Match -o, --out-interface
Example iptables -A FORWARD -o eth0
Explanation 以包离开本地所使用的网络接口来匹配包。使用的范围和指定接口的方法与--in-interface完全一样。
Match -f, --fragment
Example iptables -A INPUT -f
Explanation 用来匹配一个被分片的包的第二片或及以后的部分。因为它们不包含源或目的地址,或ICMP类型等信息,其他规则无法匹配到它,所以才有这个匹配操作。要注意碎片攻击哦。这个操作也可以加英文感叹号表示取反,但要注意位置,如:! -f 。取反时,表示只能匹配到没有分片的包或者是被分片的包的第一个碎片,其后的片都不行。现在内核有完善的碎片重组功能,可以防止碎片攻击,所以不必使用取反的功能来防止碎片通过。如果你使用连接跟踪,是不会看到任何碎片的,因为在它们到达任何链之前就被处理过了。
--------------------------------------------------------------------------------
这种匹配操作是自动地或隐含地装载入内核的。例如我们使用--protocol tcp 时,不需再装入任何东西就可以匹配只有IP包才有的一些特点。现在有三种隐含的匹配针对三种不同的协议,即TCP matches,UDP matches和 ICMP matches。它们分别包括一套只适用于相应协议的判别标准。相对于隐含匹配的是显式匹配,它们必须使用-m或--match被明确地装载,而不能是自动地或隐含地,下一节会介绍到。
--------------------------------------------------------------------------------
TCP matches只能匹配TCP包或流的细节,它们必须有--protocol tcp作为前提条件。
Example iptables -A INPUT -p tcp --sport 22
Explanation 基于TCP包的源端口来匹配包,端口的指定形式如下:
1、不指定此项,则暗示所有端口。
Match --dport, --destination-port
Example iptables -A INPUT -p tcp --dport 22
Explanation 基于TCP包的目的端口来匹配包,端口的指定形式和--sport完全一样。
Match --tcp-flags
Example
Explanation 匹配指定的TCP标记。有两个参数,它们都是列表,列表内部用英文的逗号作分隔符,这两个列表之间用空格分开。第一个参数指定我们要检查的标记(作用就象掩码),第二个参数指定“在第一个列表中出现过的且必须被设为1(即状态是打开的)的”标记(第一个列表中其他的标记必须置0)。也就是说,第一个参数提供检查范围,第二个参数提供被设置的条件(就是哪些位置1)。这个匹配操作可以识别以下标记:SYN, ACK,FIN,RST ,URG,PSH。另外还有两个词也可使用,就是ALL和NONE。顾名思义,ALL是指选定所有的标记,NONE是指未选定任何标记。这个匹配也可在参数前加英文的感叹号表示取反。例如:
1、iptables -p tcp --tcp-flags SYN,FIN,ACK SYN表示匹配那些SYN标记被设置而FIN和ACK标记没有设置的包,注意各标记之间只有一个逗号而没有空格。
Match --syn
Example iptables -p tcp --syn
Explanation 这个匹配或多或少算是ipchains时代的遗留物,之所以还保留它,是为了向后兼容,也是为了方便规则在iptables和ipchains间的转换。它匹配那些SYN标记被设置而 ACK和RST标记没有设置的包,这和iptables -p tcp --tcp-flags SYN,RST,ACK SYN 的作用毫无二样。这样的包主要用在TCP连接初始化时发出请求。如果你阻止了这样的包,也就阻止了所有由外向内的连接企图,这在一定程度上防止了一些攻击。但外出的连接不受影响,恰恰现在有很多攻击就利用这一点。比如有些攻击黑掉服务器之后安装会一些软件,它们能够利用已存的连接到达你的机子,而不要再新开一个端口。这个匹配也可用英文感叹号取反,如:! --syn用来匹配那些 RST或ACK被置位的包,换句话说,就是状态为已建立的连接的包。
Match --tcp-option
Example iptables -p tcp --tcp-option 16
Explanation 根据匹配包。TCP选项是TCP头中的特殊部分,有三个不同的部分。第一个8位组表示选项的类型,第二个8位组表示选项的长度(这个长度是整个选项的长度,但不包含填充部分所占的字节,而且要注意不是每个TCP选项都有这一部分的),第三部分当然就是选项的内容了。为了适应标准,我们不必执行所有的选项,但我们可以查看选项的类型,如果不是我们所支持的,那就只是看看长度然后跳过数据部分。这个操作是根据选项的十进制值来匹配的,它也可以用英文感叹号取反。所有的选项都可在Internet Engineering Task Force里找到。
--------------------------------------------------------------------------------
UDP matches是在指定--protocol UDP时自动装入的。UDP是一种无连接协议,所以在它打开、关闭连接以及在发送数据时没有多少标记要设置,它也不需要任何类型的确认。数据丢失了,就丢失了(不会发送ICMP错误信息的)。这就说明UDP matches要比TCP matches少多了。即使UDP和ICMP是无连接协议,状态机制也可以很好的工作,就象在TCP上一样,这在前面讨论过。
Example iptables -A INPUT -p udp --sport 53
Explanation 基于UDP包的源端口来匹配包,端口的指定形式和TCP matches中的--sport完全一样。
Match --dport, --destination-port
Example iptables -A INPUT -p udp --dport 53
Explanation 基于UDP包的目的端口来匹配包,端口的指定形式和TCP matches中的--sport完全一样。
--------------------------------------------------------------------------------
ICMP协议也是无连接协议,ICMP包更是短命鬼,比UDP的还短。ICMP协议不是IP协议的下属协议,而是它的辅助者,其主要作用是报告错误和连接控制。ICMP包的头和IP的很相似,但又有很多不同。这个协议最主要的特点是它有很多类型,以应对不同的情况。比如,我们想访问一个无法访问的地址,就会收到一个ICMP host unreachable信息,它的意思是主机无法到达。在附录ICMP类型里有完整的ICMP类型列表。虽然有这么多类型,但只有一个 ICMP matche,这就足够对付它们了。这个matche是在指定--protocol ICMP时自动装入的。注意所有的通用匹配都可以使用,这样我们就可以匹配ICMP包的源、目地址。
Example iptables -A INPUT -p icmp --icmp-type 8
Explanation 根据ICMP类型匹配包,类型的指定可以使用十进制数值或相应的名字,数值在RFC792中有定义,名字可以用iptables --protocol icmp --help 查看,或者在附录ICMP类型中查找。这个匹配也可用英文感叹号取反,如:--icmp-type ! 8就表示匹配除类型8之外的所有ICMP包。要注意有些ICMP 类型已经废弃不用了,还有一些可能会对无防护的主机带来“危险”,因为它们可能把包重定向到错误的地方。
--------------------------------------------------------------------------------
显式匹配必须用-m或--match装载,比如要使用状态匹配就必须使用-m state。有些匹配还需要指定协议,有些就不需要,比如连接状态就不要。这些状态是NEW(还未建立好的连接的第一个包), ESTABLISHED(已建立的连接,也就是已经在内核里注册过的),RELATED(由已经存在的、处于已建立状态的连接生成的新连接),等等。有些匹配还处在开发阶段,或者还只是为了说明iptables的强大能力。这说明不是所有的匹配一开始就是实用的,但以后你可能会用到它。随着iptables 新版本的发布,会有一些新的匹配可用。隐含匹配和显式匹配最大的区别就是一个是跟随协议匹配自动装载的,一个是显式装载的。
--------------------------------------------------------------------------------
这个匹配操作必须由-m limit明确指定才能使用。有了它的帮助,就可以对指定的规则的日志数量加以限制,以免你被信息的洪流淹没哦。比如,你可以事先设定一个限定值,当符合条件的包的数量不超过它时,就记录;超过了,就不记录了。我们可以控制某条规则在一段时间内的匹配次数(也就是可以匹配的包的数量),这样就能够减少DoS syn flood攻击的影响。这是它的主要作用,当然,还有很多其他作用(译者注:比如,对于某些不常用的服务可以限制连接数量,以免影响其他服务)。limit match也可以用英文感叹号取反,如:-m limit ! --limit 5/s表示在数量超过限定值后,所有的包都会被匹配。
Example iptables -A INPUT -m limit --limit 3/hour
Explanation 为limit match设置最大平均匹配速率,也就是单位时间内limit match可以匹配几个包。它的形式是一个数值加一个时间单位,可以是/second /minute /hour /day 。默认值是每小时3次(用户角度),即3/hour ,也就是每20分钟一次(iptables角度)。
Match --limit-burst
Example iptables -A INPUT -m limit --limit-burst 5
Explanation 这里定义的是limit match的峰值,就是在单位时间(这个时间由上面的--limit指定)内最多可匹配几个包(由此可见,--limit-burst的值要比--limit的大)。默认值是5。为了观察它是如何工作的,你可以启动“只有一条规则的脚本”Limit- match.txt,然后用不同的时间间隔、发送不同数量的ping数据包。这样,通过返回的 echo replies就可以看出其工作方式了。
--------------------------------------------------------------------------------
基于包的MAC源地址匹配包。到写这篇文章时,这个match还有一点限制(就是只能匹配MAC源地址匹),但今后定会有所发展,会更有用的。
注意,这个match是由-m mac装入的,而不是一些人想当然的-m mac-source,后者只是前者的选项而已。
Example iptables -A INPUT -m mac --mac-source 00:00:00:00:00:01
Explanation 基于包的MAC源地址匹配包,地址格式只能是XX:XX:XX:XX:XX:XX,当然它也可以用英文感叹号取反,如--mac- source ! 00:00:00:00:00:01,意思很简单了,就是除此之外的地址都可接受嘛。注意,因为 MAC addresses只用于Ethernet类型的网络,所以这个match只能用于Ethernet接口。而且,它还只能在PREROUTING,FORWARD 和INPUT链里使用。
--------------------------------------------------------------------------------
以包被设置的mark来匹配包,这个值只能由内核更改。前面曾经提到过,mark比较特殊,它不是包本身的一部分,而是在包穿越计算机的过程中由内核分配的和它相关联的一个字段。它可能被用来改变包的传输路径或过滤。时至今日,在linux里只有一种方法能设置mark,即iptables的MARK target,以前在ipchains里是FWMARK target。这就是为什么在高级路由里我们仍要参照FWMARK的原因。mark字段的值是一个无符号的整数,在32位系统上最大可以是4294967296(就是2的32次方),这足够用的了:)
Example iptables -t mangle -A INPUT -m mark --mark 1
Explanation 以包被设置的mark值来匹配包,这个值是是由下面将要介绍的 MARK target来设置的,它是一个无符号的整数。所有通过 Netfilter的包都会被分配一个相关联的mark field 。但要注意mark值可不是在任何情况下都能使用的,它只能在分配给它值的那台机子里使用,因为它只是由内核在内存里分配的和包相关的几个字节,并不属于包本身,所以我们不能在本机之外的路由器上使用。mark的格式是--mark value[/mask],如上面的例子是没有掩码的,带掩码的例子如--mark 1/1。如果指定了掩码,就先把mark值和掩码取逻辑与,然后再和包的mark值比较。
--------------------------------------------------------------------------------
多端口匹配扩展使我们能够在一条规则里指定不连续的多个端口,如果没有这个扩展,我们只能按端口来写规则了。其实这只是标准端口匹配的增强版罢了,使我们书写规则更方便而已。
注意:不能在一条规则里同时使用标准端口匹配和多端口匹配,如--sport 1024:63353 -m multiport --dport 21,23,80。这条规则并不能想你想象的那样工作,但也不是不能工作,iptables会使用第一个合法的条件,那么这里多端口匹配就白写了:)
Example iptables -A INPUT -p tcp -m multiport --source-port 22,53,80,110
Explanation 源端口多端口匹配,最多可以指定15个端口,以英文逗号分隔,注意没有空格。使用时必须有-p tcp或-p udp为前提条件。
Match --destination-port
Example iptables -A INPUT -p tcp -m multiport --destination-port 22,53,80,110
Explanation 目的端口多端口匹配,使用方法和源端口多端口匹配一样,唯一的区别是它匹配的是目的端口。
Match --port
Example iptables -A INPUT -p tcp -m multiport --port 22,53,80,110
Explanation 同端口多端口匹配,意思就是它匹配的是那种源端口和目的端口是同一个端口的包,比如:端口80到端口80的包,110到110的包等。使用方法和源端口多端口匹配一样。
--------------------------------------------------------------------------------
基于包的生成者(也就是所有者,或称作拥有者,owner)的ID来匹配包,owner可以是启动进程的用户的ID,或用户所在的组的ID,或进程的ID,或会话的ID。这个扩展原本只是为了说明iptables可以做什么,现在发展到实用阶段了。但要注意,此扩展只能用在OUTPUT中,原因显而易见:我们几乎不可能得到发送端例程的ID的任何信息,或者在去往真正目的地的路上哪儿有路由。甚至在 OUTPUT链里,这也不是十分可靠,因为有些包根本没有owner,比如 ICMP responses,所以它们从不会被这个match抓到:)
Example iptables -A OUTPUT -m owner --uid-owner 500
Explanation 按生成包的用户的ID(UID)来匹配外出的包。使用这个匹配可以做这样一些事,比如,阻止除root外的用户向防火墙外建立新连接,或阻止除用户http外的任何人使用HTTP端口发送数据。
Match --gid-owner
Example iptables -A OUTPUT -m owner --gid-owner 0
Explanation 按生成包的用户所在组的ID(GID)来匹配外出的包。比如,我们可以只让属于network组的用户上Internet,而其他用户都不行;或者只允许http组的成员能从HTTP端口发送数据。
Match --pid-owner
Example iptables -A OUTPUT -m owner --pid-owner 78
Explanation 按生成包的进程的ID(GID)来匹配外出的包。比如,我们可以只允许PID为94的进程(http进程当然不能是多线程的)使用http端口。这个匹配使用起来有一点难度,因为你要知道进程的ID号。当然,你也可以写一个小小的脚本,先从ps的输出中得到PID,再添加相应的规则,这儿有个例子Pid-owner.txt。
Match --sid-owner
Example iptables -A OUTPUT -m owner --sid-owner 100
Explanation 按生成包的会话的ID(SID)来匹配外出的包。一个进程以及它的子进程或它的多个线程都有同一个SID。比如,所有的HTTPD进程的SID和它的父进程一样(最初的 HTTPD进程),即使HTTPD是多线程的(现在大部分都是,比如Apache和Roxen)也一样。这里有个脚本Sid-owner.txt可以反映出这一点。
--------------------------------------------------------------------------------
状态匹配扩展要有内核里的连接跟踪代码的协助,因为它是从连接跟踪机制中得到包的状态的。这样我们就可以了解连接所处的状态。它几乎适用于所有的协议,包括那些无状态的协议,如ICMP和UDP。针对每个连接都有一个缺省的超时值,如果连接的时间超过了这个值,那么这个连接的记录就被会从连接跟踪的记录数据库中删除,也就是说连接就不再存在了。这个match必须有-m state作为前提才能使用。状态机制的详细内容在章节状态机制 中。
Example iptables -A INPUT -m state --state RELATED,ESTABLISHED
Explanation 指定要匹配包的的状态,当前有4种状态可用:INVALID,ESTABLISHED,NEW和RELATED。 INVALID意味着这个包没有已知的流或连接与之关联,也可能是它包含的数据或包头有问题。ESTABLISHED意思是包是完全有效的,而且属于一个已建立的连接,这个连接的两端都已经有数据发送。NEW表示包将要或已经开始建立一个新的连接,或者是这个包和一个还没有在两端都有数据发送的连接有关。RELATED说明包正在建立一个新的连接,这个连接是和一个已建立的连接相关的。比如,FTP data transfer,ICMP error 和一个TCP或UDP连接相关。注意NEW状态并不在试图建立新连接的TCP包里寻找SYN标记,因此它不应该不加修改地用在只有一个防火墙或在不同的防火墙之间没有启用负载平衡的地方。具体如何使用,你就再看看章节状态机制吧:)
--------------------------------------------------------------------------------
根据TOS字段匹配包,必须使用-m tos才能装入。TOS是IP头的一部分,其含义是Type Of Service,由8个二进制位组成,包括一个3 bit的优先权子字段(现在已被忽略),4 bit的TOS子字段和1 bit未用位(必须置0)。它一般用来把当前流的优先权和需要的服务(比如,最小延时、最大吞吐量等)通知路由器。但路由器和管理员对这个值的处理相差很大,有的根本就不理会,而有的就会尽量满足要求。
Example iptables -A INPUT -p tcp -m tos --tos 0x16
Explanation 根据TOS字段匹配包。这个match常被用来mark包,以便后用,除此之外,它还常和iproute2或高级路由功能一起使用。它的参数可以是16进制数,也可以是十进制数,还可以是相应的名字(用 iptables -m tos -h能查到)。到写这篇文章时,有以下参数可用:
Minimize-Delay 16 (0x10),要求找一条路径使延时最小,一些标准服务如telnet、SSH、FTP-control 就需要这个选项。
--------------------------------------------------------------------------------
根据IP头里的TTL (Time To Live,即生存期)字段来匹配包,此必须由-m ttl装入。TTL field是一个字节(8个二进制位),一旦经过一个处理它的路由器,它的值就减去1它的值。当该字段的值减为0时,报文就被认为是不可转发的,数据报就被丢弃,并发送ICMP报文通知源主机,不可转发的报文被丢弃。这也有两种情况,一是传输期间生存时间为0,使用类型为11代码是0的ICMP报文;二是在数据报重组期间生存时间为0,使用类型为11代码是1的ICMP报文。这个match只是根据TTL匹配包,而对其不做任何更改,所以在它之后可使用任何类型的match。
Example iptables -A OUTPUT -m ttl --ttl 60
Explanation 根据TTL的值来匹配包,参数的形式只有一种,就是十进制数值。它可以被用来调试你的局域网,比如解决LAN内的主机到Internet上的主机的连接问题,或找出 Trojan(Trojan)可能的入口。这个match的用处相对有限,但它其实是很有用的,这就看你的想象力如何了。比如可以用它来发现那些TTL具有错误缺省值的机子(这可能是实现TCP/IP栈功能的那个程序本身的错误,或者是配置有问题)。
--------------------------------------------------------------------------------
这个匹配没有任何参数,也不需要显式地装载。注意这应该被看作是一个实验性的匹配,它不总是能正常工作的,对有些不正常的包(unclean package,就是所谓的脏包)或问题,它是视而不见的。这个match 试图匹配那些好象畸形或不正常的包,比如包头错或校验和错,等等。它可能常用来DROP错误的连接、检查有错的流,但要知道这样做也可能会中断合法的连接。
--------------------------------------------------------------------------------
target/jump决定符合条件的包到何处去,语法是--jump target或-j target。(译者注:本文中,原作者把target细分为两类,即Target和Jump。它们唯一的区别是jump的目标是一个在同一个表内的链,而target的目标是具体的操作。)我们会先接触到两个基本的target,就是ACCEPT和DROP。
然后再把它作为jump的目标:
--------------------------------------------------------------------------------
这个target没有任何选项和参数,使用也很简单,指定-j ACCEPT即可。一旦包满足了指定的匹配条件,就会被ACCEPT,并且不会再去匹配当前链中的其他规则或同一个表内的其他规则,但它还要通过其他表中的链,而且在那儿可能会百DROP也说不准哦。
--------------------------------------------------------------------------------
这个target是用来做目的网络地址转换的,就是重写包的目的IP地址。如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以被路由到正确的主机或网络。DNAT target是非常有用的。比如,你的Web服务器在LAN内部,而且没有可在Internet上使用的真实IP地址,那就可以使用这个 target让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的Web服务器。目的地址也可以是一个范围,这样的话,DNAT会为每一个流随机分配一个地址。因此,我们可以用这个target做某种类型地负载平衡。
Example iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10
Explanation 指定要写入IP头的地址,这也是包要被转发到的地方。上面的例子就是把所有发往地址15.45.23.67的包都转发到一段LAN使用的私有地址中,即192.168.1.1到 192.168.1.10。如前所述,在这种情况下,每个流都会被随机分配一个要转发到的地址,但同一个流总是使用同一个地址。我们也可以只指定一个IP地址作为参数,这样所有的包都被转发到同一台机子。我们还可以在地址后指定一个或一个范围的端口。比如:--to-destination 192.168.1.1:80或 --to-destination 192.168.1.1:80-100。SNAT的语法和这个target的一样,只是目的不同罢了。要注意,只有先用--protocol指定了TCP或 UDP协议,才能使用端口。
包从地址为$EXT_BOX的机子出发,去往地址为$INET_IP 的机子。
包离开$LAN_BOX,去往$INET_IP。
警告:我们刚才写的这条规则会对日志产生很大影响,这种影响应该说是很不好的。因为来自 Internet包在防火墙内先后经过了DNAT和SNAT处理,才能到达HTTP服务器(上面的例子),所以HTTP服务器就认为包是防火墙发来的,而不知道真正的源头是其他的IP。这样,当它记录服务情况时,所有访问记录的源地址都是防火墙的IP而不是真正的访问源。我们如果想根据这些记录来了解访问情况就不可能了。因此上面提供的“简单办法”并不是一个明智的选择,但它确实可以解决“能够访问”的问题,只是没有考虑到日志而已。
我想大家应该能明白这些规则只说明了数据包是如何恰当地被DNAT和SNAT的。除此之外,在 filter表中还需要其他的规则(在FORWARD链里),以允许特定的包也能经过前面写的(在POSTROUTING链和 OUTPUT链里的)规则。千万不要忘了,那些包在到达FORWARD链之前已经在PREROUTING链里被DNAT过了,也就是说它们的目的地址已被改写,在写规则时要注意这一点。