(3)iptables匹配条件总结
1. 配置多源 ip 或者网段限制
1 | 丢弃掉来自192.168.1.111,192.168.1.112的所有报文 |
2. 配置对目标 ip 的限制
是用 -d
参数对目的地址进行限制。注意,如果是对源和目标地址都有限制,需要同时满足才会执行对应规则。
1 | 禁止报文从192.168.1.146发到192.168.1.156 |
3. 协议类型匹配
使用 -p
参数对报文协议进行匹配,协议内容包含: tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh。
1 | REJECT掉发往192.168.1.156的tcp协议报文 |
4. 匹配网卡
使用 -i
对车机报文通过某一网卡流入进行限制,使用 -o
对车机报文通过某一网卡流出进行限制。
-i
选项只能用于 PREROUTING 链、INPUT 链、FORWARD 链,那么 -o
选项只能用于 FORWARD 链、OUTPUT 链、POSTROUTING 链
1 | DROP掉经过wlan0口的ping报文 |
5. 限制端口
5.1 限制目标端口
使用 --dport
限制目标端口。在使用 --dport
选项时,必须事先指定了使用哪种协议,即必须先使用 -p
选项。
使用 -–dport
之前,我们使用 -m
选项,指定了对应的扩展模块为 tcp,也就是说,如果想要使用 -–dport
这个扩展匹配条件,则必须依靠某个扩展模块完成。
1 | REJECT 外来报文的目标端口为本机的22号端口(ssh默认端口) |
5.2 限制源端口
使用 --sport
可以判断报文是否从指定的端口发出,即匹配报文的源端口是否与指定的端口一致
1 | iptables -t filter -I INPUT -s 192.168.1.146 -p tcp --sport 22 -j REJECT |
5.3 限制端口范围
1 | REJECT目标端口为22到25之间的所有端口 |
6. iprange 扩展模块
-s
选项与 -d
选项并不能一次性的指定一段连续的 IP 地址范围,如果我们需要指定一段连续的 IP 地址范围,可以使用 iprange 扩展模块。
iprange 扩展模块中有两个扩展匹配条件可以使用: –src-range 和 –dst-range
1 | 如果报文的源IP地址如果在192.168.1.127到192.168.1.146之间,则丢弃报文 |
7.String 扩展模块
使用 string 扩展模块,可以指定要匹配的字符串,如果报文中包含对应的字符串,则符合匹配条件。
1 | iptables -t filter -I INPUT -m string --algo bm --string "xxxx" -j REJECT |
-m string
表示使用 string 模块,--algo bm
表示使用 bm 算法去匹配指定的字符串,--string "xxxx"
则表示我们想要匹配的字符串为”xxxx”.
- –algo:用于指定匹配算法,可选的算法有 bm 与 kmp,此选项为必须选项,我们不用纠结于选择哪个算法,但是我们必须指定一个。
- –string:用于指定需要匹配的字符串。
8.time 扩展模块
可以通过 time 扩展模块,根据时间段区匹配报文,如果报文到达的时间在指定的时间范围以内,则符合匹配条件。
8.1 约束在晚上 12 点 - 早上 7 点不能上网,保证充足睡眠。
1 | 限制http端口 |
8.2 约束周末不能上网
--weekdays
可以取反
1 | iptables -t filter -I INPUT -p tcp --dport 80 -m time --weekdays 6,7 -j REJECT |
8.3 约束每月某些天不能上网
--monthdays
可以取反
1 | iptables -t filter -I INPUT -p tcp --dport 80 -m time --monthdays 10,11 -j REJECT |
8.4 限制时间段
1 | iptables -t filter -I INPUT -p tcp --dport 80 -m time --datestart 2021-05-24 --datestop 2021-05-30 -j REJECT |
9.connlimit 扩展模块
使用 connlimit 扩展模块,可以限制每个 IP 地址同时链接到 server 端的链接数量,注意:我们不用指定 IP,其默认就是针对” 每个客户端 IP”,即对单 IP 的并发连接数限制。
9.1 限制每个 IP 地址最多只能占用两个 ssh 链接远程到 server 端
使用–connlimit-above 2
表示限制每个 IP 的链接数量上限为 2,再配合 -p tcp
, –dport 22
,即表示限制每个客户端 IP 的 ssh 并发链接数量不能高于 2。
1 | iptables -t filter -I INPUT -p tcp --dport 22 -m connlimt --connlimit-above 2 -j ACCEPT |
9.2 限制某个网段,最多多少个链接
使用 --connlimit-mask
限制某个网段,–connlimit-mask 27
表示某个 C 类网段,这个网段中最多只能有 30 台机器(30 个 IP),这 30 个 IP 地址最多只能有 10 个 ssh 连接同时连接到服务器端。
1 | iptables -t filter -I INPUT -p tcp --dport 22 -m connlimt --connlimit-above 10 --connlimit-mask 27 -j ACCEPT |
mask 是子网掩码的意思,通过子网掩码来限制 ip 段。
10.limit 扩展模块
使用 limit 模块是对” 报文到达速率” 进行限制,可以以秒为单位进行限制,也可以以分钟、小时、天作为单位进行限制。
10.1 限制,外部主机对本机进行 ping 操作时,本机最多每 6 秒中放行一个 ping。
1 | iptables -t filter -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT |
如果单是以上规则,是无法限制每 6 秒到来的报文的。因为当 1-5 秒到来的报文,会走默认规则,默认是 ACCEPT。
因此,还需要添加默认的匹配规则。
1 | iptables -t filter -I INPUT -p icmp -j REJECT |
需要注意的是,需要先配置接受规则,再配置拒绝规则。
如上配置之后,我们看看现象如下
可以看到 1-5 的报文没有被过滤到,后面的报文每 6 秒接受到一次,以满足拦截需求的。
出现这个现象的原因是:limit 模块使用了令牌桶算法。
令牌桶算法:我们可以这样想象,有一个木桶,木桶里面放了 5 块令牌,而且这个木桶最多也只能放下 5 块令牌,所有报文如果想要出关入关,都必须要持有木桶中的令牌才行,这个木桶有一个神奇的功能,就是每隔 6 秒钟会生成一块新的令牌,如果此时,木桶中的令牌不足 5 块,那么新生成的令牌就存放在木桶中,如果木桶中已经存在 5 块令牌,新生成的令牌就无处安放了,只能溢出木桶(令牌被丢弃),如果此时有 5 个报文想要入关,那么这 5 个报文就去木桶里找令牌,正好一人一个,于是他们 5 个手持令牌,快乐的入关了,此时木桶空了,再有报文想要入关,已经没有对应的令牌可以使用了,但是,过了 6 秒钟,新的令牌生成了,此刻,正好来了一个报文想要入关,于是,这个报文拿起这个令牌,就入关了,在这个报文之后,如果很长一段时间内没有新的报文想要入关,木桶中的令牌又会慢慢的积攒了起来,直到达到 5 个令牌,并且一直保持着 5 个令牌,直到有人需要使用这些令牌,这就是令牌桶算法的大致逻辑。
因此,我们可以–limit-burst
来限制桶的令牌数目。
1 | iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT |
11. 匹配 TCP 报文头标志位
可以使用 --tcp-flags
匹配报文 tcp 头部的标志位。
1 | 匹配第一次握手 |
”SYN,ACK,FIN,RST,URG,PSH SYN”, 这串字符就是用于配置我们要匹配的标志位的,我们可以把这串字符拆成两部分去理解,第一部分为”SYN,ACK,FIN,RST,URG,PSH”,第二部分为”SYN”。
第一部分表示:我们需要匹配报文 tcp 头中的哪些标志位,那么上例的配置表示,我们需要匹配报文 tcp 头中的 6 个标志位,这 6 个标志位分别为为”SYN、ACK、FIN、RST、URG、PSH”,我们可以把这一部分理解成需要匹配的标志位列表。
第二部分表示:第一部分的标志位列表中,哪些标志位必须为 1,上例中,第二部分为 SYN,则表示,第一部分需要匹配的标志位列表中,SYN 标志位的值必须为 1,其他标志位必须为 0。
所以,上例中的”SYN,ACK,FIN,RST,URG,PSH SYN” 表示,需要匹配报文 tcp 头中的”SYN、ACK、FIN、RST、URG、PSH” 这些标志位,其中 SYN 标志位必须为 1,其他的 5 个标志位必须为 0 .
1 | 匹配第二次握手 |
以上两条可以简写为:
1 | iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN -j REJECT |
12.icmp 扩展
我们平常使用 ping 命令 ping 某主机时,如果主机可达,对应主机会对我们的 ping 请求做出回应(此处不考虑禁 ping 等情况),也就是说,我们发出 ping 请求,对方回应 ping 请求,虽然 ping 请求报文与 ping 回应报文都属于 ICMP 类型的报文,但是如果在概念上细分的话,它们所属的类型还是不同的,我们发出的 ping 请求属于类型 8 的 icmp 报文,而对方主机的 ping 回应报文则属于类型 0 的 icmp 报文,根据应用场景的不同,icmp 报文被细分为如下各种类型。
从上图可以看出,所有表示” 目标不可达” 的 icmp 报文的 type 码为 3,而” 目标不可达” 又可以细分为多种情况,是网络不可达呢?还是主机不可达呢?再或者是端口不可达呢?所以,为了更加细化的区分它们,icmp 对每种 type 又细分了对应的 code,用不同的 code 对应具体的场景, 所以,我们可以使用 type/code 去匹配具体类型的 ICMP 报文,比如可以使用”3/1″表示主机不可达的 icmp 报文。
上图中的第一行就表示 ping 回应报文,它的 type 为 0,code 也为 0,从上图可以看出,ping 回应报文属于查询类(query)的 ICMP 报文,从大类上分,ICMP 报文还能分为查询类与错误类两大类,目标不可达类的 icmp 报文则属于错误类报文。
而我们发出的 ping 请求报文对应的 type 为 8,code 为 0。
12.1 此时我们只想要 ping 通别人,但是不想让别人 ping 通我们
1 | iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8/0 -j REJECT |
使用”-m icmp” 表示使用 icmp 扩展,因为上例中使用了”-p icmp”,所以”-m icmp” 可以省略,使用”–icmp-type” 选项表示根据具体的 type 与 code 去匹配对应的 icmp 报文,而上图中的”–icmp-type 8/0″表示 icmp 报文的 type 为 8,code 为 0 才会被匹配到,也就是只有 ping 请求类型的报文才能被匹配到,所以,别人对我们发起的 ping 请求将会被拒绝通过防火墙,而我们之所以能够 ping 通别人,是因为别人回应我们的报文的 icmp type 为 0,code 也为 0,所以无法被上述规则匹配到,所以我们可以看到别人回应我们的信息。
13. 判断报文是来自回应还是请求
我们可以使用 state 模块的 --state
来追踪链接的状态。
对于 state 模块的连接而言,” 连接” 其中的报文可以分为 5 种状态,报文状态可以为 NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED。(详细定义参考文档)
NEW:连接中的第一个包,状态就是 NEW,我们可以理解为新连接的第一个包的状态为 NEW。
ESTABLISHED:我们可以把 NEW 状态包后面的包的状态理解为 ESTABLISHED,表示连接已建立。
RELATED:从字面上理解 RELATED 译为关系,但是这样仍然不容易理解,我们举个例子。
比如 FTP 服务,FTP 服务端会建立两个进程,一个命令进程,一个数据进程。
命令进程负责服务端与客户端之间的命令传输(我们可以把这个传输过程理解成 state 中所谓的一个” 连接”,暂称为” 命令连接”)。
数据进程负责服务端与客户端之间的数据传输 (我们把这个过程暂称为” 数据连接” )。
但是具体传输哪些数据,是由命令去控制的,所以,” 数据连接” 中的报文与” 命令连接” 是有” 关系” 的。
那么,” 数据连接” 中的报文可能就是 RELATED 状态,因为这些报文与” 命令连接” 中的报文有关系。
(注:如果想要对 ftp 进行连接追踪,需要单独加载对应的内核模块 nf_conntrack_ftp,如果想要自动加载,可以配置 /etc/sysconfig/iptables-config 文件)
INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是 INVALID,我们可以主动屏蔽状态为 INVALID 的报文。
UNTRACKED:报文的状态为 untracked 时,表示报文未被追踪,当报文的状态为 Untracked 时通常表示无法找到相关的连接。
1 | iptables -t filter -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT |
14. 禁止某个域名访问
禁止 包含 qq.com 的域名访问
1 | iptables -I OUTPUT -p tcp -m string --string "qq.com" --algo bm -j DROP |