{"record":{"id":"c4cb1921822964ad","repo":"netbirdio/netbird","slug":"add-static-nat-rules-w","errorCode":null,"errorMessage":"add static nat rules: %w","messagePattern":"add static nat rules: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/router_linux.go","lineNumber":471,"sourceCode":"\t\t\tif err := r.iptablesClient.ClearAndDeleteChain(chainInfo.table, chainInfo.chain); err != nil {\n\t\t\t\tlog.Warnf(\"clear stale chain %s in %s: %v\", chainInfo.chain, chainInfo.table, err)\n\t\t\t}\n\t\t}\n\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(),","sourceCodeStart":453,"sourceCodeEnd":489,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/router_linux.go#L453-L489","documentation":"Returned by the NetBird iptables router manager when addPostroutingRules() fails while programming the NETBIRD-RT-NAT chain in the nat table. The agent (running as root) shells out to iptables via coreos/go-iptables to append two static masquerade rules, and any non-zero iptables exit is wrapped with this message inside createContainers(). It aborts router initialization, so network routes / exit-node forwarding cannot come up.","triggerScenarios":"Calling router.init() -> createContainers() -> addPostroutingRules() when `iptables -t nat -A NETBIRD-RT-NAT -m mark --mark 0x... ! -o lo -j MASQUERADE` fails: nat table missing (iptable_nat/nft module not loaded), MASQUERADE or mark match (xt_mark) unavailable, missing CAP_NET_ADMIN, no iptables binary, or /run/xtables.lock held by another process.","commonSituations":"Containers (Docker/LXC/OpenVZ) without CAP_NET_ADMIN or without iptables kernel modules; minimal Debian/Alpine images or nftables-only distros without iptables-nft installed; kernels shipped by some VPS providers without iptable_nat; concurrent firewall daemons (firewalld, ufw, docker) holding the xtables lock during `netbird up`.","solutions":["Reproduce by hand as root: `iptables -t nat -A NETBIRD-RT-NAT -m mark --mark 0x1000 ! -o lo -j MASQUERADE` and read the stderr in the error chain","Load the missing modules: `modprobe iptable_nat xt_MASQUERADE xt_mark` (and ip6table_nat for IPv6)","Install an iptables implementation: `apt install iptables` (or iptables-nft) and confirm `iptables --version` works for both families","Run the agent as root or grant CAP_NET_ADMIN to the container; verify with `iptables -L -n`","Free the xtables lock: stop competing firewall tooling or wait and retry `netbird up`"],"exampleFix":"// before: agent fails at startup with only the wrapped error\nif err := r.addPostroutingRules(); err != nil {\n    return fmt.Errorf(\"add static nat rules: %w\", err)\n}\n\n// after: pre-flight the nat table so the real cause surfaces early\nif err := probeNatTable(r.iptablesClient); err != nil {\n    return fmt.Errorf(\"nat table check: %w\", err)\n}\nif err := r.addPostroutingRules(); err != nil {\n    return fmt.Errorf(\"add static nat rules: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// Pre-flight before starting the router: prove the nat table accepts rules\nfunc probeNatTable(ipt *iptables.IPTables) error {\n    probe := []string{\"-m\", \"comment\", \"--comment\", \"nb-nat-probe\", \"-j\", \"RETURN\"}\n    if err := ipt.Append(\"nat\", \"POSTROUTING\", probe...); err != nil {\n        return fmt.Errorf(\"nat table unusable: %w\", err)\n    }\n    return ipt.DeleteIfExists(\"nat\", \"POSTROUTING\", probe...)\n}","typeGuard":"func isPermissionError(err error) bool {\n    var ee *exec.ExitError\n    return errors.As(err, &ee) && strings.Contains(err.Error(), \"Permission denied\")\n}","tryCatchPattern":"Abort setup on first postrouting failure and run the router Reset path so half-created chains are removed before returning the error upward.","preventionTips":["Load iptable_nat, xt_MASQUERADE and xt_mark before the agent starts (systemd ExecStartPre=/usr/sbin/modprobe ...)","Smoke-test `iptables -t nat -L -n` in the container image build so missing binaries surface at build time","Run the agent as root or with CAP_NET_ADMIN; never partial privileges","Keep host firewall tooling from batching iptables writes while netbird starts"],"tags":["network","linux","iptables","nat","netbird"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}