iptables四表:filter,nat,mangle,raw;五链:PREROUTING,INPUT,OUTPUT,FORWARD,POSTROUTING。
通常查看的表:filter(默认),nat:
查看filter表:
查看nat表:
编写表(定义规则):
数据的流向分为源和目标两种类型:
源和目标都是相对于iptables而言,数据包经由iptables,数据的发送者是source,数据要达到的目标方为destination,不以设备所处的角色和作用来区分源和目标。
查看规则的其他参数:
# iptables [-t table] -L -n -v;显示详细信息 # iptables [-t table] -L -n -vv;显示更为详细信息 # iptables [-t table] -L -n -v -x;显示匹配到的包时,不进行单位转换,精确显示匹配的包数 # iptables [ -t table] -L -n -v -x --line-num;显示规则对应的行号
保存当前生效配置方法:
# iptables-save > /etc/sysconfig/iptables # service iptables save (CentOS 6系统上可用)
删除表中所有的规则,一定要注意看表的默认规则,如果是filter表,默认规则是DROP时,要先改为ACCEPT,否则SSH连接会断开:
# iptables [-t table] -F
删除规则方法:
# iptables [-t table] -D CHAIN RULE_NUM
恢复规则文件中的规则:
# iptables-restore < /etc/sysconfig/iptables # service iptables restart;恢复/etc/sysconfig/iptables中定义的规则。
设置iptables规则前的准备工作:
通常服务器的默认规则为DROP,仅允许开放部分端口,定义的是白名单,在开始定义默认的DROP规则之前,需要先放行ssh服务,保证管理员可以远程连入,如果有需要清空所有规则的需要时,要先确认该表的默认规则,如果默认规则为DROP,要先将其改为ACCEPT,否则清空规则后,所有的连接访问都会被拒绝,ssh服务也会中断。测试用机IP为192.168.1.128,先开放连入本机的ssh服务。
# iptables -A INPUT -s 192.168.1.0/24 -d 192.168.1.128 -p tcp --dport 22 -j ACCEPT # iptables -A OUTPUT -s 192.168.1.128 -d 192.168.1.0/24 -p tcp --sport 22 -j ACCEPT
这两条规则添加以后,ssh服务就可以正常连接,然后修改服务器filter表的默认规则为DROP
# iptables -P INPUT DROP # iptables -P OUTPUT DROP # iptables -P FORWARD DROP
iptables配置前的准备工作完成。
修改规则方法:
iptables [-t table] -R chain rulenum rule-specification
插入规则:
iptables [-t table] -I chain [rulenum] rule-specification
插入新的规则时,如果规则限定的条件更为苛刻,需要将规则放在前面,以便可以在前面匹配到,如果写在后面,更为宽泛的规则如果匹配到,那么限定条件更为具体的规则就会不生效。示例:
# iptables -I INPUT -i lo -j ACCEPT # iptables -I OUTPUT -o lo -j ACCEPT
通常针对一种请求报文都要在完整的报文流经的链路上写全规则,从流入到流出都有规则,很少只有一段报文流向有规则,而其他流经的链路上却没有规则的情况。
iptables规则语法:
iptables [-t TABLE] -COMMAND 链名 匹配条件 -j 处理目标
一、COMMAND可用选项:
-F:flush,清空规则链; -N:new,新建一条链 -X:delete,删除一条自定义的空链 -Z:zero,计数器归零 -P:policy,设置默认策略 -E:重命名自定义链 -A:在链的规则中附加新的规则 -I:在链的规则中插入指定的规则,插入位置由指定数值指定,不指定的情况下默认插入到第一条 -D:删除链中的某一条规则,后面跟上数字,删除指定的条目 -R:修改链中某条规则,也需要指定要修改的规则在链中所处的条目位置。 -L:查询指定的表中的规则,-L 命名的具体参数还有: -n:以数字格式显示主机地址和端口 -v:以详细格式显示,还有-vv,-vvv,显示的信息更为详细 --line-numbers:显示规则编号 -x:不对计数器的计数结果做单位换算,而是显示其精确值
二、匹配条件:
匹配条件分为通用匹配和扩展匹配,扩展匹配又分为显式匹配和隐士匹配。
1、通用匹配指定的内容的类型为IP地址和网卡接口:
-s 地址:指定报文源IP地址匹配的范围,可以是IP,也可以是网络地址,可以用!取反 -d 地址:指定报文目标IP地址匹配的范围 -p 协议:指定匹配报文的协议类型,一般有三种,tcp,udp,icmp -i INTERFACE:数据报文流入的接口 -o INTERFACE:数据报文流出的接口
通用匹配的类型范围比较窄,只有IP、接口、协议类型,只能对较大范围的类型做简单设定,如果需要做进一步精确限定,扩展匹配中的隐式匹配是对通用匹配的几种匹配类型做进一步限定,通常隐式扩展都是针对IP地址的具体属性做隐式扩展,IP地址的具体属性通常为源端口,目标端口,tcp的标志位,icmp协议的类型几种:
2、隐式扩展匹配:
1)-p tcp :
--sport PORT[-PORT]:指定源端口,示例:
# iptables -A OUTPUT -s 192.168.1.128 -p tcp --sport 80 -j ACCEPT
--dport PORT[-PORT]:指定目标端口,示例:
# iptables -A OUTPUT -s 192.168.1.128 -p tcp --dport 53 -j ACCEPT
--tcp-flags:示例: # iptables -I INPUT -p tcp --tcp-flags all all -j DROP # iptables -I INPUT -p tcp --tcp-flags all none -j DROP # iptables -I INPUT 3 -d 192.168.1.128 -p tcp --dport 22 --tcp-flags syn,ack,rst,fin syn -j ACCEPT;放行访问目标172.16.100.7的ssh服务的tcp第一次握手的数据报文,上面的这条语句还可以简写成: # iptables -I INPUT 3 -d 192.168.1.128 -p tcp --dport 22 --syn -j ACCEPT
2)-p udp:
--sport示例:
# iptables -A INPUT -d 192.168.1.128 -p udp --sport 53 -j ACCEPT
--dport示例:
# iptables -A OUTPUT -s 192.168.1.128 -p udp --dport 53 -j ACCEPT
3)-p icmp [-m icmp]
--icmp-type:0:echo-reply,ping响应;8:echo-request,ping请求,示例:
# iptables -I INPUT 3 -d 192.168.1.128 -p icmp -j ACCEPT # iptables -I OUTPUT -s 192.168.1.128 -p icmp -j ACCEPT # iptables -A OUTPUT -s 192.168.1.128 -p icmp --icmp-type 8 -j ACCEPT;从主机192.168.1.128发出的ping请求数据报文允许放行。 # iptables -A INPUT -d 192.168.1.128 -p icmp --icmp-type 0 -j ACCEPT;主机192.168.1.128接收的ping回显数据包,其他主机响应给它的数据报文允许放行。
针对tcp,udp,icmp三种协议的扩展匹配可以使用隐式匹配,实际的应用中,基本都会是扩展匹配,而很少会用通用匹配,因为默认的服务器通常只提供几种服务,所以从安全的角度考虑,也仅仅会开放几个端口,所以通常都是用扩展匹配来定义规则的。
3、显示扩展匹配:
1)multiport:多端口匹配,最多指定15个端口,专用选项:
--source-ports,可以缩写为--sports,示例:
# iptables -I OUTPUT -s 192.168.1.128 -p tcp -m multiport --sports 22,80 -j ACCEPT
--destination-ports,可以缩写为--dports,示例:
# iptables -I INTPUT -d 192.168.1.128 -p tcp -m multiport --dports 22,80 -j ACCEPT
多端口的显示扩展匹配是前面的隐式扩展匹配中的指定端口的匹配条目的合并结果,如果都单独写,会使得匹配规则很多,不易查看,而且匹配时效率不高,所以如果一个主机有多个对外提供服务的端口,可以用一条语句来指定,使用multiport显示扩展来匹配条件.
2)iprange:匹配指定范围内的地址,这种匹配方式较之前的ip地址匹配更精确,可以更细分一个网段地址的使用,通用匹配中指定的IP地址只能是单个IP或者一个网段,实际的应用中服务器端开放的往往都是端口,写的规则都是用multiport来定义,而iprange用来限定的往往是来访问的IP地址的范围,限定的是局域网内的一段连续主机IP地址。iprange使用的专用选项有:
--src-range:
# iptables -A INPUT -d 192.168.1.128 -p tcp --dport 23 -m iprange --src-range 192.168.1.100-192.168.1.150 -j ACCEPT
--dst-range:
# iptables -A OUTPUT -s 192.168.1.128 -p tcp --sport 23 -m iprange --dst-range 192.168.1.100-192.168.1.150 -j ACCEPT
上面这条语句与前一条配合起来算一个完整的规则,但它们编写在一个表的不同链中,查看时需要对应着看,在查看一个服务器的iptables规则时,INPUT链的规则往往都与OUTPUT有对应的条目。往往定义的都是对外提供服务的端口和可以访问这些服务的地址等等。查看规则时应该以提供服务的一端为中心,先看报文流入的链,后再匹配的角度查看报文流出的链。
3)字符串匹配:用于检测报文应用层中的字符串。
专用选项:--algo {kmp|bm}、--string "string" 、--hex-string "string",示例:
# iptables -I OUTPUT -m string --algo kmp --string "sex" -j DROP
对应用层报文过滤的显示匹配往往都是为了过滤掉一些报文,目的是为了屏蔽,而不是放行,所以往往这种iptables规则只在报文经过的OUTPUT链上定义就可以达到目的,所以规则只在一个链上有,基于时间的访问控制和其他的限制方式都近似。
4)基于时间做访问控制:
专用选项:--datestart YYYY[-MM][-DD][Thh[:mm[:ss]]]]、--datestop、--timestart hh:mm[:ss]、--timestop hh:mm[:ss]、--weekdays day[,day],示例:
# iptables -I INPUT -d 192.168.1.128 -p tcp --dport 80 -m time --timestart 08:20 --timestop 18:40 --weekdays Mon,Tue,Thu,Fri -j REJECT
5)基于连接数做访问控制:对每个IP所能发起并发连接数做限制
专用选项:--connlimit-above [n],示例:
# iptables -A INPUT -d 192.168.1.128 -p tcp --dport 22 -m connlimit --connlimit-above -j DROP
6、基于速率做访问控制:
专用选项:--limit n[/second|/minute|/hour|/day]、--limit-burst n ,示例:
# iptables -A INPUT -d 192.168.1.128 -p icmp --icmp-type 8 -m limit --limit 20/minute --limit-burst 5 -j ACCEPT
7、状态检查:使用连接追踪的功能对报文进行过滤,在访问量很大的服务器上慎用。
专用选项--state,可以使用的连接追踪的模块在系统的/lib/modules/KERNEL_VERSION/kernel/net/netfilter目录下,示例:放行NEW状态对21号端口的请求报文
# iptables -I INPUT -d 192.168.1.128 -p tcp --dport 21 -m state --state NEW -j ACCEPT
基于状态对会话进行连接追踪的功能模块在iptables安装后在iptables的动态共享库目录下有libxt_state.so的模块,有这个模块就可以在定义规则时使用-m state来指定具体的会话连接状态来进行追踪。而有些基于连接追踪的特殊应用的模块默认并没有装载到iptables的可用模块中,而是需要手动加载到内核中才能使该应用生效,如ftp:
ftp连接追踪功能的模块在/lib/modules/2.6.32-431.el6.x86_64/kernel/net/netfilter目录中,模块名称为nf_contrack_ftp.ko模块。
启用连接追踪ftp的方式:
# modprobe nf_conntrack_ftp;加载与ftp相关的连接追踪模块 # lsmod
如果要停用该功能,使用# modprobe -r nf_conntrack_ftp。
# iptables -A INPUT -d 192.168.1.128 -p tcp -m state --state RELATED,-j ACCEPT # iptables -A OUTPUT -s 192.168.1.128 -m state --state ESTABLISHED,RELATED -j ACCEPT
这两条规则允许后续的ftp数据连接请求,数据可以正常的传输。
iptables规则定义原则:
1、同一类规则,尽量优化条目数量,匹配条目数量越少,效率越高
2、彼此不相关的规则匹配量大的规则,放在前面,匹配量小的规则,放在后面
3、同一类规则,做具体限制的要放在前面。
通常情况下服务器端的iptables规则定义方式为(访问量不是很大的情况下开启基于状态的连接追踪的功能):
# iptables -A INPUT -d 192.168.1.128 -p tcp -m multiport --dports 22,80,53 -m state --state NEW -j ACCEPT #
ping的特殊应用:允许自己ping其他主机,而其他主机不能ping自己:
# iptables -A OUTPUT -s 192.168.1.128 -p icmp --icmp-type 8 -j ACCEPT # iptables -A INPUT -d 192.168.1.128 -p icmp --icmp-type 0 -j ACCEPT
允许其他主机Ping自己:
# iptables -A INPUT -d 192.168.1.128 -p icmp --icmp-type 8 -j ACCEPT # iptables -A OUTPUT -s 192.168.1.128 -p icmp --icmp-type 0 -j ACCEPT
三、自定义链,当iptables规则过多时,可以将不同服务的规则定义到不同的自定义链上,实现归类,以方便管理和查看,主链上我们定义的规则通常是匹配次数最多的条目,具有通用性,而具体的限制型条目往往放在自定义链上:
1、创建自定义链:iptables [-t table] -N chain ,示例:
# iptables -t filter -N http_in
2、在http_in链上写规则,示例:
# iptables -A http_in -d 192.168.1.128 -p tcp --dport 80 -m iprange --src-range 192.168.1.100-192.168.1.150 -j DROP # iptables -A http_in -d 192.168.1.128 -p tcp --dport 80 -m state --state NEW -j ACCEPT
在同一类型的规则中,DROP的规则要放在前面,ACCEPT的要放在后面,这样DROP的条目会被匹配到。
# iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT;未指定IP和协议类型,建立连接的数据报文都允许进入。 # iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT;这条语句与INPUT链的ESTABLISHED成对出现,安全放行所有建立连接的数据报文
3、自定义链的引用方式:自定义链的引用要有明确的条目指明要跳转的自定义链,自定义链的使用情况通常都为请求访问的定义规则,或拒绝或允许,主链中定义的规则都是通用性很强的安全放行的规则,放在第一条位置,实现报文的高效匹配,自定义链的引用定义,示例如下:
# iptables -A INPUT -d 192.168.1.128 -p tcp --dport 80 -j http_in
4、如果有自定义链无法匹配的情况出现还需要返回到主链进行处理,就需要在自定义链中定义规则将处理不了的情况返回至主链处理,定义方法:
# iptables -A http_in -j RETURN
自定义链示例二:
# iptables -N ssh_in # iptables -A ssh_in -d 192.168.1.128 -p tcp --dport 22 -m state --state NEW -j ACCEPT
默认规则都设置为DROP以后,所有的规则定义如下图:
在实际的应用中,每个端口提供的服务往往都是有自定义链来控制,而不是将多个端口提供的服务写在一条规则中,这样可以对某个服务的规则作具体的限制,而且管理起来很方便,不会跟其他的服务混在一起。
5、清空一条自定义链:
# iptables -F CHAIN_NAME
6、删除一条自定义的空链,需要先清空自定义链的规则,并且删除主链上的引用条目:
# iptables -F http_in # iptables -D INPUT 2 # iptables -X http_in
7、自定义链的重命名,以之前的http_in为例:
# iptables -E http_in web_in;将之前名称为http_in的自定义链改名为web_in