Iptables防火墙常用的扩展模块匹配规则

3,031 阅读17分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

1.Iptables防火墙扩展模块的匹配规则

Iptables的扩展模块有以下几种:

  • multiport:多端口匹配模块。
  • iprange:多IP范围匹配模块
  • string:
  • time:
  • icmp:
  • connlimit:
  • limit:
  • tcp-flags:

2.Iptables防火墙multiport模块扩展匹配规则

在前面做端口匹配的时候都是通过--dport参数来指定一个端口或者连续的一组端口,如果我们想同时对多个不连续的端口添加防火墙规则,那么--dport参数就无法实现了。

基于这种情况,防火墙提供了-m参数指定扩展模块,通过multiport参数就可以同时指定多个不连续的端口号,一条防火墙规则最大支持同时添加15个不同的端口号。

案例:仅允许192.168.20.21访问本机的80、443、20、21、22端口,其余所有主机都不允许访问本机的80、443、20、21、端口。

1)编写防火墙规则

在INPUT链的filter表中添加对应的规则。

 1.允许192.168.20.21访问本机的80443202122
 [root@jxl-1 ~]# iptables -t filter -I INPUT -s 192.168.20.21 -d 192.168.20.20 -p tcp -m multiport --dports 20,21,22,80,443 -j ACCEPT
 #还有另一种写法
 [root@jxl-1 ~]# iptables -t filter -I INPUT -s 192.168.20.21 -d 192.168.20.20 -p tcp -m multiport --dports 20:22,80,443 -j ACCEPT 
 ​
 2.拒绝所有主机访问本机的TCP端口
 [root@jxl-1 ~]# iptables -t filter -A INPUT -p tcp -m multiport --dports 20,21,80,443 -j DROP

2)查看添加的规则

允许192.168.20.21主机访问本机的20,21,22,80,443端口,其余所有主机都不允许访问本机的20,21,80,443端口。

 [root@jxl-1 ~]# iptables -L -n -v --line-number
 Chain INPUT (policy ACCEPT 653 packets, 601K bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 1        0     0 ACCEPT     tcp  --  *      *       192.168.20.21        192.168.20.20        multiport dports 20,21,22,80,443
 2        0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 20,21,80,443
 ​
 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 ​
 Chain OUTPUT (policy ACCEPT 676 packets, 993K bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 [root@jxl-1 ~]# 

3)测试效果

随便选择一个端口,以80为例,可以看到192.168.20.21可以正常使用,而192.168.20.22则无法使用。

image-20220429220845778.png

4.2.Iptables防火墙iprange模块扩展匹配规则

iprange模块可以同时设置多个IP或者设置IP的某一段连续的范围,通过iprange模块可以对多个来源地址同时设置策略。

iprange模块的参数:

  • --src-range:指定源地址范围。
  • --dst-range:指定目标地址范围。
  • ! --src-range:非指定的源地址。
  • ! --dst-range:非指定的目标地址。

可以在参数前面加!号表示去反。

案例:源地址范围为192.168.20.10-192.168.20.19的IP地址都不允许ping192.168.20.20这个目标地址。

1)编写防火墙规则

在INPUT链的filter表中添加对应的规则。

 1.无需指定目标地址
 [root@jxl-1 ~]# iptables -t filter -I INPUT -p icmp -m iprange --src-range 192.168.20.10-192.168.20.19 -j DROP
 ​
 2.也可以指定目标地址,效果都一样
 [root@jxl-1 ~]# iptables -t filter -I INPUT -p icmp -m iprange --src-range 192.168.20.10-192.168.20.19 --dst-range 192.168.20.20 -j DROP

2)查看添加的规则

禁止192.168.20.10-192.168.20.19的源地址请求的ICMP协议数据报文进入本机。

 [root@jxl-1 ~]# iptables -L -n -v --line-number
 Chain INPUT (policy ACCEPT 2033 packets, 2002K bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 1        0     0 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            source IP range 192.168.20.10-192.168.20.19
 ​
 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 ​
 Chain OUTPUT (policy ACCEPT 2072 packets, 3079K bytes)
 num   pkts bytes target     prot opt in     out     source               destination         

3)测试效果

登陆192.168.20.10这个服务器中ping192.168.20.20,发现ping不通,登陆192.168.20.21这个服务器,发现能ping通192.168.20.20。

image-20220429224507151.png

3.Iptables防火墙string模块扩展匹配规则

String模块的作用是来匹配请求报文中指定的字符串,经常应用于拦截用户访问某些网站的场景,将防火墙当做路由器使用,例如上班时间不允许用户访问淘宝网站等等场景。

String模块的常用参数:

  • --string pattern:指定要匹配的字符串。
  • ! --string pattern:反向匹配。
  • --algo:指定匹配的查询算法,有bm和kmp两种算法。

可以在参数前面加!号表示去反。

案例:当用户请求的数据报文中包含taobao.com,则拒绝通行,其余的正常放行。

用户通过防火墙流出然后访问目标端,因此需要在OUTPUT链添加规则。

1)首先来准备含有taobao.com数据报文的WEB网站。

 1.安装httpd
 [root@jxl-1 ~]# yum -y install httpd
 [root@jxl-1 ~]# echo hahaha > /var/www/html/ha.html
 [root@jxl-1 ~]# echo taobao.com > /var/www/html/taobao.html
 [root@jxl-1 ~]# systemctl restart httpd
 ​
 2.正常的两个页面
 [root@jxl-1 ~]# curl 127.0.0.1/ha.html
 hahaha
 [root@jxl-1 ~]# curl 127.0.0.1/taobao.html
 taobao.com

2)编写防火墙规则,拒绝数据包中包含taobao.com内容的数据包。

 [root@jxl-1 ~]# iptables -t filter -I OUTPUT -p tcp -m string --string "taobao.com" --algo bm -j DROP

3)查看设置的防火墙规则。

 [root@jxl-1 ~]# iptables -L -n -v --line-number
 Chain INPUT (policy ACCEPT 7011 packets, 6693K bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 ​
 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 ​
 Chain OUTPUT (policy ACCEPT 7310 packets, 11M bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 1        0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            STRING match  "taobao.com" ALGO name bm TO 65535

4)测试效果,发现hahaha的页面可以正常访问,taobao.com页面的请求将被拦截。

image-20220429231709989.png

.4.Iptables防火墙time模块扩展匹配规则

time模块的作用是根据时间范围来匹配报文,例如在上午的8点30到下午18点30关于浏览淘宝的报文都拒绝。

time模块的常用参数:

  • --timestart:指定开始时间。
  • --timestop:指定结束时间。
  • --monthdays:指定一个月中的某一天。
  • --weekdays:指定一周中的周期,例如1-7。
  • --kerneltz:使用内核时区的时间。

可以在参数前面加!号表示去反。

time模块默认使用的实际UTC时间,UTC时间比我们正常的时间慢8小时。

案例:在周一到周五的8:00到18:00禁止访问淘宝网站。

此案例也是将防火墙看做了是路由器,在流量流出时定义防火墙规则,也就是在防火墙的OUTPUT链定义规则。

1)编写防火墙规则

在周一到周五的8点到18点时间段,所有发往taobao.com的TCP 80端口的报文都会被拒绝。

 [root@jxl-1 ~]# iptables -t filter -I OUTPUT -p tcp -d taobao.com --dport 80 -m time --timestart 00:00 --timestop 10:00 --weekdays 1,2,3,4,5 -j DROP

2)查看设置的防火墙规则

淘宝网的地址有很多,写入防火墙后,会将解析出来的多个IP地址都写入到表中,如下图所示。

image-20220430100654252.png

3)测试效果

在周一到周五的早上8点到晚上18点的范围之间,再想访问淘宝网,则会被拦截。

image-20220430100752181.png

5.Iptables防火墙icmp模块扩展匹配规则

在前面做icmp协议的DROP动作规则时,其他主机确实无法ping通本机了,但是本机也同样无法ping通别的主机,那是因为拒绝动作是在INPUT链完成的,ping是有请求和回应的,INPUT链已经把icmp协议拒绝了,无法回应,就导致本机也无法ping通其他主机。

icmp模块常用的参数:

  • --icmp-type:指定icmp协议的类型,icmp协议有请求和回应两种类型,其他主机ping本机属于请求类型,本机ping其他主机属于回应类型。

    • echo-request:请求类型,ID为8。
    • echo-reply:回应类型,ID为0。

可以在参数前面加!号表示去反。

案例:禁止其他主机ping本机,本机依旧可以ping其他主机。

1)编写防火墙规则

 [root@jxl-1 ~]# iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j DROP

2)查看设置的防火墙规则

 [root@jxl-1 ~]# iptables -L -n -v --line-number 
 Chain INPUT (policy ACCEPT 962 packets, 843K bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 1        0     0 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8
 ​
 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 ​
 Chain OUTPUT (policy ACCEPT 945 packets, 1266K bytes)
 num   pkts bytes target     prot opt in     out     source               destination

3)测试效果

其他主机无法ping通本机,本机依旧可以ping通其他主机。

image-20220430103457496.png

6.Iptables防火墙connlimit模块扩展匹配规则

connlimit模块的作用是限制请求报文对特定服务的并发连接数限制的,例如Telnet服务,默认情况下没有并发连接数的限制,可以允许n个客户端同时连接,如果应用了connlimit模块,可以对并发连接数进行限制。

connlimit模块常用参数:

  • --connlimit-upto:如果现有连接数小于或等于设置的并发连接数值,那么就放行。
  • --connlimit-above:如果现有连接数大于设置的并发连接数值,那么就放行。

案例:每个客户端主机仅允许同时对本机发起两个ssh连接。

数据流入的操作,在INPUT链的filter表添加相应的规则。

1)编写具体的防火墙规则

 [root@jxl-1 ~]# iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT

2)查看设置的规则

 [root@jxl-1 ~]# iptables -L -n -v --line-number 
 Chain INPUT (policy ACCEPT 52358 packets, 43M bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 1        0     0 REJECT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 #conn src/32 > 2 reject-with icmp-port-unreachable
 ​
 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 ​
 Chain OUTPUT (policy ACCEPT 52598 packets, 68M bytes)
 num   pkts bytes target     prot opt in     out     source               destination 

3)测试效果

同时登陆两个ssh没问题,第三个时就提示无法连接了。

image-20220430114022499.png

7.Iptables防火墙limit模块扩展匹配规则

limit模块的作用是针对报文的速率进行限制,限制的单位有秒、分钟、小时、天等,例如一分钟内只接收10个请求报文,多余的报文则会被丢弃。

limit模块的常用参数:

  • --limit rate[/second|/minute|/hour|/day]:指定限制的平均速率单位,以秒(s)、分(m)、时(h)、天为单位,默认是3小时。
  • --limit-burst:要匹配的最大初始包的数量,例如1分钟内限制10个请求报文,那么首先一次性会接收我们指定初始化包的数量,剩余请求包按着速率单位来进行接收,默认值为5个报文。

1)限制每分钟接收10个ICMP数据报文

 1.先添加一条规则,限制1分钟内只收10个icmp协议的请求报文。
 [root@jxl-1 ~]# iptables -t filter -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT
 ​
 2.然后添加第二条规则,超出10个报文后,其余的报文全部丢弃。
 [root@jxl-1 ~]# iptables -t filter -A INPUT -p icmp -j DROP 
 ​
 3.查看添加的防火墙规则
 [root@jxl-1 ~]# iptables -L -n -v --line-number
 Chain INPUT (policy ACCEPT 1331 packets, 1111K bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 1        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            limit: avg 10/min burst 5
 2        0     0 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
 ​
 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 ​
 Chain OUTPUT (policy ACCEPT 1334 packets, 1844K bytes)
 num   pkts bytes target     prot opt in     out     source               destination  

image-20220430144054401.png

查看效果,可以看到前5个数据包都可以正常接收,那是因为limit默认初始包就是5个,因此没有任何问题,从第六个数据包开始后,每隔6秒才会正常处理一个数据包,因为1分钟限制10次数据包的接收,那就表示6秒收一个,效果如下图所示。

也可以理解为是一开始可以快速通过5个数据报文,后面的数据报文是每分钟通过10个。

image-20220430144158915.png

2)允许10个数据报文快速通过,然后限制每分钟接收1个个ICMP数据报文

实现思路和1)中一模一样,只不过就是调整一下初始包的数量。

 1.先添加一条规则,限制1分钟内只收10个icmp协议的请求报文。
 [root@jxl-1 ~]# iptables -t filter -I INPUT -p icmp -m limit --limit 1/m --limit-burst 10 -j ACCEPT
 ​
 2.然后添加第二条规则,超出10个报文后,其余的报文全部丢弃。
 [root@jxl-1 ~]# iptables -t filter -A INPUT -p icmp -j DROP 

效果如下,首先发送了10个数据包正常接收,剩下的数据包每隔1分钟接收1个。

image-20220430145805426.png

3)限速案例,限制网络传输的带宽不可以超过500k/s

限速如何通过limit模块来实现呢?其实也很简单,我们可以计算出1个数据包的大小,然后用500k的大小除以数据包的大小,得出500k能换算出多少个数据包,例如是300个,那么最后设置1秒钟接收的数据包的数量为300个,就可以实现每秒的传输速率带宽在500k左右。

一个数据包的大小大概在1500字节。

公式:(限制的带宽速率*1000)/(单个数据包的大小)

500k的限速,每秒可限制的数据包数量大概为(500*1000/150 = 300个)300个。

 [root@jxl-1 ~]# iptables -t filter -I OUTPUT -p  tcp -m limit --limit 300/s  -j ACCEPT
 [root@jxl-1 ~]# iptables -t filter -A OUTPUT -p  tcp -j DROP

速率带宽多多少少是由落差的,如果就想限制在500k以内,可以根据测试的结果来调整每秒数据包的效果,如下图所示,拉取文件的速率为327k/s,此时数据包的数量我是设置的120个。

image-20220430151722457.png

8.Iptables防火墙tcp-flags模块扩展匹配规则

tcp-flags模块的作用是判断TCP协议数据报文标志位的返回值的,在TCP的三次握手中,第一次握手客户端向服务器发送syn=1的数据报文,第二次握手服务端向客户端发送sync和ack=1的报文,第三次握手客户端向服务端发送ack=1的报文。

tcp-flags模块就是来判断发送报文中指定的标志位是否等于1,并且该条报文中只包含指定的标志位,否则就拒绝通行,例如我们指定的标志位是SYN,那么该条报文中就只能包含SYNC,如果再包含ACK,那么就不放行,并且标志位的值要为1。

案例: 只允许其他客户端发送TCP请求报文到本机,本机响应可以,但是本机不可向其他主机发送TCP请求报文。

首先来分析,"只允许其他客户端发送TCP请求到本机",根据这句话可以明确是在INPUT链添加相应的规则,客户端发起请求一共需要发送2次TCP握手,分别是第一次握手和第三次握手,通过tcp-flags模块确保客户端发送的报文中标志位都是正确的,需要在INPUT链添加3条规则,第一条规则是匹配客户端发送的报文中是否只包含syn标志位,并且值是否等于1,第二条规则是匹配客户端发送的报文中是否只包含ack,并且值是否等于1,如果这两条规则都满足,那么就说明是客户端向服务端发送的请求,最终的动作是允许,第三条规则是拒绝其他标志位的TCP连接请求。

然后来分析"本机只可以响应客户端发起的TCP请求,但是本机不可以向其他客户端发送请求",根据这句话可以明确出规则是要添加在OUTPUT链的,我们只需要在OUTPUT链添加上第二次握手所包含的TCP标志位的规则,完成响应客户端的TCP连接请求,最后在添加一条规则,禁止其他的TCP标志位从OUTPUT链发出,也就可以拒绝本机向其他的客户端发起TCP请求。

tcp-flags模块使用的命令格式:--tcp-flags {标志位集合} {要判断哪个标志位等于1}

1)编写具体的防火墙规则

 1.添加允许客户端向本机发起TCP请求的规则
 #syn=1的标志位规则
 [root@jxl-1 ~]# iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST SYN -j ACCEPT
 ​
 #ack=1的标志位规则
 [root@jxl-1 ~]# iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST ACK -j ACCEPT
 ​
 #其余的报文都拒绝
 [root@jxl-1 ~]# iptables -t filter -A INPUT -j DROP
 ​
 ​
 2.添加本机响应客户端TCP连接请求以及拒绝发起TCP请求的规则
 #syn和ack都等于1
 [root@jxl-1 ~]# iptables -t filter -I OUTPUT -p tcp --sport 22 -m tcp --tcp-flags SYN,ACK,FIN,RST SYN,ACK -j ACCEPT
 ​
 #ack-1
 [root@jxl-1 ~]# iptables -t filter -I OUTPUT -p tcp --sport 22 -m tcp --tcp-flags SYN,ACK,FIN,RST ACK -j ACCEPT
 ​
 #其余的报文全部拒绝
 [root@jxl-1 ~]# iptables -t filter -A OUTPUT -j DROP

2)查看设置的防火墙规则

 [root@jxl-1 ~]# iptables -L -n -v --line-number
 Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 1       82  6416 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 flags:0x17/0x10
 2        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 flags:0x17/0x02
 3     5169 1958K DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 ​
 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 ​
 Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 num   pkts bytes target     prot opt in     out     source               destination         
 1       41  4348 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp spt:22 tcp flags:0x17/0x10
 2        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp spt:22 tcp flags:0x17/0x12
 3      293 65316 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           

3)查看效果

本机无法发起TCP连接请求。

image-20220430163056348.png

其他主机可以向本机发起TCP连接。

image-20220430163257781.png

9.Iptables防火墙state模块扩展匹配规则

state模块也就是conntrack连接追踪的概念,主要作用就是源端到目标端所经过的路由跟踪记录,通过连接跟踪,就可以分析出源端到目标端所经过的地址,然后判断出有哪些是异常的,哪些是正常的。

连接追踪,第一次建立的请求时NEW状态,基于NEW状态之后,在建立的连接是ESTABLISHED状态,RELATED是相关的连接,INVALID是无效的连接。

一个典型的场景:当本机的80端口向其他客户端发起了请求,但是并不是ESTABLISHED状态,而是NEW状态,此时一定是有问题的,WEB 80端口不会向客户端发起请求,只能是ESTABLISHED状态,此时通过iptables防火墙的state模块就可以很好的解决此问题,当追踪的状态不对时,直接拒绝通行。

案例:允许接收远程主机ssh和http的请求(NEW、ESTABLISHED),响应时仅允许本机回应ssh、http的ESTABLISHED的请求。

接收请求时可能是NEW和ESTABLISHED状态,但是响应是一定只有ESTABLISHED状态,否则就是异常现象,在INPUT添加接收时的规则,在OUTPUT链添加响应时的规则。

1)编写防火墙规则

先添加允许特定状态的规则,随后添加拒绝所有的规则

 1.添加允许接收ssh和http NEW和ESTABLSHED请求的规则
 [root@jxl-1 ~]# iptables -t filter -I INPUT -p tcp -m multiport --dport 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT
 [root@jxl-1 ~]# iptables -A INPUT -j DROP
 ​
 2.添加允许响应ssh和http ESTABLSHED请求的规则
 [root@jxl-1 ~]# iptables -t filter -I OUTPUT -p tcp -m multiport --sport 22,80 -m state --state ESTABLISHED -j ACCEPT
 [root@jxl-1 ~]# iptables -A OUTPUT -j DROP

2)查看设置的防火墙规则

image-20220430171959154.png

3)查看效果

其他主机向本机发送ssh和http请求,接收正常。

image-20220430172114346.png

本机主动发起NEW状态,发起异常。

image-20220430172206908.png