{"record":{"id":"01fc57de8693ceea","repo":"netbirdio/netbird","slug":"add-mangle-postrouting-rule-w","errorCode":null,"errorMessage":"add mangle postrouting rule: %w","messagePattern":"add mangle postrouting rule: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/router_linux.go","lineNumber":507,"sourceCode":"\t\t\"-i\", r.wgIface.Name(),\n\t\t\"-m\", \"conntrack\", \"--ctstate\", \"NEW\",\n\t\t\"-j\", \"CONNMARK\", \"--set-mark\", fmt.Sprintf(\"%#x\", nbnet.DataPlaneMarkIn),\n\t}\n\n\tif err := r.iptablesClient.AppendUnique(tableMangle, chainPREROUTING, preRule...); err != nil {\n\t\tmerr = multierror.Append(merr, fmt.Errorf(\"add mangle prerouting rule: %w\", err))\n\t} else {\n\t\tr.rules[markManglePre] = preRule\n\t}\n\n\tpostRule := []string{\n\t\t\"-o\", r.wgIface.Name(),\n\t\t\"-m\", \"conntrack\", \"--ctstate\", \"NEW\",\n\t\t\"-j\", \"CONNMARK\", \"--set-mark\", fmt.Sprintf(\"%#x\", nbnet.DataPlaneMarkOut),\n\t}\n\n\tif err := r.iptablesClient.AppendUnique(tableMangle, chainPOSTROUTING, postRule...); err != nil {\n\t\tmerr = multierror.Append(merr, fmt.Errorf(\"add mangle postrouting rule: %w\", err))\n\t} else {\n\t\tr.rules[markManglePost] = postRule\n\t}\n\n\treturn nberrors.FormatErrorOrNil(merr)\n}\n\nfunc (r *router) cleanupDataPlaneMark() error {\n\tvar merr *multierror.Error\n\tif preRule, exists := r.rules[markManglePre]; exists {\n\t\tif err := r.iptablesClient.DeleteIfExists(tableMangle, chainPREROUTING, preRule...); err != nil {\n\t\t\tmerr = multierror.Append(merr, fmt.Errorf(\"remove mangle prerouting rule: %w\", err))\n\t\t} else {\n\t\t\tdelete(r.rules, markManglePre)\n\t\t}\n\t}\n\n\tif postRule, exists := r.rules[markManglePost]; exists {","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/router_linux.go#L489-L525","documentation":"Companion of the prerouting error in setupDataPlaneMark(): appends a CONNMARK rule to mangle POSTROUTING stamping outbound NEW connections with nbnet.DataPlaneMarkOut. Failures are accumulated in a multierror and only logged by init(), so a failure leaves the agent running with asymmetric or missing marks, which can degrade policy routing that matches on those fwmarks.","triggerScenarios":"AppendUnique(\"mangle\", \"POSTROUTING\", \"-o\", wgIface, \"-m\", \"conntrack\", \"--ctstate\", \"NEW\", \"-j\", \"CONNMARK\", ...) failing on missing iptable_mangle/xt_connmark/xt_conntrack modules, missing CAP_NET_ADMIN, xtables lock contention, or an interface that disappeared between creation and rule programming.","commonSituations":"Same class as the prerouting variant: stripped kernels, unprivileged containers, races with other firewall managers during `netbird up`, or hosts where the mangle table exists but connmark helpers were built as unavailable modules.","solutions":["Reproduce manually with `iptables -t mangle -A POSTROUTING -o wt0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 0x...`","`modprobe iptable_mangle xt_conntrack xt_connmark`","Verify privileges of the netbird daemon (root or CAP_NET_ADMIN)","Check the full multierror in the log (both prerouting and postrouting usually fail together, confirming a table/module problem rather than the rule itself)","Run `netbird down && netbird up` to retry setup once the host issue is fixed"],"exampleFix":"// before\nif err := r.iptablesClient.AppendUnique(tableMangle, chainPOSTROUTING, postRule...); err != nil {\n    merr = multierror.Append(merr, fmt.Errorf(\"add mangle postrouting rule: %w\", err))\n}\n\n// after: keep bookkeeping only on success, but surface stderr of iptables in context\nif err := r.iptablesClient.AppendUnique(tableMangle, chainPOSTROUTING, postRule...); err != nil {\n    merr = multierror.Append(merr, fmt.Errorf(\"add mangle postrouting rule (iface %s): %w\", r.wgIface.Name(), err))\n} else {\n    r.rules[markManglePost] = postRule\n}","handlingStrategy":"try-catch","validationCode":"func mangleWritable(ipt *iptables.IPTables) error {\n    probe := []string{\"-j\", \"MARK\", \"--set-mark\", \"0x0/0xff00\"}\n    if err := ipt.AppendUnique(\"mangle\", \"POSTROUTING\", probe...); err != nil {\n        return err\n    }\n    return ipt.DeleteIfExists(\"mangle\", \"POSTROUTING\", probe...)\n}","typeGuard":null,"tryCatchPattern":"Treat prerouting and postrouting mark failures as one unit: log once, keep going, and re-run setupDataPlaneMark on the next Reset so a transient lock failure self-heals.","preventionTips":["Ensure iptable_mangle loads on demand (modules-load.d entry) on minimal hosts","Avoid running other iptables batch writers concurrently with agent start","Keep the NetBird interface name stable; do not recreate interfaces while routes are applied"],"tags":["network","linux","iptables","mangle","conntrack"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}