connmark 的核心作用是将数据包标记持久化绑定至整个连接生命周期,确保双向流量一致打标,从而支撑策略路由、qos等多链路场景;其流程为:先 mark 打标并 connmark --save-mark 存入连接,再通过 --restore-mark 在后续包(含回程及 output)中恢复标记,最后配合 fwmark 规则实现分流。

CONNMARK 本身不直接“实现多链路”,而是保障标记在连接全生命周期内一致,让基于 MARK 的多链路策略(如分流、引流、QoS)真正可靠。关键在于:先用 MARK 在入口打标,再用 CONNMARK 把这个标“绑定到整个连接”,确保回程包也带标,从而被后续模块(如策略路由、tc)持续识别和处理。
为什么必须用 CONNMARK?
单靠 MARK 只能标记当前数据包。TCP 连接有请求和响应两个方向,若只在 PREROUTING 打标,回程包(如服务器返回的 SYN-ACK、HTTP 响应)会走默认路由或默认队列,导致:
- 策略路由失效:引流只走一半,审计系统收不到完整会话
- QoS 错乱:上行限速了,下行仍走高速通道
- 连接中断:部分状态检测设备因双向路径不一致丢包
CONNMARK 的核心操作流程
它分三步完成连接级标记同步:
- 首次入包打标并保存:在 PREROUTING 链中对匹配流量打 MARK,同时用 CONNMARK --save-mark 存入 conntrack 连接条目
- 后续所有包恢复标记:同一连接的后续包(含回程)进入 PREROUTING 后,用 -m connmark --ctmark 匹配,并用 CONNMARK --restore-mark 把连接里的标重新写回数据包
- 出向流量也要覆盖:若本机是服务端或需处理 OUTPUT 流量,同样要在 OUTPUT 链加 restore-mark 规则,避免本地响应失标
配合多链路策略的实际配置示例
假设你有两条出口链路:eth0(主线路)、eth1(审计专线),想把来自 192.168.10.0/24 的 HTTPS 流量引向审计网关 172.16.1.1:
- 在 mangle 表 PREROUTING 中标记入向流量:
iptables -t mangle -A PREROUTING -s 192.168.10.0/24 -p tcp --dport 443 -j MARK --set-mark 0x200 - 保存该标记到连接:
iptables -t mangle -A PREROUTING -m mark --mark 0x200 -j CONNMARK --save-mark - 对所有进包(含回程)恢复标记:
iptables -t mangle -A PREROUTING -m connmark --ctmark 0x200 -j CONNMARK --restore-mark - 为本机出向响应补上恢复(防止本地服务响应走错):
iptables -t mangle -A OUTPUT -m connmark --ctmark 0x200 -j CONNMARK --restore-mark - 创建策略路由表并绑定:
echo "200 audit" >> /etc/iproute2/rt_tables
ip route add default via 172.16.1.1 dev eth1 table audit
ip rule add fwmark 0x200 table audit
注意事项与常见陷阱
实际部署中容易忽略的细节:
- CONNMARK 规则必须放在 MARK 规则之后,否则 restore 时连接里还没存标
- 不要在 FORWARD 链单独打 MARK,除非你明确要区分转发流;通常统一在 PREROUTING 处理更稳妥
- 如果启用了 connection tracking(默认开启),务必确保 conntrack 模块已加载:
lsmod | grep nf_conntrack - 标记值建议用十六进制(如 0x100),避免与 tc 或其他模块冲突;不同用途分配不同 mark 值段










