From 00f789cd8df8ebace902cf4a348a352d79d8ad91 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 6 Apr 2022 10:05:00 -0400 Subject: [PATCH] proxy/iptables: move EXT chain rule creation to the end Part of reorganizing the syncProxyRules loop to do: 1. figure out what chains are needed, mark them in activeNATChains 2. write servicePort jump rules to KUBE-SERVICES/KUBE-NODEPORTS 3. write servicePort-specific chains (SVC, SVL, EXT, FW, SEP) This fixes the handling of the EXT chain. --- pkg/proxy/iptables/proxier.go | 125 ++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 60 deletions(-) diff --git a/pkg/proxy/iptables/proxier.go b/pkg/proxy/iptables/proxier.go index b7dcb50f6bc..54d3dea14be 100644 --- a/pkg/proxy/iptables/proxier.go +++ b/pkg/proxy/iptables/proxier.go @@ -1046,6 +1046,14 @@ func (proxier *Proxier) syncProxyRules() { } externalTrafficChain := svcInfo.externalChainName // eventually jumps to externalPolicyChain + // usesExternalTrafficChain is based on hasEndpoints, not hasExternalEndpoints, + // because we need the local-traffic-short-circuiting rules even when there + // are no externally-usable endpoints. + usesExternalTrafficChain := hasEndpoints && svcInfo.ExternallyAccessible() + if usesExternalTrafficChain { + activeNATChains[externalTrafficChain] = true + } + var internalTrafficFilterTarget, internalTrafficFilterComment string var externalTrafficFilterTarget, externalTrafficFilterComment string if !hasEndpoints { @@ -1078,66 +1086,6 @@ func (proxier *Proxier) syncProxyRules() { } } - // If any "external" destinations are enabled, set up external traffic - // handling. All captured traffic for all external destinations should - // jump to externalTrafficChain, which will handle some special-cases - // and then jump to externalPolicyChain. (We check hasEndpoints here not - // hasExternalEndpoints because we need the short-circuit rules in the - // EXT chain even when there are no external endpoints.) - if hasEndpoints && svcInfo.ExternallyAccessible() { - proxier.natChains.Write(utiliptables.MakeChainLine(externalTrafficChain)) - activeNATChains[externalTrafficChain] = true - - if !svcInfo.ExternalPolicyLocal() { - // If we are using non-local endpoints we need to masquerade, - // in case we cross nodes. - proxier.natRules.Write( - "-A", string(externalTrafficChain), - "-m", "comment", "--comment", fmt.Sprintf(`"masquerade traffic for %s external destinations"`, svcPortNameString), - "-j", string(kubeMarkMasqChain)) - } else { - // If we are only using same-node endpoints, we can retain the - // source IP in most cases. - - if proxier.localDetector.IsImplemented() { - // Treat all locally-originated pod -> external destination - // traffic as a special-case. It is subject to neither - // form of traffic policy, which simulates going up-and-out - // to an external load-balancer and coming back in. - proxier.natRules.Write( - "-A", string(externalTrafficChain), - "-m", "comment", "--comment", fmt.Sprintf(`"pod traffic for %s external destinations"`, svcPortNameString), - proxier.localDetector.IfLocal(), - "-j", string(clusterPolicyChain)) - } - - // Locally originated traffic (not a pod, but the host node) - // still needs masquerade because the LBIP itself is a local - // address, so that will be the chosen source IP. - proxier.natRules.Write( - "-A", string(externalTrafficChain), - "-m", "comment", "--comment", fmt.Sprintf(`"masquerade LOCAL traffic for %s external destinations"`, svcPortNameString), - "-m", "addrtype", "--src-type", "LOCAL", - "-j", string(kubeMarkMasqChain)) - - // Redirect all src-type=LOCAL -> external destination to the - // policy=cluster chain. This allows traffic originating - // from the host to be redirected to the service correctly. - proxier.natRules.Write( - "-A", string(externalTrafficChain), - "-m", "comment", "--comment", fmt.Sprintf(`"route LOCAL traffic for %s external destinations"`, svcPortNameString), - "-m", "addrtype", "--src-type", "LOCAL", - "-j", string(clusterPolicyChain)) - } - - // Anything else falls thru to the appropriate policy chain. - if hasExternalEndpoints { - proxier.natRules.Write( - "-A", string(externalTrafficChain), - "-j", string(externalPolicyChain)) - } - } - // Capture the clusterIP. if hasInternalEndpoints { args = append(args[:0], @@ -1333,6 +1281,63 @@ func (proxier *Proxier) syncProxyRules() { ) } + // Set up external traffic handling (if any "external" destinations are + // enabled). All captured traffic for all external destinations should + // jump to externalTrafficChain, which will handle some special cases and + // then jump to externalPolicyChain. + if usesExternalTrafficChain { + proxier.natChains.Write(utiliptables.MakeChainLine(externalTrafficChain)) + + if !svcInfo.ExternalPolicyLocal() { + // If we are using non-local endpoints we need to masquerade, + // in case we cross nodes. + proxier.natRules.Write( + "-A", string(externalTrafficChain), + "-m", "comment", "--comment", fmt.Sprintf(`"masquerade traffic for %s external destinations"`, svcPortNameString), + "-j", string(kubeMarkMasqChain)) + } else { + // If we are only using same-node endpoints, we can retain the + // source IP in most cases. + + if proxier.localDetector.IsImplemented() { + // Treat all locally-originated pod -> external destination + // traffic as a special-case. It is subject to neither + // form of traffic policy, which simulates going up-and-out + // to an external load-balancer and coming back in. + proxier.natRules.Write( + "-A", string(externalTrafficChain), + "-m", "comment", "--comment", fmt.Sprintf(`"pod traffic for %s external destinations"`, svcPortNameString), + proxier.localDetector.IfLocal(), + "-j", string(clusterPolicyChain)) + } + + // Locally originated traffic (not a pod, but the host node) + // still needs masquerade because the LBIP itself is a local + // address, so that will be the chosen source IP. + proxier.natRules.Write( + "-A", string(externalTrafficChain), + "-m", "comment", "--comment", fmt.Sprintf(`"masquerade LOCAL traffic for %s external destinations"`, svcPortNameString), + "-m", "addrtype", "--src-type", "LOCAL", + "-j", string(kubeMarkMasqChain)) + + // Redirect all src-type=LOCAL -> external destination to the + // policy=cluster chain. This allows traffic originating + // from the host to be redirected to the service correctly. + proxier.natRules.Write( + "-A", string(externalTrafficChain), + "-m", "comment", "--comment", fmt.Sprintf(`"route LOCAL traffic for %s external destinations"`, svcPortNameString), + "-m", "addrtype", "--src-type", "LOCAL", + "-j", string(clusterPolicyChain)) + } + + // Anything else falls thru to the appropriate policy chain. + if hasExternalEndpoints { + proxier.natRules.Write( + "-A", string(externalTrafficChain), + "-j", string(externalPolicyChain)) + } + } + // If Cluster policy is in use, create the chain and create rules jumping // from clusterPolicyChain to the clusterEndpoints if usesClusterPolicyChain {