Chinaunix首页 | 论坛 | 博客
  • 博客访问: 610322
  • 博文数量: 132
  • 博客积分: 6010
  • 博客等级: 准将
  • 技术积分: 1520
  • 用 户 组: 普通用户
  • 注册时间: 2005-03-13 17:00
文章分类

全部博文(132)

文章存档

2017年(1)

2014年(1)

2011年(1)

2009年(1)

2008年(3)

2007年(1)

2006年(1)

2005年(123)

我的朋友

分类: LINUX

2005-05-23 12:09:44

非常不错的iptables帮助指南,值得学习和收藏

转from

(二)

本章将详细介绍状态机制。通读本章,你会对状态机制是如何工作的有一个全面的了解。我们用一些例子来进行说明状态机制。实践出真知嘛。


状态机制是iptables中特殊的一部分,其实它不应该叫状态机制,因为它只是一种连接跟踪机制。但是,很多人都认可状态机制这个名字。文中我也或多或或少地用这个名字来表示和连接跟踪相同的意思。这不应该引起什么混乱的。连接跟踪可以让Netfilter知道某个特定连接的状态。运行连接跟踪的防火墙称作带有状态机制的防火墙,以下简称为状态防火墙。状态防火墙比非状态防火墙要安全,因为它允许我们编写更严密的规则。

在iptables里,包是和被跟踪连接的四种不同状态有关的。它们是NEWESTABLISHEDRELATEDINVALID。后面我们会深入地讨论每一个状态。使用--state匹配操作,我们能很容易地控制 “谁或什么能发起新的会话”。

所有在内核中由Netfilter的特定框架做的连接跟踪称作conntrack(译者注:就是connection tracking 的首字母缩写)。conntrack可以作为模块安装,也可以作为内核的一部分。大部分情况下,我们想要,也需要更详细的连接跟踪,这是相比于缺省的conntrack而言。也因为此,conntrack中有许多用来处理TCP, UDP或ICMP协议的部件。这些模块从数据包中提取详细的、唯一的信息,因此能保持对每一个数据流的跟踪。这些信息也告知conntrack流当前的状态。例如,UDP流一般由他们的目的地址、源地址、目的端口和源端口唯一确定。

在以前的内核里,我们可以打开或关闭重组功能。然而,自从iptables和Netfilter,尤其是连接跟踪被引入内核,这个选项就被取消了。因为没有包的重组,连接跟踪就不能正常工作。现在重组已经整合入 conntrack,并且在conntrack启动时自动启动。不要关闭重组功能,除非你要关闭连接跟踪。

除了本地产生的包由OUTPUT链处理外,所有连接跟踪都是在PREROUTING链里进行处理的,意思就是, iptables会在PREROUTING链里从新计算所有的状态。如果我们发送一个流的初始化包,状态就会在OUTPUT链里被设置为NEW,当我们收到回应的包时,状态就会在PREROUTING链里被设置为ESTABLISHED。如果第一个包不是本地产生的,那就会在PREROUTING链里被设置为NEW状态。综上,所有状态的改变和计算都是在nat表中的PREROUTING链和OUTPUT链里完成的。


我们先来看看怎样阅读/proc/net/ip_conntrack里的conntrack记录。这些记录表示的是当前被跟踪的连接。如果安装了ip_conntrack模块,cat /proc/net/ip_conntrack 的显示类似:

tcp      6 117 SYN_SENT src=192.168.1.6 dst=192.168.1.9 sport=32775 
     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,说明这个连接还没有收到任何回应。最后,是希望接收的应答包的信息,他们的地址和端口和前面是相反的。

连接跟踪记录的信息依据IP所包含的协议不同而不同,所有相应的值都是在头文件linux/include/netfilter-ipv4/ip_conntrack*.h中定义的。IP、TCP、UDP、ICMP协议的缺省值是在linux/include/netfilter-ipv4/ip_conntrack.h里定义的。具体的值可以查看相应的协议,但我们这里用不到它们,因为它们大都只在conntrack内部使用。随着状态的改变,生存时间也会改变。

Note

最近patch-o-matic里有一个新的补丁,可以把上面提到的超时时间也作为系统变量,这样我们就能够在系统空闲时改变它们的值。以后,我们就不必为了改变这些值而重编译内核了。

这些可通过/proc/sys/net/ipv4/netfilter下的一些特殊的系统调用来改变。仔细看看/proc/sys/net/ipv4/netfilter/ip_ct_*里的变量吧。

当一个连接在两个方向上都有传输时,conntrack记录就删除[UNREPLIED]标志,然后重置。在末尾有 [ASSURED]的记录说明两个方向已没有流量。这样的记录是确定的,在连接跟踪表满时,是不会被删除的,没有[ASSURED]的记录就要被删除。连接跟踪表能容纳多少记录是被一个变量控制的,它可由内核中的ip- sysctl函数设置。默认值取决于你的内存大小,128MB可以包含8192条目录,256MB是16376条。你也可以在 /proc/sys/net/ipv4/ip_conntrack_max里查看、设置。


就象前面说的,包的状态依据IP所包含的协议不同而不同,但在内核外部,也就是用户空间里,只有4种状态:NEWESTABLISHEDRELATEDINVALID。它们主要是和状态匹配一起使用。下面就简要地介绍以下这几种状态:

Table 4-1. 数据包在用户空间的状态

State(状态)Explanation(注释)
NEWNEW说明这个包是我们看到的第一个包。意思就是,这是conntrack模块看到的某个连接第一个包,它即将被匹配了。比如,我们看到一个SYN 包,是我们所留意的连接的第一个包,就要匹配它。第一个包也可能不是SYN包,但它仍会被认为是NEW状态。这样做有时会导致一些问题,但对某些情况是有非常大的帮助的。例如,在我们想恢复某条从其他的防火墙丢失的连接时,或者某个连接已经超时,但实际上并未关闭时。
ESTABLISHEDESTABLISHED已经注意到两个方向上的数据传输,而且会继续匹配这个连接的包。处于ESTABLISHED状态的连接是非常容易理解的。只要发送并接到应答,连接就是ESTABLISHED的了。一个连接要从NEW变为ESTABLISHED,只需要接到应答包即可,不管这个包是发往防火墙的,还是要由防火墙转发的。ICMP的错误和重定向等信息包也被看作是ESTABLISHED,只要它们是我们所发出的信息的应答。
RELATEDRELATED是个比较麻烦的状态。当一个连接和某个已处于ESTABLISHED状态的连接有关系时,就被认为是RELATED的了。换句话说,一个连接要想是RELATED的,首先要有一个ESTABLISHED的连接。这个ESTABLISHED连接再产生一个主连接之外的连接,这个新的连接就是RELATED的了,当然前提是conntrack模块要能理解RELATED。ftp是个很好的例子,FTP-data 连接就是和FTP-control有RELATED的。还有其他的例子,比如,通过IRC的DCC连接。有了这个状态,ICMP应答、FTP传输、DCC等才能穿过防火墙正常工作。注意,大部分还有一些UDP协议都依赖这个机制。这些协议是很复杂的,它们把连接信息放在数据包里,并且要求这些信息能被正确理解。
INVALIDINVALID说明数据包不能被识别属于哪个连接或没有任何状态。有几个原因可以产生这种情况,比如,内存溢出,收到不知属于哪个连接的ICMP 错误信息。一般地,我们DROP这个状态的任何东西。

这些状态可以一起使用,以便匹配数据包。这可以使我们的防火墙非常强壮和有效。以前,我们经常打开1024以上的所有端口来放行应答的数据。现在,有了状态机制,就不需再这样了。因为我们可以只开放那些有应答数据的端口,其他的都可以关闭。这样就安全多了。


本节和下面的几节,我们来详细讨论这些状态,以及在TCP、UDP和ICMP这三种基本的协议里怎样操作它们。当然,也会讨论其他协议的情况。我们还是从TCP入手,因为它本身就是一个带状态的协议,并且具有很多关于iptables状态机制的详细信息。

一个TCP连接是经过三次握手协商连接信息才建立起来的。整个会话由一个SYN包开始,然后是一个 SYN/ACK包,最后是一个ACK包,此时,会话才建立成功,能够发送数据。最大的问题在于连接跟踪怎样控制这个过程。其实非常简单。

默认情况下,连接跟踪基本上对所有的连接类型做同样的操作。看看下面的图片,我们就能明白在连接的不同阶段,流是处于什么状态的。就如你看到的,连接跟踪的代码不是从用户的观点来看待TCP连接建立的流程的。连接跟踪一看到SYN包,就认为这个连接是NEW状态,一看到返回的SYN/ACK包,就认为连接是 ESTABLISHED状态。如果你仔细想想第二步,应该能理解为什么。有了这个特殊处理,NEW和ESTABLISHED包就可以发送出本地网络,且只有ESTABLISHED的连接才能有回应信息。如果把整个建立连接的过程中传输的数据包都看作NEW,那么三次握手所用的包都是NEW状态的,这样我们就不能阻塞从外部到本地网络的连接了。因为即使连接是从外向内的,但它使用的包也是NEW状态的,而且为了其他连接能正常传输,我们不得不允许NEW状态的包返回并进入防火墙。更复杂的是,针对TCP连接内核使用了很多内部状态,它们的定义在 的21-23页。但好在我们在用户空间用不到。后面我们会详细地介绍这些内容。

正如你看到的,以用户的观点来看,这是很简单的。但是,从内核的角度看这一块还有点困难的。我们来看一个例子。认真考虑一下在/proc/net/ip_conntrack里,连接的状态是如何改变的。

tcp      6 117 SYN_SENT src=192.168.1.5 dst=192.168.1.35 sport=1031 
     dport=23 [UNREPLIED] src=192.168.1.35 dst=192.168.1.5 sport=23 
     dport=1031 use=1
   

从上面的记录可以看出,SYN_SENT状态被设置了,这说明连接已经发出一个SYN包,但应答还没发送过来,这可从[UNREPLIED]标志看出。

tcp      6 57 SYN_RECV src=192.168.1.5 dst=192.168.1.35 sport=1031 
     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包也到达了防火墙。 这就意味着在连接的两方都有数据传输,因此可以认为两个方向都有相应的回应。当然,这是假设的。

tcp      6 431999 ESTABLISHED src=192.168.1.5 dst=192.168.1.35 
     sport=1031 dport=23 src=192.168.1.35 dst=192.168.1.5 
     sport=23 dport=1031 use=1
   

现在我们发出了三步握手的最后一个包,即ACK包,连接也就进入ESTABLISHED状态了。再传输几个数据包,连接就是[ASSURED]的了。

下面介绍TCP连接在关闭过程中的状态。

如上图,在发出最后一个ACK包之前,连接(指两个方向)是不会关闭的。注意,这只是针对一般的情况。连接也可以通过发送关闭,这用在拒绝一个连接的时候。在RST包发送之后,要经过预先设定的一段时间,连接才能断掉。

连接关闭后,进入TIME_WAIT状态,缺省时间是2分钟。之所以留这个时间,是为了让数据包能完全通过各种规则的检查,也是为了数据包能通过拥挤的路由器,从而到达目的地。

如果连接是被RST包重置的,就直接变为CLOSE了。这意味着在关闭之前只有10秒的默认时间。RST包是不需要确认的,它会直接关闭连接。针对TCP连接,还有其他一些状态我们没有谈到。下面给出一个完整的状态列表和超时值。

Table 4-2. 内部状态

StateTimeout value
NONE30 minutes
ESTABLISHED5 days
SYN_SENT2 minutes
SYN_RECV60 seconds
FIN_WAIT2 minutes
TIME_WAIT2 minutes
CLOSE10 seconds
CLOSE_WAIT12 hours
LAST_ACK30 seconds
LISTEN>2 minutes

这些值不是绝对的,可以随着内核的修订而变化,也可以通过/proc/sys/net/ipv4/netfilter/ip_ct_tcp_*的变量更改。这些默认值都是经过实践检验的。它们的单位是jiffies(百分之一秒),所以3000就代表30秒。

Note

注意状态机制在用户空间里的部分不会查看TCP包的标志位(也就是说TCP标志对它而言是透明的)。如果我们想让NEW状态的包通过防火墙,就要指定NEW状态,我们理解的NEW状态的意思就是指SYN包,可是iptables又不查看这些标志位。这就是问题所在。有些没有设置SYN或ACK的包,也会被看作NEW状态的。这样的包可能会被冗余防火墙用到,但对只有一个防火墙的网络是很不利的(可能会被攻击哦)。那我们怎样才能不受这样的包的影响呢?你可以使用 里的命令。还有一个办法,就是安装patch-o-matic里的tcp-window-tracking扩展功能,它可以使防火墙能根据TCP的一些标志位来进行状态跟踪。


UDP连接是无状态的,因为它没有任何的连接建立和关闭过程,而且大部分是无序列号的。以某个顺序收到的两个数据包是无法确定它们的发出顺序的。但内核仍然可以对UDP连接设置状态。我们来看看是如何跟踪UDP连接的,以及conntrack的相关记录。

从上图可以看出,以用户的角度考虑,UDP连接的建立几乎与TCP的一样。虽然conntrack信息看起来有点儿不同,但本质上是一样的。下面我们先来看看第一个UDP包发出后的conntrack记录。

udp      17 20 src=192.168.1.2 dst=192.168.1.5 sport=137 dport=1025 
     [UNREPLIED] src=192.168.1.5 dst=192.168.1.2 sport=1025 
     dport=137 use=1
   

从前两个值可知,这是一个UDP包。第一个是协议名称,第二个是协议号,第三个是此状态的生存时间,默认是30秒。接下来是包的源、目地址和端口,还有期待之中回应包的源、目地址和端口。[UNREPLIED]标记说明还未收到回应。

udp      17 170 src=192.168.1.2 dst=192.168.1.5 sport=137 
     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]状态,连接上必须要再有些流量。

udp      17 175 src=192.168.1.5 dst=195.22.79.2 sport=1025 
     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),这些包有两种状态,NEWESTABLISHED 。时间戳请求和信息请求已经废除不用了,回显请求还是常用的,比如ping命令就用的到,地址掩码请求不太常用,但是可能有时很有用并且值得使用。看看下面的图,就可以大致了解ICMP连接的NEWESTABLISHED状态了。

如图所示,主机向目标发送一个回显请求,防火墙就认为这个包处于NEW状态。目标回应一个回显应答,防火墙就认为包处于ESTABLISHED了。当回显请求被发送时,ip_conntrack里就有这样的记录了:

icmp     1 25 src=192.168.1.6 dst=192.168.1.10 type=8 code=0 
     id=33029 [UNREPLIED] src=192.168.1.10 dst=192.168.1.6 
     type=0 code=0 id=33029 use=1
   

可以看到,ICMP的记录和TCP、UDP的有点区别,协议名称、超时时间和源、目地址都一样,不同之处在于没有了端口,而新增了三个新的字段:typecodeid。字段type说明ICMP的类型。code说明ICMP的代码,这些代码在附录里有说明。id是ICMP包的ID。每个ICMP包被发送时都被分配一个ID,接受方把同样的ID 分配给应答包,这样发送方能认出是哪个请求的应答。

[UNREPLIED]的含义和前面一样,说明数的传输只发生在一个方向上,也就是说未收到应答。再往后,是应答包的源、目地址,还有相应的三个新字段,要注意的是type和code是随着应答包的不同而变化的,id和请求包的一样。

和前面一样,应答包被认为是ESTABLISHED的。然而,在应答包之后,这个ICMP 连接就不再有数据传输了。所以,一旦应答包穿过防火墙,ICMP的连接跟踪记录就被销毁了。

以上各种情况,请求被认为NEW,应答是ESTABLISHED。换句话说,就是当防火墙看到一个请求包时,就认为连接处于NEW状态,当有应答时,就是ESTABLISHED状态。

Note

注意,应答包必须符合一定的标准,连接才能被认作established的,每个传输类型都是这样。

ICMP的缺省超时是30秒,可以在/proc/sys/net/ipv4/netfilter/ip_ct_icmp_timeout中修改。这个值是比较合适的,适合于大多数情况。

ICMP的另一个非常重要的作用是,告诉UDP、TCP连接或正在努力建立的连接发生了什么,这时ICMP应答被认为是RELATED的。主机不可达和网络不可达就是这样的例子。当试图连接某台机子不成功时(可能那台机子被关上了),数据包所到达的最后一台路由器就会返回以上的ICMP信息,它们就是RELATED的,如下图:

我们发送了一个SYN包到某一地址,防火墙认为它的状态是NEW。但是,目标网络有问题不可达,路由器就会返回网络不可达的信息,这是RELATED的。连接跟踪会认出这个错误信息是哪个连接的,连接会中断,同时相应的记录删除会被删除。

当UDP连接遇到问题时,同样会有相应的ICMP信息返回,当然它们的状态也是RELATED ,如下图:

我们发送一个UDP包,当然它是NEW的。但是,目标网络被一些防火墙或路由器所禁止。我们的防火墙就会收到网络被禁止的信息。防火墙知道它是和哪个已打开的UDP连接相关的,并且把这个信息(状态是RELATED)发给它,同时,把相应的记录删除。客户机收到网络被禁止的信息,连接将被中断。


有时,conntrack机制并不知道如何处理某个特殊的协议,尤其是在它不了解这个协议或不知道协议如何工作时,比如,NETBLT,MUX还有EGP。这种情况下,conntrack使用缺省的操作。这种操作很象对UDP连接的操作,就是第一个包被认作NEW,其后的应答包等等数据都是 ESTABLISHED

使用缺省操作的包的超时值都是一样的,600秒,也就是10分钟。当然,这个值可以通过/proc/sys/net/ipv4/netfilter/ip_ct_generic_timeout更改,以便适应你的通信量,尤其是在耗时较多、流量巨大的情况下,比如使用卫星等。


有些协议比其他协议更复杂,这里复杂的意思是指连接跟踪机制很难正确地跟踪它们,比如,ICQ、IRC 和FTP,它们都在数据包的数据域里携带某些信息,这些信息用于建立其他的连接。因此,需要一些特殊的 helper来完成工作。

下面以FTP作为例子。FTP协议先建立一个单独的连接——FTP控制会话。我们通过这个连接发布命令,其他的端口就会打开以便传输和这个命令相关的数据。这些连接的建立方法有两种:主动模式和被动模式。先看看主动模式,FTP客户端发送端口和IP地址信息给服务器端,然后,客户端打开这个端口,服务器端从它自己的20端口(FTP-Data端口号)建立与这个端口的连接,接着就可以使用这个连接发送数据了。

问题在于防火墙不知道这些额外的连接(相对于控制会话而言),因为这些连接在建立时的磋商信息都在协议数据包的数据域内,而不是在可分析的协议头里。因此,防火墙就不知道是不是该放这些从服务器到客户机的连接过关。

解决的办法是为连接跟踪模块增加一个特殊的helper,以便能检测到那些信息。这样,那些从FTP服务器到客户机的连接就可以被跟踪了,状态是RELATED,过程如下图所示:

被动FTP工作方式下,data连接的建立过程和主动FTP的相反。客户机告诉服务器需要某些数据,服务器就把地址和端口发回给客户机,客户机据此建立连接接受数据。如果FTP服务器在防火墙后面,或你对用户限制的比较严格,只允许他们访问HTTP和FTP,而封闭了其他所有端口,为了让在Internet是的客户机能访问到FTP,也需要增加上面提到的helper。下面是被动模式下data连接的建立过程:

有些conntrack helper已经包含在内核中,在写这篇文章时,FTP和IRC已有了相应的conntrack helper。如果在内核里没有你想要的helper,可以到iptables用户空间的patch-o-matic目录中看看,那里有很多的helper,比如针对ntalk或H.323协议的等等。如果没找到,还有几个选择:可以查查iptables的 CVS,或者联系Netfilter-devel问问有没有你要的。还不行的话,只有你自己写了,我可以给你介绍一篇好文章,,连接放在附录里。

Conntrack helper即可以被静态地编译进内核,也可以作为模块,但要用下面的命令装载:

modprobe ip_conntrack_*
   

注意连接跟踪并不处理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-saveiptables-restore,它们把规则存入一个与标准脚本代码只有细微查别的特殊格式的文件中,或从中恢复规则。


使用iptables-saveiptables-restore的一个最重要的原因是,它们能在相当程度上提高装载、保存规则的速度。使用脚本更改规则的问题是,改动每个规则都要调运命令iptables,而每一次调用iptables,它首先要把Netfilter内核空间中的整个规则集都提取出来,然后再插入或附加,或做其他的改动,最后,再把新的规则集从它的内存空间插入到内核空间中。这会花费很多时间。

为了解决这个问题,可以使用命令iptables-saverestore iptables-save用来把规则集保存到一个特殊格式的文本文件里,而iptables-restore是用来把这个文件重新装入内核空间的。这两个命令最好的地方在于一次调用就可以装载和保存规则集,而不象脚本中每个规则都要调用一次iptables。 iptables-save运行一次就可以把整个规则集从内核里提取出来,并保存到文件里,而iptables-restore每次装入一个规则表。换句话说,对于一个很大的规则集,如果用脚本来设置,那这些规则就会反反复复地被卸载、安装很多次,而我们现在可以把整个规则集一次就保存下来,安装时则是一次一个表,这可是节省了大量的时间。

如果你的工作对象是一组巨大的规则,这两个工具是明显的选择。当然,它们也有不足之处,下面的章节会详细说明。


iptables-restore能替代所有的脚本来设置规则吗?不,到现在为止不行,很可能永远都不行。iptables-restore的主要不足是不能用来做复杂的规则集。例如,我们想在计算机启动时获取连接的动态分配的IP地址,然后用在脚本里。这一点,用iptables-restore来实现,或多或少是不可能的。

一个可能的解决办法是写一个小脚本来获取那个IP地址,并在iptables-restore调用的配置文件中设置相应的关键字,然后用获取的IP值替换关键字。你可以把更改后的配置文件存到一个临时文件中,再由 iptables-restore使用它。然而这会带来很多问题,并且你不能用iptables-save来保存带关键字的配置文件。此法较笨。

另一个办法是先装入iptables-restore文件,再运行一个特定的脚本把动态的规则装入。其实,这也是较笨的方法。iptables-restore并不适合于使用动态IP的场合,如果你想在配置文件里使用选项来实现不同的要求,iptables-restore也不适用。

iptables-restore和iptables-save还有一个不足,就是功能不够齐全。因为使用的人不是太多,所以发现这个问题的人也不多,还有就是一些match和target被引用时考虑不细致,这可能会出现我们预期之外的行为。 尽管存在这些问题,我还是强烈建议你使用它们,因为它们对于大部分规则集工作的还是很好的,只要在规则中别包含那些新的都不知如何使用的match和target。


iptables-save用来把当前的规则存入一个文件里以备iptables-restore使用。它的使用很简单,只有两个参数:

iptables-save [-c] [-t table]

参数-c的作用是保存包和字节计数器的值。这可以使我们在重启防火墙后不丢失对包和字节的统计。带-c参数的iptables-save命令使重启防火墙而不中断统计记数程序成为可能。这个参数默认是不使用的。

参数-t指定要保存的表,默认是保存所有的表。下面给出未装载任何规则的情况下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

我们来解释一下这个输出格式。#后面的是注释。表都以*开始,例如*mangle。每个表都包含链和规则,链的详细说明是: [:]。例如,链的名字是 PREROUTING,策略是ACCEPT,然后是包记数器和字节计数器,这两个计数器和iptables -L -v输出中用到的计数器一样。每个表的描述都以关键字COMMIT结束,它说明在这一点,就要把规则装入内核了。

上面的例子是最基本的,我想用一个简短的例子说明会更好,其中包含一个非常小的规则集。iptables-save的输出如下:

# 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

每个命令前都有包和字节计数器,这说明使用了-c参数。除了有计数器,其他的都和普通的脚本一样。现在的问题是怎么把输出保存到文件中。非常简单,既然使用linux,你应该早就知道了,用重定向啊:

iptables-save -c > /etc/iptables-save

这就会把规则集保存到/etc/iptables-save中,而且还有计数器。


iptables-restore用来装载由iptables-save保存的规则集。不幸的是,它只能从标准输入接受输入,而不能从文件接受。下面是它的事方法:

iptables-restore [-c] [-n]

参数-c要求装入包和字节计数器。如果你用iptables-save保存了计数器,现在想重新装入,就必须用这个参数。它的另一种较长的形式是--counters

参数-n告诉iptables-restore不要覆盖已有的表或表内的规则。默认情况是清除所有已存的规则。这个参数的长形式是--noflush

iptables-restore装载规则有好几种方法,我们来看看最简单、最一般的:

这样规则集应该正确地装入内核并正常工作了。如果有问题,你就要除措了。


本章将详细地讨论如何构件你自己的规则。规则就是指向标,在一条链上,对不同的连接和数据包阻塞或允许它们去向何处。插入链的每一行都是一条规则。我们也会讨论基本的matche及其用法,还有各种各样的target,以及如何建立我们自己的target(比如,一个新的子链)。


我们已经解释了什么是规则,在内核看来,规则就是决定如何处理一个包的语句。如果一个包符合所有的条件(就是符合matche语句),我们就运行target或jump指令。书写规则的语法格式是:

iptables [-t table] command [match] [target/jump]

对于这个句法没什么可说的,但注意target指令必须在最后。为了易读,我们一般用这种语法。总之,你将见到的大部分规则都是按这种语法写的。因此,如果你看到别人写的规则,你很可能会发现用的也是这种语法,当然就很容易理解那些规则了。

如果你不想用标准的表,就要在[table]处指定表名。一般情况下没有必要指定使用的表,因为iptables 默认使用filter表来执行所有的命令。也没有必要非得在这里指定表名,实际上几乎可在规则的任何地方。当然,把表名在开始处已经是约定俗成的标准。

尽管命令总是放在开头,或者是直接放在表名后面,我们也要考虑考虑到底放在哪儿易读。command告诉程序该做什么,比如:插入一个规则,还是在链的末尾增加一个规则,还是删除一个规则,下面会仔细地介绍。

match细致地描述了包的某个特点,以使这个包区别于其它所有的包。在这里,我们可以指定包的来源IP 地址,网络接口,端口,协议类型,或者其他什么。下面我们将会看到许多不同的match。

最后是数据包的目标所在。若数据包符合所有的match,内核就用target来处理它,或者说把包发往 target。比如,我们可以让内核把包发送到当前表中的其他链(可能是我们自己建立的),或者只是丢弃这个包而没有什么处理,或者向发送者返回某个特殊的应答。下面有详细的讨论。


选项-t用来指定使用哪个表,它可以是下面介绍的表中的任何一个,默认的是 filter表。注意,下面的介绍只是章节的摘要。

Table 6-1. Tables

Table (表名)Explanation (注释)
natnat表的主要用处是网络地址转换,即Network Address Translation,缩写为NAT。做过NAT操作的数据包的地址就被改变了,当然这种改变是根据我们的规则进行的。属于一个流的包只会经过这个表一次。如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自动地被做相同的操作。也就是说,余下的包不会再通过这个表,一个一个的被NAT,而是自动地完成。这就是我们为什么不应该在这个表中做任何过滤的主要原因,对这一点,后面会有更加详细的讨论。PREROUTING 链的作用是在包刚刚到达防火墙时改变它的目的地址,如果需要的话。OUTPUT链改变本地产生的包的目的地址。POSTROUTING链在包就要离开防火墙之前改变其源地址。
mangle这个表主要用来mangle数据包。我们可以改变不同的包及包头的内容,比如 TTLTOSMARK。注意MARK并没有真正地改动数据包,它只是在内核空间为包设了一个标记。防火墙内的其他的规则或程序(如tc)可以使用这种标记对包进行过滤或高级路由。这个表有五个内建的链: PREROUTINGPOSTROUTING OUTPUTINPUT FORWARDPREROUTING在包进入防火墙之后、路由判断之前改变包,POSTROUTING是在所有路由判断之后。 OUTPUT在确定包的目的之前更改数据包。INPUT在包被路由到本地之后,但在用户空间的程序看到它之前改变包。FORWARD在最初的路由判断之后、最后一次更改包的目的之前mangle包。注意,mangle表不能做任何NAT,它只是改变数据包的 TTLTOSMARK,而不是其源目地址。NAT是在nat表中操作的。
filterfilter表是专门过滤包的,内建三个链,可以毫无问题地对包进行DROPLOGACCEPTREJECT等操作。FORWARD 链过滤所有不是本地产生的并且目的地不是本地(所谓本地就是防火墙了)的包,而 INPUT恰恰针对那些目的地是本地的包。OUTPUT 是用来过滤所有本地生成的包的。

上面介绍了三个不同的表的最基本的内容。你应该知道它们的使用目的完全不同,还要清楚每一条链的使用。如果你不了解,就可能会在防火墙上留下漏洞,给人以可乘之机。在章节 中,我们已详细地讨论了这些必备的的表和链。如果你没有完全理解包是怎样通过这些表、链的话,我建议你回过头去再仔细看看。


在这一节里,我们将要介绍所有的command以及它们的用途。command指定iptables 对我们提交的规则要做什么样的操作。这些操作可能是在某个表里增加或删除一些东西,或做点儿其他什么。以下是iptables可用的command(要注意,如不做说明,默认表的是 filter表。):

Table 6-2. Commands

Command-A, --append
Exampleiptables -A INPUT ...
Explanation在所选择的链末添加规则。当源地址或目的地址是以名字而不是ip地址的形式出现时,若这些名字可以被解析为多个地址,则这条规则会和所有可用的地址结合。
Command-D, --delete
Exampleiptables -D INPUT --dport 80 -j DROPiptables -D INPUT 1
Explanation从所选链中删除规则。有两种方法指定要删除的规则:一是把规则完完整整地写出来,再就是指定规则在所选链中的序号(每条链的规则都各自从1被编号)。
Command-R, --replace
Exampleiptables -R INPUT 1 -s 192.168.0.1 -j DROP
Explanation在所选中的链里指定的行上(每条链的规则都各自从1被编号)替换规则。它主要的用处是试验不同的规则。当源地址或目的地址是以名字而不是ip地址的形式出现时,若这些名字可以被解析为多个地址,则这条command会失败。
Command-I, --insert
Exampleiptables -I INPUT 1 --dport 80 -j ACCEPT
Explanation根据给出的规则序号向所选链中插入规则。如果序号为1,规则会被插入链的头部,其实默认序号就是1。
Command-L, --list
Exampleiptables -L INPUT
Explanation显示所选链的所有规则。如果没有指定链,则显示指定表中的所有链。如果什么都没有指定,就显示默认表所有的链。精确输出受其它参数影响,如-n -v等参数,下面会介绍。
Command-F, --flush
Exampleiptables -F INPUT
Explanation清空所选的链。如果没有指定链,则清空指定表中的所有链。如果什么都没有指定,就清空默认表所有的链。当然,也可以一条一条地删,但用这个command会快些。
Command-Z, --zero
Exampleiptables -Z INPUT
Explanation把指定链(如未指定,则认为是所有链)的所有计数器归零。
Command-N, --new-chain
Exampleiptables -N allowed
Explanation根据用户指定的名字建立新的链。上面的例子建立了一个名为allowed的链。注意,所用的名字不能和已有的链、target同名。
Command-X, --delete-chain
Exampleiptables -X allowed
Explanation删除指定的用户自定义链。这个链必须没有被引用,如果被引用,在删除之前你必须删除或者替换与之有关的规则。如果没有给出参数,这条命令将会删除默认表所有非内建的链。
Command-P, --policy
Exampleiptables -P INPUT DROP
Explanation为链设置默认的target(可用的是DROP ACCEPT,如果还有其它的可用,请告诉我),这个target称作策略。所有不符合规则的包都被强制使用这个策略。只有内建的链才可以使用规则。但内建的链和用户自定义链都不能被作为策略使用,也就是说不能象这样使用:iptables -P INPUT allowed(或者是内建的链)。
Command-E, --rename-chain
Exampleiptables -E allowed disallowed
Explanation对自定义的链进行重命名,原来的名字在前,新名字在后。如上,就是把allowed改为disallowed。这仅仅是改变链的名字,对整个表的结构、工作没有任何影响。

在使用iptables时,如果必须的参数没有输入就按了回车,那么它就会给出一些提示信息:告诉你需要哪些参数等等。iptables的选项-v用来显示iptables的版本,-h给出语法的简短说明。。下面将要介绍的就是部分选项,还有它们的作用。

Table 6-3. Options

Option(选项)-v, --verbose(详细的)
可用此选项的命令--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 withAll
Explanation此选项告诉iptables探测并装载要使用的模块。这是非常有用的一个选项,万一modprobe命令不在搜索路径中,就要用到了。有了这个选项,在装载模块时,即使有一个需要用到的模块没装载上,iptables也知道要去搜索。

这一节,我们会详细讨论一些matche,我把它们归为五类。第一类是generic matches(通用的匹配),适用于所有的规则;第二类是TCP matches,顾名思义,这只能用于TCP包;第三类是UDP matches,当然它只能用在UDP包上了;第四类是ICMP matches ,针对ICMP包的;第五类比较特殊,针对的是状态(state),所有者(owner)和访问的频率限制(limit)等,它们已经被分到更多的小类当中,尽管它们并不是完全不同的。我希望这是一种大家都容易理解的分类。


无论我们使用的是何种协议,也不管我们又装入了匹配的何种扩展,通用匹配都使可用的。也就是说,它们可以直接使用,而不需要什么前提条件,在后面你会看到,有很多匹配操作是需要其他的匹配作为前提的。

Table 6-4. Generic matches

Match-p, --protocol
Exampleiptables -A INPUT -p tcp
Explanation匹配指定的协议。指定协议的形式有以下几种:

1、名字,不分大小写,但必须是在中定义的。

2、可以使用它们相应的整数值。例如,ICMP的值是1,TCP是6,UDP是17。

3、缺省设置,ALL,相应数值是0,但要注意这只代表匹配TCP、UDP、ICMP,而不是中定义的所有协议。

4、可以是协议列表,以英文逗号为分隔符,如:udp,tcp

5、可以在协议前加英文的感叹号表示取反,注意有空格,如: --protocol ! tcp 表示非tcp协议,也就是UDP和ICMP。可以看出这个取反的范围只是TCP、UDP和ICMP。

Match-s, --src, --source
Exampleiptables -A INPUT -s 192.168.1.1
Explanation以IP源地址匹配包。地址的形式如下:

1、单个地址,如192.168.1.1,也可写成 192.168.1.1/255.255.255.255192.168.1.1/32

2、网络,如192.168.0.0/24,或 192.168.0.0/255.255.255.0

3、在地址前加英文感叹号表示取反,注意空格,如--source ! 192.168.0.0/24 表示除此地址外的所有地址

4、缺省是所有地址

Match-d, --dst, --destination
Exampleiptables -A INPUT -d 192.168.1.1
Explanation以IP目的地址匹配包。地址的形式和 -- source完全一样。
Match-i, --in-interface
Exampleiptables -A INPUT -i eth0
Explanation以包进入本地所使用的网络接口来匹配包。要注意这个匹配操作只能用于INPUTFORWARD PREROUTING这三个链,用在其他任何地方都会提示错误信息。指定接口有一下方法:

1、指定接口名称,如:eth0、ppp0等

2、使用通配符,即英文加号,它代表字符数字串。若直接用一个加号,即iptables -A INPUT -i +表示匹配所有的包,而不考虑使用哪个接口。这也是不指定接口的默认行为。通配符还可以放在某一类接口的后面,如:eth+表示所有Ethernet接口,也就是说,匹配所有从Ethernet接口进入的包。

3、在接口前加英文感叹号表示取反,注意空格,如:-i ! eth0意思是匹配来自除eth0外的所有包。

Match-o, --out-interface
Exampleiptables -A FORWARD -o eth0
Explanation以包离开本地所使用的网络接口来匹配包。使用的范围和指定接口的方法与--in-interface完全一样。
Match-f, --fragment
Exampleiptables -A INPUT -f
Explanation用来匹配一个被分片的包的第二片或及以后的部分。因为它们不包含源或目的地址,或ICMP类型等信息,其他规则无法匹配到它,所以才有这个匹配操作。要注意碎片攻击哦。这个操作也可以加英文感叹号表示取反,但要注意位置,如:! -f 。取反时,表示只能匹配到没有分片的包或者是被分片的包的第一个碎片,其后的片都不行。现在内核有完善的碎片重组功能,可以防止碎片攻击,所以不必使用取反的功能来防止碎片通过。如果你使用连接跟踪,是不会看到任何碎片的,因为在它们到达任何链之前就被处理过了。

这种匹配操作是自动地或隐含地装载入内核的。例如我们使用--protocol tcp 时,不需再装入任何东西就可以匹配只有IP包才有的一些特点。现在有三种隐含的匹配针对三种不同的协议,即TCP matchesUDP matches ICMP matches。它们分别包括一套只适用于相应协议的判别标准。相对于隐含匹配的是显式匹配,它们必须使用-m--match被明确地装载,而不能是自动地或隐含地,下一节会介绍到。


TCP matches只能匹配TCP包或流的细节,它们必须有--protocol tcp作为前提条件。

Table 6-5. TCP matches

Match--sport, --source-port
Exampleiptables -A INPUT -p tcp --sport 22
Explanation基于TCP包的源端口来匹配包,端口的指定形式如下:

1、不指定此项,则暗示所有端口。

2、使用服务名或端口号,但名字必须是在 中定义的,因为iptables从这个文件里查找相应的端口号。从这可以看出,使用端口号会使规则装入快一点儿,当然,可读性就差些了。但是如果你想写一个包含200条或更多规则的规则集,那你还是老老实实地用端口号吧,时间是主要因素(在一台稍微慢点儿地机子上,这最多会有10秒地不同,但要是1000条、10000 条呢)。

3、可以使用连续的端口,如:--source-port 22:80这表示从22到80的所有端口,包括22和80。如果两个号的顺序反了也没关系,如:--source-port 80:22这和 --source-port 22:80的效果一样。

4、可以省略第一个号,默认第一个是0,如:--source-port :80表示从0到80的所有端口。

5、也可以省略第二个号,默认是65535,如:--source-port 22:表示从22到 65535的所有端口

6、在端口号前加英文感叹号表示取反,注意空格,如:--source-port ! 22表示除22号之外的所有端口;--source-port ! 22:80表示从22到80(包括22和80)之外的所有端口。

注意:这个匹配操作不能识别不连续的端口列表,如:--source-port ! 22, 36, 80 这样的操作是由后面将要介绍的多端口匹配扩展来完成的。

Match--dport, --destination-port
Exampleiptables -A INPUT -p tcp --dport 22
Explanation基于TCP包的目的端口来匹配包,端口的指定形式和--sport完全一样。
Match--tcp-flags
Example
Explanation匹配指定的TCP标记。有两个参数,它们都是列表,列表内部用英文的逗号作分隔符,这两个列表之间用空格分开。第一个参数指定我们要检查的标记(作用就象掩码),第二个参数指定“在第一个列表中出现过的且必须被设为1(即状态是打开的)的”标记(第一个列表中其他的标记必须置0)。也就是说,第一个参数提供检查范围,第二个参数提供被设置的条件(就是哪些位置1)。这个匹配操作可以识别以下标记:SYN ACKFINRST URGPSH。另外还有两个词也可使用,就是ALL和NONE。顾名思义,ALL是指选定所有的标记,NONE是指未选定任何标记。这个匹配也可在参数前加英文的感叹号表示取反。例如:

1、iptables -p tcp --tcp-flags SYN,FIN,ACK SYN表示匹配那些SYN标记被设置而FIN和ACK标记没有设置的包,注意各标记之间只有一个逗号而没有空格。

2、--tcp-flags ALL NONE匹配所有标记都未置1的包。

3、iptables -p tcp --tcp-flags ! SYN,FIN,ACK SYN表示匹配那些FIN和ACK标记被设置而SYN标记没有设置的包,注意和例1比较一下。

Match--syn
Exampleiptables -p tcp --syn
Explanation这个匹配或多或少算是ipchains时代的遗留物,之所以还保留它,是为了向后兼容,也是为了方便规则在iptables和ipchains间的转换。它匹配那些SYN标记被设置而 ACK和RST标记没有设置的包,这和iptables -p tcp --tcp-flags SYN,RST,ACK SYN 的作用毫无二样。这样的包主要用在TCP连接初始化时发出请求。如果你阻止了这样的包,也就阻止了所有由外向内的连接企图,这在一定程度上防止了一些攻击。但外出的连接不受影响,恰恰现在有很多攻击就利用这一点。比如有些攻击黑掉服务器之后安装会一些软件,它们能够利用已存的连接到达你的机子,而不要再新开一个端口。这个匹配也可用英文感叹号取反,如:! --syn用来匹配那些 RSTACK被置位的包,换句话说,就是状态为已建立的连接的包。
Match--tcp-option
Exampleiptables -p tcp --tcp-option 16
Explanation根据匹配包。TCP选项是TCP头中的特殊部分,有三个不同的部分。第一个8位组表示选项的类型,第二个8位组表示选项的长度(这个长度是整个选项的长度,但不包含填充部分所占的字节,而且要注意不是每个TCP选项都有这一部分的),第三部分当然就是选项的内容了。为了适应标准,我们不必执行所有的选项,但我们可以查看选项的类型,如果不是我们所支持的,那就只是看看长度然后跳过数据部分。这个操作是根据选项的十进制值来匹配的,它也可以用英文感叹号取反。所有的选项都可在里找到。

UDP matches是在指定--protocol UDP时自动装入的。UDP是一种无连接协议,所以在它打开、关闭连接以及在发送数据时没有多少标记要设置,它也不需要任何类型的确认。数据丢失了,就丢失了(不会发送ICMP错误信息的)。这就说明UDP matches要比TCP matches少多了。即使UDP和ICMP是无连接协议,状态机制也可以很好的工作,就象在TCP上一样,这在前面讨论过。

Table 6-6. UDP matches

Match--sport, --source-port
Exampleiptables -A INPUT -p udp --sport 53
Explanation基于UDP包的源端口来匹配包,端口的指定形式和TCP matches中的--sport完全一样。
Match--dport, --destination-port
Exampleiptables -A INPUT -p udp --dport 53
Explanation基于UDP包的目的端口来匹配包,端口的指定形式和TCP matches中的--sport完全一样。

ICMP协议也是无连接协议,ICMP包更是短命鬼,比UDP的还短。ICMP协议不是IP协议的下属协议,而是它的辅助者,其主要作用是报告错误和连接控制。ICMP包的头和IP的很相似,但又有很多不同。这个协议最主要的特点是它有很多类型,以应对不同的情况。比如,我们想访问一个无法访问的地址,就会收到一个ICMP host unreachable信息,它的意思是主机无法到达。在附录里有完整的ICMP类型列表。虽然有这么多类型,但只有一个 ICMP matche,这就足够对付它们了。这个matche是在指定--protocol ICMP时自动装入的。注意所有的通用匹配都可以使用,这样我们就可以匹配ICMP包的源、目地址。

Table 6-7. ICMP matches

Match--icmp-type
管理员在2009年8月13日编辑了该文章文章。 -->
阅读(1877) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~