DanielLavrushin:b4 的 queue.mark 为重启生效项,不应单独改动 DNS 拷贝监听的 mark

在 b4 PR #418(为 Keenetic/Netcraze 修复 iptables UDP 53 队列规则下并发 A+AAAA 丢 AAAA 应答)中,DanielLavrushin 回应一处代码审查意见「应用队列 mark 变更时应更新监听器的 mark」,表示不改:queue.mark 是重启才生效的设置(UI 标注「重启后生效」),在重启前整条包路径沿用连接池启动时的 mark——工作进程的原始套接字在 Worker.Start 中一次性设置 SO_MARK,队列处理器的自有包判断也用同一个 mark,监听器按设计与之匹配,因此带旧 mark 的查询在拷贝模式下与 held 模式一样被忽略,直到重启。若只把监听器改到新 mark,它会去处理仍带旧 mark 的 b4 自身数据包(例如从工作进程原始套接字发出的 FragmentQuery 重定向查询,在 mangle OUTPUT 之前已被重组)。作者认为一致的修法是在 mark 变更时重启包引擎,属于另一项改动。

作者原文

🔵 Needs a closer look

The DNS-copy listener retains a stale queue mark after live configuration updates.

0 open findings

1 resolved since last review

  • <img alt="High severity" width="62" height="18" src="https://camo.githubusercontent.com/3a45afe3f70ffe1b8bd7e55cd010b3cfdea3251a5d0661ebd6237ecb6846bcb6/68747470733a2f2f6769746875622e6769746875626173736574732e636f6d2f7374617469632f696d616765732f69636f6e732f636f70696c6f742d636f64652d7265766965772f686967682d76322d6c696768742e706e67"> Monitor does not verify the exact B4 mark-return rule

Previously missed (1)
In code that hasn't changed since last review

<img alt="Medium severity" width="62" height="18" src="https://camo.githubusercontent.com/61bc3f51460c23a17b60ad45bd0941ac833960ebf1f0f46c74b915e68f750e93/68747470733a2f2f6769746875622e6769746875626173736574732e636f6d2f7374617469632f696d616765732f69636f6e732f636f70696c6f742d636f64652d7265766965772f6d656469756d2d76322d6c696768742e706e67"> Update listener mark when applying live queue.mark changes
src/​nfq/​pool.go:157

The listener records the queue mark only here, but Pool.UpdateConfig supports live queue.mark changes and never updates dnsCopy.mark. After such a change, the firewall is rebuilt for the new mark while ignoresMark still treats packets carrying the old mark as b4-injected, so copied DNS requests with that now-unreserved mark bypass set handling until restart. Update the listener's mark when applying a new pool configuration as well.

🧠 Review effort: Balanced

Not changing this. queue.mark is a restart-only setting (the UI marks it "Applies after a restart"), and until that restart the whole packet path keeps the mark the pool started with: the workers' raw sockets set SO_MARK once in Worker.Start, and the queue handler's own-packet check uses that same mark. The listener matches them on purpose, so an old-mark query is ignored in copy mode exactly as in held mode until the restart. Moving only the listener to the new mark would make it act on b4's own packets that still carry the old one, for example FragmentQuery redirect lookups, which leave through the worker's raw socket and are reassembled before mangle OUTPUT. The consistent fix is to restart the packet engine on a mark change, which is a separate change.