linux下防火墙iptables用法规则详解

2016-06-27  佳人看书

linux下防火墙iptables用法规则详解

IPTable规则

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


1. 基础

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

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

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

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

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

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

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


2. Tables

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

Table 1-1. Tables

Table (表名)

Explanation (注释)

nat

nat表的主要用处是网络地址转换,即Network Address Translation,缩写为NAT。做过NAT操作的数据包的地址就被改变了,当然这种改变是根据我们的规则进行的。属于一个流的包只会经过这个表一次。如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自动地被做相同的操作。也就是说,余下的包不会再通过这个表,一个一个的被NAT,而是自动地完成。这就是我们为什么不应该在这个表中做任何过滤的主要原因,对这一点,后面会有更加详细的讨论。PREROUTING 链的作用是在包刚刚到达防火墙时改变它的目的地址,如果需要的话。OUTPUT链改变本地产生的包的目的地址。POSTROUTING链在包就要离开防火墙之前改变其源地址。

mangle

这个表主要用来mangle数据包。我们可以改变不同的包及包头的内容,比如 TTLTOSMARK。注意MARK并没有真正地改动数据包,它只是在内核空间为包设了一个标记。防火墙内的其他的规则或程序(如tc)可以使用这种标记对包进行过滤或高级路由。这个表有五个内建的链: PREROUTINGPOSTROUTING OUTPUTINPUTFORWARDPREROUTING在包进入防火墙之后、路由判断之前改变包,POSTROUTING是在所有路由判断之后。 OUTPUT在确定包的目的之前更改数据包。INPUT在包被路由到本地之后,但在用户空间的程序看到它之前改变包。FORWARD在最初的路由判断之后、最后一次更改包的目的之前mangle包。注意,mangle表不能做任何NAT,它只是改变数据包的TTLTOSMARK,而不是其源目地址。NAT是在nat表中操作的。

filter

filter表是专门过滤包的,内建三个链,可以毫无问题地对包进行DROPLOGACCEPTREJECT等操作。FORWARD 链过滤所有不是本地产生的并且目的地不是本地(所谓本地就是防火墙了)的包,而 INPUT恰恰针对那些目的地是本地的包。OUTPUT 是用来过滤所有本地生成的包的。

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


3. Commands

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

Table 1-2. Commands

Command

-A--append

Example

iptables -A INPUT ...

Explanation

在所选择的链末添加规则。当源地址或目的地址是以名字而不是ip地址的形式出现时,若这些名字可以被解析为多个地址,则这条规则会和所有可用的地址结合。

Command

-D--delete

Example

iptables -D INPUT --dport 80 -j DROPiptables -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。这仅仅是改变链的名字,对整个表的结构、工作没有任何影响。

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

Table 1-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 with

All

Explanation

此选项告诉iptables探测并装载要使用的模块。这是非常有用的一个选项,万一modprobe命令不在搜索路径中,就要用到了。有了这个选项,在装载模块时,即使有一个需要用到的模块没装载上,iptables也知道要去搜索。


4. Matches

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


4.1. 通用匹配

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

Table 1-4. Generic matches

Match

-p--protocol

Example

iptables -A INPUT -p tcp

Explanation

匹配指定的协议。指定协议的形式有以下几种:

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

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

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

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

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

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.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

Example

iptables -A INPUT -d 192.168.1.1

Explanation

以IP目的地址匹配包。地址的形式和 -- source完全一样。

Match

-i--in-interface

Example

iptables -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

Example

iptables -A FORWARD -o eth0

Explanation

以包离开本地所使用的网络接口来匹配包。使用的范围和指定接口的方法与--in-interface完全一样。

Match

-f--fragment

Example

iptables -A INPUT -f

Explanation

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


4.2. 隐含匹配

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


4.2.1. TCP matches

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

Table 1-5. TCP matches

Match

--sport--source-port

Example

iptables -A INPUT -p tcp --sport 22

Explanation

基于TCP包的源端口来匹配包,端口的指定形式如下:

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

2、使用服务名或端口号,但名字必须是在/etc/services 中定义的,因为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

Example

iptables -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

Example

iptables -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

Example

iptables -p tcp --tcp-option 16

Explanation

根据匹配包。TCP选项是TCP头中的特殊部分,有三个不同的部分。第一个8位组表示选项的类型,第二个8位组表示选项的长度(这个长度是整个选项的长度,但不包含填充部分所占的字节,而且要注意不是每个TCP选项都有这一部分的),第三部分当然就是选项的内容了。为了适应标准,我们不必执行所有的选项,但我们可以查看选项的类型,如果不是我们所支持的,那就只是看看长度然后跳过数据部分。这个操作是根据选项的十进制值来匹配的,它也可以用英文感叹号取反。所有的选项都可在Internet Engineering Task Force里找到。


4.2.2. UDP matches

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

Table 1-6. UDP matches

Match

--sport--source-port

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完全一样。


4.2.3. ICMP matches

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

Table 1-7. ICMP matches

Match

--icmp-type

Example

iptables -A INPUT -p icmp --icmp-type 8

Explanation

根据ICMP类型匹配包,类型的指定可以使用十进制数值或相应的名字,数值在RFC792中有定义,名字可以用iptables --protocol icmp --help 查看,或者在附录ICMP类型中查找。这个匹配也可用英文感叹号取反,如:--icmp-type ! 8就表示匹配除类型8之外的所有ICMP包。要注意有些ICMP 类型已经废弃不用了,还有一些可能会对无防护的主机带来“危险”,因为它们可能把包重定向到错误的地方。


4.3. 显式匹配

显式匹配必须用-m--match装载,比如要使用状态匹配就必须使用-m state。有些匹配还需要指定协议,有些就不需要,比如连接状态就不要。这些状态是NEW(还未建立好的连接的第一个包),ESTABLISHED(已建立的连接,也就是已经在内核里注册过的),RELATED(由已经存在的、处于已建立状态的连接生成的新连接),等等。有些匹配还处在开发阶段,或者还只是为了说明iptables的强大能力。这说明不是所有的匹配一开始就是实用的,但以后你可能会用到它。随着iptables 新版本的发布,会有一些新的匹配可用。隐含匹配和显式匹配最大的区别就是一个是跟随协议匹配自动装载的,一个是显式装载的。


4.3.1. Limit match

这个匹配操作必须由-m limit明确指定才能使用。有了它的帮助,就可以对指定的规则的日志数量加以限制,以免你被信息的洪流淹没哦。比如,你可以事先设定一个限定值,当符合条件的包的数量不超过它时,就记录;超过了,就不记录了。我们可以控制某条规则在一段时间内的匹配次数(也就是可以匹配的包的数量),这样就能够减少DoS syn flood攻击的影响。这是它的主要作用,当然,还有很多其他作用(译者注:比如,对于某些不常用的服务可以限制连接数量,以免影响其他服务)。limit match也可以用英文感叹号取反,如:-m limit ! --limit 5/s表示在数量超过限定值后,所有的包都会被匹配。

(译者注:为了更好地理解这个匹配操作,我们通过一个比喻来解释一下。原文也做了类似地比喻,但我觉得对于初学者不易理解,故未采用。)limit match的工作方式就像一个单位大门口的保安,当有人要进入时,需要找他办理通行证。早上上班时,保安手里有一定数量的通行证,来一个人,就签发一个,当通行证用完后,再来人就进不去了,但他们不会等,而是到别的地方去(在iptables里,这相当于一个包不符合某条规则,就会由后面的规则来处理,如果都不符合,就由缺省的策略处理)。但有个规定,每隔一段时间保安就要签发一个新的通行证。这样,后面来的人如果恰巧赶上,也就可以进去了。如果没有人来,那通行证就保留下来,以备来的人用。如果一直没人来,可用的通行证的数量就增加了,但不是无限增大的,最多也就是刚开始时保安手里有的那个数量。也就是说,刚开始时,通行证的数量是有限的,但每隔一段时间就有新的通行证可用。limit match有两个参数就对应这种情况,--limit-burst指定刚开始时有多少通行证可用,--limit指定要隔多长时间才能签发一个新的通行证。要注意的是,我这里强调的是“签发一个新的通行证”,这是以iptables的角度考虑的。在你自己写规则时,就要从这个角度考虑。比如,你指定了--limit 3/minute --limit-burst 5 ,意思是开始时有5个通行证,用完之后每20秒增加一个(这就是从iptables的角度看的,要是以用户的角度看,说法就是每一分钟增加三个或者每分钟只能过三个)。你要是想每20分钟过一个,只能写成--limit 3/hour --limit-burst 5,也就是说你要把时间单位凑成整的。

Table 1-8. Limit match options

Match

--limit

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就可以看出其工作方式了。


4.3.2. MAC match

基于包的MAC源地址匹配包。到写这篇文章时,这个match还有一点限制(就是只能匹配MAC源地址匹),但今后定会有所发展,会更有用的。

 

注意,这个match是由-m mac装入的,而不是一些人想当然的-m mac-source,后者只是前者的选项而已。

Table 1-9. MAC match options

Match

--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接口。而且,它还只能在PREROUTINGFORWARD INPUT链里使用。


4.3.3. Mark match

以包被设置的mark来匹配包,这个值只能由内核更改。前面曾经提到过,mark比较特殊,它不是包本身的一部分,而是在包穿越计算机的过程中由内核分配的和它相关联的一个字段。它可能被用来改变包的传输路径或过滤。时至今日,在linux里只有一种方法能设置mark,即iptables的MARK target,以前在ipchains里是FWMARK target。这就是为什么在高级路由里我们仍要参照FWMARK的原因。mark字段的值是一个无符号的整数,在32位系统上最大可以是4294967296(就是2的32次方),这足够用的了:)

Table 1-10. Mark match options

Match

--mark

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值比较。


4.3.4. Multiport match

多端口匹配扩展使我们能够在一条规则里指定不连续的多个端口,如果没有这个扩展,我们只能按端口来写规则了。其实这只是标准端口匹配的增强版罢了,使我们书写规则更方便而已。

 

注意:不能在一条规则里同时使用标准端口匹配和多端口匹配,如--sport 1024:63353 -m multiport --dport 21,23,80。这条规则并不能想你想象的那样工作,但也不是不能工作,iptables会使用第一个合法的条件,那么这里多端口匹配就白写了:)

Table 1-11. Multiport match options

Match

--source-port

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的包等。使用方法和源端口多端口匹配一样。


4.3.5. Owner match

基于包的生成者(也就是所有者,或称作拥有者,owner)的ID来匹配包,owner可以是启动进程的用户的ID,或用户所在的组的ID,或进程的ID,或会话的ID。这个扩展原本只是为了说明iptables可以做什么,现在发展到实用阶段了。但要注意,此扩展只能用在OUTPUT中,原因显而易见:我们几乎不可能得到发送端例程的ID的任何信息,或者在去往真正目的地的路上哪儿有路由。甚至在 OUTPUT链里,这也不是十分可靠,因为有些包根本没有owner,比如 ICMP responses,所以它们从不会被这个match抓到:)

Table 1-12. Owner match options

Match

--uid-owner

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可以反映出这一点。


4.3.6. State match

状态匹配扩展要有内核里的连接跟踪代码的协助,因为它是从连接跟踪机制中得到包的状态的。这样我们就可以了解连接所处的状态。它几乎适用于所有的协议,包括那些无状态的协议,如ICMP和UDP。针对每个连接都有一个缺省的超时值,如果连接的时间超过了这个值,那么这个连接的记录就被会从连接跟踪的记录数据库中删除,也就是说连接就不再存在了。这个match必须有-m state作为前提才能使用。状态机制的详细内容在章节状态机制 中。

Table 1-13. State matches

Match

--state

Example

iptables -A INPUT -m state --state RELATED,ESTABLISHED

Explanation

指定要匹配包的的状态,当前有4种状态可用:INVALIDESTABLISHEDNEWRELATED。 INVALID意味着这个包没有已知的流或连接与之关联,也可能是它包含的数据或包头有问题。ESTABLISHED意思是包是完全有效的,而且属于一个已建立的连接,这个连接的两端都已经有数据发送。NEW表示包将要或已经开始建立一个新的连接,或者是这个包和一个还没有在两端都有数据发送的连接有关。RELATED说明包正在建立一个新的连接,这个连接是和一个已建立的连接相关的。比如,FTP data transferICMP error 和一个TCP或UDP连接相关。注意NEW状态并不在试图建立新连接的TCP包里寻找SYN标记,因此它不应该不加修改地用在只有一个防火墙或在不同的防火墙之间没有启用负载平衡的地方。具体如何使用,你就再看看章节状态机制吧:)


4.3.7. TOS match

根据TOS字段匹配包,必须使用-m tos才能装入。TOS是IP头的一部分,其含义是Type Of Service,由8个二进制位组成,包括一个3 bit的优先权子字段(现在已被忽略),4 bit的TOS子字段和1 bit未用位(必须置0)。它一般用来把当前流的优先权和需要的服务(比如,最小延时、最大吞吐量等)通知路由器。但路由器和管理员对这个值的处理相差很大,有的根本就不理会,而有的就会尽量满足要求。

Table 1-14. TOS matches

Match

--tos

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 就需要这个选项。

Maximize-Throughput 8 (0x08),要求找一条路径能使吞吐量最大,标准服务FTP-data能用到这个。

Maximize-Reliability 4 (0x04),要求找一条路径能使可靠性最高,使用它的有BOOTP和TFTP。

Minimize-Cost 2 (0x02),要求找一条路径能使费用最低,一般情况下使用这个选项的是一些视频音频流协议,如RTSP(Real Time Stream Control Protocol)。

Normal-Service 0 (0x00),一般服务,没有什么特殊要求。


4.3.8. TTL match

根据IP头里的TTL (Time To Live,即生存期)字段来匹配包,此必须由-m ttl装入。TTL field是一个字节(8个二进制位),一旦经过一个处理它的路由器,它的值就减去1它的值。当该字段的值减为0时,报文就被认为是不可转发的,数据报就被丢弃,并发送ICMP报文通知源主机,不可转发的报文被丢弃。这也有两种情况,一是传输期间生存时间为0,使用类型为11代码是0的ICMP报文;二是在数据报重组期间生存时间为0,使用类型为11代码是1的ICMP报文。这个match只是根据TTL匹配包,而对其不做任何更改,所以在它之后可使用任何类型的match。

Table 1-15. TTL matches

Match

--ttl

Example

iptables -A OUTPUT -m ttl --ttl 60

Explanation

根据TTL的值来匹配包,参数的形式只有一种,就是十进制数值。它可以被用来调试你的局域网,比如解决LAN内的主机到Internet上的主机的连接问题,或找出 Trojan(Trojan)可能的入口。这个match的用处相对有限,但它其实是很有用的,这就看你的想象力如何了。比如可以用它来发现那些TTL具有错误缺省值的机子(这可能是实现TCP/IP栈功能的那个程序本身的错误,或者是配置有问题)。


4.4. 针对非正常包的匹配

这个匹配没有任何参数,也不需要显式地装载。注意这应该被看作是一个实验性的匹配,它不总是能正常工作的,对有些不正常的包(unclean package,就是所谓的脏包)或问题,它是视而不见的。这个match 试图匹配那些好象畸形或不正常的包,比如包头错或校验和错,等等。它可能常用来DROP错误的连接、检查有错的流,但要知道这样做也可能会中断合法的连接。


5. Targets/Jumps

target/jump决定符合条件的包到何处去,语法是--jump target-j target。(译者注:本文中,原作者把target细分为两类,即Target和Jump。它们唯一的区别是jump的目标是一个在同一个表内的链,而target的目标是具体的操作。)我们会先接触到两个基本的target,就是ACCEPT和DROP。

前面提到过用户自定义链要用到-N命令。下面我们在filter表中建一个名为tcp_packets的链:

iptables -N tcp_packets

然后再把它作为jump的目标:

iptables -A INPUT -p tcp -j tcp_packets

这样我们就会从INPUT链跳入tcp_packets链,开始在tcp_packets中的旅行。如果到达了tcp_packets链的结尾(也就是未被链中的任何规则匹配),则会退到INPUT链的下一条规则继续它的旅行。如果在子链中被ACCEPT了,也就相当于在父链中被ACCEPT了,那么它不会再经过父链中的其他规则。但要注意这个包能被其他表的链匹配,过程可查看章节 表和链

target指定我们要对包做的操作,比如DROP和ACCEPT,还有很多,我们后面会介绍。不同的target有不同的结果。一些target会使包停止前进,也就是不再继续比较当前链中的其他规则或父链中的其他规则,最好的例子就是DROP和ACCEPT。而另外一些target在对包做完操作之后,包还会继续和其他的规则比较,如LOGULOGTOS。它们会对包进行记录、mangle,然后让包通过,以便匹配这条链中的其他规则。有了这样的target,我们就可以对同一个包既改变它的TTL又改变它的TOS。有些target必须要有准确的参数(如TOS需要确定的数值),有些就不是必须的,但如果我们想指定也可以(如日志的前缀,伪装使用的端口,等等)。本节我们会尽可能全面地介绍每一个target。现在我们就来看看有哪几种target。


5.1. ACCEPT target

这个target没有任何选项和参数,使用也很简单,指定-j ACCEPT即可。一旦包满足了指定的匹配条件,就会被ACCEPT,并且不会再去匹配当前链中的其他规则或同一个表内的其他规则,但它还要通过其他表中的链,而且在那儿可能会被DROP也说不准哦。


5.2. DNAT target

这个target是用来做目的网络地址转换的,就是重写包的目的IP地址。如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以被路由到正确的主机或网络。DNAT target是非常有用的。比如,你的Web服务器在LAN内部,而且没有可在Internet上使用的真实IP地址,那就可以使用这个 target让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的Web服务器。目的地址也可以是一个范围,这样的话,DNAT会为每一个流随机分配一个地址。因此,我们可以用这个target做某种类型地负载平衡。

注意,DANT target只能用在nat表的PREROUTING和OUTPUT链中,或者是被这两条链调用的链里。但还要注意的是,包含DANT target的链不能被除此之外的其他链调用,如POSTROUTING。

Table 1-16. DNAT target

Option

--to-destination

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-100SNAT的语法和这个target的一样,只是目的不同罢了。要注意,只有先用--protocol指定了TCP或 UDP协议,才能使用端口。

因为DNAT要做很多工作,所以我要再罗嗦一点。我们通过一个例子来大致理解一下它是如何工作的。比如,我想通过Internet连接发布我们的网站,但是HTTP server在我们的内网里,而且我们对外只有一个合法的IP,就是防火墙那个对外的IP——$INET_IP。防火墙还有一个内网的IP——$LAN_IP,HTTP server的IP是$HTTP_IP (这当然是内网的了)。为了完成我们的设想,要做的第一件事就是把下面的这个简单的规则加入到nat表的PREROUTING链中:

iptables -t nat -A PREROUTING --dst $INET_IP -p tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP

现在,所有从Internet来的、到防火墙的80端口去的包都会被转发(或称做被DNAT )到在内网的HTTP服务器上。如果你在Internet上试验一下,一切正常吧。再从内网里试验一下,完全不能用吧。这其实是路由的问题。下面我们来好好分析这个问题。为了容易阅读,我们把在外网上访问我们服务器的那台机子的IP地址记为$EXT_BOX

  1. 包从地址为$EXT_BOX的机子出发,去往地址为$INET_IP 的机子。
  2. 包到达防火墙。
  3. 防火墙DNAT(也就是转发)这个包,而且包会经过很多其他的链检验及处理。
  4. 包离开防火墙向$HTTP_IP前进。
  5. 包到达HTTP服务器,服务器就会通过防火墙给以回应,当然,这要求把防火墙作为HTTP到达$EXT_BOX的网关。一般情况下,防火墙就是HTTP服务器的缺省网关。
  6. 防火墙再对返回包做Un-DNAT(就是照着DNAT的步骤反过来做一遍),这样就好像是防火墙自己回复了那个来自外网的请求包。
  7. 返回包好象没经过这么复杂的处理、没事一样回到$EXT_BOX

现在,我们来考虑和HTTP服务器在同一个内网(这里是指所有机子不需要经过路由器而可以直接互相访问的网络,不是那种把服务器和客户机又分在不同子网的情况)的客户访问它时会发生什么。我们假设客户机的IP为$LAN_BOX,其他设置同上。

  1. 包离开$LAN_BOX,去往$INET_IP
  2. 包到达防火墙。
  3. 包被DNAT,而且还会经过其他的处理。但是包没有经过SNAT 的处理,所以包还是使用它自己的源地址,就是$LAN_BOX(译者注:这就是IP 传输包的特点,只根据目的地的不同改变目的地址,但不因传输过程中要经过很多路由器而随着路由器改变其源地址,除非你单独进行源地址的改变。其实这一步的处理和对外来包的处理是一样的,只不过内网包的问题就在于此,所以这里交待一下原因)。
  4. 包离开防火墙,到达HTTP服务器。
  5. HTTP服务器试图回复这个包。它在路由数据库中看到包是来自同一个网络的一台机子,因此它会把回复包直接发送到请求包的源地址(现在是回复包的目的地址),也就是$LAN_BOX
  6. 回复包到达客户机,但它会很困惑,因为这个包不是来自它访问的那台机子。这样,它就会把这个包扔掉而去等待“真正”的回复包。

针对这个问题有个简单的解决办法,因为这些包都要进入防火墙,而且它们都去往需要做DNAT才能到达的那个地址,所以我们只要对这些包做SNAT操作即可。比如,我们来考虑上面的例子,如果对那些进入防火墙而且是去往地址为$HTTP_IP、端口为80的包做SNAT操作,那么这些包就好象是从$LAN_IP来的了,也就是说,这些包的源地址被改为$LAN_IP了。这样,HTTP服务器就会把回复包发给防火墙,而防火墙会再对包做 Un-DNAT操作,并把包发送到客户机。解决问题的规则如下:

iptables -t nat -A POSTROUTING -p tcp --dst $HTTP_IP --dport 80 -j SNAT \ --to-source $LAN_IP

要记住,按运行的顺序POSTROUTING链是所有链中最后一个,因此包到达这条链时,已经被做过DNAT操作了,所以我们在规则里要基于内网的地址$HTTP_IP(包的目的地)来匹配包。

 

警告:我们刚才写的这条规则会对日志产生很大影响,这种影响应该说是很不好的。因为来自 Internet包在防火墙内先后经过了DNAT和SNAT处理,才能到达HTTP服务器(上面的例子),所以HTTP服务器就认为包是防火墙发来的,而不知道真正的源头是其他的IP。这样,当它记录服务情况时,所有访问记录的源地址都是防火墙的IP而不是真正的访问源。我们如果想根据这些记录来了解访问情况就不可能了。因此上面提供的“简单办法”并不是一个明智的选择,但它确实可以解决“能够访问”的问题,只是没有考虑到日志而已。

其他的服务也有类似的问题。比如,你在LAN内建立了SMTP服务器,那你就要设置防火墙以便能转发SMTP的数据流。这样你就创建了一个开放的SMTP中继服务器,随之而来的就是日志的问题了。

一定要注意,这里所说的问题只是针对没有建立DMZ或类似结构的网络,并且内网的用户访问的是服务器的外网地址而言的。(译者注:因为如果建立了DMZ,或者服务器和客户机又被分在不同的子网里,那就不需要这么麻烦了。因为所有访问的源头都不在服务器所在的网里,所以就没必要做SNAT去改变包的源地址了,从而记录也就不是问题了。如果内网客户是直接访问服务器的内网地址那就更没事了)

较好的解决办法是为你的LAN在内网建立一台单独的DNS服务器(译者注:这样,内网的客户使用网站名访问HTTP服务器时,DNS就可以把它解析成内网地址。客户机就可以直接去访问HTTP服务器的内网地址了,从而避免了通过防火墙的操作,而且包的源地址也可以被HTTP服务器的日志使用,也就没有上面说的日志问题了。),或者干脆建立DMZ得了(这是最好的办法,但你要有钱哦,因为用的设备多啊)。

对上面的例子应该考虑再全面些,现在还有一个问题没解决,就是防火墙自己要访问HTTP服务器时会发生什么,能正常访问吗?你觉得呢:)很可惜,现在的配置还是不行,仔细想想就明白了。我们这里讨论的基础都是假设机子访问的是HTTP服务器的外网地址,但这个外网地址其实就是防火墙对外的地址,所以当防火墙访问这个外网地址时,就是访问它自己。防火墙上如果有HTTP服务,那客户机就会看到页面内容,不过这不是它想看到的(它想要的在DNAT上了),如果没有HTTP服务,客户就只能收到错误信息了。前面给出的规则之所以不起作用是因为从防火墙发出的请求包不会经过那两条链。还记得防火墙自己发出的包经过哪些链吧:)我们要在nat表的OUTPUT链中添加下面的规则:

iptables -t nat -A OUTPUT --dst $INET_IP -p tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP

有了最后这条规则,一切都正常了。和HTTP服务器不在同一个网的机子能正常访问服务了,和它在一个网内的机子也可以正常访问服务了,防火墙本身也能正常访问服务了,没有什么问题了。这种心情,套用《大话西游》里的一句话,就是“世界又清净了”。(不要说你不知道什么是《大话西游》)

 

我想大家应该能明白这些规则只说明了数据包是如何恰当地被DNAT和SNAT的。除此之外,在 filter表中还需要其他的规则(在FORWARD链里),以允许特定的包也能经过前面写的(在POSTROUTING链和 OUTPUT链里的)规则。千万不要忘了,那些包在到达FORWARD链之前已经在PREROUTING链里被DNAT过了,也就是说它们的目的地址已被改写,在写规则时要注意这一点。


5.3. DROP target

顾名思义,如果包符合条件,这个target就会把它丢掉,也就是说包的生命到此结束,不会再向前走一步,效果就是包被阻塞了。在某些情况下,这个target会引起意外的结果,因为它不会向发送者返回任何信息,也不会向路由器返回信息,这就可能会使连接的另一方的sockets因苦等回音而亡:) 解决这个问题的较好的办法是使用REJECT target,(译者注:因为它在丢弃包的同时还会向发送者返回一个错误信息,这样另一方就能正常结束),尤其是在阻止端口扫描工具获得更多的信息时,可以隐蔽被过滤掉的端口等等(译者注:因为扫描工具扫描一个端口时,如果没有返回信息,一般会认为端口未打开或被防火墙等设备过滤掉了)。还要注意如果包在子链中被DROP了,那么它在主链里也不会再继续前进,不管是在当前的表还是在其他表里。总之,包死翘翘了。


5.4. LOG target

这个target是专门用来记录包地有关信息的。这些信息可能是非法的,那就可以用来除错。LOG会返回包的有关细节,如IP头的大部分和其他有趣的信息。这个功能是通过内核的日志工具完成的,一般是syslogd。返回的信息可用dmesg阅读,或者可以直接查看syslogd的日志文件,也可以用其他的什么程序来看。LOG对调试规则有很大的帮助,你可以看到包去了哪里、经过了什么规则的处理,什么样的规则处理什么样的包,等等。当你在生产服务器上调试一个不敢保证100%正常的规则集时,用LOG代替DROP是比较好的(有详细的信息可看,错误就容易定位、解决了),因为一个小小的语法错误就可能引起严重的连接问题,用户可不喜欢这样哦。如果你想使用真正地扩展日志地话,可能会对ULOG target有些兴趣,因为它可以把日志直接记录到MySQL databases或类似的数据库中。

 

注意,如果在控制台得到的信息不是你想要的,那不是iptables或Netfilter的问题,而是 syslogd 配置文件的事,这个文件一般都是/etc/syslog.conf。有关这个问题的更多信息请查通过man syslog.conf查看。

LOG现在有5个选项,你可以用它们指定需要的信息类型或针对不同的信息设定一些值以便在记录中使用。选项如下:

Table 1-17. LOG target options

Option

--log-level

Example

iptables -A FORWARD -p tcp -j LOG --log-level debug

Explanation

告诉iptables syslog使用哪个记录等级。记录等级的详细信息可以查看文件syslog.conf,一般来说有以下几种,它们的级别依次是:debuginfonoticewarningwarnerrerrorcritalert emergpanic。其中,error和err、warn和warning、panic和emerg分别是同义词,也就是说作用完全一样的。注意这三种级别是不被赞成使用的,换句话说,就是不要使用它们(因为信息量太大)。信息级别说明了被记录信息所反映的问题的严重程度。所有信息都是通过内核的功能被记录的,也就是说,先在文件 syslog.conf里设置kern.=info /var/log/iptables,然后再让所有关于iptables的LOG信息使用级别info,就可以把所有的信息存入文件/var/log/iptables内。注意,其中也可能会有其他的信息,它们是内核中使用info 这个等级的其他部分产生的。有关日志的详细信息,我建议你看看syslog和syslog.conf的帮助,还有HOWTO,等等。

Option

--log-prefix

Example

iptables -A INPUT -p tcp -j LOG --log-prefix 'INPUT packets'

Explanation

告诉iptables在记录的信息之前加上指定的前缀。这样和grep或其他工具一起使用时就容易追踪特定的问题,而且也方便从不同的规则输出。前缀最多能有29个英文字符,这已经是包括空白字符和其他特殊符号的总长度了。

Option

--log-tcp-sequence

Example

iptables -A INPUT -p tcp -j LOG --log-tcp-sequence

Explanation

把包的TCP序列号和其他日志信息一起记录下来。TCP序列号可以唯一标识一个包,在重组时也是用它来确定每个分组在包里的位置。注意,这个选项可能会带来危险,因为这些记录被未授权的用户看到的话,可能会使他们更容易地破坏系统。其实,任何iptables的输出信息都增加了这种危险。(译者注:现在,我深刻理解了什么是“言多必失”,什么是“沉默是金”)

Option

--log-tcp-options

Example

iptables -A FORWARD -p tcp -j LOG --log-tcp-options

Explanation

记录TCP包头中的字段大小不变的选项。这对一些除错是很有价值的,通过它提供的信息,可以知道哪里可能出错,或者哪里已经出了错。

Option

--log-ip-options

Example

iptables -A FORWARD -p tcp -j LOG --log-ip-options

Explanation

记录IP包头中的字段大小不变的选项。这对一些除错是很有价值的,还可以用来跟踪特定地址的包。


5.5. MARK target

用来设置mark值,这个值只能在本地的mangle表里使用,不能用在其他任何地方,就更不用说路由器或另一台机子了。因为mark比较特殊,它不是包本身的一部分,而是在包穿越计算机的过程中由内核分配的和它相关联的一个字段。它可以和本地的高级路由功能联用,以使不同的包能使用不同的队列要求,等等。如果你想在传输过程中也有这种功能,还是用TOS target吧。有关高级路由的更多信息,可以查看Linux Advanced Routing and Traffic Control HOW-TO

Table 1-18. MARK target options

Option

--set-mark

Example

iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 2

Explanation

设置mark值,这个值是一个无符号的整数。比如,我们对一个流或从某台机子发出的所有的包设置了mark值,就可以利用高级路由功能来对它们进行流量控制等操作了。


5.6. MASQUERADE target

这个target和SNAT target的作用是一样的,区别就是它不需要指定--to-source 。MASQUERADE是被专门设计用于那些动态获取IP地址的连接的,比如,拨号上网、DHCP连接等。如果你有固定的IP地址,还是用SNAT target吧。

伪装一个连接意味着,我们自动获取网络接口的IP地址,而不使用--to-source 。当接口停用时,MASQUERADE不会记住任何连接,这在我们kill掉接口时是有很大好处的。如果我们使用SNAT target,连接跟踪的数据是被保留下来的,而且时间要好几天哦,这可是要占用很多连接跟踪的内存的。一般情况下,这种处理方式对于拨号上网来说是较好的(这有利于已有那连接继续使用)。如果我们被分配给了一个不同于前一次的IP,不管怎样已有的连接都要丢失,但或多或少地还是有一些连接记录被保留了(真是白痴,是吧)。

即使你有静态的IP,也可以使用MASQUERADE,而不用SNAT 。不过,这不是被赞成的,因为它会带来额外的开销,而且以后还可能引起矛盾,比如它也许会影响你的脚本,使它们不能用。

注意,MASQUERADESNAT一样,只能用于nat表的 POSTROUTING链,而且它只有一个选项(不是必需的):

Table 1-19. MASQUERADE target

Option

--to-ports

Example

iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE --to-ports 1024-31000

Explanation

在指定TCP或UDP的前提下,设置外出包能使用的端口,方式是单个端口,如--to-ports 1025,或者是端口范围,如--to- ports 1024-3000。注意,在指定范围时要使用连字号。这改变了SNAT中缺省的端口选择,详情请查看 SNAT target


5.7. MIRROR target

这个target是实验性的,它只是一个演示而已,不建议你使用它,因为它可能引起循环,除此之外,还可能引起严重的DoS。这个target的作用是颠倒IP头中的源目地址,然后再转发包。这会引起很有趣的事,一个骇客最后攻破的可能就是他自己的机子。看来,使用这个target至少可以使我们的机子更强壮:) 我们如果对机子A的80端口使用了MIRROR,会发生什么呢?假设有来自yahoo.com的机子B 想要访问A的HTTP服务,那他得到的将是yahoo的主页,因为请求是来自yahoo的。

注意,MIRROR只能用在INPUT FORWARD、 PREROUTING链和被它们调用的自定义链中。还要注意,如果外出的包是因 MIRROR target发出的,则它们是不会被filter、nat或mangle表内的链处理的,这可能引起循环或其他问题。比如,一台机子向另一台配置了MIRRORTTL值为255的机子发送一个会被认为是欺骗的数据包,同时这台机子也欺骗自己的数据包,以使它被认为好像是来自第三个使用了MIRROR 的机子。这样,那个包就会不间断地往来很多次,直到TTL为0。如果两台机子之间只有一个路由器,这个包就会往返240-255次。对骇客来说,这是不坏的情况,因为他只要发送一个1500字节的数据(也就是一个包),就可以消耗你的连接的380K字节。对于骇客或者叫做脚本小子(不管我们把他们称作什么)来说,这可是很理想的情况。


5.8. QUEUE target

这个target为用户空间的程序或应用软件管理包队列。它是和iptables之外的程序或工具协同使用的,包括网络计数工具,高级的数据包代理或过滤应用,等等。讨论程序的编码已超出了本文的范围。即使讨论,也要花很多时间,而且在这样一篇文章之内也无法说清有关Netfilter和iptables的编程。具体的信息请查看Netfilter Hacking HOW-TO。


5.9. REDIRECT target

在防火墙所在的机子内部转发包或流到另一个端口。比如,我们可以把所有去往端口HTTP的包REDIRECT到HTTP proxy(例如squid),当然这都发生在我们自己的主机内部。本地生成的包都会被映射到127.0.0.1。换句话说,这个target把要转发的包的目的地址改写为我们自己机子的IP。我们在做透明代理(LAN内的机子根本不需要知道代理的存在就可以正常上网)时,这个target可是起了很大作用的。

注意,它只能用在nat表的PREROUTING、OUTPUT链和被它们调用的自定义链里。 REDIRECT只有一个选项:

Table 1-20. REDIRECT target

Option

--to-ports

Example

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

Explanation

在指定TCP或UDP协议的前提下,定义目的端口,方式如下:

1、不使用这个选项,目的端口不会被改变。

2、指定一个端口,如--to-ports 8080

3、指定端口范围,如--to-ports 8080-8090


5.10. REJECT target

REJECTDROP基本一样,区别在于它除了阻塞包之外,还向发送者返回错误信息。现在,此target还只能用在INPUT、FORWARD、OUTPUT和它们的子链里,而且包含 REJECT的链也只能被它们调用,否则不能发挥作用。它只有一个选项,是用来控制返回的错误信息的种类的。虽然有很多种类,但如果你有TCP/IP方面的基础知识,就很容易理解它们。

Table 1-21. REJECT target

Option

--reject-with

Example

iptables -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset

Explanation

告诉REJECT target应向发送者返回什么样的信息。一旦包满足了设定的条件,就要发送相应的信息,然后再象DROP一样无情地抛弃那些包。可用的信息类型有:1、icmp-net-unreachable 2、icmp-host-unreachable 3、 icmp-port-unreachable 4、icmp-proto-unreachable 5、icmp-net-prohibited 6、icmp-host-prohibited 。其中缺省的是port-unreachable。你可以在附录ICMP类型中看到更多的信息。还有一个类型——echo-reply,它只能和匹配 ICMP ping包的规则联用。最后一个类型是tcp-reset,(显然,只能用于TCP协议)它的作用是告诉REJECT返回一个TCP RST包(这个包以文雅的方式关闭TCP连接,有关它的详细信息在RFC 793 - Transmission Control Protocol里)给发送者。正如iptables的 man page中说的,tcp-reset主要用来阻塞身份识别探针(即113/tcp,当向被破坏的邮件主机发送邮件时,探针常被用到,否则它不会接受你的信)。


5.11. RETURN target

顾名思义,它使包返回上一层,顺序是:子链——>父链——>缺省的策略。具体地说,就是若包在子链中遇到了RETURN,则返回父链的下一条规则继续进行条件的比较,若是在父链(或称主链,比如INPUT)中遇到了RETURN,就要被缺省的策略(一般是ACCEPT或DROP)操作了。(译者注:这很象C语言中函数返回值的情况)

我们来举个例子说明一下,假设一个包进入了INPUT链,匹配了某条target为--jump EXAMPLE_CHAIN规则,然后进入了子链EXAMPLE_CHAIN。在子链中又匹配了某条规则,恰巧target是--jump RETURN,那包就返回INPUT链了。如果在INPUT链里又遇到了--jump RETURN,那这个包就要交由缺省的策略来处理了。


5.12. SNAT target

这个target是用来做源网络地址转换的,就是重写包的源IP地址。当我们有几个机子共享一个Internet 连接时,就能用到它了。先在内核里打开ip转发功能,然后再写一个SNAT规则,就可以把所有从本地网络出去的包的源地址改为Internet连接的地址了。如果我们不这样做而是直接转发本地网的包的话,Internet上的机子就不知道往哪儿发送应答了,因为在本地网里我们一般使用的是IANA组织专门指定的一段地址,它们是不能在Internet上使用的。SNAT target的作用就是让所有从本地网出发的包看起来都是从一台机子发出的,这台机子一般就是防火墙。

SNAT只能用在nat表的POSTROUTING链里。只要连接的第一个符合条件的包被SNAT了,那么这个连接的其他所有的包都会自动地被SNAT,而且这个规则还会应用于这个连接所在流的所有数据包。

Table 1-22. SNAT target

Option

--to-source

Example

iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to-source 194.236.50.155-194.236.50.160:1024-32000

Explanation

指定源地址和端口,有以下几种方式:

1、单独的地址。

2、一段连续的地址,用连字符分隔,如194.236.50.155-194.236.50.160,这样可以实现负载平衡。每个流会被随机分配一个IP,但对于同一个流使用的是同一个IP。

3、在指定-p tcp 或 -p udp的前提下,可以指定源端口的范围,如194.236.50.155:1024-32000,这样包的源端口就被限制在1024-32000了。

注意,如果可能,iptables总是想避免任何的端口变更,换句话说,它总是尽力使用建立连接时所用的端口。但是如果两台机子使用相同的源端口,iptables 将会把他们的其中之一映射到另外的一个端口。如果没有指定端口范围, 所有的在512以内的源端口会被映射到512以内的另一个端口,512和1023之间的将会被映射到 1024内,其他的将会被映射到大于或对于1024的端口,也就是说是同范围映射。还要注意,这种映射和目的端口无关。因此,如果客户想和防火墙外的HTTP服务器联系,它是不会被映射到FTP control所用的端口的。


5.13. TOS target

TOS是用来设置IP头中的Type of Service字段的。这个字段长一个字节,可以控制包的路由情况。它也是iproute2及其子系统可以直接使用的字段之一。值得注意的是,如果你有几个独立的防火墙和路由器,而且还想在他们之间利用包的头部来传递路由信息,TOS是唯一的办法。前面说过,MARK是不能用来传递这种信息的。如果你需要为某个包或流传递路由信息,就要使用TOS字段,它也正是为这个而被开发的。

Internet上有很多路由器在这一方面并没有做好工作,因此,在发送包之前改变其TOS没有什么大用处。最好的情况是路由器根本不理它,最坏的情况是路由器会根据TOS处理,但都是错误的。然而,如果你是在一个很大的WAN或LAN里,而且有很多路由器,TOS还是能有很好的作为的。总的来说,基于TOS的值给包以不同的路由和参数还是可能的,即使在网络里是受限制的(译者注:大不了不起作用就是了)。

 

TOS只能用来设置具体的或者说是特定的值(这些预定义的值在内核源码的include文件——Linux/ip.h中),原因是很多的,但不管怎么说,你不要使用其他的值就是了。当然,我们也有办法突破这个限制,就是使用一个名为FTOS的patch,你可在由Matthew G. Marsh维护的站点 Paksecured Linux Kernel patches得到它,但要小心使用哦。除了非常特殊、极端的情况,我们是不应该使用预定义以外的值的。

 

注意,这个target只能在mangle表内使用。

 

 

还要注意,在一些老版(1.2.2或更低)的iptables中包含的这个target在设置了TOS之后,不会调整包的校验和,这样包会被认为是错误的并要求重发。而且,这很可能会导致更多的mangle操作,从而使整个连接无法工作。(译者注:好在我们现在不会再用这么老的版本了:) )

TOS target只有一个选项:

Table 1-23. TOS target

Option

--set-tos

Example

iptables -t mangle -A PREROUTING -p TCP --dport 22 -j TOS --set-tos 0x10

Explanation

设置TOS的值,值的形式可以是名字或者使相应的数值(十进制或16进制的)。一般情况下,建议你使用名字而不使用数值形式,因为以后这些数值可能会有所改变,而名字一般是固定的。TOS字段有8个二进制位,所以可能的值是0-255(十进制)或0x00-0xFF(16进制)。如前所述,你最好使用预定义的值,它们是:

1、Minimize-Delay 16 (0x10),要求找一条路径使延时最小,一些标准服务如telnet、SSH、FTP- control 就需要这个选项。

2、Maximize-Throughput 8 (0x08),要求找一条路径能使吞吐量最大,标准服务FTP-data能用到这个。

3、Maximize-Reliability 4 (0x04),要求找一条路径能使可靠性最高,使用它的有BOOTP和TFTP。

4、Minimize-Cost 2 (0x02),要求找一条路径能使费用最低,一般情况下使用这个选项的是一些视频音频流协议,如RTSP(Real Time Stream Control Protocol)。

5、Normal-Service 0 (0x00),一般服务,没有什么特殊要求。这个值也是大部分包的缺省值。

完整的列表可以通过命令iptables -j TOS -h

得到。在1.2.5版时,这个列表就已经是完整的了,而且会保持很长一段时间。


5.14. TTL target

 

这个target需要patch-o-matic里的名为TTL的patch,可从 http://www.netfilter.org获得。此站点的FAQ是开始学习iptables和Netfilter的好地方。

TTL可以修改IP头中Time To Live字段的值。它有很大的作用,我们可以把所有外出包的Time To Live值都改为一样的,比如64,这是Linux的默认值。有些ISP不允许我们共享连接(他们可以通过TTL的值来区分是不是有多个机子使用同一个连接),如果我们把TTL都改为一样的值,他们就不能再根据TTL来判断了。

关于任何设置Linux的TTL默认值,请参阅附录其他资源和链接 内的ip-sysctl.txt

TTL只能在mangle表内使用,它有3个选项:

Table 1-24. TTL target

Option

--ttl-set

Example

iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-set 64

Explanation

设置TTL的值。这个值不要太大,也不要太小,大约64就很好。值太大会影响网络,而且有点不道德,为什么这样说呢?如果有些路由器的配置不太正确,包的TTL又非常大,那它们就会在这些路由器之间往返很多次,值越大,占用的带宽越多。这个target就可以被用来限制包能走多远,一个比较恰当的距离是刚好能到达DNS服务器。

Option

--ttl-dec

Example

iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-dec 1

Explanation

设定TTL要被减掉的值,比如--ttl-dec 3。假设一个进来的包的TTL是53,那么当它离开我们这台机子时,TTL就变为49了。为什么不是50呢?因为经过我们这台机子,TTL本身就要减1,还要被TTL target再减3,当然总共就是减去4了。使用这个 target可以限制“使用我们的服务的用户”离我们有多远。比如,用户总是使用比较近的DNS,那我们就可以对我们的DNS服务器发出的包进行几个--ttl-dec。(译者注:意思是,我们只想让距离DNS服务器近一些的用户访问我们的服务)当然,用--set-ttl控制更方便些。

Option

--ttl-inc

Example

iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-inc 1

Explanation

设定TTL要被增加的值,比如--ttl-inc 4。假设一个进来的包的TTL是53,那么当它离开我们这台机子时,TTL应是多少呢?答案是56,原因同--ttl-dec。使用这个选项可以使我们的防火墙更加隐蔽,而不被trace-routes发现,方法就是设置--ttl-inc 1。原因应该很简单了,包每经过一个设备,TTL就要自动减1,但在我们的防火墙里这个1又被补上了,也就是说,TTL的值没变,那么trace-routes就会认为我们的防火墙是不存在的。Trace-routes让人又爱又恨,爱它是因为在连接出问题时,它可以给我们提供极有用的信息,告诉我们哪里有毛病;恨它是由于它也可以被黑客或骇客用来收集目标机器的资料。怎么使用它呢?这里有个很好的例子,请看脚本Ttl-inc.txt


5.15. ULOG target

ULOG可以在用户空间记录被匹配的包的信息,这些信息和整个包都会通过netlink socket被多播。然后,一个或多个用户空间的进程就会接受它们。换句话说,ULOG是至今iptables和Netfilter下最成熟、最完善的日志工具,它包含了很多更好的工具用于包的记录。这个target可以是我们把信息记录到MySQL或其他数据库中。这样,搜索特定的包或把记录分组就很方便了。你可以在ULOGD project page里找到ULOGD用户空间的软件。

Table 1-25. ULOG target

Option

--ulog-nlgroup

Example

iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-nlgroup 2

Explanation

指定向哪个netlink组发送包,比如-- ulog-nlgroup 5。一个有32个netlink组,它们被简单地编号位1-32。默认值是1。

Option

--ulog-prefix

Example

iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-prefix 'SSH connection attempt: '

Explanation

指定记录信息的前缀,以便于区分不同的信息。使用方法和 LOG的prefix一样,只是长度可以达到32个字符。

Option

--ulog-cprange

Example

iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-cprange 100

Explanation

指定每个包要向“ULOG在用户空间的代理”发送的字节数,如--ulog-cprange 100,表示把整个包的前100个字节拷贝到用户空间记录下来,其中包含了这个包头,还有一些包的引导数据。默认值是0,表示拷贝整个包,不管它有多大。

Option

--ulog-qthreshold

Example

iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-qthreshold 10

Explanation

告诉ULOG在向用户空间发送数据以供记录之前,要在内核里收集的包的数量(译者注:就像集装箱),如--ulog-qthreshold 10。这表示先在内核里积聚10个包,再把它们发送到用户空间里,它们会被看作同一个netlink的信息,只是由好几部分组成罢了。默认值是1,这是为了向后兼容,因为以前的版本不能处理分段的信息。

    猜你喜欢
    发表评论评论公约
    喜欢该文的人也喜欢 更多