{"record":{"id":"9b8c1d4aa23cdd68","repo":"netbirdio/netbird","slug":"failed-to-insert-established-rule-v","errorCode":null,"errorMessage":"failed to insert established rule: %v","messagePattern":"failed to insert established rule: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/router_linux.go","lineNumber":599,"sourceCode":"\t\t\"-p\", \"tcp\",\n\t\t\"--tcp-flags\", \"SYN,RST\", \"SYN\",\n\t\t\"-j\", \"TCPMSS\",\n\t\t\"--set-mss\", fmt.Sprintf(\"%d\", mss),\n\t}\n\tif err := r.iptablesClient.Append(tableMangle, chainRTMSSCLAMP, ruleOut...); err != nil {\n\t\treturn fmt.Errorf(\"add outbound MSS clamp rule: %w\", err)\n\t}\n\tr.rules[\"mss-clamp-out\"] = ruleOut\n\n\treturn nil\n}\n\nfunc (r *router) insertEstablishedRule(chain string) error {\n\testablishedRule := getConntrackEstablished()\n\n\terr := r.iptablesClient.Insert(tableFilter, chain, 1, establishedRule...)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to insert established rule: %v\", err)\n\t}\n\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}","sourceCodeStart":581,"sourceCodeEnd":617,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/router_linux.go#L581-L617","documentation":"insertEstablishedRule() puts `-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT` at position 1 of NETBIRD-RT-FWD-IN / NETBIRD-RT-FWD-OUT (filter table) so replies to routed flows are not dropped by later filtering rules. Wrapped by createContainers() as 'insert established rule', its failure aborts router init and routed traffic would break even if setup continued.","triggerScenarios":"`iptables -t filter -I NETBIRD-RT-FWD-IN 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT` failing when xt_conntrack is unavailable, the filter table is inaccessible, CAP_NET_ADMIN is missing, or the chain NETBIRD-RT-FWD-IN was deleted by external tooling between chain creation and this insert.","commonSituations":"Hosts without conntrack match support (rare, custom kernels); 'security' tooling or a second NetBird instance deleting NETBIRD-* chains mid-setup; containers where the filter table is read-only; fresh minimal systems where the conntrack module loads lazily and the first iptables call races module loading.","solutions":["Run the insert by hand to see stderr: `sudo iptables -t filter -I NETBIRD-RT-FWD-IN 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT`","`modprobe xt_conntrack ip_conntrack`","Check `sudo iptables -S | grep NETBIRD-RT-FWD` for chains deleted by other tooling and stop that tooling","Confirm root/CAP_NET_ADMIN for the daemon","Retry `netbird up`; createContainers recreates chains and reruns the insert"],"exampleFix":"// before\nerr := r.iptablesClient.Insert(tableFilter, chain, 1, establishedRule...)\nif err != nil {\n    return fmt.Errorf(\"failed to insert established rule: %v\", err)\n}\n\n// after: self-heal a vanished chain before inserting\nif ok, _ := r.iptablesClient.ChainExists(tableFilter, chain); !ok {\n    if err := r.iptablesClient.NewChain(tableFilter, chain); err != nil {\n        return fmt.Errorf(\"recreate chain %s: %w\", chain, err)\n    }\n}\nif err := r.iptablesClient.Insert(tableFilter, chain, 1, establishedRule...); err != nil {\n    return fmt.Errorf(\"insert established rule into %s: %w\", chain, err)\n}","handlingStrategy":"validation","validationCode":"func conntrackMatchSupported(ipt *iptables.IPTables) error {\n    probe := []string{\"-m\", \"conntrack\", \"--ctstate\", \"ESTABLISHED\", \"-j\", \"ACCEPT\"}\n    if err := ipt.Append(\"filter\", \"FORWARD\", probe...); err != nil {\n        return err\n    }\n    return ipt.DeleteIfExists(\"filter\", \"FORWARD\", probe...)\n}","typeGuard":null,"tryCatchPattern":"Return the error from createContainers so routing fails loudly rather than shipping a router that drops reply traffic; no partial continuation.","preventionTips":["modprobe xt_conntrack and ensure nf_conntrack is loaded","Stop third-party tools from deleting NETBIRD-* chains","Treat any 'insert established rule' log line as routing-down and alert"],"tags":["network","linux","iptables","conntrack","firewall"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}