{"record":{"id":"b779d7d595e86747","repo":"tailscale/tailscale","slug":"installing-egress-proxy-rules-w-b779d7","errorCode":null,"errorMessage":"installing egress proxy rules: %w","messagePattern":"installing egress proxy rules: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/containerboot/main.go","lineNumber":862,"sourceCode":"\t\t\t\tvar cd string\n\t\t\t\tif nmState.certDomains.Len() != 0 {\n\t\t\t\t\tcd = nmState.certDomains.At(0)\n\t\t\t\t}\n\t\t\t\tif cd == \"\" {\n\t\t\t\t\tcd = kubetypes.ValueNoHTTPS\n\t\t\t\t}\n\t\t\t\tprev := certDomain.Swap(new(cd))\n\t\t\t\tif prev == nil || *prev != cd {\n\t\t\t\t\tselect {\n\t\t\t\t\tcase certDomainChanged <- true:\n\t\t\t\t\tdefault:\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif cfg.TailnetTargetIP != \"\" && ipsHaveChanged && len(addrs) != 0 {\n\t\t\t\tlog.Printf(\"Installing forwarding rules for destination %v\", cfg.TailnetTargetIP)\n\t\t\t\tif err := installEgressForwardingRule(ctx, cfg.TailnetTargetIP, addrs, nfr); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"installing egress proxy rules: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If this is a L7 cluster ingress proxy (set up\n\t\t\t// by Kubernetes operator) and proxying of\n\t\t\t// cluster traffic to the ingress target is\n\t\t\t// enabled, set up proxy rule each time the\n\t\t\t// tailnet IPs of this node change (including\n\t\t\t// the first time they become available).\n\t\t\tif cfg.AllowProxyingClusterTrafficViaIngress && cfg.ServeConfigPath != \"\" && ipsHaveChanged && len(addrs) != 0 {\n\t\t\t\tlog.Printf(\"installing rules to forward traffic for %s to node's tailnet IP\", cfg.PodIP)\n\t\t\t\tif err := installTSForwardingRuleForDestination(ctx, cfg.PodIP, addrs, nfr); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"installing rules to forward traffic to node's tailnet IP: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurrentIPs = newCurrentIPs\n\n\t\t\t// Only store device FQDN and IP addresses to\n\t\t\t// Kubernetes Secret when any required proxy","sourceCodeStart":844,"sourceCodeEnd":880,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/cmd/containerboot/main.go#L844-L880","documentation":"Egress proxying to a fixed tailnet IP (TS_DEST_IP holding a tailnet address): when this node's tailnet IPs changed, installEgressForwardingRule (forwarding.go:98) programs DNAT, SNAT and MSS clamp for cfg.TailnetTargetIP. This fatal error wraps the netfilter failure or the 'no tailscale IP matching family' family mismatch from forwarding.go:115.","triggerScenarios":"DNATNonTailscaleTraffic / EnsureSNATForDst / ClampMSSToPMTU failing due to missing capabilities or firewall mode; TailnetTargetIP family (v4 vs v6) not present among the node's own tailnet addresses.","commonSituations":"IPv6 tailnet target with an IPv4-only proxy node; NET_ADMIN dropped from the pod spec; host switched firewall stack after initial deployment.","solutions":["Check the wrapped error to distinguish family mismatch from netfilter failure","Match families: give the node a tailnet address of the same family as TS_DEST_IP","Ensure NET_ADMIN and correct TS_FIREWALL_MODE","Validate that the target IP is a single-host address reachable in the tailnet"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# TS_DEST_IP family must exist among the node's own tailnet addrs\nif echo \"$TS_DEST_IP\" | grep -q ':'; then test -n \"$(tailscale ip -6)\" || echo 'proxy needs a v6 tailnet addr'; else test -n \"$(tailscale ip -4)\" || echo 'proxy needs a v4 tailnet addr'; fi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm the target tailnet IP family matches the proxy before deploy","Keep NET_ADMIN and pinned firewall mode","Re-check after tailnet address reassignments"],"tags":["tailscale","containerboot","egress","netfilter","dnat","snat"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}