nftables本身不解析应用层协议,需协同用户态或eBPF程序完成HTTP Host、TLS SNI等字段识别,再通过socket元数据、conntrack helper、ct mark或NFQUEUE反馈结果,由nftables执行高速标记与过滤。

nftables 本身不解析应用层协议,无法直接识别 HTTP Host、TLS SNI 或 DNS 查询名这类字段。它工作在内核网络栈的 L3/L4 层,不具备解密或深度解析加密载荷的能力。要实现“针对应用层协议的数据包标记”,必须采用协同架构:由用户态或 eBPF 程序完成协议解析与决策,再将结果通过标准内核机制反馈给 nftables,由其执行高速匹配与标记动作。
利用 socket 元数据做进程级粗粒度标记
这是最轻量、最稳定的方式——不看内容,只看连接归属:
- nftables 支持
meta skuid、meta skgid、socket cgroupv2等元数据匹配 - 配合 systemd 的
Delegate=yes和 cgroup v2,可让 nginx、curl、python 脚本等各自运行在独立 cgroup 下 - 示例规则:只允许
www-data用户发起的 TCP 连接访问 443 端口nft add rule inet filter output meta skuid 33 tcp dport 443 accept nft add rule inet filter output meta skuid != 33 tcp dport 443 drop
借助 conntrack helper 提取明文特征并写入 map
适用于 TLS ClientHello(SNI)、HTTP GET 行等未加密初期载荷:
- 启用自定义 userspace helper(如基于 libnetfilter_queue)监听新连接前几个包
- 提取 SNI 或 Host 字段,写入 nftables 的
inet filter sni_map { type ipv4_addr : verdict; } - 后续规则查表跳转:
nft add rule inet filter input ip saddr @sni_map drop
用 eBPF 提取字段并设置 ct mark
这是当前主流高精度方案,适合生产环境:
- 编写 eBPF 程序(C + libbpf),在
sk_skb或sockethook 点解析 TCP payload - 成功匹配 SNI 或 HTTP Host 后,调用
bpf_skb_mark_ingress()或更新ct_mark - nftables 规则读取标记并快速决策:
nft add rule inet filter input ct mark & 0x1000 == 0x1000 drop
典型流程:eBPF 提取
youtube.com→ 用户态守护进程设ct mark 0x1000→ nftables 拦截该标记所有流量
结合 NFQUEUE 实现灵活用户态标记
当需要复杂逻辑(如正则匹配、外部数据库查询)时:
- nftables 将指定流量重定向到 NFQUEUE(如
queue num 1) - 用户态程序(如 Python + netfilterqueue)收到原始包,解析应用层字段
- 标记后通过
nfq_set_verdict2()设置NF_ACCEPT并附带skb mark或触发 conntrack 更新 - nftables 后续规则用
meta mark或ct mark做分流
不复杂但容易忽略

















