Iptables 指南 1.1.19 (2)

上面,我简要介绍了很多选项,但这只是内核2.4.9中的。要想看看更多的选项,建议你去Netfilter 看看patch-o-matic。在那里,有其他的一些选项。POM可能会被加到内核里,当然现在还没有。这有很多原因,比如,还不稳定,Linus Torvalds没打算或没坚持要把这些补丁放入主流的内核,因为它们还在实验。

把以下选项编译进内核或编译成模块,rc.firewall.txt才能使用。

*

CONFIG_PACKET
*

CONFIG_NETFILTER
*

CONFIG_IP_NF_CONNTRACK
*

CONFIG_IP_NF_FTP
*

CONFIG_IP_NF_IRC
*

CONFIG_IP_NF_IPTABLES
*

CONFIG_IP_NF_FILTER
*

CONFIG_IP_NF_NAT
*

CONFIG_IP_NF_MATCH_STATE
*

CONFIG_IP_NF_TARGET_LOG
*

CONFIG_IP_NF_MATCH_LIMIT
*

CONFIG_IP_NF_TARGET_MASQUERADE

以上是为保证 rc.firewall.txt正常工作而需要的最少的选项。其他脚本需要的选项,在相应的章节里都有说明。目前,我们只需注意要学习的这个脚本。
2.3. 编译与安装

下面,我们来看看如何编译iptables。iptables很多组件的配置、编译是与内核的配置、编译相关联的,了解这一点是很重要的。某些 Linux产品预装了iptables,比如Red Hat,但是它的缺省设置是不启用iptables的。后文我们会介绍如何启用它,也会介绍一下其他 Linux产品里的iptables情况。
2.3.1. 编译

首先要解压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文件有很多对编译、运行有用的信息。

这一步,你将配置、安装一些额外的模块,也可以为内核增加一些选项。我们这里只是检查、安装一些未被纳入内核的标准的补丁。当然,更多的在实验阶段的补丁,仅在进行其他某些操作时才会用到。

Note

有一些补丁仅仅处在实验阶段,把它们也安装上不是一个好主意。这一步,你会遇到很多十分有趣的匹配和对数据包的操作,但它们还正在实验。

为了完成这一步,我们要在iptables的目录内用到如下一些命令:

make pending-patches KERNEL_DIR=/usr/src/linux/

变量KERNEL_DIR指向内核原码的真实路径。一般情况下,都是/usr/src/linux/ ,但也会不一样,这要看你所用的Linux产品了。

Note

总之,只有某些补丁会被询问是否加入内核,而Netfilter的开发者们有大量的补丁或附件想要加入内核,但还要再实验一阵子才能做到。如果你想安装这些东西,就用下面的命令:

make most-of-pom KERNEL_DIR=/usr/src/linux/

这个命令会安装部分patch-o-matic(netfilter世界对补丁的称呼),忽略掉的是非常极端的那一部分,它们可能会对内核造成严重的破坏。你要知道这个命令的作用,要了解它们对内核原码的影响,好在在你选用之前,会有所提示。下面的命令可以安装所有的patch-o-matic(译者注:一定要小心哦)。

make patch-o-matic KERNEL_DIR=/usr/src/linux/

要仔细的读读每一个补丁的帮助文件,因为有些patch-o-matic会损坏内核,而有些对其他补丁有破坏作用。

Note

你要是不打算用patch-o-matic修补内核,以上的命令都用不着,它们不是必需的。不过,你可以用这些命令来看看有什么有趣的玩意儿,这不会影响任何东西。

安装好patch-o-matic,现在应该重新编译内核了,因为其中增加了一些补丁。但别忘了重新配置内核,现有的配置文件里可没有你增加的补丁的信息。当然,你也可以先编译iptables , 再来编译内核。

接下来就该编译iptables了,用下面这个简单的命令:

make KERNEL_DIR=/usr/src/linux/

iptables应该编译好了,如果不行,好好考虑考虑问题在哪儿,要么订阅 Netfilter mailing list,那里可能有人能帮助你。

一切顺利的话,我们该安装iptables了,这几乎不会有什么问题的。我们用下面的命令来完成这一步:

make install KERNEL_DIR=/usr/src/linux/

现在大功告成了。如果你在前面没有重新编译、安装内核,现在就要做了,不然,你还是不能使用更新后的iptables。好好看看INSTALL吧,那里面有详细的安装信息。
2.3.2. 在Red Hat 7.1上安装

Red Hat 7.1使用2.4.x的内核,支持Netfilter和iptables。Red Hat包含了所有基本的程序和需要的配置文件,但缺省使用的是B class=COMMAND>ipchains。“iptables为什么不能用”是最常见的问题,下面就让我们就来说说如何关闭ipchains 而起用iptables 。

Note

Red Hat 7.1预装的iptables版本有些老了,在使用之前,你可能想装个新的,再自己编译一下内核。

我们先要关闭ipchains,并且不想再让它运行起来,做到这一点,要更改目录/etc/rc.d/下的一些文件名。用以下命令完成:

chkconfig --level 0123456 ipchains off

这个命令把所有指向/etc/rc.d/init.d/ipchains的软连接改名为 K92ipchains。以S开头表示,在启动时会由初始化脚本运行此脚本。改为K开头后,就表示终止服务,或以后在启动时不再运行。这样, ipchains以后不会再开机就运行了。

要想终止正在运行的服务,要用service命令。终止ipchains 服务的命令是:

service ipchains stop

现在,我们可以启动iptables服务了。首先,要确定在哪个运行层运行,一般是 2,3和5,这些层有不同的用处:

*

2. 不带NFS的多用户环境,和层3的区别仅在于不带网络支持。
*

3. 多用户环境,就是我们一般事用的层。
*

5. X11,图形界面。

用下面的命令以使iptables能在这些层运行:

chkconfig --level 235 iptables on

你也可以使用这个命令使iptables能在其他层运行。但没这个必要,因为层1是单用户模式,一般用在维修上;层4保留不用;层6用来关闭计算机。

启动iptables用:

service iptables start

在脚本iptables里还没有定义规则。在Red Hat 7.1中添加规则的方法有二:第一个方法是编辑/etc/rc.d/init.d/iptables,要注意在用RPM升级iptables时,已有的规则可能会被删除。另一个方法是先装载规则,然后用命令iptables-save把规则保存到文件中,再由目录rc.d下的脚本(/etc/rc.d/init.d/iptables)自动装载。

我们先来说明如何利用“剪切粘贴大法”设置/etc/rc.d/init.d/iptables。为了能在计算机启动iptables时装载规则,可以把规则放在“start)”节或函数start()中。注意:如果把规则放在“start)”节里,则不要在“start)”节里运行start (),还要编辑“stop)”节,以便在关机时或进入一个不需要iptables的层时,脚本知道如何处理。还应检查“restart”节和 “condrestart”节的设置。一定要注意,我们所做的改动在升级iptables时可能会被删除,而不管是通过Red Hat网络自动升级还是用 RPM升级。

下面介绍第二种方法:先写一个规则的脚本,或直接用iptables命令生成规则。规则要适合自己的需要,别忘了实验一下是否有问题,确认正常之后,使用命令iptables-save来保存规则。一般用iptables-save > /etc/sysconfig/iptables生成保存规则的文件 /etc/sysconfig/iptables,也可以用service iptables save,它能把规则自动保存在/etc/sysconfig/iptables中。当计算机启动时,rc.d下的脚本将用命令iptables- restore调用这个文件,从而就自动恢复了规则。

以上两种方法最好不要混用,以免用不同方法定义的规则互相影响,甚至使防火墙的设置无效。

至此,可以删除预装的ipchains和iptables了,这样可以避免新旧版本的iptables之间的冲突。其实,只有当你从原码安装时,才需要这样做。但一般来说,也不会出现互相影响的问题,因为基于rpm的包不使用原码的缺省目录。删除用以下命令:

rpm -e iptables

既然不用ipchains为什么要保留呢?删吧!命令如下:

rpm -e ipchains

历经磨难,胜利终于到来了。你已经能够从源码安装iptables了。那些老版的东西就删掉吧。
Chapter 3. 表和链

这一章我们来讨论数据包是以什么顺序、如何穿越不同的链和表的。稍后,在你自己写规则时,就会知道这个顺序是多么的重要。一些组件是 iptables与内核共用的,比如,数据包路由的判断。了解到这一点是很重要的,尤其在你用iptables改变数据包的路由时。这会帮助你弄明白数据包是如何以及为什么被那样路由,一个好的例子是DNAT和SNAT,不要忘了TOS的作用。
3.1. 概述

当数据包到达防火墙时,如果MAC地址符合,就会由内核里相应的驱动程序接收,然后会经过一系列操作,从而决定是发送给本地的程序,还是转发给其他机子,还是其他的什么。

我们先来看一个以本地为目的的数据包,它要经过以下步骤才能到达要接收它的程序:

下文中有个词mangle,我实在没想到什么合适的词来表达这个意思,只因为我的英语太差!我只能把我理解的写出来。这个词表达的意思是,会对数据包的一些传输特性进行修改,在mangle表中允许的操作是 TOS、TTL、MARK。也就是说,今后只要我们见到这个词能理解它的作用就行了。

Table 3-1. 以本地为目标(就是我们自己的机子了)的包
Step(步骤) Table(表) Chain(链) Comment(注释)
1 在线路上传输(比如,Internet)
2 进入接口 (比如, eth0)
3 mangle PREROUTING 这个链用来mangle数据包,比如改变TOS等
4 nat PREROUTING 这个链主要用来做DNAT。不要在这个链做过虑操作,因为某些情况下包会溜过去。
5 路由判断,比如,包是发往本地的,还是要转发的。
6 mangle INPUT 在路由之后,被送往本地程序之前,mangle数据包。
7 filter INPUT 所有以本地为目的的包都要经过这个链,不管它们从哪儿来,对这些包的过滤条件就设在这里。
8 到达本地程序了(比如,服务程序或客户程序)

注意,相比以前(译者注:就是指ipchain)现在数据包是由INPUT链过,而不是FORWARD链。这样更符合逻辑。刚看上去可能不太好理解,但仔细想想就会恍然大悟的。

现在我们来看看源地址是本地器的包要经过哪些步骤:

Table 3-2. 以本地为源的包
Step Table Chain Comment
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)

在这个例子中,我们假设一个包的目的是另一个网络中的一台机子。让我们来看看这个包的旅程:

Table 3-3. 被转发的包
Step Table Chain Comment
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)

就如你所见的,包要经历很多步骤,而且它们可以被阻拦在任何一条链上,或者是任何有问题的地方。我们的主要兴趣是iptables的概貌。注意,对不同的接口,是没有什么特殊的链和表的。所有要经防火墙/ 路由器转发的包都要经过FORWARD链。

Caution

在上面的情况里,不要在INPUT链上做过滤。INPUT是专门用来操作那些以我们的机子为目的地址的包的,它们不会被路由到其它地方的。

现在,我们来看看在以上三种情况下,用到了哪些不同的链。图示如下:

要弄清楚上面的图,可以这样考虑。在第一个路由判断处,不是发往本地的包,我们会发送它穿过 FORWARD链。若包的目的地是本地监听的IP地址,我们就会发送这个包穿过INPUT链,最后到达本地。

值得注意的是,在做NAT的过程中,发往本机的包的目的地址可能会在PREROUTING链里被改变。这个操作发生在第一次路由之前,所以在地址被改变之后,才能对包进行路由。注意,所有的包都会经过上图中的某一条路径。如果你把一个包DNAT回它原来的网络,这个包会继续走完相应路径上剩下的链,直到它被发送回原来的网络。

Tip

想要更多的信息,可以看看rc.test-iptables.txt ,这个脚本包括了一些规则,它们会向你展示包是怎样通过各个表和链的。
3.2. mangle 表

这个表主要用来mangle包,你可以使用mangle匹配来改变包的TOS等特性。

Caution

强烈建议你不要在这个表里做任何过滤,不管是DANT,SNAT或者Masquerade。

以下是mangle表中仅有的几种操作:

*

TOS
*

TTL
*

MARK

TOS操作用来设置或改变数据包的服务类型域。这常用来设置网络上的数据包如何被路由等策略。注意这个操作并不完善,有时得不所愿。它在 Internet上还不能使用,而且很多路由器不会注意到这个域值。换句话说,不要设置发往Internet的包,除非你打算依靠TOS来路由,比如用 iproute2。

TTL操作用来改变数据包的生存时间域,我们可以让所有数据包只有一个特殊的TTL。它的存在有一个很好的理由,那就是我们可以欺骗一些ISP。为什么要欺骗他们呢?因为他们不愿意让我们共享一个连接。那些ISP会查找一台单独的计算机是否使用不同的TTL,并且以此作为判断连接是否被共享的标志。

MARK用来给包设置特殊的标记。iproute2能识别这些标记,并根据不同的标记(或没有标记)决定不同的路由。用这些标记我们可以做带宽限制和基于请求的分类。
3.3. nat 表

此表仅用于NAT,也就是转换包的源或目标地址。注意,就象我们前面说过的,只有流的第一个包会被这个链匹配,其后的包会自动被做相同的处理。实际的操作分为以下几类:

*

DNAT
*

SNAT
*

MASQUERADE

DNAT操作主要用在这样一种情况,你有一个合法的IP地址,要把对防火墙的访问重定向到其他的机子上(比如DMZ)。也就是说,我们改变的是目的地址,以使包能重路由到某台主机。

SNAT改变包的源地址,这在极大程度上可以隐藏你的本地网络或者DMZ等。一个很好的例子是我们知道防火墙的外部地址,但必须用这个地址替换本地网络地址。有了这个操作,防火墙就能自动地对包做SNAT和De-SNAT(就是反向的SNAT),以使LAN能连接到Internet。如果使用类似 192.168.0.0/24这样的地址,是不会从Internet得到任何回应的。因为IANA定义这些网络(还有其他的)为私有的,只能用于LAN内部。

MASQUERADE的作用和MASQUERADE完全一样,只是计算机的负荷稍微多一点。因为对每个匹配的包,MASQUERADE都要查找可用的IP地址,而不象SNAT用的IP地址是配置好的。当然,这也有好处,就是我们可以使用通过PPP、 PPPOE、SLIP等拨号得到的地址,这些地址可是由ISP的DHCP随机分配的。
3.4. Filter 表

filter 表用来过滤数据包,我们可以在任何时候匹配包并过滤它们。我们就是在这里根据包的内容对包做DROP或ACCEPT的。当然,我们也可以预先在其他地方做些过滤,但是这个表才是设计用来过滤的。几乎所有的target都可以在这儿使用。大量具体的介绍在后面,现在你只要知道过滤工作主要是在这儿完成的就行了。
Chapter 4. 状态机制

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

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

在iptables里,包是和被跟踪连接的四种不同状态有关的。它们是NEW,ESTABLISHED,RELATED和INVALID。后面我们会深入地讨论每一个状态。使用--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链里完成的。
4.2. conntrack记录

我们先来看看怎样阅读/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里查看、设置。
4.3. 数据包在用户空间的状态

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

Table 4-1. 数据包在用户空间的状态
State(状态) Explanation(注释)
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这个状态的任何东西。

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

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

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

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

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

阅读更多
想对作者说点什么? 我来说一句

Iptable指南1.1.19

2010年01月20日 925KB 下载

Iptables 指南 1.1.19.(html版).rar

2008年07月24日 521KB 下载

iptables指南 1.1.19

2016年05月06日 1.06MB 下载

iptables指南1.1.19电子书

2010年05月06日 532KB 下载

Iptables 1.1.19指南

2014年10月20日 2.28MB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭