{"record":{"id":"00b5186ff52c3e67","repo":"netbirdio/netbird","slug":"add-jump-rules-w","errorCode":null,"errorMessage":"add jump rules: %w","messagePattern":"add jump rules: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/router_linux.go","lineNumber":475,"sourceCode":"\t\tif err := r.iptablesClient.NewChain(chainInfo.table, chainInfo.chain); err != nil {\n\t\t\treturn fmt.Errorf(\"create chain %s in table %s: %w\", chainInfo.chain, chainInfo.table, err)\n\t\t}\n\t}\n\n\tif err := r.insertEstablishedRule(chainRTFWDIN); err != nil {\n\t\treturn fmt.Errorf(\"insert established rule: %w\", err)\n\t}\n\n\tif err := r.insertEstablishedRule(chainRTFWDOUT); err != nil {\n\t\treturn fmt.Errorf(\"insert established rule: %w\", err)\n\t}\n\n\tif err := r.addPostroutingRules(); err != nil {\n\t\treturn fmt.Errorf(\"add static nat rules: %w\", err)\n\t}\n\n\tif err := r.addJumpRules(); err != nil {\n\t\treturn fmt.Errorf(\"add jump rules: %w\", err)\n\t}\n\n\tif err := r.addMSSClampingRules(); err != nil {\n\t\tlog.Errorf(\"failed to add MSS clamping rules: %s\", err)\n\t}\n\n\treturn nil\n}\n\n// setupDataPlaneMark configures the fwmark for the data plane\nfunc (r *router) setupDataPlaneMark() error {\n\tvar merr *multierror.Error\n\tpreRule := []string{\n\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","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/router_linux.go#L457-L493","documentation":"Returned when addJumpRules() fails during router container setup. It inserts three jump rules (-j NETBIRD-RT-NAT into nat POSTROUTING, -j NETBIRD-RT-PRE into mangle PREROUTING, -j NETBIRD-RT-RDR into nat PREROUTING) at position 1 of built-in chains via go-iptables Insert(). The first failing insert aborts createContainers(), so traffic never reaches NetBird's custom chains and routing/NAT is dead.","triggerScenarios":"router.init() -> addJumpRules() when `iptables -t nat -I POSTROUTING 1 -j NETBIRD-RT-NAT` (or the mangle/nat PREROUTING equivalents) exits non-zero: iptable_mangle module not loaded, nat table absent, CAP_NET_ADMIN missing, xtables.lock contention, or iptables-legacy vs nft family mismatch.","commonSituations":"Host kernels without iptable_mangle (common in stripped VPS/OpenVZ kernels); agents inside Kubernetes/Docker pods without NET_ADMIN; systems where another tool (Docker, firewalld) rewrites built-in chains concurrently; WSL2 or nftables-only images lacking iptables compat binaries.","solutions":["Run the failing insert manually: `iptables -t mangle -I PREROUTING 1 -j NETBIRD-RT-PRE` and `iptables -t nat -I POSTROUTING 1 -j NETBIRD-RT-NAT` to see stderr","`modprobe iptable_mangle iptable_nat` (plus ip6table_mangle/ip6table_nat for IPv6)","Install iptables (iptables-nft) and ensure the same implementation exists for ip6tables when the peer network is dual-stack","Verify root/CAP_NET_ADMIN: `capsh --print | grep cap_net_admin`","Retry after releasing /run/xtables.lock (stop docker/firewalld temporarily or rerun `netbird up`)"],"exampleFix":"// before: single wrapper hides which of the three jump rules failed\nif err := r.addJumpRules(); err != nil {\n    return fmt.Errorf(\"add jump rules: %w\", err)\n}\n\n// after: fail on the first unusable table before mutating built-in chains\nfor _, t := range []string{\"nat\", \"mangle\"} {\n    if err := r.iptablesClient.List(t, \"PREROUTING\"); err != nil {\n        return fmt.Errorf(\"table %s unusable: %w\", t, err)\n    }\n}\nif err := r.addJumpRules(); err != nil {\n    return fmt.Errorf(\"add jump rules: %w\", err)\n}","handlingStrategy":"validation","validationCode":"func jumpTargetsReady(ipt *iptables.IPTables) error {\n    for _, c := range []struct{ table, chain string }{\n        {\"nat\", \"POSTROUTING\"}, {\"mangle\", \"PREROUTING\"}, {\"nat\", \"PREROUTING\"},\n    } {\n        if _, err := ipt.List(c.table, c.chain); err != nil {\n            return fmt.Errorf(\"%s/%s not programmable: %w\", c.table, c.chain, err)\n        }\n    }\n    return nil\n}","typeGuard":"func isExitCode(err error, code int) bool {\n    var ee *exec.ExitError\n    return errors.As(err, &ee) && ee.ExitCode() == code\n}","tryCatchPattern":"Wrap addJumpRules failures as fatal for router init; on error, invoke cleanJumpRules + cleanUpDefaultForwardRules to unwind the earlier inserts before propagating.","preventionTips":["Preload iptable_mangle and iptable_nat on hosts running routed peers","Pin one iptables implementation (legacy or nft) system-wide, including ip6tables","Alert on 'create containers' or 'add jump rules' in agent logs; they always mean routing is down","Use netbird down before reconfiguring host firewall backends"],"tags":["network","linux","iptables","firewall","netbird"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}