3、iptables扩展及使用
iptables/netfilter
netfilter: kernel framework,位于内核中的协议框架
iptables 是规则管理命令行工具
四表:filter, nat, mangle, raw
五链:PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING
iptables
子命令:
链:-F, -X, -N, -E, -Z, -P, -L
规则:-A, -I, -D, -R
-j TARGET:
ACCEPT, DROP, REJECT, RETURN, LOG, MARK, DNAT, SNAT, MASQUEARDE, ...
匹配标准:
- 通用匹配:-s, -d, -p, -i, -o
- 扩展匹配
- 隐含扩展:
- -p tcp: --dport, --sport, --tcp-flags, --syn (--tcp-flags SYN,ACK,FIN,RST SYN)
- -p udp: --dport, --sport
- -p icmp: --icmp-type
- 显式扩展: -m
iptables:
显式扩展:
multiport扩展、iprange扩展、string扩展、time扩展、connlimit扩展、limit扩展、state扩展
必须显式指明使用的扩展模块(rpm -ql iptables | grep "\.so"或rpm -ql iptables | grep "[[:lower:]]\+\.so$")
CentOS 6: man iptables
CentOS 7: man iptables-extensions
1、multiport扩展 (--dport/--sport指明端口时必须是单个的或连续的)
以离散方式定义多端口匹配;最多指定15个端口;
[!] --source-ports,--sports port[,port|,port:port]...:指明多个源端口;
[!] --destination-ports,--dports port[,port|,port:port]...:指明多个离散的目标端口;
[!] --ports port[,port|,port:port]...:既能匹配源端口,也能匹配目标端口
-m multiport 示例
# iptables -A INPUT -d 192.168.184.142 -p tcp --dport 22 -j ACCEPT //放行22号端口
# iptables -A OUTPUT -s 192.168.184.142 -p tcp --sport 22 -j ACCEPT
# iptables -P INPUT DROP //修改表的默认策略
# iptables -P FORWARD DROP
# iptables -P OUTPUT DROP
此时web服务是无法响应的,下面演示一次性定义开放22和80端口
# iptables -I INPUT -s 192.168.184.0/24 -d 192.168.184.142 -p tcp -m multiport --dports 22,80 -j ACCEPT 入栈
// -s 指定源IP,这里指的是一个网段,-m 指是使用显式扩展,--dports指定多个离散端口
# iptables -I OUTPUT -d 192.168.184.0/24 -s 192.168.184.142 -p tcp -m multiport --sports 22,80 -j ACCEPT
# iptables -D INPUT 2
# iptables -D OUTPUT 2
此时的80端口也可以访问了
2、iprange扩展 ip范围
指明连续的(但一般是不能扩展为整个网络)ip地址范围时使用;
[!] --src-range from[-to]:指明连续的源IP地址范围;
[!] --dst-range from[-to]:指明连续的目标IP地址范围;
iprange示例
# iptables -I INPUT -d 192.168.184.142 -p tcp -m multiport --dports 22:23,80 -m iprange --src-range 192.168.184.1-192.168.184.150 -j ACCEPT
# iptables -I OUTPUT -s 192.168.184.142 -p tcp -m multiport --sports 22:23,80 -m iprange --dst-range 192.168.184.1-192.168.184.150 -j ACCEPT
//连续端口之间用冒号隔开:22:23,不连续的用80隔开
# iptables -D INPUT 2
# iptables -D OUTPUT 2
3、string扩展
功能:基于字符串匹配去检查协议传输单元中的内容
1、任何通过网络传输的数据都必定是可以被流式化的数据,
2、数据通过网络传输时,会被封装上各种首部,
string可以检查在网络上发送的每一个报文,报文虽然编码,却可以匹配编码中是否出现了string指定的字符串的。
iptables工作在网络层和传输层,却可以通过string扩展去检查所传输的内容中是否有要匹配的字符串的
检查报文中出现的字符串;
--algo {bm|kmp} 指明字符串比对算法,必须给定算法
bm = Boyer-Moore
kmp = Knuth-Pratt-Morris
[!] --string pattern 指明字符串是什么
string示例
在web服务器的web页面文件中定义一个bad.html
# vim /var/www/html/bad.html
This is a movie page. //网页内容,如果用户请求的网页中包含movie,那么就拒绝
一般来说当用户请求一个网页,他请求的报文中一般不包含非法内容,因为只有网页响应的时候,网页上的内容有可能包含非法内容,所以应该在output规则上添加规则,同时应该放在output定义的80规则上面,因为如果放在80下面,那么响应报文被80规则匹配到以后直接就发送出去了
未定义之前是可以被访问的
# iptables -I OUTPUT -m string --algo bm --string 'movie' -j REJECT //下图未做修改
142的默认网页可以查看
但是带有movie的网页无法查看
请求可以进来,但由于含有movie字符串,所以web服务器并不响应
4、time扩展
根据报文到达的时间与指定的时间范围进行匹配;
#man iptables-extensions 即可查看下面的用法
- --datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
- --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
- --timestart hh:mm[:ss]
- --timestop hh:mm[:ss]
- [!] --monthdays day[,day...]
- [!] --weekdays day[,day...]
从0点到23点之间不允许访问,因为Linux系统用的是CST时间,这里既然拒绝就直接在请求上即INPUT上拒绝,同时同类规则匹配范围小的放前面,所以放在INPUT第一条规则
# iptables -I INPUT -d 192.168.184.142 -p tcp --dport 80 -m time --timestart 00:00 --timestop 23:59 -j REJECT
此时在浏览器中输入192.168.184.142就不再提供web服务了
5、connlimit扩展
根据每客户端IP(也可以是地址块)做并发连接数数量匹配;即对每个IP可以对服务器同时发送请求的数量的限制。
--connlimit-above n:连接的数量大于n
--connlimit-upto n: 连接的数量小于等于n
默认策略是拒绝, 使用--connlimit-upto来允许,默认是允许,使用--connlimit-above允许
限制ssh的并发链接数,放在INPUT链上ssh服务即22号端口的规则的上面
# iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j REJECT
6、limit扩展
基于收发报文的速率做检查;
令牌桶过滤器 令牌桶算法 https://jinnianshilongnian.iteye.com/blog/2305117 https://blog.csdn.net/SunnyYoona/article/details/51228456#commentBox
--limit rate[/second|/minute|/hour|/day] //表示每秒钟/分钟/小时/天多少个 30/minute:表示每两秒响应一个请求
--limit-burst number 表示未响应前的峰值即第一次响应可以一次性响应多少个请求
示例
- 0:echo-reply 回显应答
- 8: echo-request 回显请求
# iptables -A OUTPUT -s 192.168.184.144 -p icmp --icmp-type 8 -j ACCEPT ping别的主机,先从本主机出去,目标地址不知道,ping请求是8
# iptables -A INPUT -d 192.168.184.144 -p icmp --icmp-type 0 -j ACCEPT ping别的主机,要接受ping后的报文,目标地址是本机,报文类型是回显应答
以上是只能本机ping别的主机,别的主机无法ping本主机,下面就定义规则为限制别的主机ping本主机的速率
# iptables -A INPUT -d 192.168.184.142 -p icmp --icmp-type 0 -m limit --limit-burst 5 --limit 30/minute -j ACCEPT //响应请求的速率
//-s源地址省略,表示所有主机可以ping本主机;别的主机ping本主机,请求类型为8,表示回显请求;limit:表示做速率限制,--limit-burst 5:表示第一次可以一次性响应5个请求;--limit 30/minute:表示每两秒一个,
# iptables -A OUTPUT -s 192.168.184.142 -p icmp --icmp-type 8 -j ACCEPT //响应请求后,从本机响应的报文不再做限制,只要ping进来就能响应
# ping -W 1 192.168.184.142 //使用-W表示ping每隔1秒钟向外发一个包
7、state扩展 状态扩展 (重要)
根据连接追踪机制检查连接的状态,对链接做出匹配检查;
连接追踪是iptables在内核内部找一段内核空间,并在这段内核空间中记录下来此前每一个源地址,和这个源地址访问的目标地址(目标地址一般是本机地址),然后给每一个源地址和目标地址的链接记录下来,并在后面记录一个倒计时的计时器(可以记录的非常详细,比如包括协议、源端口、目标端口等),这个内存空间是在内核中,所以这个内核比较小
链接与链接之间的状态,跟tcp、udp、icmp协议无关,是iptables自己在内核中的一个功能
调整连接追踪功能所能够容纳的最大连接数量:
/proc/sys/net/nf_conntrack_max
已经追踪到并记录下的连接:
/proc/net/nf_conntrack
不同协议或连接类型追的时长:
/proc/sys/net/netfilter/
可追踪的连接状态:
NEW:新发出的请求;连接追踪模板中不存此连接相关的信息条目,因此,将其识别为第一次发出的请求;
ESTABLISHED:NEW状态之后,连接追踪模板中为其建立的条目失效之前,这段期间内所进行的通信的状态;
RELATED:相关的连接;如ftp协议的命令连接与数据连接之间的关系;
INVALIED:无法识别的连接;
RELATED:一个新的链接请求发起时本来是NEW,但是对ftp这样的应用来讲,数据链接是与一个已存在的命令链接或控制链接是相互关联的,因此在这种场景中,数据链接新发起的链接状态可以识别为NEW,实际上更多在nf_conntrack_ftp打开以后被识别成RELATED请求,不过RELATED这个链接请求建立完成后,后续的传输过程中都是ESTABLISHED。
--state STATE1,STATE2,... --state NEW,ESTABLISHED
示例
对22和80端口只能是响应,不能去请求。所以对NEW状态的应该放行,因为别的主机可能请求服务器,对于ESTABLISHED也应该放行,因为这是响应。但是对于响应的只能放行ESTABLISHED状态的
# iptables -I INPUT -d 192.168.184.142 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
//--state NEW,ESTABLISHED 这里是入栈的链接,放行22端口的NEW和ESTABLISHED两种状态
# iptables -I OUTPUT -s 192.168.184.142 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT //出去的报文,只放行状态为ESTABLISHED
像放行22号端口一样放行80端口,就直接修改上面的规则
# iptables -I INPUT -d 192.168.184.142 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -I OUTPUT -s 192.168.184.142 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
下面把两个端口合二为一
# iptables -I INPUT -d 192.168.184.142 -p tcp -m multiport --dports 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -I OUTPUT -s 192.168.184.142 -p tcp -m multiport --sports 22,80 -m state --state ESTABLISHED -j ACCEPT
如果别的主机ping本主机?
# iptables -A INPUT -d 192.168.184.142 -p icmp --icmp-type 0 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -s 192.168.184.142 -p icmp --icmp-type 8 -m state --state ESTABLISHED -j ACCEPT
此时ping就可以建立链接了
从以上可以发现无论是tcp协议还是icmp协议,或者无论是22号端口或者80端口,只要允许进入INPUT,都要放行,所以可以在OUTPUT上定义一条规则,这条规则不定义端口、协议、源IP和目标IP,只定义链接状态ESTABLISHED。
# iptables -I OUTPUT -m state --state ESTABLISHED -j ACCEPT //此时这里只定义链接状态
一条规则就可以直接对N条规则直接放行,这就是规则优化
可以假设入栈的只要是ESTABLISHED状态的,就说明此前访问过,那么所有ESTABLISHED状态就可以统统放行,只要对NEW状态不放行就可以。
# iptables -I INPUT -m state --state ESTABLISHED -j ACCEPT //无论tcp、icmp协议的请求,只要是已经建立的链接,只要被第一条匹配到直接通过
# iptables -I INPUT 2 -d 192.168.184.142 -p tcp -m multiport --dports 22,80 -m state --state NEW -j ACCEPT
问题:如何开放被动模式的ftp服务?
对21号端口开放NEW和ESTABLISHED,因为命令链接一般是通过21号端口实现,由于数据链接工作在非固定的随机端口上,
所以只需要检查这个链接的状态是不是为RELATED就可以了,如果是RELATED,无论是入栈还是出栈直接放行就可以。
(1) 装载ftp追踪时的专用的模块:
/lib/modules/3.10.0-693.el7.x86_64/kernel/net
/lib/modules/3.10.0-693.el7.x86_64/kernel/net/netfilter
# modprobe nf_conntrack_ftp //装载模块
# lsmod //可以查看装载的模块
(2) 放行请求报文:
命令连接:NEW, ESTABLISHED
数据连接:RELATED, ESTABLISHED
(数据刚建立链接时的状态叫RELATED,这个只是第一次建立数据链接时,而且不叫新连接,而是RELATED链接,而不是NEW,命令链接才是NEW)
ftp专用放行规则
# iptables -A INPUT -d LocalIP -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT //放行的命令链接
# iptables -A INPUT -d LocalIP -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT //放行的数据链接,不再限制端口
(3) 放行响应报文:
ESTABLISEHD
# iptables -A OUTPUT -s LocalIP -p tcp -m state --state ESTABLISHED -j ACCEPT //出栈放行
示例
1、安装vsftpd软件并启动
# yum install vsftpd -y
# cp /etc/issue /var/ftp/pub/ //cp文件到vsftp的默认下
# systemctl start vsftpd //启动ftp服务
# ss -tunl //查看21号端口是否启动
2、关闭防火墙并清空规则,下图是已经配置的iptables规则链,可以先保存
# iptables-save > /root/iptables.1
修改成下图的样子
可以在浏览器中访问ftp服务
3、添加规则链
# iptables-restore < /root/iptables.1 //把之前保存的规则重新导入,这里换成了141服务器,在文件中修改IP即可
# modprobe nf_conntrack_ftp //装载ftp模块
# lsmod | grep ftp
nf_conntrack_ftp 18638 0
nf_conntrack 133387 3 xt_conntrack,nf_conntrack_ftp,nf_conntrack_ipv4
# iptables -R INPUT 2 -d 192.168.184.141 -p tcp -m multiport --dport 21,22,80 -m state --state NEW -j ACCEPT
//这里直接修改了INPUT的第二条规则,即在--dport上添加了21号端口,这是放行(进栈)的命令链接,是NEW状态
# iptables -R INPUT 1 -m state --state ESTABLISHED,RELATED -j ACCEPT
//RELATED无法确定是tcp的哪个端口,而且只有用到RELATED功能的才会检查RELATED状态,所以很少用,所以直接把第一条规则改为ESTABLISHED和RELATED都放行
出栈的无论什么协议、什么IP、什么端口只要是ESTABLISHED状态全都放行,所以无需再改,所以ftp服务就可以访问了
命令链接和数据链接的区别?
一个新的链接请求发起时本来是NEW,但是对ftp这样的应用来讲,数据链接是与一个已存在的命令链接或控制链接是相互关联的,因此在这种场景中,数据链接新发起的链接状态可以识别为NEW,实际上更多在nf_conntrack_ftp打开以后被识别成RELATED请求,不过RELATED这个链接请求建立完成后,后续的传输过程中都是ESTABLISHED。