linux iptables使用入门

分类:CentOS教程 阅读:33368 次

iptables的概述

.netfilter/iptables是在linux 2.4及后继版本的内核中集成的一种服务.
.netfilter/iptables工作在OSI七层模型的2,3层.
.netfilter/iptables由netfilter组件和iptables组件构成,其中netfilter组件集成在内核的一部分,由一些信息包过滤表组成,这些表包含内核用来控制信息包过滤处理的规则集.
模块位于/lib/modules/$(uname -r)/kernel/net/netfilter/,iptables组件是一种工具,它运行于用户空间,它使插入,修改和除去信息包过滤表中的规则变得容易.


2)iptables中表和链

2.1)表和链的概述:
iptables包括3个表,即:filter表,nat表,mangle表,它们分别代表对经过iptables的数据包进行筛选(filter),转译(nat),改写(mangle).
iptables包括5个链,即:INPUT链,FORWARD链,OUTPUT链,PREROUTING链,POSTROUTING链.



mangle表包括全部的5个链.
nat表包括PREROUTING链,OUTPUT链,POSTROUTING链.
filter表包括FORWARE链,INPUT链,OUTPUT链.


2.2)表和链的功能

2.2.1)filter表
filter主要用于过滤数据包,对数据包进行ACCEPT,DROP,REJECT,LOG等操作,filter表包含以下3条链:
INPUT链:过滤所有目标地址是本机的数据包.
FORWARD链:过滤所有路过本机的数据包.也就是目的地址和源地址都不是本机的数据包.
OUTPUT链:过滤所有由本机产生的数据包,也就是源地址是本机的数据包.


2.2.2)nat表
nat表用于网络地址转换,iptables可以进行以下的nat:
DNAT:主要用于改变数据包的目的地址.以使数据包能重新路由到某台主机.
SNAT:主要用于改变数据包的源地址,以帮助内部网络能连接到internet.
MASQUERADE:和SNAT完全一样,只是MASQUERADE会查找可用的IP地址,而不像SNAT要有一个固定的IP,所以MASQUERADE一般用于ADSL/PPP等拔号共享上网的方式.

nat表包含以下3条链:
PREROUTING链:可以在数据包到达防火墙的时候改变包的目标地址.
OUTPUT链:可以改变本地产生的数据包的目标地址.
POSTROUTING链:在数据包就要离开防火墙的时候改变数据包的源地址.


2.2.3)mangle表
mangle表主要用于修改数据包,通过mangle可以根据需要改变包头中的内容(如TTL,TOS,MARK),mangle表主要有以下几种操作:
TOS操作:主要用于设置或改变数据包的服务类型域.该操作并不完善,无法在internet上使用.
TTL操作:主要用于改变数据包的生存时间域,可以让所有的数据包只有一个特殊的TTL,这样可以欺骗一些ISP,比如ISP不希望看到共享上网的情况.
MARK:主要用于给数据包设置特殊的标记,通过这些标记可以配置带宽限制和基于请求的分类,不过MARK并没有真正改动数据包,它只是在内核空间中为包设置了标记.防火墙通过其标记对包进行过滤和高级路由.

mangle表包含全部5条链.

注意:
iptables的所有链里有3条链是可以改变数据包的目的地址及源地址的,分别是nat表的PREROUTING链,nat表的POSTROUTING链和nat表的OUTPUT链.


2.3)工作流程
2.3.1)当数据包的目标地址是本机时
第一步:数据包进入网络接口
第二步:进入mangle表的PREROUTING链,在这里可以根据需要改变数据包头内容(比如数据包的TTL值)
第三步:进入nat表的PREROUTING链,在这里可以根据需要做DNAT(目标地址转换)
第四步:进行路由判断(进入本地还是要转发)
第五步:进入mangle表的INPUT链,在路由之后到达本地程序之前修改数据包头内容.
第六步:进入filter表的INPUT链,所有目标地址是本机的数据包都会经过这里,可以在这里对数据包的过滤和件进行设置.
第七步:到达本地应用程序处理.


2.3.2)当数据包的源地址是本机是

第一步:本地应用程序产生数据包.
第二步:路由判断.
第三步:进入mangle表的OUTPUT链,在这里可以根据需要改变包头内容.
第四步:进入nat表的OUTPUT链,在这里可以根据需要对防火墙产生的数据包做DNAT.
第五步:进入filter表的OUTPUT链,在这里可以对数据包的过滤条件进行设置.
第六步:进入mangle表的POSTROUTING链,这里主要对数据包做DNAT操作,数据包离开本机之前修改数据包头内容.
第七步:进入nat表的POSTROUTING链,在这里对数据包做SNAT(源地址转换).
第八步:离开本地.


2.3.3)经过本机转发的数据包(源地址,目标地址都不是本机)

第一步:数据包进入网络接口.
第二步:进入mangle表的PREROUTING链,在这里可以根据需要修改数据包头内容(如TTL值).
第三步:进入nat表的PREROUTING链,在这里可以根据需要对数据包做DNAT.
第四步:进入路由判断(进入本地还要转发).
第五步:进入mangle表的FORWARD链,在这里数据包头内容被修改.这次mangle发生在最初的路由判断之后,在最后一次更改数据包的目标之前.
第六步:进入filter表的FROWARD链,只有需要转发的数据包才会到达这里,并且针对这些数据包的所有过滤也在这里进行,即所有转发的数据都要经过这里.
第七步:进入mangle表的POSTROUTING链,这个链也是针对一些特殊类型的数据包,这一步修改数据包内容是在所有包的目的地址的操作完成之后才进行.
第八步:进入nat表的POSTROUTING链,在这里可以根据需要对数据包做SNAT,当然也包括Masquerade(伪装),但不进行过滤.
第九步:离开网络接口.


2.4)iptables的状态机制

在iptables中数据包和被跟踪连接的4种不同状态相关联,这4种状态分别是NEW,ESTABLISHED,RELATED,INVALID.
除了本地产生的包由OUTPUT链处理外,所有连接跟踪都是在PREROUTING链里进行处理的.
如果本机发送一个流的初始化包,状态就会在OUTPUT链里被设置为NEW.
当我们收到回应的包时,状态就会在PREROUTING链里设置为ESTABLISHED.

2.4.1)NEW状态
NEW状态的数据包说明这个数据包是收到的第一个数据包.比如收到一个SYN数据包,这是连接的第一个数据包,就会匹配NEW状态.


2.4.2)ESTABLISHED状态
只要发送并接到应答,一个数据连接就从NEW变为ESTABLISHED,而且该状态会继续匹配这个连接的后继数据包.
说白了ESTABLISHED表示的就是一个已经连接成功的状态.

2.4.3)RELATED状态
当一个连接和某个已处于ESTABLISHED状态的连接有关系时,就被认为是RELATED,也就是说一个连接要想是RELATED的,首先要有一个ESTABLISHED的连接.
其实RELATED状态是最常用到的,即这个数据包与我们主机发送出去的封包有关的就是RELATED状态的数据包.

2.4.4)INVALID状态
INVALID状态表示无效的数据包.

注:
不管是TCP/UDP还是ICMP,请求被认为NEW,应答是ESTABLISHED,也就是说,当防火墙看到一个请求包时,就认为连接处于NEW状态,当有应答时,就是ESTABLISHED状态.



3)iptables的应用

3.1)iptables的命令格式如下:

iptables [-t table] command [match] [target|jump]
例如:
iptables -t filter -A INPUT -s 192.168.0.200 -j DROP

[-t table]:指明需要操作的表,可以指定的表包括filter,nat,mangle,不指定该参数默认操作filter表,在上例中就是: -t filter
command:iptables所作的操作,比如增加一条规则或者删除一条已存在的规则.在上例就是: -A INPUT
[match]:指定一个数据包的源地址,目的地址,所使用的协议,端口等,在上例就是: -s 192.168.0.200
[Targe/jump]:如果数据包符合Match的描述,就需要使用targe/jump定义的目标或跳转来处理数据包,比如是丢弃还是发送给其它链,在上例就是:-j DROP



3.2)iptables可用的操作


3.2.1) -L:显示所有链的所有策略,如果我们没有指定表,则显示filter表的所有链.如下:

iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

或者用:
iptables -L -t filter
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination


3.2.2)-A <链名称>:在所选择的链最尾部添加一条新的策略.如下:
iptables -t filter -A INPUT -s 192.168.75.129 -j DROP
iptables -t filter -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP all -- 192.168.75.129 anywhere

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

3.2.3)-D <链名称> <策略内容|策略序号>,删除一条策略,如下:

增加一条策略:
iptables -t filter -A INPUT -s 192.168.75.129 -j DROP

查看filter表里的所有策略,并输出策略号:
iptables -t filter -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.75.129 anywhere
2 DROP all -- 192.168.75.130 anywhere

Chain FORWARD (policy ACCEPT)
num target prot opt source destination

Chain OUTPUT (policy ACCEPT)
num target prot opt source destination

我们删除第二条filter表的INPUT策略,如下:
iptables -t filter -D INPUT 2

查看filter表里的所有策略,我们看到已经删了第二条策略,如下:
iptables -t filter -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.75.130 anywhere

Chain FORWARD (policy ACCEPT)
num target prot opt source destination

Chain OUTPUT (policy ACCEPT)
num target prot opt source destination

注:
如果我们建了两条一样的策略,比如它们的策略号为1和3,这样我们不指定策略号删除策略时,是从后面的策略号删起.
如果我们删除策略号为1的策略,后面的策略会向前面递进减1.


3.2.4)-R<链名称><策略序号>:替换所选中链指定的策略,如下:

iptables -t filter -R INPUT 1 -s 192.168.75.131 -j DROP

iptables -t filter -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.75.131 anywhere

Chain FORWARD (policy ACCEPT)
num target prot opt source destination

Chain OUTPUT (policy ACCEPT)
num target prot opt source destination


3.2.5)-I<链名称><策略序号>:从所选链中指定策略前面插入一条新的策略:

iptables -t filter -I INPUT 1 -s 192.168.75.130 -j DROP

iptables -t filter -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 192.168.75.130 anywhere
2 DROP all -- 192.168.75.131 anywhere

Chain FORWARD (policy ACCEPT)
num target prot opt source destination

Chain OUTPUT (policy ACCEPT)
num target prot opt source destination


3.2.6)-F[链名称]:清空所选链的策略,如果没有指定链,则清空指定表中的所有链的策略,如下:

清空filter表中INPUT链的所有策略:
iptables -t filter -F INPUT


3.2.7)-Z[链名称]:将所选链的所有计数器归零,如果没有指定链,则清空指定表中的所有链的策略,如下:

将filter表的INPUT链中所有计数器归零:
iptables -t filter -Z INPUT


3.2.8)-N<链名称>:根据用户指定的名字建立新的链,如下:

新建iptables链,链名为taomee:
iptables -t filter -N taomee

查看新的链,如下:
iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain taomee (0 references)
target prot opt source destination

用自定义链建立相关的策略:
iptables -t filter -A taomee -s 192.168.75.129 -j DROP

在INPUT链中引用自定义链,如下:
iptables -A INPUT -j taomee

iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
taomee all -- anywhere anywhere

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain taomee (1 references)
target prot opt source destination
DROP all -- 192.168.75.129 anywhere

注:如果不引用我们自定义的链,自定义键的策略是不会生效的.


3.2.9)-X[链名称]:删除指定的用户自定义键,如果没有定义键名称,则删除所有自定义链,如下:
iptables -X

值得说明的是必须要删除自定义链的所有引用,才能删除自定义链,如下:
iptables -t filter -X taomee
iptables: Too many links.

删除引用自定义链的策略:
iptables -t filter -D INPUT 1

删除自定义键中的策略:
iptables -t filter -D taomee 1

删除自定义链:
iptables -t filter -X taomee

查看filter表中现在所有的链:
iptables -t filter -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination


3.2.10)-E<链名称> <链名称>:对自定义的链进行重命名,注意仅仅是改变自定义链的名字,对整个表的结构和工作没有任何影响.如下:

新建链taomee
iptables -t filter -N taomee

更改链taomee为blacktaomee
iptables -t filter -E taomee blacktaomee

再次查看改名的链:
iptables -t filter -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain blacktaomee (0 references)
target prot opt source destination


3.2.11)-P <链名称>:为链设置默认的策略,即所有不符合策略的数据包都被强制使用这个策略,如下:

iptables -t filter -P INPUT ACCEPT



3.3)iptables可用的数据描述

3.3.1)[!] -p [<tcp|udp|icmp|...>]:匹配指定的协议

注意以下几点:
.名字不区分大小写,但必须在/etc/protocols中定义过
.可以使用协议对应的整数值(比如ICMP的值是1,TCP是6,UDP是17)
.当不使用-p参数指定协议时,默认为ALL(数值为0),但要注意这只代表匹配TCP,UDP,ICMP,而不是/etc/protocols中定义所有协议.
.在指定协议时,可以在协议前加感叹号表示取反,(感叹号与协议名之间必须有空格),例如: ! -p tcp表示非TCP协议.


拒绝192.168.75.129的机器通过icmp协议连接本地服务器,如下:
iptables -t filter -A INPUT -p icmp -s 192.168.75.129 -j DROP

测试如下:
ping 192.168.75.128 -c 10
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.

--- 192.168.75.128 ping statistics ---
10 packets transmitted, 0 received, 100% packet loss, time 19025ms


拒绝除192.168.75.1的服务器连接本地服务器,如下:

iptables -t filter -A INPUT ! -s 192.168.75.1 -j DROP

测试如下:
ping 192.168.75.128 -c 5
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.

--- 192.168.75.128 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 14015ms


3.3.2)-s<IP地址/网段>:匹配指定源地址的IP/网段

拒绝192.168.75.0/24这个网段通过icmp访问本机,如下:
iptables -t filter -A INPUT -s 192.168.75.0/24 -p icmp -j DROP

发送5个测试包,被防火墙拒绝,如下:
ping 192.168.75.128 -c 5
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.

--- 192.168.75.128 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 14011ms


3.3.3)-d<IP地址/网段>:匹配指定的IP目标地址匹配数据包.

拒绝向192.168.75.129发送icmp数据包,如下:
iptables -t filter -A OUTPUT -d 192.168.75.129 -p icmp -j DROP

向192.168.75.129发送数据包,被拒绝,如下:
ping 192.168.75.129
PING 192.168.75.129 (192.168.75.129) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted


3.3.4)-i<网络接口>:以数据包进入本地所使用的网络接口来匹配数据包.这个匹配操作只能用于INPUT,FORWARD和PREROUTING这3个链.

注意以下几点:
.指定时使用网络接口名称,比如eth0,ppp0
.我们也可以用! -i eth0的方式进行取反匹配
.可以使用加号作为通配符,比如iptables -A INPUT -i +表示匹配所有的包,与使用iptables -A INPUT -i any的作用是等同的,比如:
iptables -t filter -A INPUT -p tcp -i + -s 192.168.75.129 -j DROP

查看防火墙相关信息:
iptables -L -n -v
Chain INPUT (policy ACCEPT 38 packets, 2664 bytes)
pkts bytes target prot opt in out source destination
16 1344 DROP icmp -- + * 192.168.75.129 0.0.0.0/0

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 26 packets, 3044 bytes)
pkts bytes target prot opt in out source destination

注:我们看到INPUT链的in字段是+号,此时对所有的网络接口都应用.


另外我们也可用了eth+表示所有ethernet接口,如下:
iptables -t filter -A INPUT -p icmp -i eth+ -s 192.168.75.129 -j DROP

查看防火墙的相关信息:
iptables -L -n -v
Chain INPUT (policy ACCEPT 30 packets, 2136 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP icmp -- eth+ * 192.168.75.129 0.0.0.0/0

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 22 packets, 2288 bytes)

pkts bytes target prot opt in out source destination



3.3.5)-o<网络接口>:以数据包离开本地所使用的网络接口来匹配数据包,其配置方案与-i是一样的.如下:

设定所有网络介质(eth+)不通向192.168.75.129发送数据包.
iptables -t filter -A OUTPUT -p all -o eth+ -d 192.168.75.129 -j DROP

测试:
ping 192.168.75.129
PING 192.168.75.129 (192.168.75.129) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted


3.3.6)--sport <端口>:基于数据包的源端口来匹配数据包

注:
.该参数必须与-p参数配合使用
.不指定--sport参数时,表示所有端口
.可以使用连续的端口,比如:"--sport 1000:1024"表示从1000到1024的所有端口(包括1000,1024),--sport 1024:1000与--sport 1000:1024的效果相同
.当省略冒号前面的端口号时,比如--sport :1000,则表示使用0到1000的所有端口.(端口号是从0算起的)
.当省略冒号后面的端口号时,比如--sport 1000:,则表示从1000到65535的所有端口.(端口号最大为65535)
.当在--sport <端口号>前加入!号时,表示排除该端口,比如 ! --sport 1000,则表示除1000之外的所有端口.

示例1)拒绝192.168.75.129通过20000到65535的端口连接本地服务器,如下:
iptables -t filter -A INPUT -p tcp --sport 20000:65535 -s 192.168.75.129 -j DROP

示例2)拒绝192.168.75.129通过除0-1000端口之间的所有端口连接本机,如下:
iptables -t filter -A INPUT -p tcp ! --sport 0-1000 -s 192.168.75.129 -j DROP


3.3.7)--dport <端口>:基于数据包的目的端口来匹配包,也就是说匹配目的主机连接本机的哪个端口,操作方面与--sport参数相同.

示例1)拒绝192.168.75.129连接本机的22端口,如下:
iptables -t filter -A INPUT -p tcp --dport 22 -s 192.168.75.129 -j DROP

示例2)拒绝192.168.75.129连接除本机的22端口外的所有端口,如下:
iptables -t filter -A INPUT -p tcp ! --dport 22 -s 192.168.75.129 -j DROP


3.3.8)-m multiport --sport <端口>:源端口多端口匹配,作用同--sport一样.

注:
.最多可以指定15个端口,使用逗号分隔.
.该参数必须与-p参数配合使用

示例)拒绝192.168.75.129用40000,50000两个端口连接本机
iptables -t filter -A INPUT -m multiport -p tcp --sport 40000,50000 -s 192.168.75.129 -j DROP


3.3.9)-m multiport --dport <端口>:目的端口多端口匹配,作用同--dport一样.

注:
.最多可以指定15个端口,使用逗号分隔.
.该参数必须与-p参数配合使用


3.3.10)-m multiport --port <端口>:过滤条件包括源端口和目标端口.

示例)拒绝192.168.75.129用22,56000端口访问本机的22,56000端口,如下:
iptables -t filter -A INPUT -p tcp -m multiport --port 22,56000 -s 192.168.75.129 -j DROP


3.3.11)--tcp-flags<检查标记列表> <条件列表>:匹配指定的TCP标记,有两个参数,它们都是列表,列表内容用英文的逗号作分隔符,两个列表之间用空格分开,如下:
--tcp-flags SYN,FIN,ACK SYN
注:
我们看到--tcp-flags选项后面的关键字分为两个列表,即SYN,FIN,ACK和SYN
第一个列表指定需要检查的TCP标记,第二个列表指定在第一个列表中出现过的且必须被设为1(即打开状态)的标记.
也就是说第一个列表提供检查范围,第二个列表提供被设置条件.
这个匹配操作可以识别SYN,ACK,FIN,RST,URG,PSH标记.

示例1)阻止192.168.75.129发送SYN标记(设置为1)以及阻止FIN/ACK标记(没有设置,即为0)的发送.
iptables -t filter -A INPUT -p tcp --tcp-flags SYN,FIN,ACK SYN -s 192.168.75.129 -j DROP

在192.168.75.129主机上测试:
nmap -sS 192.168.75.128

Starting Nmap 5.21 ( http://nmap.org ) at 2011-08-02 15:03 CST
Nmap scan report for 192.168.75.128
Host is up (0.00s latency).
All 1000 scanned ports on 192.168.75.128 are filtered
MAC Address: 00:0C:29:EC:A0:CE (VMware)

Nmap done: 1 IP address (1 host up) scanned in 22.62 seconds
注:我们用nmap/SYN包的方式扫描主机(192.168.75.128),但没有查到相关的信息(比如端口),同时我们也花费了20多秒.

下面我们关闭上面的iptables设置,如下:
iptables -t filter -D INPUT -p tcp --tcp-flags SYN,FIN,ACK SYN -s 192.168.75.129 -j DROP

再次扫描该主机,如下:
nmap -sS 192.168.75.128

Starting Nmap 5.21 ( http://nmap.org ) at 2011-08-02 15:06 CST
Nmap scan report for 192.168.75.128
Host is up (0.00056s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
25/tcp open smtp
111/tcp open rpcbind
MAC Address: 00:0C:29:EC:A0:CE (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.93 seconds
注:
我们看到已经扫描出端口,同时只花了不到1秒的时间.


示例2)阻止所有标记都未置1的通信,如下:
iptables -t filter -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

注:
--tcp-flags ALL NONE中的ALL指选定所有标记,NONE是指未选定任何标记.


示例3)阻止FIN和ACK标记被设置而SYN标记没有设置的通信.
iptables -t filter -A INPUT -p tcp ! --tcp-flags SYN,FIN,ACK SYN -s 192.168.75.129 -j DROP


用FIN标记进行扫描,如下:
nmap -sF 192.168.75.128

Starting Nmap 5.21 ( http://nmap.org ) at 2011-08-02 16:09 CST
Nmap scan report for 192.168.75.128
Host is up (0.00s latency).
All 1000 scanned ports on 192.168.75.128 are open|filtered
MAC Address: 00:0C:29:EC:A0:CE (VMware)

Nmap done: 1 IP address (1 host up) scanned in 22.41 seconds
注:扫描被拒绝.


用SYN标记进行扫描,如下:
nmap -sS 192.168.75.128

Starting Nmap 5.21 ( http://nmap.org ) at 2011-08-02 16:10 CST
Nmap scan report for 192.168.75.128
Host is up (0.00050s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
25/tcp open smtp
111/tcp open rpcbind
MAC Address: 00:0C:29:EC:A0:CE (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.78 seconds
注:可以扫描到对映的端口.


3.3.12)--syn:匹配SYN标记被设置而ACK/RST标记没有设置的数据包(该参数与iptables -p tcp --tcp-flags SYN,RST,ACK SYN"有相同的效果)

示例)阻止192.168.75.129发送SYN标记(设置为1)以及阻止FIN/ACK标记(没有设置,即为0)的发送.
iptables -t filter -A INPUT -p tcp --syn -s 192.168.75.129 -j DROP

用SYN标记对端口进行扫描,如下:
nmap -sS 192.168.75.128

Starting Nmap 5.21 ( http://nmap.org ) at 2011-08-03 06:14 CST
Nmap scan report for 192.168.75.128
Host is up (0.00068s latency).
All 1000 scanned ports on 192.168.75.128 are filtered
MAC Address: 00:0C:29:EC:A0:CE (VMware)

Nmap done: 1 IP address (1 host up) scanned in 22.63 seconds

用FIN标记对端口进行扫描,如下:
nmap -sF 192.168.75.128

Starting Nmap 5.21 ( http://nmap.org ) at 2011-08-03 06:16 CST
Nmap scan report for 192.168.75.128
Host is up (0.00064s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
21/tcp open|filtered ftp
22/tcp open|filtered ssh
25/tcp open|filtered smtp
111/tcp open|filtered rpcbind
MAC Address: 00:0C:29:EC:A0:CE (VMware)

Nmap done: 1 IP address (1 host up) scanned in 3.79 seconds


3.3.13)--icmp-type <类型数值>:根据icmp类型匹配包,类型的指定可以使用十进制数值.

示例1)关闭ICMP的回显,如下:
iptables -t filter -A INPUT -p icmp --icmp-type 8 -j DROP

客户端向服务端发送icmp数据包进行测试:
ping 192.168.75.128 -c 5
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.

--- 192.168.75.128 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 14006ms
注:--icmp-type 8表示回显请求


示例2)关闭ICMP的请求,如下:
iptables -t filter -A INPUT -p icmp --icmp-type 0 -j DROP

服务端向客户端发送icmp数据包进行测试:
ping 192.168.75.129 -c 5
PING 192.168.75.129 (192.168.75.129) 56(84) bytes of data.

--- 192.168.75.129 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 14002ms
注:--icmp-type 0表示回显示应答


3.3.14)--limit <匹配次数/时间>:匹配操作必须由-m limit明确指定才能使用,该参数用于控制某条规则在一段时间的匹配次数

示例)每分钟允许一个icmp包进入主机,如下:

iptables -t filter -A INPUT -p icmp -m limit --limit 1/m -j ACCEPT
iptables -A INPUT -p icmp -j DROP
注:时间单位可以是秒(second/s),分钟(minute/m),小时(hour/h)


在远程客户端测试:
ping 192.168.75.128
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.
64 bytes from 192.168.75.128: icmp_seq=39 ttl=64 time=0.447 ms
64 bytes from 192.168.75.128: icmp_seq=99 ttl=64 time=0.441 ms
64 bytes from 192.168.75.128: icmp_seq=159 ttl=64 time=0.350 ms
64 bytes from 192.168.75.128: icmp_seq=219 ttl=64 time=0.343 ms
64 bytes from 192.168.75.128: icmp_seq=279 ttl=64 time=0.350 ms
64 bytes from 192.168.75.128: icmp_seq=339 ttl=64 time=0.332 ms
64 bytes from 192.168.75.128: icmp_seq=399 ttl=64 time=0.346 ms
64 bytes from 192.168.75.128: icmp_seq=459 ttl=64 time=0.352 ms

注:我们看到icmp_seq=39是接收到的,icmp_seq=99是接收到的,中间的数据包都被丢弃了.


3.3.15)--limit-burst <次数>:定义--limit的峰值,可以理解为允许建立连接的阈值.

示例1)允许向本地发送50次icmp封包,接收50次之后该封包将被拒绝
iptables -t filter -A INPUT -p icmp -m limit --limit-burst 50 -j ACCEPT


示例2)允许每分钟5次icmp包,如果接收了50次以上的icmp包,将拒绝icmp包,在12秒后将允许一次icmp封包,如下:

iptables -t filter -R INPUT 1 -p icmp -m limit --limit 5/m --limit-burst 50 -j ACCEPT
iptables -t filter -A INPUT -p icmp -j DROP

客户端测试:
ping 192.168.75.128
64 bytes from 192.168.75.128: icmp_seq=44 ttl=64 time=0.388 ms
64 bytes from 192.168.75.128: icmp_seq=56 ttl=64 time=0.313 ms
64 bytes from 192.168.75.128: icmp_seq=68 ttl=64 time=0.346 ms

注:我们看到icmp_seq=44到icmp_seq=56之间的数据包被丢了,正好是12秒.
如果1分钟内没有接收icmp包,--limit-burst中的限制将为每分钟5次进行恢复.
另外--limit-burst的值一定要比--limit的值大.


3.3.16)--mac-source <MAC地址>:基于数据包的源MAC地址匹配数据包,只能用于PREROUTING,FORWARD,INPUT三个链.

示例)拒绝MAC地址为00:0C:29:DF:13:E6的主机向本机发送icmp数据,如下:
iptables -t filter -A INPUT -m mac --mac-source 00:0C:29:DF:13:E6 -j DROP

客户端测试:
ping 192.168.75.128 -c 5
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.

--- 192.168.75.128 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 14009ms


3.3.17)--uid-owner <UID>:按生成包的用户ID(UID)来匹配数据包.

示例)拒绝uid为500的用户发送ICMP到其它机器,如下:
iptables -t filter -A OUTPUT -p icmp -m owner --uid-owner 500 -j DROP

为测试关闭ping命令的setuid,因为如果不关闭,其它用户用ping命令时都会以root用户来执行,如下:
chmod u-s /bin/ping

用setcap使ping命令有cap_net_raw的能力,如下:
setcap cap_net_raw=eip /bin/ping

切换到test用户(uid=500)
su - test

向外发送icmp包测试,发现被拒绝,如下:
ping 192.168.75.129
PING 192.168.75.129 (192.168.75.129) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted


3.3.18)--gid-owner <GID>:按生成包的用户组ID(GID)来匹配数据包.

示例)拒绝gid为500的用户向外发送数据包,如下:
iptables -t filter -A OUTPUT -m owner --gid-owner 500 -j DROP

为测试关闭ping命令的setuid,因为如果不关闭,其它用户用ping命令时都会以root用户来执行,如下:
chmod u-s /bin/ping

用setcap使ping命令有cap_net_raw的能力,如下:
setcap cap_net_raw=eip /bin/ping

切换到test用户(uid=500)
su - test

向外发送icmp包测试,发现被拒绝,如下:
ping 192.168.75.129
PING 192.168.75.129 (192.168.75.129) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted


3.3.19)--state <状态列表>:匹配数据包的状态,多个状态使用逗号号分隔,TOS在网络设备上传输也需要网络设备的支持,否则对其优化也是没有效果的.

示例)允许192.168.75.129连接本机的22端口,允许NEW,ESTABLISHED两种状态的连接
iptables -t filter -A INPUT -m state --state NEW,ESTABLISHED -p tcp --dport 22 -s 192.168.75.129 -j ACCEPT

iptables -t filter -A INPUT -s 192.168.75.129 -j DROP


3.3.20)--tos <TOS值>:根据TOS字段匹配数据包,TOS是IP头的一部分,其含义是Type Of Service,由8个二进制位组成.

示例1)针对ssh服务,我们设置它为最小延时.
iptables -A PREROUTING -t mangle -p tcp --dport ssh -j TOS --set-tos Minimize-Delay

示例2)针对ftp服务,我们设置它为最大合理量.
iptables -A PREROUTING -t mangle -p tcp --dport ftp -j TOS --set-tos Maximize-Throughput

示例3)针对snmp服务,我们设置它为最大可靠度.
iptables -A PREROUTING -t mangle -p tcp --dport snmp -j TOS --set-tos Maximize-Reliability

示例4)针对icmp协议,我们采用最小花费.
iptables -A PREROUTING -t mangle -p icmp -j TOS --set-tos Minimize-Cost

注:我们通过上面的方式来对各种服务的网络传输进行优化.


3.3.21)--ttl根据TTL的值来匹配数据包.

示例)阻止TTL值为64的数据包,如下:
iptables -A INPUT -m ttl --ttl 64 -s 192.168.75.129 -j DROP

客户端测试:
ping 192.168.75.128 -c 5
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.

--- 192.168.75.128 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 14007ms


3.4)iptables可用动作

3.4.1)ACCEPT
-j ACCEPT表示一旦数据包满足了指定的匹配条件,就会被允许,并且不会再去匹配当前链中的其他规则或同一个表内的其他规则,但它还要通过其它表中的链.

示例1)测试在-j ACCEPT匹配后是否还会匹配当前表中其它规则.

iptables -A INPUT -p icmp -s 192.168.75.129 -j ACCEPT
iptables -A INPUT -p icmp -s 192.168.75.129 -j DROP

客户端测试:
ping 192.168.75.128
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.
64 bytes from 192.168.75.128: icmp_seq=1 ttl=64 time=4.91 ms
64 bytes from 192.168.75.128: icmp_seq=2 ttl=64 time=0.971 ms
64 bytes from 192.168.75.128: icmp_seq=3 ttl=64 time=0.368 ms
64 bytes from 192.168.75.128: icmp_seq=4 ttl=64 time=0.456 ms
64 bytes from 192.168.75.128: icmp_seq=5 ttl=64 time=0.538 ms
^C
--- 192.168.75.128 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4228ms
rtt min/avg/max/mdev = 0.368/1.450/4.919/1.746 ms


示例2)测试在-j ACCEPT匹配后是否还要通过其它表中的链.

iptables -t mangle -A INPUT -p icmp -s 192.168.75.129 -j ACCEPT
iptables -t filter -A INPUT -p icmp -s 192.168.75.129 -j DROP

客户端测试:
ping 192.168.75.128 -c 5
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.

--- 192.168.75.128 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 14013ms

查看服务端防火墙的封包接收情况:
iptables -L -v -n
Chain INPUT (policy ACCEPT 52 packets, 3640 bytes)
pkts bytes target prot opt in out source destination
5 420 ACCEPT icmp -- * * 192.168.75.129 0.0.0.0/0
0 0 DROP icmp -- * * 192.168.75.129 0.0.0.0/0

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 38 packets, 5512 bytes)
pkts bytes target prot opt in out source destination


3.4.2)DNAT/SNAT/MASQUERADE
DNAT用于进行目标网络地址转换,也就是重写数据包的目标IP地址,DNAT只能在nat表里的PREROUTING和OUTPUT链中使用.
SNAT用于进行源网络地址转换,也就是重写数据包的源IP地址,SNAT只能在nat表里的POSTROUTING链中使用.
MASQUERADE该选项与SNAT作用相同,只是使用该选项时不需要指明--to-source,一般MASQUERADE用于动态获取IP地址的链接.

示例:将访问本地的22端口都转发到192.168.75.131主机
iptables -t nat -A PREROUTING -p tcp -d 192.168.75.128 --dport 22 -s 192.168.75.129 -j DNAT --to-dest 192.168.75.131:22
注意:这里用DNAT修改了数据包的目地地址,即修改数据包中目标地址192.168.75.128为192.168.75.131

接上例,将数据包中源地址为192.168.75.129通过SNAT转换为192.168.75.128
iptables -t nat -A POSTROUTING -p tcp -d 192.168.75.131 -s 192.168.75.129 --dport 22 -j SNAT --to-source 192.168.75.128
注意:这里用SNAT修改了数据包的源地址为192.168.75.128,因为我们在PREROUTING链中已经将目的地址改为192.168.75.131,所以这里就用-d 192.168.75.131做为目标地址进行匹配.

同时我们也可以将上面的指令用MASQUERADE来代替,如下:
iptables -t nat -A POSTROUTING -p tcp -d 192.168.75.131 -s 192.168.75.129 --dport 22 -j MASQUERADE


客户端测试:
ssh root@192.168.75.128
root@192.168.75.128's password:
Last login: Fri Aug 5 21:54:06 2011 from 192.168.75.128
Linux test2 2.6.18-4-k7 #1 SMP Mon Mar 26 17:57:15 UTC 2007 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
inspanidual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

查看IP,说明我们已经连接到了192.168.75.131的主机,如下:
ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:0c:29:f9:5e:06
inet addr:192.168.75.131 Bcast:192.168.75.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fef9:5e06/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:956 errors:0 dropped:0 overruns:0 frame:0
TX packets:642 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:95310 (93.0 KiB) TX bytes:83595 (81.6 KiB)
Interrupt:177 Base address:0x1080

查看建立连接的源IP,我们看到是从192.168.75.128过来的数据包,如下:
netstat -etnp
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp6 0 0 192.168.75.131:22 192.168.75.1:3388 ESTABLISHED 0 6640 2074/0
tcp6 0 0 192.168.75.131:22 192.168.75.128:50133 ESTABLISHED 0 7432 2172/1


3.4.3)DROP/REJECT

DROP:如果数据包符合条件,这个目标就会把它阻止,但它不会向发送者返回任何信息,这就有可能会使连接的另一个方socket一直等待回应.
REJECT:同DROP一样,但它会在丢弃包的同时还会向发送者返回一个错误信息.
DROP和REJECT不会向ACCEPT那样可以通过若干个表,在匹配到数据包时,会直接拒绝,而不会让其继续前进.

示例1:用-j DROP拒绝192.168.75.129向本机发送 icmp包,如下:
iptables -t filter -A INPUT -s 192.168.75.129 -p icmp -j DROP

客户端测试:
ping 192.168.75.131 -c 5
PING 192.168.75.131 (192.168.75.131) 56(84) bytes of data.

--- 192.168.75.131 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 14025ms

示例2):用-j REJECT拒绝192.168.75.129向本机发送icmp包,如下:
iptables -t filter -R INPUT 1 -s 192.168.75.129 -p icmp -j REJECT

客户端测试:

ping 192.168.75.131 -c 5
PING 192.168.75.131 (192.168.75.131) 56(84) bytes of data.
From 192.168.75.131 icmp_seq=1 Destination Port Unreachable
From 192.168.75.131 icmp_seq=2 Destination Port Unreachable
From 192.168.75.131 icmp_seq=3 Destination Port Unreachable
From 192.168.75.131 icmp_seq=4 Destination Port Unreachable
From 192.168.75.131 icmp_seq=5 Destination Port Unreachable

--- 192.168.75.131 ping statistics ---
5 packets transmitted, 0 received, +5 errors, 100% packet loss, time 4024ms


3.4.4)LOG
如果数据包符合条件,就记录数据包的相关信息到log文件.

为完成下面的示例,我们要调整syslog,如下:

vi /etc/rsyslog.conf
添加如下内容:
kern.debug /var/log/iptables

重启rsyslog服务:
/etc/init.d/rsyslog restart

示例1)我们记录进入INPUT链的icmp封包,并指定记录的等级,如下:
iptables -t filter -A INPUT -p icmp -j LOG --log-level debug

客户端测试:
ping -c 4 192.168.75.128
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.
64 bytes from 192.168.75.128: icmp_seq=1 ttl=64 time=0.239 ms
64 bytes from 192.168.75.128: icmp_seq=2 ttl=64 time=0.637 ms
64 bytes from 192.168.75.128: icmp_seq=3 ttl=64 time=0.625 ms
64 bytes from 192.168.75.128: icmp_seq=4 ttl=64 time=0.640 ms

--- 192.168.75.128 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4008ms
rtt min/avg/max/mdev = 0.239/0.501/0.640/0.167 ms

查看iptables日志,如下:
tail -f /var/log/iptables
Aug 7 07:37:07 ckhitler kernel: IN=eth1 OUT= MAC=00:0c:29:ec:a0:ce:00:0c:29:df:13:e6:08:00 SRC=192.168.75.129 DST=192.168.75.128 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=34054 SEQ=1
Aug 7 07:37:08 ckhitler kernel: IN=eth1 OUT= MAC=00:0c:29:ec:a0:ce:00:0c:29:df:13:e6:08:00 SRC=192.168.75.129 DST=192.168.75.128 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=34054 SEQ=2
Aug 7 07:37:09 ckhitler kernel: IN=eth1 OUT= MAC=00:0c:29:ec:a0:ce:00:0c:29:df:13:e6:08:00 SRC=192.168.75.129 DST=192.168.75.128 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=34054 SEQ=3
Aug 7 07:37:10 ckhitler kernel: IN=eth1 OUT= MAC=00:0c:29:ec:a0:ce:00:0c:29:df:13:e6:08:00 SRC=192.168.75.129 DST=192.168.75.128 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=34054 SEQ=4


示例2)记录进入INPUT链的icmp封包,并在记录信息前加上指定的前缀,这里我们指定前缀为hacker
iptables -t filter -A INPUT -p icmp -j LOG --log-prefix "hacker"

客户端测试:
ping -c 2 192.168.75.128
PING 192.168.75.128 (192.168.75.128) 56(84) bytes of data.
64 bytes from 192.168.75.128: icmp_seq=1 ttl=64 time=0.584 ms
64 bytes from 192.168.75.128: icmp_seq=2 ttl=64 time=0.386 ms

--- 192.168.75.128 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 0.386/0.485/0.584/0.099 ms

查看iptables日志,如下:
Aug 7 07:42:56 ckhitler kernel: IN=eth1 OUT= MAC=00:0c:29:ec:a0:ce:00:0c:29:df:13:e6:08:00 SRC=192.168.75.129 DST=192.168.75.128 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=39174 SEQ=1
Aug 7 07:42:56 ckhitler kernel: hackerIN=eth1 OUT= MAC=00:0c:29:ec:a0:ce:00:0c:29:df:13:e6:08:00 SRC=192.168.75.129 DST=192.168.75.128 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=39174 SEQ=1
Aug 7 07:42:57 ckhitler kernel: IN=eth1 OUT= MAC=00:0c:29:ec:a0:ce:00:0c:29:df:13:e6:08:00 SRC=192.168.75.129 DST=192.168.75.128 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=39174 SEQ=2
Aug 7 07:42:57 ckhitler kernel: hackerIN=eth1 OUT= MAC=00:0c:29:ec:a0:ce:00:0c:29:df:13:e6:08:00 SRC=192.168.75.129 DST=192.168.75.128 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=39174 SEQ=2


3.4.5)REDIRECT
在防火墙所在的主机内部转发数据包或流到另一个端口,当然这都发生在主机内部.

示例:将访问本机80端口的请求,转发到22端口上,如下:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 22

客户端测试:
telnet 192.168.75.128 80
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
SSH-2.0-OpenSSH_5.3