nftables 中的 mark 依赖 skb→mark 字段,通过 meta mark(包级)和 ct mark(连接级)实现策略路由与分流;二者独立需手动同步,常用于多路径、应用分流及日志分类。

nftables 中的流量标记(Mark)不是直接给数据包打标签的独立功能,而是依赖内核 skb->mark 字段,配合 Netfilter 的 mangle 链与策略路由协同工作。它本身不生成 mark,但能读取、设置、匹配 mark,并驱动后续转发或过滤决策。
Mark 和 ct mark 是两套机制,用途不同
-
meta mark操作单个数据包的 skb mark,常用于策略路由分流、eBPF 协同标记、日志分类等; -
ct mark操作连接跟踪(conntrack)条目的 mark,影响整条连接的所有包,适合多路径回程一致性(如双 WAN 场景中保证请求和响应走同一出口)。
在 nftables 中设置和使用 mark 的典型方式
- 使用
meta mark set设置包级 marknft add rule inet filter prerouting ip saddr 192.168.50.100 meta mark set 0x100
- 使用
ct mark set标记连接(需在 conntrack 已创建后操作,通常放在prerouting或output)nft add rule inet filter prerouting tcp dport 443 ct mark set 0x200
- 匹配 mark 做策略动作
nft add rule inet filter output meta mark & 0x100 == 0x100 meta mark set 0x1000 counter accept
与策略路由联动是 mark 的核心价值
Linux 内核 RPDB(ip rule)可基于 fwmark 查找路由表:
ip rule add fwmark 0x100 table 100 ip route add default via 10.0.1.1 dev eth0 table 100
nftables 设置 meta mark 后,只要该 mark 被 ip rule 捕获,数据包就会跳转到对应路由表,实现按流/按源/按应用分离路径。
常见误用提醒
-
meta mark不会自动同步到ct mark,反之亦然。需要显式用ct mark set或ct mark load手动桥接; - mark 是 32 位整数,建议用十六进制(如
0x100)避免十进制歧义; - 在
prerouting中设 mark 后,若后续经过 DNAT,部分旧内核版本可能丢失 mark,建议在input/forward链中再次确认或重设; - 容器或 Pod 场景中,host 网络命名空间的 mark 对 pod 内流量无效,需在 cni 插件或 eBPF 层统一注入。
实用组合示例:区分管理流量与业务流量
# 给 SSH 流量打标 nft add rule inet filter prerouting tcp dport 22 meta mark set 0x10 # 给数据库同步端口打标(假设为 5432) nft add rule inet filter prerouting tcp dport 5432 meta mark set 0x20 # 策略路由:SSH 走管理网卡,数据库走专线网卡 ip rule add fwmark 0x10 table 10 ip rule add fwmark 0x20 table 20 ip route add default via 192.168.100.1 dev mgmt0 table 10 ip route add default via 10.10.200.1 dev专线0 table 20
不复杂但容易忽略











