{"record":{"id":"7fd6ece84e0b19c1","repo":"netbirdio/netbird","slug":"add-mangle-prerouting-jump-rule-v","errorCode":null,"errorMessage":"add mangle prerouting jump rule: %v","messagePattern":"add mangle prerouting jump rule: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/router_linux.go","lineNumber":619,"sourceCode":"\n\truleKey := \"established-\" + chain\n\tr.rules[ruleKey] = establishedRule\n\n\treturn nil\n}\n\nfunc (r *router) addJumpRules() error {\n\t// Jump to nat chain\n\tnatRule := []string{\"-j\", chainRTNAT}\n\tif err := r.iptablesClient.Insert(tableNat, chainPOSTROUTING, 1, natRule...); err != nil {\n\t\treturn fmt.Errorf(\"add nat postrouting jump rule: %v\", err)\n\t}\n\tr.rules[jumpNatPost] = natRule\n\n\t// Jump to mangle prerouting chain\n\tpreRule := []string{\"-j\", chainRTPRE}\n\tif err := r.iptablesClient.Insert(tableMangle, chainPREROUTING, 1, preRule...); err != nil {\n\t\treturn fmt.Errorf(\"add mangle prerouting jump rule: %v\", err)\n\t}\n\tr.rules[jumpManglePre] = preRule\n\n\t// Jump to nat prerouting chain\n\trdrRule := []string{\"-j\", chainRTRDR}\n\tif err := r.iptablesClient.Insert(tableNat, chainPREROUTING, 1, rdrRule...); err != nil {\n\t\treturn fmt.Errorf(\"add nat prerouting jump rule: %v\", err)\n\t}\n\tr.rules[jumpNatPre] = rdrRule\n\n\treturn nil\n}\n\nfunc (r *router) cleanJumpRules() error {\n\tfor _, ruleKey := range []string{jumpNatPost, jumpManglePre, jumpNatPre, jumpMSSClamp} {\n\t\tif rule, exists := r.rules[ruleKey]; exists {\n\t\t\tvar table, chain string\n\t\t\tswitch ruleKey {","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/router_linux.go#L601-L637","documentation":"Second insert in addJumpRules(): `-j NETBIRD-RT-PRE` at position 1 of mangle PREROUTING, feeding prerouting marks (used by routing decisions and the later NAT marking rules) into NetBird's chain. Failure aborts createContainers() with 'add jump rules'; prerouting marks, and therefore the whole mark-based routing/NAT design, cannot work.","triggerScenarios":"`iptables -t mangle -I PREROUTING 1 -j NETBIRD-RT-PRE` failing due to a missing iptable_mangle module, no CAP_NET_ADMIN, xtables lock contention, or the NETBIRD-RT-PRE chain not existing because an earlier NewChain in createContainers partially failed.","commonSituations":"Minimal container hosts lacking mangle support; unprivileged daemon; concurrent firewall rewrites; systems where the v4 router succeeded but the v6 router instance fails because ip6table_mangle is absent while ip6table_filter loads fine.","solutions":["Reproduce: `sudo iptables -t mangle -I PREROUTING 1 -j NETBIRD-RT-PRE`","`modprobe iptable_mangle` and for the v6 router `modprobe ip6table_mangle`","Confirm the NETBIRD-RT-PRE chain exists (`iptables -t mangle -S`) and check earlier createContainers errors if not","Verify daemon privileges and xtables lock availability","Retry `netbird down && netbird up` after fixes"],"exampleFix":"// before\nif err := r.iptablesClient.Insert(tableMangle, chainPREROUTING, 1, preRule...); err != nil {\n    return fmt.Errorf(\"add mangle prerouting jump rule: %v\", err)\n}\n\n// after: probe the mangle table first so the cause is explicit\nif _, err := r.iptablesClient.List(tableMangle, chainPREROUTING); err != nil {\n    return fmt.Errorf(\"mangle table unavailable: %w\", err)\n}\nif err := r.iptablesClient.Insert(tableMangle, chainPREROUTING, 1, preRule...); err != nil {\n    return fmt.Errorf(\"add mangle prerouting jump rule: %w\", err)\n}","handlingStrategy":"validation","validationCode":"func chainReady(ipt *iptables.IPTables, table, chain string) error {\n    if ok, err := ipt.ChainExists(table, chain); err != nil {\n        return err\n    } else if !ok {\n        return fmt.Errorf(\"chain %s missing in %s\", chain, table)\n    }\n    return nil\n}\n\n// usage: chainReady(ipt, \"mangle\", \"NETBIRD-RT-PRE\") before addJumpRules","typeGuard":null,"tryCatchPattern":"Fatal-for-init pattern; unwind prior jump inserts (nat POSTROUTING) when the mangle insert fails so built-in chains are left clean.","preventionTips":["modprobe iptable_mangle (and ip6table_mangle for dual-stack)","Check earlier 'create chain' errors in the log before debugging the jump itself","Keep exactly one iptables implementation installed"],"tags":["network","linux","iptables","mangle","firewall"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}