1  概述

iptables命令中,需要根据匹配的条件作出相应的动作,本文将结合例子,讲解匹配条件

匹配条件分为基本和扩展的条件

基本:通用的,PARAMETERS,无需加载模块,由iptables/netfilter自行提供

扩展:需要加载扩展模块(/usr/lib64/xtables/*.so),方可生效。其中扩展分为显示扩展隐式扩展

2  实验环境准备:

.Centos7:

因为在centos7上,firewalldiptables是二选一,这里禁用默认的firewalld,启用iptables

systemctl  stop firewalld.service
systemctl  disable firewalld.service

.Centos6:

centos6上执行以下两个语句,关掉默认的防火墙策略,而不是直接禁用防火墙。可以用自定义的防火墙策略

service iptables  stop; 
chkconfig    iptables off;

3  基本匹配条件:

无需加载模块,由iptables/netfilter自行提供

iptables命令本身就带有这些功能,不需要添加模块。

定义防火墙要注意,不要制定错误的策略,把自己拒绝了。

[!] -s, --sourceaddress[/mask][,...]:源IP地址或范围

这里可以用!感叹号表示取反,如下语句表示仅允许192.168.32.65这个ip,其他的ip都拒绝了。注意,以下的语句如果192.168.32.65不是本机ip的话,则此次连接就会被拒绝。这个要注意。

iptables -A INPUT ! -s 192.168.32.65 -j REJECT

表示除了192.168.32.0/24的网段不拒绝,其他网段都拒绝

iptables -A INPUT ! -s192.168.32.0/24 -j REJECT

[!] -d, --destinationaddress[/mask][,...]:目标IP地址或范围

[!] -p, --protocol protocol:指定协议,可使用数字如0all

protocol: tcp, udp, icmp,icmpv6,udplite,esp, ah, sctp, mh   or all“参看:/etc/protocols

[!] -i, --in-interface name:报文流入的接口;只能应用于数据

报文流入环节,只应用于INPUTFORWARDPREROUTING

#以下策略表示eth0拒绝icmp协议,即禁ping

iptables -A INPUT -i eth0 -p icmp -j REJECT

[!] -o, --out-interface name:报文流出的接口;只能应用于数据报文流出的环节,只应用于FORWARDOUTPUTPOSTROUTING

4  扩展匹配条件:

需要加载扩展模块(/usr/lib64/xtables/*.so),方可生效

.查看帮助maniptables-extensions

4.1  隐式扩展:

在使用-p选项指明了特定的协议时,无需再用-m选项指明扩展模块的扩展机制,不需要手动加载扩展模块。

.tcp协议的扩展选项

[!] --source-port, --sportport[:port]:匹配报文源端口,可为端口范围

[!] --destination-port,--dport  port[:port]:匹配报文目标端口,可为范围

[!] --tcp-flags mask comp

例子:禁止tcp协议的80端口被访问

iptables -A INPUT -p tcp--dport 80 -j REJECT

mask 需检查的标志位列表,用,分隔

例如SYN,ACK,FIN,RST

comp mask列表中必须为1的标志位列表,无指定则必须为0,用,分隔

tcp协议的扩展选项

.示例:

--tcp-flags SYN,ACK,FIN,RST SYN 表示要检查的标志位为SYN,ACK,FIN,RST四个,其中SYN必须为1,余下的必须为0

#以下例子表示要检查SYN,ACK,FIN,RST四位,其中SYN,ACK必须为1 FIN,RST必须为0.

--tcp-flags SYN,ACK,FIN,RST SYN,ACK

#表示检查所有的位都为1,这个是不正常的报文,可能是***构造的问题报文

--tcp-flags ALL ALL

#表示检查所有的位都为0,这个也是不正常报文

--tcp_flagsALL NONE

.[!] --syn:用于匹配第一次握手

相当于:--tcp-flagsSYN,ACK,FIN,RST SYN

.udp协议的扩展选项

[!] --source-port, --sportport[:port]:匹配报文的源端口;可以是端口范围

 port[:port]:这里的端口是多个端口,但是必须是连续的端口

[!]--destination-port,--dportport[:port]:匹配报文的目标端口;可以是端口范围

.icmp协议的扩展选项

[!] --icmp-type{type[/code]|typename}

type/code

0/0 echo-reply      icmp应答

#以下命令禁止了主机去ping其他主机,因为这样该机器就不能收到其他主机发回来的应答的ping包。

iptables -A INPUT -p icmp--icmp-type 0 -j REJECT

8/0 echo-request icmp请求

#如以下命令拒绝了ping的请求包,该主机就禁止别的主机来ping,因为把ping的请求包都拒绝了

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

4.2  显式扩展:

必须使用-m选项指明要调用的扩展模块的扩展机制,要手动加载扩展模块,[-mmatchname  [per-match-options]]

.使用帮助,查看显示扩展的选项

CentOS 6: man iptables

CentOS 7: man iptables-extensions

.1multiport扩展

注意要加上-m ,表示要调用multiport这个模块

以离散方式定义多端口匹配,最多指定15个端口

[!] --source-ports,--sportsport[,port|,port:port]...:指定多个源端口

#以下例子表示拒绝源主机是172.18.50.75的机器的8021端口的包。控制本主机访问指定主机的指定端口

iptables -A INPUT -s172.18.50.75  -p tcp -m multiport--sports 80,21 -j REJECT

[!]--destination-ports,--dports  port[,port|,port:port]...:指定多个目标端口,这个配置是禁止别的主机来访问本主机的这些端口。控制别的主机来访问本主机的指定端口

[!] --portsport[,port|,port:port]...多个源或目标端口

#示例一:

# -s 172.16.0.0/16 表示禁止 172.16.0.0/16 这个网段的主机来访问

iptables-A INPUT -s 172.16.0.0/16 -d172.16.100.10 -p tcp  -m multiport--dports  20:22,80 -j ACCEPT

#例子二

iptables -A INPUT -s172.18.50.73 -p tcp -m multiport --dports 80,22 -j REJECT

.2iprange扩展

指明连续的(但一般不是整个网络)ip地址范围

[!] --src-range from[-to]IP地址范围

#以下语句本机将拒绝来自172.18.50.60-172.18.50.80ssh连接和80端口的访问

iptables -A INPUT -miprange --src-range 172.18.50.60-172.18.50.80 -p tcp -m multiport --dports22,80 -j REJECT

[!] --dst-range from[-to]目标IP地址范围

#以下将本机将拒绝去往172.18.50.60-172.18.50.80ssh连接80端口的访问

iptables -A INPUT -miprange --dst-range 172.18.50.60-172.18.50.80 -p tcp -m multiport --dports22,80 -j REJECT

#表示来自172.16.100.5-172.16.100.10ip访问172.16.100.10这台主机的80端口都拒绝

iptables -A INPUT -d 172.16.100.10-p tcp --dport 80 -m iprange --src-range172.16.100.5-172.16.100.10 -j DROP

.3mac扩展

指明源MAC地址

适用于:PREROUTING,FORWARDINPUTchains

[!] --mac-source XX:XX:XX:XX:XX:XX

示例:

#拒绝源ip172.16.0.100的网卡mac00:50:56:12:34:56的访问

iptables -A INPUT -s 172.16.0.100 -mmac --mac-source 00:50:56:12:34:56

-j ACCEPT

#拒绝来自源ip:172.16.0.100的所有访问

iptables-A INPUT -s 172.16.0.100 -jREJECT

.4string扩展

对报文中的应用层数据做字符串模式匹配检测

--algo {bm|kmp}:字符串匹配检测算法

bmBoyer-Moore

kmpKnuth-Pratt-Morris

--from offset 开始偏移

--to offset 结束偏移

[!] --string pattern:要检测的字符串模式,只能处理明文数据

[!] --hex-string pattern:要检测字符串模式,16进制格式

示例:

#禁止去往目的地是172.18.50.7580端口中包含有sunny的数据包

iptables -A OUTPUT -d172.18.50.75 -p tcp --sport 80 -m string --algo bm --string "sunny"-j REJECT

#禁止来自172.18.50.7580端口返回的包中有sunny字符串的包

iptables -A INPUT -s172.18.50.75 -p tcp --sport 80 -m string --algo bm --string "sunny"-j REJECT

.5time扩展

根据将报文到达的时间与指定的时间范围进行匹配

--datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]日期

--datestopYYYY[-MM[-DD[Thh[:mm[:ss]]]]]

--timestart hh:mm[:ss] 时间

--timestop hh:mm[:ss]

[!] --monthdays day[,day...] 每个月的几号

[!] --weekdays day[,day...] 星期几

--kerneltz:内核时区,本地时间,不建议使用,CentOS7系统默认为UTC,所以需要转换时间,差八个小时

注意:centos6不支持kerneltz --localtz指定本地时区(默认)centos6默认使用本地时间

注意:默认情况下,centos7用的是UTC时间(世界协调时间:UniversalTime Coordinated),而中国主机一般都是用CST时间(China Standard Time UT 8:00)UTC时间比CST时间晚八个小时,所以在centos7上通过iptables来定义时间范围时,如果系统使用CST时间,就要减去8个小时,如要定义时间为9:00--18:00,那么用iptables定义的时间应该是1:00--10:00

centos6默认则是使用的是当地时间,即在中国就是使用CST时间,不需要减去8小时进行转换

示例:

centos6上以下这配置表示CST 时间9:00--12:55。不允许其他主机访问80端口

centos7上以下这配置表示UTC 时间9:00--12:55,要转换为CST时间,需要加上8小时,即表示CST时间 17:00--20:55期间不允许访问80端口

iptables -A INPUT -m time--timestart 09:00 --timestop 12:55 -p tcp --dport 80 -j REJECT

centos6上,以下语句表示星期3,5,6这三天CST 时间9:00--12:55期间不允许其他主机访问80端口

iptables -R INPUT 1 -mtime --weekdays Wed,Fr,Sa --timestart 09:00 --timestop 12:55 -p tcp --dport 80-j REJECT

.6connlimit扩展

根据每客户端IP并发连接数数量匹配,可防止CC(ChallengeCollapsar挑战黑洞)***

--connlimit-upton:连接的数量小于等于n时匹配,小于或者等于多少的这个数字一般是允许的

--connlimit-above n:连接的数量大于n时匹配,一般大于多少的时候是拒绝

通常分别与默认的拒绝或允许策略配合使用

示例:

#表示同一个主机ip来连接时,只允许一个ipssh进行连接,当同一ip超过一个ssh连接的时候拒绝ssh连接.但是如果客户端不是复制出来的时候,那么就不会拒绝

iptables -A INPUT -p tcp--dport 22 -m connlimit --connlimit-above 1 -j REJECT

#以下语句表示访问80端口的并发数超过15的时候,就拒绝访问,可以用ab -c 15-n 1000 http://172.18.50.65/这个命令进行测试,当并发数大于15的时候就会拒绝访问

iptables -A INPUT -p tcp--dport 80 -m connlimit --connlimit-above 15 -j REJECT

.7limit扩展

基于收发报文的速率做匹配

令牌桶过滤器

--limit rate[/second|/minute|/hour|/day]表示每分钟或者每秒允许通过多少

--limit-burst number:表示前面几个包不限制,超过多少的时候开始限制

两个选项要一起使用

示例:

#以下语句表示前5个包icmp的请求包不限制,超过5个包后,每分钟只运行3个,

iptables -A INPUT -d 172.16.100.10-p icmp --icmp-type 8 -m limit --limit3/minute --limit-burst 5 -j ACCEPT

#插入第2条记录,拒绝所有的icmp请求包

iptables -A INPUT 2 -p icmp -j REJECT

以上两条规则要一起加。默认的行为就拒绝

.8state扩展

根据连接追踪机制去检查连接的状态,较耗资源

.conntrack机制:追踪本机上的请求和响应之间的关系

.状态有如下几种:

这里的状态跟踪和tcp的状态是不一样的概念。

一般做防火墙策略时,新发起的请求拒绝,但是已经是连接状态的包是被允许的。而且一般把允许已经连接的策略放在前面。

NEW:新发出请求;连接追踪信息库中不存在此连接的相关信息条目,因此,将其识别为第一次发出的请求

ESTABLISHEDNEW状态之后,连接追踪信息库中为其建立的条目失效之前期间内所进行的通信状态

RELATED:新发起的但与已有连接相关联的连接,如:ftp协议中的数据连接与命令连接之间的关系

INVALID:无效的连接,如flag标记不正确

UNTRACKED:未进行追踪的连接,如raw表中关闭追踪

.[!] --state state

.示例:

iptables  -A INPUT -d 172.16.100.10 -p tcp  -m  multiport --dports22,80 -m state --stateNEW,ESTABLISHED -j ACCEPT

一般把正在建立连接的防火墙策略放在前面。这样不好影响正在连接的用户,而且效率高。常用的要放在前面。

iptables  -A OUTPUT -s 172.16.100.10 -p tcp  -m multiport --sports 22,80 -m state --stateESTABLISHED -j ACCEPT

.已经追踪到的并记录下来的连接信息库

/proc/net/nf_conntrack

.调整连接追踪功能所能够容纳的最大连接数量,这个数值可以更改

/proc/sys/net/nf_conntrack_max

.不同的协议的连接追踪时长

/proc/sys/net/netfilter/

.注意:CentOS7需要加载模块:modprobe  nf_conntrack

.iptables的链接跟踪表最大容量为/proc/sys/net/nf_conntrack_max,各种状态的超时链接会从表中删除;当模板满载时,后续连接可能会超时

.解决方法两个:

(1) 加大nf_conntrack_max值,编辑/etc/sysctl.conf这个文件,写入.nf_conntrack_max = 200000 将改为20000.重启网络服务后生效

vi /etc/sysctl.conf
net.nf_conntrack_max= 393216
net.netfilter.nf_conntrack_max=393216

(2) 降低nf_conntrack  timeout时间

vi /etc/sysctl.conf
net.netfilter.nf_conntrack_tcp_timeout_established=300
net.netfilter.nf_conntrack_tcp_timeout_time_wait=120
net.netfilter.nf_conntrack_tcp_timeout_close_wait=60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait=120
iptables  -t nat -L -n

 9、开放被动模式的ftp服务例子

.(1) 装载ftp连接追踪的专用模块:

一般不定义OUTPUT,否则很可能会把自己主机出去的连接拒绝。

跟踪模块路径:/lib/modules/kernelversion/kernel/net/netfilter

vim /etc/sysconfig/iptables-config #配置文件
IPTABLES_MODULES="nf_conntrack_ftp"
modprobe  nf_conntrack_ftp

检查:lsmod | grep ftp 查看是否成功加载模块,nf_conntrack_ftp这个模块如果不加载,将不能识别ftp服务,不能进行跟踪,导致策略失败

.(2) 放行请求报文:

命令连接:NEW,ESTABLISHED

数据连接:RELATED,ESTABLISHED

iptables  –IINPUT -d LocalIP  -p tcp  -m state --state   RELATED,ESTABLISHED -j ACCEPT
iptbles  -A INPUT -d LocalIP  -p tcp--dport 21 -m state --state NEW -j ACCEPT

例子

iptables -A INPUT -m state--state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp--dport 21 -m state --state NEW -j ACCEPT

.(3) 放行响应报文:

#这一步可以不操作

iptables  -I OUTPUT -s LocalIP  -p tcp-m state --state  ESTABLISHED -j ACCEPT

开放被动模式的ftp服务示例

yum install vsftpd
systemctl start vsftpd
modprobe nf_conntrack_ftp
iptables -F
iptables -A INPUT -m state--state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp--dport 21 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -mstate --state ESTABLISHED -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT DROP