规则
Table of Contents
在内核看来,规则就是决定如何处理一个包的语句
基础
如果一个包符合所有的条件(就是符合matche语句),就运行target或jump指令。书写规则的语法格式是:
iptables [-t table] command [match] [target/jump]
- table :指定表名
- 一般情况下没有必要指定使用的表,iptables默认使用 filter 表来执行所有的命令
- 没有必要非得在这里指定表名,当然 把表名在开始处已经是约定俗成的标准
- command : 告诉程序该做什么
- 插入一个规则
- 在链的末尾增加一个规则
- 删除一个规则
- match : 细致地描述了包的某个特点,以使这个包区别于其它所有的包
- 来源IP地址
- 网络接口
- 端口
- 协议类型 或者其他什么
- target : 数据包的目标所在。 若数据包符合所有的match,内核就用target来处理它 ,或者说把包发往 target
- 让内核把包发送到当前表中的其他链(可能是自己建立的)
- 丢弃这个包而没有什么处理
- 向发送者返回某个特殊的应答
注意: target 指令必须在最后。为了易读,一般用这种语法。大部分规则都是按这种语法写的
Tables
选项 -t 用来指定使用哪个表,它可以是下面介绍的表中的任何一个,默认的是 filter 表
nat
网络地址转换 ,即 Network Address Translation ,缩写为 NAT 。做过NAT操作的数据包的地址就被改变了,当然这种改变是根据定义的规则进行的
属于一个流的包只会经过这个表一次。如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自动地被做相同的操作 。也就是说,余下的包不会再通过这个表,一个一个的被NAT,而是自动地完成。这就是为什么 不应该在这个表中做任何过滤的主要原因 。
- PREROUTING 链:在包刚刚到达防火墙时改变它的目的地址,如果需要的话
- OUTPUT 链:改变本地产生的包的目的地址
- POSTROUTING 链:包就要离开防火墙之前改变其源地址
mangle
改变不同的包及包头的内容 :
- TTL
- TOS
- MARK
MARK并没有真正地改动数据包,它只是在内核空间为包设了一个标记 防火墙内的其他的规则或程序可以使用这种标记对包进行过滤或高级路由
这个表有五个内建的链:
- PREROUTING : 包进入防火墙之后、路由判断之前改变包
- POSTROUTING : 在所有路由判断之后
- OUTPUT : 在确定包的目的之前更改数据包
- INPUT : 在包被路由到本地之后,但在用户空间的程序看到它之前改变包
- FORWARD : 在最初的路由判断之后、最后一次更改包的目的之前mangle包
mangle表不能做任何NAT,它只是改变数据包的 TTL,TOS或MARK,而不是其源目地址
filter
专门过滤包 的,可以毫无问题地对包进行
- DROP
- LOG
- ACCEPT
- REJECT
内建三个链:
- FORWARD : 过滤所有不是本地产生的并且目的地不是本地(所谓本地就是防火墙了)的包
- INPUT : 针对那些目的地是本地的包
- OUTPUT : 过滤所有本地生成的包的
Commands
command 指定iptables对 提交的规则要做什么样的操作
命令
append
-A, --append
在所选择的链末添加规则。当源地址或目的地址是以名字而不是ip地址的形式出现时,若这些名字可以被解析为多个地址,则这条规则会和所有可用的地址结合
iptables -A INPUT ...
delete
-D, --delete
从所选链中删除规则。有两种方法指定要删除的规则:
- 把规则完完整整地写出来
- 指定规则在所选链中的序号:每条链的规则都各自从1被编号
iptables -D INPUT --dport 80 -j DROP iptables -D INPUT 1
replace
-R, --replace
在所选中的链里指定的行上(每条链的规则都各自从1被编号)替换规则
主要的用处是 试验不同的规则 。当源地址或目的地址是以名字而不是ip地址的形式出现时,若这些名字可以被解析为多个地址,则 这条command会失败
iptables -R INPUT 1 -s 192.168.0.1 -j DROP
insert
-I, --insert
根据给出的规则序号向所选链中插入规则。 如果序号为1, 规则会被插入链的头部 , 默认序号就是1
iptables -I INPUT 1 --dport 80 -j ACCEPT
list
-L, --list
显示所选链的所有规则:
- 如果没有指定链,则显示指定表中的所有链
- 如果什么都没有指定,就显示默认表所有的链
精确输出受其它参数影响,如 -n 和 -v 等参数
iptables -L INPUT
flush
-F, --flush
清空所选的链:
- 如果没有指定链,则清空指定表中的所有 链
- 如果什么都没有指定,就清空默认表所有的链
也可以一条一条地删,但用这个command会快些
iptables -F INPUT
zero
-Z, --zero
把指定链(如未指定,则认为是所有链)的所有计数器归零
iptables -Z INPUT
new-chain
-N, --new-chain
根据用户指定的名字建立新的链
iptables -N allowed
注意:所用的名字不能和已有的链、target同名
delete-chain
-X, --delete-chain
删除指定的用户自定义链:
- 如果没有给出参数,这条命令将会 删除默认表所有非内建的链
iptables -X allowed
注意: 这个链必须没有被引用 ,如果被引用,在删除之前你必须删除或者替换与之有关的规则
policy
-P, --policy
为链设置默认的target(可用的是DROP 和ACCEPT),这个target称作策略
iptables -P INPUT DROP
- 所有不符合规则的包都被强制使用这个策略
- 只有内建的链才可以使用规则
- 但内建的链和用户自定义链都不能被作为策略使用,也就是说不能象这样使用:
iptables -P INPUT allowed(或者是内建的链)
rename-chain
-E, --rename-chain
对自定义的链进行重命名,原来的名字在前,新名字在后
iptables -E allowed disallowed
把 allowed 改为 disallowed 。这仅仅是改变链的名字,对整个表的结构、工作没有任何影响
选项
verbose
-v, --verbose
这个选项使输出详细化,常与 –list 连用:
- –list 连用时:输出中包括
- 网络接口的地址
- 规则的选项
- TOS掩码
- 字节和包计数器:
- 计数器是以K、M、G(这里用的是10的幂而不是2的幂哦)为单位的
- 和 –append 、 –insert 、 –delete 或 –replace 连用,iptables会输出详细的信息告诉规则是如何被解释的、是否正确地插入等等
exact
-X --exact
使 –list 输出中的计数器显示准确的数值,而不用K、M、G等估值
注意:此选项只能和–list连用
numeric
-n, --numeric
使输出中的IP地址和端口以数值的形式显示,而不是默认的名字:
- 主机名
- 网络名
- 程序名等
注意:此选项也只能和 –list 连用
line-numbers
--line-numbers
显示出每条规则在相应链中的序号。这样可以知道序号了,这对插入新规则很有用
注意:此选项也只能和 –list 连用
set-counters
-c, --set-counters
在创建或更改规则时设置计数器
--set-counters 20 4000
让内核把包计数器设为20,把字节计数器设为4000
可以搭配的命令:
- –insert
- –append
- –replace
modprobe
--modprobe
告诉iptables探测并装载要使用的模块。万一modprobe命令不在搜索路径中,就要用到了。有了这个选项, 在装载模块时,即使有一个需要用到的模块没装载上,iptables也知道要去搜索
Matches
可以把匹配归为五类:
- 通用 匹配 :适用于所有的规则
- TCP 匹配 : 只能用于TCP包
- UDP 匹配 : 只能用在UDP包上了
- ICMP 匹配:针对ICMP包的
- 特殊 匹配:针对
- 状态( state )
- 所有者( owner )
- 访问的频率限制( limit )等
通用匹配
无论使用的是何种协议,也不管装入了匹配的何种扩展,通用匹配都使可用的。也就是说, 它们可以直接使用,而不需要什么前提条件
protocol
-p, --protocol
匹配 指定的协议 。指定协议的形式有以下几种:
- 名字,不分大小写,但必须是在 /etc/protocols 中定义的
- 可以使用它们相应的整数值。例如
- ICMP : 1
- TCP : 6
- UDP : 17
- 缺省设置, ALL ,相应数值是 0 ,但要注意这只代表匹配TCP、UDP、ICMP,而不是/etc/protocols中定义的所有协议
- 可以是协议列表,以英文逗号为分隔符,如: udp,tcp
- 可以在协议前加英文的感叹号表示取反,注意 有空格 ,如:
- –protocol ! tcp 表示非tcp协议,也就是 UDP和ICMP 。可以看出这个取反的范围只是TCP、UDP和ICMP
iptables -A INPUT -p tcp
source
-s, --src, --source
以 IP源地址 匹配包。地址的形式如下:
- 单个地址,如
- 192.168.1.1
- 192.168.1.1/255.255.255.255
- 192.168.1.1/32
- 网络,如
- 192.168.0.0/24
- 192.168.0.0/255.255.255.0
- 在地址前加 感叹号 表示取反,注意 空格
- –source ! 192.168.0.0/24 表示除此地址外的所有地址
- 缺省: 所有地址
iptables -A INPUT -s 192.168.1.1
destination
-d, --dst, --destination
以 IP目的地址 匹配包。地址的形式和 –source 完全一样
iptables -A INPUT -d 192.168.1.1
in-interface
-i, --in-interface
以 包进入本地所使用的网络接口 来匹配包。这个匹配操作只能用于 INPUT , FORWARD 和 PREROUTING 这三个链,用在其他任何地方都会提示错误信息。指定接口有以下方法:
- 指定接口名称,如:
- eth0
- ppp0等
- 使用 通配符 ,即 加号,它代表字符数字串
- iptables -A INPUT -i + : 匹配所有的包,而不考虑使用哪个接口。这也是不指定接口的默认行为
- eth+ : 所有Ethernet接口,也就是说,匹配所有从Ethernet接口进入的包
- 在接口前加 感叹号 表示取反,注意 _空格,
- -i ! eth0 :匹配来自除eth0外的所有包
iptables -A INPUT -i eth0
out-interface
-o, --out-interface
以 包离开本地所使用的网络接口 来匹配包。指定接口的方法与 –in-interface 完全一样
iptables -A FORWARD -o eth0
fragment
-f, --fragment
用来匹配 一个被分片的包的第二片或及以后的部分 。因为它们不包含源或目的地址,或ICMP类型等信息,其他规则无法匹配到它,所以才有这个匹配操作:
- 防止碎片攻击
- 可以加 感叹号 表示取反,但注意 位置
- ! -f : 只能匹配到没有分片的包或者是被分片的包的第一个碎片,其后的片都不行
iptables -A INPUT -f
现在内核有完善的碎片重组功能,可以防止碎片攻击,所以不必使用取反的功能来防止碎片通过 如果使用连接跟踪,是不会看到任何碎片的,因为在它们到达任何链之前就被处理过了
隐含匹配
这种匹配操作是 自动地或隐含地 装载入内核的。例如使用 –protocol tcp 时,不需再装入任何东西就可以匹配只有IP包才有的一些特点。现在有三种隐含的匹配针对三种不同的协 议,即
- TCP
- UDP
- ICMP
它们分别包括一套只适用于相应协议的判别标准
TCP
TCP matches只能匹配 TCP包或流 的细节,必须有 –protocol tcp 作为前提条件
source-port
--sport, --source-port
基于TCP包的 源端口 来匹配包,端口的指定形式如下:
- 不指定此项: 默认 所有端口
- 使用 服务名或端口号 ,但名字必须是在 /etc/services 中定义的,因为iptables从这个文件里查找相应的端口号。从这可以看出,使用端口号会使规则装入快一点 儿,当然,可读性就差些了
- 使用 连续的端口 ,
- –source-port 22:80 : 从22到80的所有端 口,包括22和80。如果两个号的顺序反了也没关系, –source-port 80:22 这和 –source-port 22:80 的效果一样
- 省略第一个号, 默认第一个是0
- –source-port :80 : 从0到80的 所有端口
- 省略第二个号, 默认是65535
- –source-port 22: : 从22到 65535的所有端口
- 在端口号前加 感叹号 表示取反,注意 空格
- –source-port ! 22 : 除22号之外的所有端口
- –source-port ! 22:80 : 从22到80(包括22和80)之外的所有端口
iptables -A INPUT -p tcp --sport 22
注意:这个匹配操作不能识别不连续的端口列表,如: –source-port ! 22, 36, 80 这样的操作
destination-port
--dport, --destination-port
基于TCP包的 目的端口 来匹配包,端口的指定形式和 –sport 完全一样
iptables -A INPUT -p tcp --dport 22
tcp-flags
--tcp-flags
匹配 指定的TCP标记 。有两个参数,它们都是列表,列表内部用 逗号作分隔符,这两个列表之间用空格分开
- 第一个参数: 要 检查的标记 ,作用就象掩码。提供 检查范围
- 第二个参数: 在第一个列表中出现过的且必须被设为1 (即状态是打开的)标记(第一个列表中其他的标记必须置0) 。提供被 设置的条件 , 就是哪些位置为设置
这个匹配操作可以识别以下标记:
- SYN
- ACK
- FIN
- RST
- URG
- PSH
- ALL : 选定所有的标记
- NONE : 未选定任何标记
iptables -p tcp --tcp-flags SYN,FIN,ACK SYN
匹配那些 SYN标记被设置而FIN和ACK标记没有设置 的包
注意: 标记之间只有一个逗号而没有空格
iptables --tcp-flags ALL NONE
匹配所有标记都未置1的包
也可在参数前加 感叹号 表示取反。例如:
iptables -p tcp --tcp-flags ! SYN,FIN,ACK SYN
匹配那些 FIN和ACK标记被设置而SYN标记没有设置 的包
syn
--syn 这个匹配或多或少算是ipchains时代的遗留物,之所以还保留它,是为了向后兼容,也是为了方便规则在iptables和ipchains间的转换
匹配那些SYN标记被设置而ACK和RST标记没有设置的包 ,这和 iptables -p tcp –tcp-flags SYN,RST,ACK SYN 的作用毫无二样。主要用在 TCP连接初始化时发出请求
iptables -p tcp --syn
如果你阻止了这样的包,也就阻止了所有由外向内的连接企图,这在一定程度上防止了一些攻击 但外出的连接不受影响,恰恰现在有很多攻击就利用这一点 比如有些攻击黑掉服务器之后安装会一些软件,它们能够利用已存的连接到达你的机子,而不要再新开一个端口
这个匹配也可用 感叹号 取反:
- ! –syn : 那些RST或ACK被置位的包,就是 状态为已建立的连接 的包
tcp-option
--tcp-option
TCP选项 是TCP头中的特殊部分,有三个不同的 部分
- 第一个8位组: 选项的类型
- 第二个8位组: 选项的长度 (这个长度是整个选项的长度,但不包含填充部分所占的字节,而且要注意不是每个TCP选项都有这一部分的)
- 第三部分: 选项的内容
为了适应标准,不必执行所有的选项,但可以查看选项的类型,如果不是所支持的,那就只是看看长度然后跳过数据部分。这个操作是根据 选项的十进制值 来匹配的,它也可以用 感叹号 取反
iptables -p tcp --tcp-option 16
UDP
UDP matches是在指定 –protocol UDP 时自动装入的。UDP是一种 无连接协议 ,所以在它打开、关闭连接以及在发送数据时没有多少标记要设置,它也不需要任何类型的确认。数据丢失了, 就丢失了(不会发送ICMP错误信息的)。这就说明UDP matches要比TCP matches少多了。 即使UDP和ICMP是无连接协议,状态机制也可以很好的工作 ,就象在TCP上一样
source-port
--sport, --source-port
基于 UDP包的源端口 来匹配包,端口的指定形式和TCP matches中的 –sport 完全一样
iptables -A INPUT -p udp --sport 53
destination-port
--dport, --destination-port
基于 UDP包的目的端口 来匹配包,端口的指定形式和TCP matches中的 –sport 完全一样
iptables -A INPUT -p udp --dport 53
ICMP
ICMP协议也是无连接协议,ICMP包更是短命鬼,比UDP的还短。ICMP协议不是IP协议的下属协议,而是它的辅助者,其主要作用是 报告错误和连接控制 。ICMP包的头和IP的很相似,但又有很多不同。这个协议最主要的特点是它有很多类型,以应对不同的情况。比如,想访问一个无法访问的地址,就会收到一个ICMP host unreachable信息,它的意思是主机无法到达。虽然有这么多类型,但只有一个 ICMP matche,这就足够对付它们了。这个matche是在指定 –protocol ICMP 时自动 装入的。注意所有的通用匹配都可以使用,这样就可以匹配 ICMP包的源、目地址
icmp-type
--icmp-type
根据 ICMP类型 匹配包,类型的指定可以使用 十进制数值 或 相应的名字 :
- 数值:在 RFC792 中有定义
- 名字:用 iptables –protocol icmp –help 查看
这个匹配也可用 感叹号 取反
- –icmp-type ! 8 : 匹配除类型8之外的所有ICMP包
iptables -A INPUT -p icmp --icmp-type 8
有些ICMP类型已经废弃不用了 还有一些可能会对无防护的主机带来危险,因为它们可能把包重定向到错误的地方
显示匹配
显式匹配必须用 -m 或 –match 装载,比如要使用状态匹配就必须使用 -m state
有些匹配还需要指定协议,有些就不需要,比如连接状态就不要。这些状态是
- NEW : 还未建立好的连接的第一个包
- ESTABLISHED: 已建立的连接,也就是已经在内核里注册过的
- RELATED: 已经存在的、处于已建立状态的连接生成的新连接
隐含匹配和显式匹配最大的区别就是 一个是跟随协议匹配自动装载的,一个是显式装载的
Limit
这个匹配操作必须由 -m limit 明确指定才能使用:
- 对指定的规则的日志数量加以限制,以免你被信息的洪流淹没哦。比如,你可以事先设定一个限定值,当符合条件的包的数量不超过它时,就记录;超过了,就不记录了
- 可以控制某条规则在一段时间内的匹配次数 (也就是可以匹配的包的数量),这样就能够减少 DoS syn flood 攻击的影响
imit match也可以用 感叹号 取反: -m limit ! –limit 5/s : 表示在数量超过限定值后,所有的包都会被匹配
limit match的工作方式就像一个单位大门口的保安,当有人要进入时,需要找他办理通行证 早上上班时,保安手里有一定数量的通行证,来一个人,就签发一个,当通行证用完后,再来人就进不去了,但他们不会等,而是到别的地方去 在iptables里,这相当于一个包不符合某条规则,就会由后面的规则来处理,如果都不符合,就由缺省的策略处理 但有个规定,每隔一段时间保安就要签发一个新的通行证。这样,后面来的人如果恰巧赶上,也就可以进去了 如果没有人来,那通行证就保留下来,以备来的人用 如果一直没人来,可用的通行证的数量就增加了,但不是无限增大的,最多也就是刚开始时保安手里有的那个数量 也就是说,刚开始时,通行证的数量是有限的,但每隔一段时间就有新的通行证可用
limit match有两个参数就对应这种情况:
- –limit-burst :刚开始时有多少通行证可用
- –limit :要隔多长时间才能签发一个新的通行证
这里强调的是 签发一个新的通行证 ,这是 以iptables的角度 考虑的。在自己写规则时,就要从这个角度考虑。比如,指定了 –limit 3/minute –limit-burst 5 :
- iptables的角度:开始时有5个通行证,用完之后每20秒增加一个
- 以用户的角度看:说法就是每一分钟增加三个或者每分钟只能过三个
要是想每20分钟过一个,只能写成 –limit 3/hour –limit-burst 5 ,也就是说 要把时间单位凑成整
limit
--limit
为limit match设置最大平均匹配速率 ,也就是单位时间内limit match可以匹配几个包。它的形式是 一个数值加一个时间单位 :
- /second
- /minute
- /hour
- /day
默认值是 每小时3次 (用户角度),即 3/hour ,也就是 每20分钟一次 (iptables角度)
iptables -A INPUT -m limit --limit 3/hour
limit-burst
--limit-burst
定义的是 limit match的峰值 , 就是在单位时间(这个时间由上面的–limit指定)内最多可匹配几个包(–limit-burst的值要比–limit的大)。默认值是5
iptables -A INPUT -m limit --limit-burst 5
MAC
基于 包的MAC源地址 匹配包
这个match是由-m mac装入的,而不是一些人想当然的-m mac-source,后者只是前者的选项而已
mac-source
--mac-source
基于包的MAC源地址匹配包,地址格式只能是 XX:XX:XX:XX:XX:XX ,当然也可以用 感叹号 取反
- –mac- source ! 00:00:00:00:00:01 : 除此之外的地址都可接受嘛
- MAC addresses只用于 Ethernet 类型的网络,所以这个match只能用于Ethernet接口。而且,它还只能在
- PREROUTING
- FORWARD
- INPUT 链里使用
iptables -A INPUT -m mac --mac-source 00:00:00:00:00:01
Mark
以 包被设置的mark 来匹配包,这个值只能由内核更改
mark比较特殊,它不是包本身的一部分,而是在包穿越计算机的过程中由内核分配的和它相关联的一个字段 它可能被用来改变包的传输路径或过滤 时至今日,在linux里只有一种方法能设置mark,即iptables的MARK target 以前在ipchains里是FWMARK target。这就是为什么在高级路由里仍要参照FWMARK的原因
mark字段的值是一个 无符号的整数 , 在32位系统上最大可以是 4294967296 ,就是2的32次方
mark
--mark value[/mask]
iptables -t mangle -A INPUT -m mark --mark 1
以包被设置的mark值来匹配包,这个值是通过 MARK target 来设置的,它是一个无符号的整数。上面的例子是没有掩码的,如果指定了掩码:
- –mark 1/1 :先把 mark值和掩码取逻辑与 ,然后再和包的mark值比较
所有通过Netfilter的包都会被分配一个相关联的mark field 但是mark值可不是在任何情况下都能使用的,它只能在分配给它值的那台机子里使用 因为它只是由内核在内存里分配的和包相关的几个字节,并不属于包本身,所以不能在本机之外的路由器上使用
Multiport
多端口匹配 扩展能够在一条规则里指定不连续的多个端口,如果没有这个扩展,只能按端口来写规则了
不能在一条规则里同时使用标准端口匹配和多端口匹配,如--sport 1024:63353 -m multiport --dport 21,23,80 这条规则并不能想你想象的那样工作,但也不是不能工作,iptables会使用第一个合法的条件,那么这里多端口匹配就白写了
source-port
--source-port
源端口多端口 匹配:
- 最多可以指定 15 个端口
- 以 逗号 分隔
- 没有空格
- 必须有 -p tcp 或 -p udp 为前提条件
iptables -A INPUT -p tcp -m multiport --source-port 22,53,80,110
destination-port
--destination-port
目的端口多端口 匹配,使用方法和 源端口多端口 匹配一样
iptables -A INPUT -p tcp -m multiport --destination-port 22,53,80,110
port
--port
同端口多端口 匹配,意思就是它匹配的是那种 源端口和目的端口是同一个端口 的包,比如: 端口80到端口80 的包。使用方法和 源端口多端口 匹配一 样
iptables -A INPUT -p tcp -m multiport --port 22,53,80,110
Owner
基于 包的生成者 ( owner )的ID来匹配包,owner可以是:
- 启动进程的用户的ID
- 用户所在的组的ID
- 进程的ID
- 会话的ID
只能用在OUTPUT中 原因显而易见:几乎不可能得到发送端例程的ID的任何信息,或者在去往真正目的地的路上哪儿有路由 甚至在 OUTPUT链里,这也不是十分可靠,因为有些包根本没有owner,比如 ICMP responses,所以它们从不会被这个match抓到
uid-owner
--uid-owner
按 生成包的用户的ID 来匹配外出的包。使用这个匹配可以做这样一些事:
- 阻止除root外的用户向防火墙外建立新连接
- 阻止除用户http外的任何人使用HTTP端口发送数据
iptables -A OUTPUT -m owner --uid-owner 500
gid-owner
--gid-owner
按 生成包的用户所在组的ID 来匹配外出的包:
- 可以只让属于network组的用户上Internet,而其他用户都不 行
- 只允许http组的成员能从HTTP端口发送数据
iptables -A OUTPUT -m owner --gid-owner 0
pid-owner
--pid-owner
按 生成包的进程的ID 来匹配外出的包:
- 可以只允许PID为94的进程(http进程当然不能是多线程的)使用http端口
iptables -A OUTPUT -m owner --pid-owner 78
这个匹配使用起来有一点难度,因为要知道进程的ID号。当然,也可以写一个小小的脚本,先从ps的输出中得到PID,再添加相应的规则
sid-owner
--sid-owner
按 生成包的会话的ID 来匹配外出的包。 一个进程以及它的子进程或它的多个线程都有同一个SID :
- 所有的HTTPD进程的SID和它的父进程一样(最初的 httpd进程),即使httpd是多线程的也一样
iptables -A OUTPUT -m owner --sid-owner 100
State
状态匹配扩展要有 内核里的连接跟踪代码的协助 ,因为它是从连接跟踪机制中得到包的状态的。这样就可以了解连接所处的状态。它几乎适用于所有的协议,包括那些无状态的协议,如ICMP和UDP。针对每个连接都有一个 缺省的超时值 ,如果连接的时间超过了这个值,那么这个连接的记录就被会从连接跟踪的记录数据库中删除,也就是说连接就不再存在了。这个match必须有 -m state 作为前提才能使用
state
--state
指定要匹配 包的状态 ,当前有4种状态可用:
- INVALID
- ESTABLISHED
- NEW
- RELATED
iptables -A INPUT -m state --state RELATED,ESTABLISHED
注意: NEW状态并不在试图建立新连接的TCP包里寻找SYN标 记,因此它不应该不加修改地用在只有一个防火墙或在不同的防火墙之间没有启用负载平衡的地方
TOS
根据TOS字段匹配包,必须使用 -m tos 才能装 入。TOS是IP头的一部分,其含义是Type Of Service,由8个二进制位组成:
- 3 bit: 优先权 子字段,现在已被忽略
- 4 bit: TOS子字段
- 1 bit: 未用位,必须置 0
一般用来把当前流的优先权和需要的服务(比如,最小延时、最大吞吐量 等)通知路由器 但路由器和管理员对这个值的处理相差很大,有的根本就不理会,而有的就会尽量满足要求
tos
--tos
根据 TOS字段 匹配包。它的参数可以是:
- 16进制数
- 十进制数
- 相应的名字 : 用 iptables -m tos -h 能查到
iptables -A INPUT -p tcp -m tos --tos 0x16
这个match常被 用来mark 包,以便后用,还常和iproute2或高级路由功能一起使用:
- 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
- Normal-Service 0 (0x00) : 一般服务,没有什么特殊要求
TTL
根据 IP头里的TTL ( Time To Live )字段 来匹配包,此必须由 -m ttl 装入
TTL field是一个字节(8个二进制位),一旦经过一个处理它的路由器,它的值就减去1它的值 当该字段的值减为0时,报文就被认为是不可转发的,数据报就被丢弃,并发送ICMP报文通知源主机,不可转发的报文被丢弃 这也有两种情况,一是传输期间生存时间为0,使用类型为11代码是0的ICMP报文 二是在数据报重组期间生存时间为0,使用类型 为11代码是1的ICMP报文
这个match只是根据TTL匹配包,而对其不做任何更改,所以在它之后可使用任何类型的match
ttl
--ttl
根据TTL的值来匹配包,参数的形式只有一种,就是 十进制 数值:
- 它可以被用来调试你的局域网,比如解决LAN内的主机到Internet上的主机的连接问题
- 找出 Trojan 可能的入口
iptables -A OUTPUT -m ttl --ttl 60
这个match的用处相对有限,但它其实是很有用的,这就看你的想象力如何了:
- 可以用它来发现那些TTL具有错误缺省值的机子:这可能是实现TCP/IP栈功能的那个程序本身的错误,或者是配置有问题
非正常包的匹配
这个匹配没有任何参数,也不需要显式地装载:
- 一个实验性的匹配,它不总是能正常工作的,对有些不正常的包(unclean package,就是所谓的脏包)或问题,它是视而不见的
- 试图匹配那些好象畸形或不正常的包,比如包头错或校验和错,等等
它可能常用来:
- DROP错误的连接
- 检查有错的流
但要知道这样做也可能会中断合法的连接
Target/Jump
target/jump 决定符合条件的包到何处去,语法是
--jump target 或 -j target
Target和Jump唯一的区别:
- jump: 目标是一个在同一个表内的链
- target: 目标是具体的操作
下面在 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在对包做完操作之后,包还会继续和其他的规则比较,如LOG,ULOG和TOS。它们会对包进行记 录、mangle,然后让包通过,以便匹配这条链中的其他规则。有了这样的target,就可以对同一个包既改变它的TTL又改变它的TOS
- 有些target必须要有准确的参数(如TOS需要确定的数值)
- 有些就不是必须要有准确的参数,但如果想指定也可以(如日志的前缀,伪装使用的端口,等等)
ACCEPT
-j ACCEPT
没有任何选项和参数,使用也很简单,指定 -j ACCEPT 即可:
- 一旦包满足了指定的匹配条件,就会被ACCEPT,并且不会再去匹配当前链中的其他规则或同一个表内的其他规则
- 但它还要通过其他表中的链,而且在那儿可能会被DROP掉
DNAT
用来做 目的网络地址转换 的,就是重写包的目的IP地址。如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以被路由到正确的主机或网络:
- Web服务器在LAN内部,而且没有可在Internet上使用的真实IP地址,可以使用这个让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的Web服务器
- 目的地址也可以是一个范 围,这样的话,DNAT会为每一个流随机分配一个地址。因此,可以用这个target做某种类型地负载平 衡。
DANT只能用在nat表的PREROUTING和OUTPUT链中,或者是被这两条链调用的链里 包含DANT target的链不能被除此之外的其他链调用,如POSTROUTING
to-destination
--to-destination
指定要写入IP头的地址,这也是包要被转发到的地方
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
把所有发往地址 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
只有先用--protocol指定了TCP或UDP协议,才能使用端口
SNAT 的语法和这个target的一样,只是目的不同罢了
更详细的例子
我想通过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
- 包从地址为 $EXT _BOX的机子出发,去往地址为$INET _ IP的机子
- 包到达防火墙
- 防火墙DNAT(也就是转发)这个包,而且包会经过很多其他的链检验及处理
- 包离开防火墙向$HTTP _ IP前进
- 包到达HTTP服务器,服务器就会通过防火墙给以回应,当然,这要求 把防火墙作为 HTTP 到达 $EXT _ BOX 的网关 。一般情况下,防火墙就是HTTP服务器的缺省网关
- 防火墙再对返回包做 Un-DNAT (就是照着DNAT的步骤反过来做一遍),这样就好像是防火墙自己回复了那个来自外网的请求包
- 返回包好象没经过这么复杂的处理、没事一样回到 $EXT _ BOX
现在,来考虑和HTTP服务器在同一个内网(这里是指所有机子不需要经过路由器而可以直接互相访问的网络,不是那种把服务器和客户机又分在不同子网的情况)的客户访问它时会发生什么。假设客户机的IP为$LAN _ BOX,其他设置同上
- 包离开$LAN _ BOX,去往$INET _ IP
- 包到达防火墙
- 包被 DNAT ,而且还会经过其他的处理。但是包没有经过 SNAT 的处理,所以 包还是使用它自己的源地址,就是$LAN _ BOX
- 包离开防火墙,到达HTTP服务器
- HTTP服务器试图回复这个包。它在 路由数据库中看到包是来自同一个网络的一台机子,因此它会把回复包直接发送到请求包的源地址 (现在是回复包的目的地址),也就是$LAN _ BOX
- 回复包到达客户机,但它会很困惑,因为 这个包不是来自它访问的那台机子 。这样,它就会把这个包 扔掉 而去等待 真正 的回复包
IP传输包的特点:只根据目的地的不同改变目的地址,但不因传输过程中要经过很多路由器而随着路由器改变其源地址,除非你单独进行源地址的改变 这是造成内网无法访问的根本原因
有个简单的解决办法:因为这些包都要进入防火墙,而且它们都去往需要做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
警告:刚才写的这条规则会对日志产生很大影响,这种影响应该说是很不好的。因为来自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
有了最后这条规则,一切都正常了:
- PREROUTING 链做 DNAT :和HTTP服务器不在同一个网的机子能正常访问服务了
- POSTROUTING 链做 SNAT :和它在一个网内的机子也可以正常访问服务了:
- OUTPUT 链做 DNAT :防火墙本身也能正常访问服务了
除此之外,在 filter表中还需要其他的规则(在FORWARD链里),以允许特定的包也能经过前面写的(在POSTROUTING链和 OUTPUT链里的)规则 在写规则时要注意:千万不要忘了,那些包在到达FORWARD链之前已经在PREROUTING链里被DNAT过了,也就是说它们的目的地址已被改写
DROP
如果包符合条件,这个target就会把它丢掉,也就是说包的生命到此结束,不会再向前走一 步,效果就是包被阻塞了:
在某些情况下,这个target会引起意外的结果,因为它不会向发送者返回任何信 息,也不会向路由器返回信息,这就可能会使连接的另一方的sockets因苦等响应
解决这个问题的较好的办法是使用 REJECT target
因为它在丢弃包的同时还会向发送者返 回一个错误信息,这样另一方就能正常结束 尤其是在阻止端口扫描工具获得更多的信息时,可以隐蔽被过滤掉的端口等等 因为扫描工具扫描一个端口时,如果没有返回信息,一般会认为端口未打开或被防火墙等设备过滤掉了
注意:如果包在子链中被DROP了,那么它在主链里也不会再继续前进,不管是在当前的表还是在其他表里。总之,包被丢弃了
LOG
专门用来 记录包的有关信息 的。这些信息可能是非法的,那就可以用来除错。LOG会返回包的有关细节,如IP头的大部分和其他有趣的信息。这个功能是通过内核的日志工具完成的,一般是syslogd。返回的信息可用dmesg阅读,或者可以直接查看syslogd的日志文件,也可以用其他的什么程序来看
LOG对调试规则有很大的帮助,可以看到包去了哪里、经过了什么规则的处理,什么样的规则处理什么样的包,等等。当你在生产服务器上调试一个不敢保证100%正常的规则集时,用LOG代替DROP是比较好的,因为一个小小的语法错误就可能引起严重的连接问题
如果你想使用真正地扩展日志地话,可能会对 ULOG target有些兴趣,因为它可以把日志直接记录到MySQL databases或类似的数据库中
如果在控制台得到的信息不是你想要的,那不是iptables或Netfilter的问题,而是 syslogd 配置文件的事,这个文件一般都是/etc/syslog.conf
log-level
--log-level
告诉iptables和 syslog使用哪个记录等级。记录等级的详细信息可以查看文件syslog.conf,一般来说有以下几种,它们的级别依次是:
- debug
- info
- notice
- warning/warn
- err/error
- crit
- alert
- emerg/panic
信息级别说明了 被记录信息所反映的问题的严重程度 。所有信息都是通过内核的功能被记录的:
- 先在文件 syslog.conf里设置kern.=info /var/log/iptables
- 再让所有关于iptables的LOG信息使用级别info,就可以把所有的信息存入文件/var/log/iptables内
iptables -A FORWARD -p tcp -j LOG --log-level debug
log-prefix
--log-prefix
告诉iptables在记录的信息之前加上指定的前缀。这样和grep或其他工具一起使用时就容易追踪特定的问题,而且也方便从不同的规则输出。前缀最多能有29个英文字符,这已经是包括空白字符和其他特殊符号的总长度了
iptables -A INPUT -p tcp -j LOG --log-prefix "INPUT packets"
log-tcp-sequence
--log-tcp-sequence
把包的TCP序列号和其他日志信息一起记录下来。 TCP序列号 可以唯一标识一个包,在重组时也是用它来确定每个分组在包里的位置
iptables -A INPUT -p tcp -j LOG --log-tcp-sequence
这个选项可能会带来危险, 因为这些记录被未授权的用户看到的话,可能会使他们更容易地破坏系统 任何iptables的输出信息都增加了这种危险
log-tcp-options
--log-tcp-options
记录TCP包头中的字段大小不变的选项。这对一些除错是很有价值的,通过它提供的信息,可以知道哪里可能出错,或者哪里已经出了错
iptables -A FORWARD -p tcp -j LOG --log-tcp-options
log-ip-options
--log-ip-options
记录IP包头中的字段大小不变的选项。这对一些除错是很有 价值的,还可以用来跟踪特定地址的包
iptables -A FORWARD -p tcp -j LOG --log-ip-options
MARK
用来设置mark值,这个值只能在 本地 的 mangle 表里使用,不能用在其他任何地方,就更不用说路由器或另一台机子了。因为mark比较特殊,它不是包本身的一部分,而是在包穿越计算机的过程中由内核分配的和它相关联的一个字段。它可以和本地的高级路由功能联用,以使不同的包能使用不同的队列要求等等
如果想在传输过程中也有这种功能,还是用 TOS target吧
set-mark
--set-mark
设置mark值,这个值是一个无符号的整数。比如,对一 个流或从某台机子发出的所有的包设置了mark值,就可以利用高级路由功能来对它们进行流量控制等操作
iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 2
MASQUERADE
和 SNAT target的作用是一样的,区别就是它不需要指定 –to-source 。MASQUERADE是被专门设计 用于那些动态获取IP地址的连接的 :
- 拨号上网
- DHCP连接
如果有固定的IP地址,还是用SNAT target吧
伪装一个连接意味着, 自动获取网络接口的IP地址 ,而不使用 –to-source 。当接口停用时,MASQUERADE不会记住任何连接,这在kill掉接口时是有很大好处的。如果我们使用SNAT target,连接跟踪的数据是被保留下来的,而且时间要好几天哦,这可是要占用很多连接跟踪的内存的。一般情况下,这种处理方式对于拨号上网来说是较好 的(这有利于已有那连接继续使用)
。如果我们被分配给了一个不同于前一次的IP,不管怎样已有的连接都要丢失,但或多或少地还是有一些连接记录被保留了
即使你有静态的IP,也可以使用MASQUERADE,而不用SNAT 。这不是被赞成的,因为它会带来额外的开销,而且以后还可能引起矛盾,比如它也许会影响你的脚本,使它们不能用
注意:MASQUERADE和SNAT一样,只能 用于nat表的POSTROUTING链
to-ports
--to-ports
在指定TCP或UDP的前提下,设置外出包能使用的端口:
- 单个端口: –to-ports 1025
- 端口范围: –to- ports 1024-3000
- 不是必需的
iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE --to-ports 1024-31000
注意:在指定范围时要使用 连字号 。这改变了SNAT中缺省的端口选择
REDIRECT
防火墙所在的机子内部转发包或流到另一个端口 。比如,可以把所有去往端口HTTP的包REDIRECT到HTTP proxy(例如squid),当然这都 发生在自己的主机内部 。本地生成的包都会被映射到127.0.0.1。换句话说,这个target把要转发的包的目的地址改写为我们自己机子的IP:
- 透明代理:LAN内的机子根本不需要知道代理的存在就可以正常上网时,这个target很有用
注意:它只能用在 nat表的PREROUTING、OUTPUT链和被它们调用的自定义链 里
to-ports
--to-ports
在指定TCP或UDP协议的前提下,定义目的端口,方式如下:
- 不使用这个选项:目的端口不会被改变
- 指定一个端口: –to-ports 8080
- 指定端口范围: –to-ports 8080-8090
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
REJECT
REJECT 和 DROP 基本一样,区别在于它 除了阻塞包之外, 还向发送者返回错误信息 。
注意:
- 只能用在 INPUT、FORWARD、OUTPUT和它们的子链里
- 包含 REJECT 的链也只能被它们调用,否则不能发挥作用
reject-with
它只有一个选项,是用来控制返回的错误信息的种类的
--reject-with
告诉REJECT target应向发送者返回什么样的信息。一旦包满足了设定的条件,就要发送相应的信息,然后再象DROP一样无情地抛弃那些包。可用的信息类型有:
- icmp-net-unreachable
- icmp-host-unreachable
- icmp-port-unreachable
- icmp-proto-unreachable
- icmp-net-prohibited
- icmp-host-prohibited
- echo-reply
- tcp-reset:告诉REJECT返回一个TCP RST包,以文雅的方式关闭TCP连接
其中缺省的是 port-unreachable
iptables -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
tcp-reset主要用来 阻塞身份识别探针 ,即113/tcp,当向被破坏的邮件主机发送邮件时, 探针常被用到,否则它不会接受你的信
RETURN
它使包返回上一层,顺序是: 子链 ->父链 -> 缺省的策略 。具体地说,就是若包在子链中遇到了RETURN,则返回父链的下一条规则继续进行条件的比较,若是在父链(或称主链,比如INPUT)中遇到了RETURN,就要被缺省的策略(一般是ACCEPT或DROP)操作了
假设一个包进入了INPUT链,匹配了某条target为 –jump EXAMPLECHAIN 规则,然后进入了子链 EXAMPLECHAIN 。在子链中又匹配了某条规则,恰巧target是 –jump RETURN ,那包就返回 INPUT 链了。如果在INPUT链里又遇到了 –jump RETURN ,那这个包就要交由 缺省的策略 来处理
SNAT
用来做 源网络地址 转换的,就是重写包的源IP地址
有几个机子共享一个Internet连接时,就能用到它了:
- 先在内核里打开 ip转发 功能
- 再写一个 SNAT规则
就可以把所有从本地网络出去的包的源地址改为Internet连接的地址了
如果我们不这样做而是直接转发本地网的包的话,Internet上的机子就不知道往哪儿发送应答了,因为在 本地网里一般使用的是专门指定的一段地址,它们是不能在Internet上使用的 。SNAT target的作用就是让所有从本地网出发的包看起来都是从一台机子发出的,这台机子一般就是防火墙
注意:
- SNAT只能 用在nat表的POSTROUTING链里
- 只要连接的第一个符合条件的包被SNAT了,那么这个连接的其他所有的包都会自动地被SNAT,这个规则还会应用于这个连接所在流的所有数据包
to-source
--to-source
指定源地址和端口,有以下几种方式:
- 单独的地址
- 一段连续的地址,用 连字符 分隔
- 194.236.50.155-194.236.50.160 :可以实现负载平衡。每个流会被随机分配一个IP,但对于同一个流使用的是同一个IP
- 在指定 -p tcp 或 -p udp 的前提下,可以指定源端口的范围
- 194.236.50.155:1024-32000 :包的源端口就被限制在 1024-32000
iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to-source 194.236.50.155-194.236.50.160:1024-32000
注意:
- 如果可能,iptables总是想 避免任何的端口变更 ,换句话说,它总是尽力使用建立连接时所用的 端口。但是如果两台机子使用相同的源端口,iptables 将会把他们的其中之一映射到另外的一个端口。如果没有指定端口范围:
- 所有的在512以内的源端口会被映射到512以内的另一个端口
- 512和1023之间的将会被映射到 1024内
- 其他的将会被映射到大于或对于1024的端口,也就是说是同范围映射
- 这种映射和目的端口无关。因此,如果客户想和防火墙外的HTTP服务器联系,它是不会被映射到FTP control所用的端口的
TOS
用来设置IP头中的 Type of Service 字段 的。这个字段长一个字节,可以控制包的路由情况。它也是iproute2及其子系统可以直接使用的字段之一。如果你有几个独立的防火墙和路由器,而且还想在他们之间利用包的头部来传递路由信息,TOS是唯 一的办法。前面说过,MARK是不能用来传递这种信息的。如果你需要为某个包或流传递路由信息,就要使用TOS字段,它也正是为这个而被开发的
Internet上有很多路由器在这一方面并没有做好工作,因此,在发送包之前改变其TOS没有什么大用处。 最好的情况是路由器根本不理它,最坏的情况是路由器会根据TOS处理,但都是错误的。然而,如果你是在一个很大的WAN或LAN里,而且有很多路由器,TOS还是能有很好的作为的。总的来说,基于TOS的值给包以不同的路由和参数还是可能的,即使在网络里是受限制的
TOS只能用来设置具体的或者说是特定的值,但不管怎么说,不要使用其他的值就是了
注意:只能在 mangle 表内使用
set-tos
--set-tos
设置TOS的值,值的形式可以是名字或者使相应的数值(十进制或16进制的)。一般情况下,建议使用名字而不使用数值形式,因为以后这些数值可能会有所改变, 而名字一般是固定的。TOS字段有8个二进制位,所以可能的值是0-255(十进制)或0x00-0xFF(16进制):
- 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
- Normal-Service 0 (0x00):一般服务,没有什么特殊要求。这个值也是大部分包的缺省值
iptables -t mangle -A PREROUTING -p TCP --dport 22 -j TOS --set-tos 0x10
TTL
TTL可以 修改IP头中Time To Live字段 的值。它有很大的作用,可以把所有外出包的Time To Live值 都改为一样的,比如 64 ,这是Linux的默认值。有些ISP不允许共享连接(可以通过TTL的值来区分是不是有多个机子使用同一个连接),如果把TTL都改为一样的值,他们就不能再根据TTL来判断了
注意:TTL只能在 mangle 表内使用
ttl-set
--ttl-set
设置TTL的值
iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-set 64
这个值不要太大,也不要太小,大约64就很好。值越大,占用的带宽越多,这个target就可以被用来限制包能走多远,一个比较恰当的距离是刚好能到达DNS服务器
值太大会影响网络,而且有点不道德,为什么这样说呢? 如果有些路由器的配置不太正确,包的TTL又非常大,那它们就会在这些路由器之间往返很多次
ttl-dec
--ttl-dec
设定TTL要被减掉的值
iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-dec 3
假设一个进来的包的TTL是 53 ,那么当它离开我们这台机子时,TTL就变为 49 了。因为经过我们这台机子,TTL本身就要减1,还要被TTL target再减3,当然总共就是减去4了
可以限制使用我们的服务的用户*离我们有多远 比如,用户总是使用比较近的DNS,那我们就可以对我们的DNS服务器发出的包进行几个--ttl-dec 当然用--set-ttl控制更方便些
ttl-inc
--ttl-inc
设定TTL要被增加的值
iptables -t mangle -A PREROUTING -i eth0 -j TTL --ttl-inc 3
假设一个进来的包的TTL是53,那么当它离开我们这台机子时,TTL应是多少呢?答案是56。
使用这个选项可以使我们的防火墙更加隐蔽,而不被trace-routes发现, 方法就是设置--ttl-inc 1 原因应该很简单了,包每经过一个设备,TTL就要自动减1,但在我们的防火墙里这个1又被补上了 也就是说,TTL的值没变,那么trace-routes就会认为我们的防火墙是不存在的 Trace-routes让人又爱又恨: 爱它是因为在连接出问题时,它可以给我们提供极有用的信息,告诉我们哪里有毛病 恨它是由于它也可以被黑客或骇客用来收集目标机器的资料
ULOG
ULOG可以 在用户空间记录被匹配的包的信息 :
- 这些信息和整个包都会通过 netlink socket被多播
- 一个或多个用户空间的进程就会接受它们
ULOG是至今iptables和Netfilter下最成熟、最完善的日志工具,它包含了很多更好的工具用于包的记录。这个target可以让我们把信息记录到MySQL或其他数据库中。这样,搜索特定的包或把记录分组就很方便了
ulog-nlgroup
--ulog-nlgroup
指定向哪个netlink组发送包
iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-nlgroup 2
一个有32个netlink组,它们被简单地编号位1-32。默认值是1
ulog-prefix
--ulog-prefix
指定记录信息的前缀,以便于区分不同的信息。使用方法和LOG的prefix一样,只是长度可以达到32个字符
iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-prefix "SSH connection attempt: "
ulog-cprange
--ulog-cprange
指定每个包要向 ULOG在用户空间的代理 发送的字节数:
- –ulog-cprange 100 : 把整个包的前100个字节拷贝到用户空间记录下来,其中包含了这个包头,还有一些包的引导数据。默认值是0,表示拷贝整个包,不管它有多大
iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-cprange 100
ulog-qthreshold
--ulog-qthreshold
告诉ULOG在向用户空间发送数据以供记录之前,要在内核里收集的包的数量:
- –ulog-qthreshold 10 :表示先在内核里积聚10个包,再把它们发送到用户空间里,它们会被看作同一个netlink的信息,只是由好几部分组成罢了。默认值是1,这是为了向后兼容,因为以前的版本不能处理分段的信息
iptables -A INPUT -p TCP --dport 22 -j ULOG --ulog-qthreshold 10