This repository reproduces, diagnoses, and mitigates an OpenWrt 24.10.0 bug where enabling software or hardware flow offloading can misdeliver policy-routed NAT traffic to the wrong LAN MAC address (often the MAC of the PBR next-hop/VPN gateway). It ships a netns lab, diagnostics bundle, and an OpenWrt-ready mitigation that excludes risky flows from flow offload.
- Requirements: Linux kernel with nftables + flowtable,
iproute2,nft,conntrack(fromconntrack-tools),tcpdump,python3. Run as root. - Reproduce:
./reproducer/netns-lab.sh run(adds namespaces, programs nftables, generates A+AAAA DNS-like traffic, captures MACs, dumps flowtable). Toggle offload withFLOW_OFFLOAD=1env. - Smoke test:
./scripts/smoke-test.shormake smoke(offload off/on with mitigation; checks MAC correctness). - Clean up:
./reproducer/netns-lab.sh cleanormake clean.
FLOW_OFFLOAD=1enables nft flowtable offload; default 0.MITIGATION=0disables the guard rules inside the lab to demonstrate the risky path.USE_PBR_MARK=0avoids tagging DNS flows with fwmark 0xff (table 100); default 1.DNS_QUERIES=<n>controls concurrent UDP queries (default 4) to stress flowtable.CLEAN_LOGS=1removes previousreproducer/output/*.{pcap,log}on cleanup.
make smoke— runs the lab with mitigation and offload off/on.make clean— tears down namespaces and purges logs whenCLEAN_LOGS=1.make diag— runs diagnostics/collect.sh locally (overrideOUT_DIR,LAN_IF,WAN_IF).
- Apply mitigation:
ssh root@router 'sh -s' < mitigation/apply.sh - Rollback:
ssh root@router 'sh -s' < mitigation/rollback.sh - The include adds nftables rules that skip flow offload when
meta mark != 0(PBR-marked traffic) or whenct status { dnat, snat }is present. Performance impact is limited to policy-routed/NATted flows.
- README.md — overview, quick start, upstreaming notes.
- docs/theory-of-failure.md — packet path analysis, hypotheses, measurements.
- reproducer/ — netns lab and traffic generator.
- diagnostics/ — data collection helper.
- mitigation/ — firewall4-compatible mitigation and installer/rollback.
- patches/ — proposed firewall4 change and guidance for kernel/nftables report.
- scripts/smoke-test.sh — CI-friendly check of lab and mitigation.
When filing upstream bugs (OpenWrt firewall4, netfilter, or kernel), attach:
nft list rulesetandnft list flowtable inet ftoffloadoutputip rule show,ip route show table all,ip -s neigh showconntrack -Lexcerpt for affected flowstcpdump -etraces showing wrong destination MAC vs expected- Flowtable counters before/after mitigation
- Install dependencies:
opkg update && opkg install tcpdump conntrack-tools(nftables/firewall4 are present by default in 24.10.0 images). - Copy
diagnostics/collect.shto the router (or run viascp && ssh). - Apply mitigation via
mitigation/apply.sh. - Re-run diagnostics after reproducing to confirm offload exclusion of marked/NAT flows.
- Build ipk on a Linux host:
./scripts/build-ipk.sh(uses latest git tag for version; override withVERSION=0.1.0). - Install on the router:
scp dist/openwrt-flowoffload-pbr-mitigation_<ver>_all.ipk root@router:/tmp && ssh root@router opkg install /tmp/openwrt-flowoffload-pbr-mitigation_<ver>_all.ipk. - Post-install automatically reloads firewall4 to pick up the include; removing the package reloads firewall to drop it.
- Copy mitigation/firewall4-offload-mitigation.nft to
/etc/nftables.d/99-flowoffload-pbr.nft. - Ensure firewall4 loads includes (default on 24.10.0) and restart:
/etc/init.d/firewall restart. - Optionally still run mitigation/apply.sh to insert guards immediately; the include handles persistence.
- Trace packet path vs flowtable:
sudo nft monitor trace - Inspect flowtable entries and counters:
sudo nft list flowtable inet filter ftoffload - Watch ARP/ND churn:
sudo ip -s neigh show - Capture L2 headers on LAN:
sudo tcpdump -nn -e -i br-lan udp port 53 - Observe conntrack events:
sudo conntrack -E -p udp
- firewall4: in
ft_offloadchain (or equivalent flowtable hook), add a guardmeta mark != 0 returnandct status { dnat, snat } returnbeforeflow add @ft. See patches/firewall4-flowoffload-pbr.patch. - Kernel/netfilter: investigate flowtable neighbor/route caching interaction with skb marks and NAT, particularly on mt7621 hw offload path; ensure dst/neighbor ref invalidation on mark/routing changes.
- .github/workflows/smoke.yml runs the netns smoke test on ubuntu-latest with nftables/conntrack/tcpdump installed.
- Scripts are idempotent and exit on error (
set -euo pipefail). - The lab targets correctness over throughput; mitigation is deliberately conservative to avoid misdelivery.