iptables(6)扩展匹配条件--tcp-flags、icmp

简介

        前面我们已经介绍了不少的扩展模块,例如multiport、iprange、string、time、connlimit模块,但是在tcp扩展模块中只介绍了tcp扩展模块中的”--sport”与--dport”选项,并没有介绍”--tcp-flags”选项,那么这篇文章,我们就来认识一下tcp扩展模块中的”--tcp-flags”和icmp。

--tcp-flags

TCP报文介绍

”--tcp-flags”指的就是tcp头中的标志位,在使用iptables时,我们可以通过此扩展匹配条件,去匹配tcp报文的头部的标识位,然后根据标识位的实际情况实现访问控制的功能。

那我们来看下tcp的报头结构

标志符(9比特长)
NS—ECN-nonce。ECN显式拥塞通知(Explicit Congestion Notification)是对TCP的扩展,定义于 RFC 3540 (2003)。ECN允许拥塞控制的端对端通知而避免丢包。ECN为一项可选功能,如果底层网络设施支持,则可能被启用ECN的两个端点使用。在ECN成功协商的情况下,ECN感知路由器可以在IP头中设置一个标记来代替丢弃数据包,以标明阻塞即将发生。数据包的接收端回应发送端的表示,降低其传输速率,就如同在往常中检测到包丢失那样。
CWR—Congestion Window Reduced,定义于 RFC 3168(2001)。
ECE—ECN-Echo有两种意思,取决于SYN标志的值,定义于 RFC 3168(2001)。
URG—为1表示高优先级数据包,紧急指针字段有效。
ACK—为1表示确认号字段有效
PSH—为1表示是带有PUSH标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满。
RST—为1表示出现严重差错。可能需要重新建立TCP连接。还可以用于拒绝非法的报文段和拒绝连接请求。
SYN—为1表示这是连接请求或是连接接受请求,用于建立连接和使顺序号同步
FIN—为1表示发送方没有数据要传输了,要求释放连接。

 在使用iptables时,使用tcp扩展模块的”–tcp-flags”选项,即可对上图中的标志位进行匹配,判断指定的标志位的值是否为”1″,在tcp协议建立连接的过程中,需要先进行三次握手,而三次握手就要依靠tcp头中的标志位进行。

TCP三次握手过程

  1. 客户端(通过执行connect函数)向服务器端发送一个SYN包,请求一个主动打开。该包携带客户端为这个连接请求而设定的随机数A作为消息序列号。
  2. 服务器端收到一个合法的SYN包后,把该包放入SYN队列中;回送一个SYN/ACK。ACK的确认码应为A+1,SYN/ACK包本身携带一个随机产生的序号B
  3. 客户端收到SYN/ACK包后,发送一个ACK包,该包的序号被设定为A+1,而ACK的确认码则为B+1。然后客户端的connect函数成功返回。当服务器端收到这个ACK包的时候,把请求帧从SYN队列中移出,放至ACCEPT队列中;这时accept函数如果处于阻塞状态,可以被唤醒,从ACCEPT队列中取出ACK包,重新建立一个新的用于双向通信的sockfd,并返回。

如果服务器端接到了客户端发的SYN后回了SYN-ACK后客户端掉线了,服务器端没有收到客户端回来的ACK,那么,这个连接处于一个中间状态,既没成功,也没失败。于是,服务器端如果在一定时间内没有收到的TCP会重发SYN-ACK。

“三次握手”的目的是“为了防止已失效的连接(connect)请求报文段传送到了服务端,因而产生错误”,也即为了解决“网络中存在延迟的重复分组”问题。例如:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。

抓包查看下tcp建立连接的具体过程

此时客户端发起syn,seq0,服务端回应syn ack seq 0,客户端回应ack seq1

分别看下不同步骤的flags信息

此时三次握手第一次,只有syn为1,其他标志位均为0,下方可以看到”[TCP Flags: ··········S·]”,其中的”S”就表示SYN位,整体表示只有SYN位为1

第二次握手,ACK标志位与SYN标志位为1,ACK标志位与SYN标志位为1
第三次握手只有ACK标志位为1

设置iptables

通过以上描述,我们简单介绍了tcp的三次握手和标志位信息,那么我们该如何设置iptables呢。

--tcp-flags设置的规则如下:

        使用 --tcp-flags 选项时,你需要指定两个用空格分隔的字符串。第一个字符串是你想要检查的标志位,而第二个字符串是你希望这些标志位中的哪些位被设置(或者未被设置)类似

--tcp-flags <flags> <mask>

此时如果想要匹配三次握手中第一次握手的tcp flags报文,应该使用一下命令

iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -j ACCEPT
--tcp-flags用于匹配报文tcp头部的标志位,”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

第二次握手应该使用如下方式

iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN,ACK -j ACCEPT
第二部分匹配syn,ack

第三次握手

iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST ACK -j ACCEPT

上面的所有命令都可以将前面第一部分进行简写即

iptables -A INPUT -p tcp --tcp-flags ALL SYN -j ACCEPT
iptables -A INPUT -p tcp --tcp-flags ALL SYN,ACK -j ACCEPT
iptables -A INPUT -p tcp --tcp-flags ALL ACK -j ACCEPT
可以用ALL表示所有的标志位

tcp扩展模块专门提供了一个选项,可以匹配上文中提到的”第一次握手”,那就是–syn选项

使用”–syn”选项相当于使用”–tcp-flags SYN,RST,ACK,FIN  SYN”,也就是说,可以使用”–syn”选项去匹配tcp新建连接的请求报文。

iptables -A INPUT -p tcp --dport 443 --syn -j ACCEPT

测试 

从140.248通过ssh连接240.250,已经匹配到该条目,应为第一次握手的数据包就是syn
可以发现,上图中两种设置方式的效果是一模一样的,可以根据自己的喜好,选择一种方式进行配置就可以。

--tcp-flags的设置非常灵活,大家在设置的时候一定要多做测试,举一反三,注意应用的位置是INPUT还是OUTPUT,比如三次握手的第二次,那么是服务器进行响应,如果我们匹配第二次的数据包,是服务器主动发出的,就需要应用的OUTPUT链上。类似的情况在前面的文章中配置string扩展模块时也有介绍。

ICMP扩展

ICMP协议的全称为Internet Control Message Protocol,互联网控制报文协议,它主要用于探测网络上的主机是否可用,目标是否可达,网络是否通畅,路由是否可用等。

当使用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。

我们现在想要禁止所有icmp类型的报文进入本机,可以进行如下设置

图中我们没有使用任何扩展匹配条件,我们只是使用”-p icmp”匹配了所有icmp协议类型的报文,,别的主机向我们发送的ping请求报文无法进入防火墙,我们向别人发送的ping请求对应的回应报文也无法进入防火墙。所以,我们既无法ping通别人,别人也无法ping通我们。
此时已经无法ping通了
自己向外ping也是无法ping通的

如果只想要ping通别人,但是不想让别人ping通我,需要如下设置

使用”-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,所以无法被上述规则匹配到,所以我们可以看到别人回应我的信息。因为type为8的类型下只有一个code为0的类型,所以我们可以省略对应的code,写为iptables -I INPUT -p icmp  --icmp-type 8 -j REJECT

需要将第三条禁止任何icmp协议删除,此时我们去ping别人是可以ping通的,但是别人ping我们就会显示不可达,因为匹配上规则被REJECT了

除了能够使用对应type/code匹配到具体类型的icmp报文以外,我们还能用icmp报文的描述名称去匹配对应类型的报文

–icmp-type “echo-request”与 –icmp-type 8/0的效果完全相同
主注意使用报文描述名称去匹配中间要用-符号代替空格

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,让我来给你总结一下iptables的常见匹配条件: 1. 匹配协议:使用 `-p` 参数指定协议,常见协议包括 TCP、UDP、ICMP等,例如: ``` # 匹配 TCP 协议 iptables -A INPUT -p tcp --dport 22 -j ACCEPT ``` 2. 源/目标地址:使用 `-s` 和 `-d` 参数指定源地址和目标地址,例如: ``` # 允许来自 IP 地址为 192.168.1.100 的主机访问 SSH 服务 iptables -A INPUT -s 192.168.1.100 -p tcp --dport 22 -j ACCEPT # 允许向 IP 地址为 192.168.1.100 的主机发送 HTTP 请求 iptables -A OUTPUT -d 192.168.1.100 -p tcp --dport 80 -j ACCEPT ``` 3. 匹配端口:使用 `--dport` 和 `--sport` 参数指定目标端口和源端口,例如: ``` # 允许访问 SSH 服务 iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 允许从本地主机向远程主机发送 HTTP 请求 iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT ``` 4. 匹配数据包的状态:使用 `--state` 参数指定数据包的状态,例如: ``` # 允许已经建立的 TCP 连接通过 iptables -A INPUT -p tcp --dport 80 -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许 ICMP 数据包通过 iptables -A INPUT -p icmp -m state --state NEW -j ACCEPT ``` 5. 匹配 MAC 地址:使用 `-m mac --mac-source` 参数指定源 MAC 地址,例如: ``` # 允许来自 MAC 地址为 00:11:22:33:44:55 的主机访问 SSH 服务 iptables -A INPUT -p tcp --dport 22 -m mac --mac-source 00:11:22:33:44:55 -j ACCEPT ``` 这些是iptables的常见匹配条件,希望能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Monster✺◟(∗❛ัᴗ❛ั∗)◞✺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值