u32模块通过字节偏移匹配数据包任意内容,需按4字节对齐计算偏移、使用网络字节序和掩码提取字段,适用于深度特征识别但复杂度高,推荐优先使用tcp、string等专用模块。

iptables 的 u32 模块可用于基于数据包任意字节偏移位置的内容匹配,常用于识别并封禁特定协议特征、恶意载荷或绕过常规规则的流量。它比简单端口/协议匹配更底层,但需准确理解 IP/TCP/UDP 头部结构和字节序(网络字节序,大端)。
理解 u32 匹配语法与偏移计算
u32 使用形如 "4&0x000000FF=0xXX" 的表达式,其中:
-
数字前缀(如 4):表示从 IP 头起始(第 0 字节)开始的**4 字节对齐偏移量**(单位是 4 字节,即一个“word”)。例如偏移 12 字节 → 写为
3(因为 12 ÷ 4 = 3);TCP 头中源端口在偏移 0(相对于 TCP 头),但整个 TCP 头起始位置需先算出。 -
&0x000000FF:按位与掩码,提取最低 8 位(即 1 字节);若要取连续 2 字节(如端口),用
&0x0000FFFF;取整个 word(4 字节)则不加掩码或用&0xFFFFFFFF。 -
=0xXX:匹配目标值(十六进制,网络字节序)。例如 TCP 标志位 SYN=0x02,但实际在 TCP 头偏移 12(字节)→ 对应 u32 偏移为
12>>2 = 3,且该字节位于 word 的最低字节位,所以写为"3&0x000000FF=0x02"。
封禁含特定 HTTP User-Agent 的请求(示例)
假设想封禁所有 User-Agent: sqlmap 的 HTTP 请求(明文传输时):
- HTTP 载荷通常在 TCP 数据部分,需跳过 IP 头 + TCP 头。IP 头长度由 IHL 字段决定(IHL × 4 字节),TCP 头长度由 Data Offset 字段决定(DO × 4 字节)。u32 支持动态计算:
0>>28&0xF提取 IP IHL,8>>26&0x3C提取 TCP DO(较复杂,实践中常用固定头长假设或结合其他模块)。 - 保守做法:假设无 IP 选项(IHL=5 → 20 字节)、无 TCP 选项(DO=5 → 20 字节),则 HTTP 数据起始于第 40 字节(0-based)。User-Agent 首字母 'U' 出现在其字段内,但需定位到具体偏移。可先用 tcpdump 抓包确认:如在 TCP payload 偏移 100 字节处出现 "User-Agent: sqlmap",则总偏移 = 20(IP) + 20(TCP) + 100 = 140 字节 → u32 偏移 =
140 >> 2 = 35。 - 匹配 's'(0x73):使用
"35&0x000000FF=0x73";匹配完整字符串需多个条件组合(u32 支持 && 逻辑),但易误匹配。更稳妥方式是配合string模块(需 kernel ≥ 2.6.14 + xt_string)。
封禁特定 TCP 标志组合(如 XMAS 扫描)
XMAS 扫描发送 FIN+URG+PSH 标志置位的包(0x29),TCP 标志字节位于 TCP 头偏移 12(字节):
- u32 偏移 =
12 >> 2 = 3,标志所在字节是该 word 的最低字节 → 表达式:"3&0x000000FF=0x29" - 添加 iptables 规则:
iptables -A INPUT -p tcp -m u32 --u32 "3&0x000000FF=0x29" -j DROP - 注意:此规则仅匹配 TCP 头无选项的情况。若 TCP 头更长(如含时间戳),标志位偏移后移,需动态计算或改用
tcpflags模块(更简洁:-m tcp --tcp-flags ALL FIN,URG,PSH)。
关键提醒与替代建议
-
字节序不可错:所有值按网络字节序(大端)书写。如匹配 TCP 目标端口 80(0x0050),需写为
"2&0x0000FFFF=0x0050"(TCP 头偏移 2 字节 → u32 偏移 0.5?不对!端口占 2 字节,起始偏移 2 → 属于第 0 个 word(0–3 字节)的高 2 字节,正确写法是"0>>16&0xFFFF=0x0050"或更可靠:"0&0xFFFF0000=0x00500000"—— 实际推荐用tcp dport模块)。 -
性能与可维护性:u32 规则解析开销高,多条件嵌套易出错。非必要场景优先使用
tcp、udp、string、iprange等专用模块。 -
验证手段:用
tcpdump -xx查看原始字节,结合 wireshark 分析头部长度和 payload 偏移;用iptables -L -v -n -t filter查看命中计数确认规则生效。










