{"record":{"id":"038d62579d7e6fa2","repo":"netbirdio/netbird","slug":"add-outbound-mss-clamp-rule-w","errorCode":null,"errorMessage":"add outbound MSS clamp rule: %w","messagePattern":"add outbound MSS clamp rule: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/iptables/router_linux.go","lineNumber":587,"sourceCode":"\n\t// Add jump rule from FORWARD chain in mangle table to our custom chain\n\tjumpRule := []string{\n\t\t\"-j\", chainRTMSSCLAMP,\n\t}\n\tif err := r.iptablesClient.Insert(tableMangle, chainFORWARD, 1, jumpRule...); err != nil {\n\t\treturn fmt.Errorf(\"add jump to MSS clamp chain: %w\", err)\n\t}\n\tr.rules[jumpMSSClamp] = jumpRule\n\n\truleOut := []string{\n\t\t\"-o\", r.wgIface.Name(),\n\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","sourceCodeStart":569,"sourceCodeEnd":605,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/iptables/router_linux.go#L569-L605","documentation":"addMSSClampingRules() appends the TCPMSS rule to the NETBIRD-RT-MSSCLAMP mangle chain: outgoing TCP SYN packets on the NetBird interface get --set-mss = mtu - (40 for IPv4 / 60 for IPv6). Failure is logged, not propagated, so the clamp chain exists but stays empty. Note mss is computed with uint16 arithmetic, so an MTU below the header size would underflow to a huge value.","triggerScenarios":"`iptables -t mangle -A NETBIRD-RT-MSSCLAMP -o wt0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss <mss>` failing when xt_tcpmss is missing, the NetBird interface name is stale, or iptables rejects the computed MSS value; also triggered by misconfigured tiny MTUs making the subtraction underflow.","commonSituations":"Kernels without xt_tcpmss (or it built as an unloaded module); overlay MTU set unusually low (bad management-side MTU config); IPv6 peers (v6=true, 60-byte header) on a host with an MTU below 60 (extreme misconfig); silent failure noticed only as PMTU blackholes for routed TCP.","solutions":["Reproduce manually with the MSS value from the log to confirm whether xt_tcpmss is the problem","`modprobe xt_tcpmss`","Check the configured MTU (management network config / interface): it must exceed 40 (IPv4) or 60 (IPv6) by a sane margin","Verify the clamp chain received the rule: `sudo iptables -t mangle -S NETBIRD-RT-MSSCLAMP`","Restart the agent after fixing modules/MTU so addMSSClampingRules runs again"],"exampleFix":"// before: uint16 underflow possible when mtu < header size\nmss := r.mtu - overhead\n\n// after: guard the subtraction before building the rule\nif int(r.mtu) <= int(overhead) {\n    return fmt.Errorf(\"mtu %d too small for MSS clamp (needs > %d)\", r.mtu, overhead)\n}\nmss := r.mtu - overhead","handlingStrategy":"validation","validationCode":"func validMSS(mtu uint16, v6 bool) (uint16, error) {\n    overhead := uint16(40)\n    if v6 {\n        overhead = 60\n    }\n    if mtu <= overhead {\n        return 0, fmt.Errorf(\"mtu %d must exceed header size %d\", mtu, overhead)\n    }\n    return mtu - overhead, nil\n}","typeGuard":null,"tryCatchPattern":"Log-only at the call site; on catch, check whether xt_tcpmss exists and whether the MSS value was sane, then retry once after loading the module.","preventionTips":["Keep overlay MTU at or above 1280 (IPv6 minimum) in management config","modprobe xt_tcpmss on hosts forwarding TCP over the overlay","Re-run MSS clamp setup after interface MTU changes"],"tags":["network","linux","iptables","mss-clamping","tcp"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}