标题说的"神"一样,肯定是我夸张了,但是说它像神一样,主要体现在两个方面:
- 强大: 理论上能够匹配三层网络以上的任何数据包。
- 复杂: 需要对OSI七层网络模型和各类型协议有基础了解。
事情是这样的,在我某台服务器上跑了某个TCP服务,这个端口总是受到某个TCP包的恶意干扰,所以抓包分析了一下,发现这些恶意包有个明显特征是TCP的首包 syn
包,window
值等于35688
,很显然我也不知道这个数值有什么特别含意,可能是神一样的数字。
因为我的服务是动态开放式的,所以肯定不能玩白名单那一套规则,维护成本也高(我这么懒的人 ),所以想法很简单,把所有 syn 包 window=35688
的包给 tcp-reset
掉就行;说干就干逛了一圈,发现 iptables
在新版内核中的 tcp-window
匹配根本不能用,于是和chatGPT
battle半天,发现了一个这个“神”东西。
先上两张图震住,怕大家跑了,本帖不会过多解释 u32 的功能(感兴趣请看本文最后的参考),这里仅作使用记录。
最后我的规则如下:
iptables -A INPUT -p tcp --syn -m u32 --u32 "0>>22&0x3C@12&0xFFFF=0x8b68" -j REJECT --reject-with tcp-reset
# 不要急,一点点解析
iptables -A INPUT -p tcp --syn -m u32 --u32 # 很好理解,匹配所有TCP首包,并且使用 u32 开始匹配当然这里也可以指定 --dport 加上指定端口,我没加。
# "0>>22&0x3C@12&0xFFFF=0x8b68" 这段是匹配语法,最重要的一点,主要分三段,拆开讲。
# ---
# 0>>22&0x3C@ 从IP头中匹配出整个IP头长度,并且跳过这部分。
# 12&0xFFFF 表示从TCP报头开始像后偏移12个字节,然后取出后面的4个字节数,最后与 0xFFFF 进行按位与计算。
# =0x8b68 表示上一步的计算结果和这个值(端口35688的十六进制)相同,即:匹配成功。
-j REJECT --reject-with tcp-reset 拒绝包,并且响应一个 reset包,可表示此端口无监听服务。
所以呀,这东西虽然强大但是也的确复杂,需要对OSI模型有基础了解,并且如果没一丝毅力的话(反正我是错了半天,也不知哪里有问题,只能疯狂试错),否则玩不动,希望对来者有所帮助。