什么是状态检测

每个网络连接包括以下信息:源地址、目的地址、源端口和目的端口,叫作套接字对(socket pairs);协议类型、连接状态(TCP协议)和超时时间等。防火墙把这些信息叫作状态(stateful),能够检测每个连接状态的防火墙叫作状态包过滤防火墙。它除了能够完成简单包过滤防火墙的包过滤工作外,还在自己的内存中维护一个跟踪连接状态的表,比简单包过滤防火墙具有更大的安全性。

  --state state

   这里,state是一个用逗号分割的列表,表示要匹配的连接状态。有效的状态选项包括:INVAILD,表示分组对应的连接是未知的;ESTABLISHED,表示分组对应的连接已经进行了双向的分组传输,也就是说连接已经建立;NEW,表示这个分组需要发起一个连接,或者说,分组对应的连接在两个方向上都没有进行过分组传输;RELATED,表示分组要发起一个新的连接,但是这个连接和一个现有的连接有关,例如:FTP的数据传输连接和控制连接之间就是RELATED关系。


ICMP
在iptables看来,只有四种ICMP分组,这些分组类型可以被归为NEW、ESTABLISHED两类:
ECHO请求(ping,8)和ECHO应答(pong,0)。
时间戳请求(13)和应答(14)。
信息请求(15)和应答(16)。
地址掩码请求(17)和应答(18)。
这些ICMP分组类型中,请求分组属于NEW,应答分组属于ESTABLISHED。而其它类型的ICMP分组不基于请求/应答方式,一律被归入RELATED。

我们先看一个简单的例子:
iptables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED, RELATED -j ACCEPT
iptables -A INPUT -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT

这链条规则进行如下的过滤:

一个ICMP echo请求是一个NEW连接。因此,允许ICMP echo请求通过OUTPUT链。
当对应的应答返回,此时连接的状态是ESTABLISED,因此允许通过INPUT链。而INPUT链没有NEW状态,因此不允许echo请求通过INPUT链。也就是说,这两条规则允许内部主机ping外部主机,而不允许外部主机ping内部主机。
一个重定向ICMP(5)分组不是基于请求/应答方式的,因此属于RELATED。INPUT和OUTPUT链都允许RELATED状态的连接,因此重定向(5)分组可以通过INPUT和OUTPUT链。


3.FTP协议的状态检测

上面,我们比较详细地介绍了iptables的态检测机制。现在,我们以FTP状态检测为例介绍如何使用iptables进行连接状态检测。

首先,你需要加载ip_conntrack_ftp模块。使用如下规则就可以允许建立FTP控制连接(这里没有考虑IMCP问题):
iptables -A INPUT -p tcp --sport 21 -m state --state ESTABLESED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISED -j ACCEPT

除了控制连接之外,FTP协议还需要一个数据通道,不过,数据连接可以通过主动和被动两种模式建立,我们需要分别讨论。

3.1.主动模式

在主动模式下,客户程序在控制通道上,使用PORT命令告诉FTP服务器自己这边的数据传输端口,然后FTP从20端口向这个端口发起一个连接。连接建立后,服务器端和客户端就可以使用这个连接传输数据了,例如:传诵的文件、ls等命令的结果等。因此,在主动模式下FTP数据传输通道是反向建立的,它从FTP服务器端向客户端发起。

在主动模式下,客户端使用的数据传输端口是不固定的,因此我们需要在规则中使用端口范围。由于客户端使用的端口都是大于1024的,这并不会降低系统的安全性。

在iptables中,有一个专门跟踪FTP状态的模块--ip_conntrack_ftp。这个模块能够识别出PORT命令,并从中提取端口号。这样,FTP数据传输连接就被归入RELATED状态,它和向外的FTP控制连接相关,因此我们不需要在INPUT链中使用NEW状态。下面的规则可以实现我们的意图:
iptables -A INPUT -p tcp --sport 20 -m state --state ESTABLISED,RELATED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 20 -m state --state ESTABLISED -j ACCEPT


3.2.被动模式
和主动模式相反,在被动模式下,指定连接端口的PORT命令是服务器端发出的。FTP服务器通过PORT命令告诉客户端自己使用的FTP数据传输端口,然后等待客户端建立数据传输连接。在被动模式下,建立数据传输连接的方向和建立控制连接的方向是相同的。因此,被动模式具有比主动模式更好的安全性。

由于ip_conntrack_ftp模块能够从PORT命令提取端口,因此我们在OUTPUT链中也不必使用NEW状态,下面的规则可以实现对被动模式下的FTP状态检测:
iptables -A INPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT

综合以上的分析,我们可以得到FTP连接的状态检测规则,对于主动模式的FTP,需要下面的iptables规则:
iptables -A INPUT -p tcp --sport 21 -m state --state ESTABLESED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISED -j ACCEPT
iptables -A INPUT -p tcp --sport 20 -m state --state ESTABLISED,RELATED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 20 -m state --state ESTABLISED -j ACCEPT

对于被动模式的FTP连接,需要使用如下iptables规则
iptables -A INPUT -p tcp --sport 21 -m state --state ESTABLESED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISED -j ACCEPT
iptables -A INPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT