nftables依赖内核conntrack实现连接状态检测,分三层:基础连接跟踪(ct state)、TCP标志增强校验(eBPF)、应用层上下文协同(userspace helper);ct state invalid必须置于new前,禁用tcp flags模拟状态。

nftables 本身不解析协议状态机,它依赖内核 conntrack 子系统提供连接级状态(如 established、related、invalid),这是实现可靠、轻量、内核原生支持的连接状态检测的唯一方式。所谓“复杂网络连接状态检测”,在 nftables 中实际分三层:基础连接跟踪、TCP 标志增强校验、应用层上下文协同。下面直接讲清楚怎么做、为什么这么写、哪些容易踩坑。
用 ct state 实现 L4 连接生命周期过滤
这是最稳定、开销最低、无需额外模块的状态检测方式。`ct state` 匹配的是 conntrack 维护的连接状态,不是包头字段,因此不受 TCP 标志位欺骗影响(比如伪造 SYN+ACK)。-
ct state established:只匹配已通过三次握手(或 UDP 已有双向通信)的连接数据包 -
ct state related:匹配由主连接触发的辅助流,例如 FTP 数据通道、ICMP 目的不可达报文、SIP 的 RTP 媒体流 -
ct state invalid:无法归入任何连接的包,常见于分片丢失、时序错乱、NAT 不一致,建议默认丢弃 -
ct state { new, untracked }:新连接请求(如首次 SYN)或未被 conntrack 跟踪的包(如 raw socket 发出、或 conntrack 表满)
示例规则组合(推荐顺序):
nft add rule inet filter input ct state invalid drop
nft add rule inet filter input ct state { new, untracked } drop
nft add rule inet filter input ct state established,related accept
注意:ct state new 仅对 TCP SYN、UDP 首包、ICMP 请求等有效;对已建立连接后的重传 SYN 包,conntrack 会判为 invalid,所以 invalid 必须放在 new 前面,否则会被漏放。
用 eBPF 补充 TCP 状态机深度校验
标准 conntrack 不验证 TCP 标志是否合法(如 SYN+FIN 同时置位、ACK 序号超出窗口、重复 FIN 等)。这类检测需 eBPF 在 `sk_skb` 或 `socket` hook 点完成:- 编写 eBPF 程序解析 TCP 头部,检查标志位组合、序列号递进关系、窗口缩放一致性
- 将异常结果写入 per-CPU map 或通过
skb mark标记(如0x200表示非法 TCP 状态) - 在 nftables 规则中用
meta mark & 0x200 == 0x200快速拦截
典型防护场景:
- 拦截 Xmas 扫描(SYN+FIN+URG)、Null 扫描(无标志位)
- 阻断 TCP sequence spoofing(如伪造 ACK 序号跳变)
- 识别半开连接耗尽(大量 SYN 未完成握手)并限速
该方案需加载 eBPF 字节码,不能纯靠 nft 命令完成,但和 nftables 完全兼容——nft 只负责策略执行,eBPF 负责状态判定。
用 userspace helper 构建应用层协议上下文
HTTP、TLS、DNS 等协议的状态机无法在内核态高效建模。这时可借助 `nfnetlink_queue`(nfqnl)将初始数据包送入用户态:- 启动守护进程监听 nfqueue(如用 Python + netfilterqueue 库)
- 对每个新连接的前 1–3 个 TCP segment 做轻量解析:提取 HTTP Method/Path、DNS QNAME、TLS ClientHello 中的 SNI 和 ALPN
- 将识别出的协议状态(如
http_host=example.com,tls_sni=api.example.net)存入内核ct helper或写入ct mark - nftables 规则即可基于
ct mark或ct helper http做后续动作,例如:nft add rule inet filter input ct helper http tcp dport 80 meta mark set 0x100nft add rule inet filter input meta mark 0x100 tcp dport 80 accept
这种方式延迟略高(首包需进用户态),但灵活、可扩展,适合做 WAF 前置过滤或灰度路由。
常见误区与关键提醒
❌ 不要试图用 `tcp flags & (syn|ack) == syn` 模拟连接状态 —— 它无法判断是否真有对应连接,且易被绕过。
❌ 不要省略 `ct state invalid drop` —— 它是防 DoS 和状态混淆的第一道防线。
✅ `ct status dnat` 和 `ct status snat` 可用于区分 NAT 前后流量,配合 `ip saddr` 判断内外网方向。
✅ `ct timeout` 可调连接超时(如缩短 UDP idle 时间),但需先加载 `nf_conntrack_proto_*` 模块。
不复杂但容易忽略。















