mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	kube-proxy: add a flag to disables the allowing NodePort services to be accessed via localhost
This commit is contained in:
		@@ -199,6 +199,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	fs.BoolVar(&o.config.IPVS.StrictARP, "ipvs-strict-arp", o.config.IPVS.StrictARP, "Enable strict ARP by setting arp_ignore to 1 and arp_announce to 2")
 | 
						fs.BoolVar(&o.config.IPVS.StrictARP, "ipvs-strict-arp", o.config.IPVS.StrictARP, "Enable strict ARP by setting arp_ignore to 1 and arp_announce to 2")
 | 
				
			||||||
	fs.BoolVar(&o.config.IPTables.MasqueradeAll, "masquerade-all", o.config.IPTables.MasqueradeAll, "If using the pure iptables proxy, SNAT all traffic sent via Service cluster IPs (this not commonly needed)")
 | 
						fs.BoolVar(&o.config.IPTables.MasqueradeAll, "masquerade-all", o.config.IPTables.MasqueradeAll, "If using the pure iptables proxy, SNAT all traffic sent via Service cluster IPs (this not commonly needed)")
 | 
				
			||||||
 | 
						fs.BoolVar(o.config.IPTables.LocalhostNodePorts, "iptables-localhost-nodeports", pointer.BoolDeref(o.config.IPTables.LocalhostNodePorts, true), "If false Kube-proxy will disable the legacy behavior of allowing NodePort services to be accessed via localhost, This only applies to iptables mode and ipv4.")
 | 
				
			||||||
	fs.BoolVar(&o.config.EnableProfiling, "profiling", o.config.EnableProfiling, "If true enables profiling via web interface on /debug/pprof handler. This parameter is ignored if a config file is specified by --config.")
 | 
						fs.BoolVar(&o.config.EnableProfiling, "profiling", o.config.EnableProfiling, "If true enables profiling via web interface on /debug/pprof handler. This parameter is ignored if a config file is specified by --config.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fs.Float32Var(&o.config.ClientConnection.QPS, "kube-api-qps", o.config.ClientConnection.QPS, "QPS to use while talking with kubernetes apiserver")
 | 
						fs.Float32Var(&o.config.ClientConnection.QPS, "kube-api-qps", o.config.ClientConnection.QPS, "QPS to use while talking with kubernetes apiserver")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -197,6 +197,7 @@ func newProxyServer(
 | 
				
			|||||||
				config.IPTables.SyncPeriod.Duration,
 | 
									config.IPTables.SyncPeriod.Duration,
 | 
				
			||||||
				config.IPTables.MinSyncPeriod.Duration,
 | 
									config.IPTables.MinSyncPeriod.Duration,
 | 
				
			||||||
				config.IPTables.MasqueradeAll,
 | 
									config.IPTables.MasqueradeAll,
 | 
				
			||||||
 | 
									*config.IPTables.LocalhostNodePorts,
 | 
				
			||||||
				int(*config.IPTables.MasqueradeBit),
 | 
									int(*config.IPTables.MasqueradeBit),
 | 
				
			||||||
				localDetectors,
 | 
									localDetectors,
 | 
				
			||||||
				hostname,
 | 
									hostname,
 | 
				
			||||||
@@ -221,6 +222,7 @@ func newProxyServer(
 | 
				
			|||||||
				config.IPTables.SyncPeriod.Duration,
 | 
									config.IPTables.SyncPeriod.Duration,
 | 
				
			||||||
				config.IPTables.MinSyncPeriod.Duration,
 | 
									config.IPTables.MinSyncPeriod.Duration,
 | 
				
			||||||
				config.IPTables.MasqueradeAll,
 | 
									config.IPTables.MasqueradeAll,
 | 
				
			||||||
 | 
									*config.IPTables.LocalhostNodePorts,
 | 
				
			||||||
				int(*config.IPTables.MasqueradeBit),
 | 
									int(*config.IPTables.MasqueradeBit),
 | 
				
			||||||
				localDetector,
 | 
									localDetector,
 | 
				
			||||||
				hostname,
 | 
									hostname,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,6 +107,7 @@ iptables:
 | 
				
			|||||||
  masqueradeBit: 17
 | 
					  masqueradeBit: 17
 | 
				
			||||||
  minSyncPeriod: 10s
 | 
					  minSyncPeriod: 10s
 | 
				
			||||||
  syncPeriod: 60s
 | 
					  syncPeriod: 60s
 | 
				
			||||||
 | 
					  localhostNodePorts: true
 | 
				
			||||||
ipvs:
 | 
					ipvs:
 | 
				
			||||||
  minSyncPeriod: 10s
 | 
					  minSyncPeriod: 10s
 | 
				
			||||||
  syncPeriod: 60s
 | 
					  syncPeriod: 60s
 | 
				
			||||||
@@ -248,6 +249,7 @@ nodePortAddresses:
 | 
				
			|||||||
			IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
 | 
								IPTables: kubeproxyconfig.KubeProxyIPTablesConfiguration{
 | 
				
			||||||
				MasqueradeAll:      true,
 | 
									MasqueradeAll:      true,
 | 
				
			||||||
				MasqueradeBit:      pointer.Int32(17),
 | 
									MasqueradeBit:      pointer.Int32(17),
 | 
				
			||||||
 | 
									LocalhostNodePorts: pointer.Bool(true),
 | 
				
			||||||
				MinSyncPeriod:      metav1.Duration{Duration: 10 * time.Second},
 | 
									MinSyncPeriod:      metav1.Duration{Duration: 10 * time.Second},
 | 
				
			||||||
				SyncPeriod:         metav1.Duration{Duration: 60 * time.Second},
 | 
									SyncPeriod:         metav1.Duration{Duration: 60 * time.Second},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								pkg/generated/openapi/zz_generated.openapi.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								pkg/generated/openapi/zz_generated.openapi.go
									
									
									
										generated
									
									
									
								
							@@ -51650,6 +51650,13 @@ func schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyIPTablesConfiguration(ref
 | 
				
			|||||||
							Format:      "",
 | 
												Format:      "",
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
 | 
										"localhostNodePorts": {
 | 
				
			||||||
 | 
											SchemaProps: spec.SchemaProps{
 | 
				
			||||||
 | 
												Description: "LocalhostNodePorts tells kube-proxy to allow service NodePorts to be accessed via localhost (iptables mode only)",
 | 
				
			||||||
 | 
												Type:        []string{"boolean"},
 | 
				
			||||||
 | 
												Format:      "",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
					"syncPeriod": {
 | 
										"syncPeriod": {
 | 
				
			||||||
						SchemaProps: spec.SchemaProps{
 | 
											SchemaProps: spec.SchemaProps{
 | 
				
			||||||
							Description: "syncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m', '2h22m').  Must be greater than 0.",
 | 
												Description: "syncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m', '2h22m').  Must be greater than 0.",
 | 
				
			||||||
@@ -51665,7 +51672,7 @@ func schema_k8sio_kube_proxy_config_v1alpha1_KubeProxyIPTablesConfiguration(ref
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				Required: []string{"masqueradeBit", "masqueradeAll", "syncPeriod", "minSyncPeriod"},
 | 
									Required: []string{"masqueradeBit", "masqueradeAll", "localhostNodePorts", "syncPeriod", "minSyncPeriod"},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Dependencies: []string{
 | 
							Dependencies: []string{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,6 +94,7 @@ func NewHollowProxyOrDie(
 | 
				
			|||||||
			proxierSyncPeriod,
 | 
								proxierSyncPeriod,
 | 
				
			||||||
			proxierMinSyncPeriod,
 | 
								proxierMinSyncPeriod,
 | 
				
			||||||
			false,
 | 
								false,
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
			0,
 | 
								0,
 | 
				
			||||||
			proxyutiliptables.NewNoOpLocalDetector(),
 | 
								proxyutiliptables.NewNoOpLocalDetector(),
 | 
				
			||||||
			nodeName,
 | 
								nodeName,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
 | 
				
			|||||||
			obj.FeatureGates = map[string]bool{c.RandString(): true}
 | 
								obj.FeatureGates = map[string]bool{c.RandString(): true}
 | 
				
			||||||
			obj.HealthzBindAddress = fmt.Sprintf("%d.%d.%d.%d:%d", c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(65536))
 | 
								obj.HealthzBindAddress = fmt.Sprintf("%d.%d.%d.%d:%d", c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(65536))
 | 
				
			||||||
			obj.IPTables.MasqueradeBit = pointer.Int32(c.Int31())
 | 
								obj.IPTables.MasqueradeBit = pointer.Int32(c.Int31())
 | 
				
			||||||
 | 
								obj.IPTables.LocalhostNodePorts = pointer.Bool(c.RandBool())
 | 
				
			||||||
			obj.MetricsBindAddress = fmt.Sprintf("%d.%d.%d.%d:%d", c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(65536))
 | 
								obj.MetricsBindAddress = fmt.Sprintf("%d.%d.%d.%d:%d", c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(256), c.Intn(65536))
 | 
				
			||||||
			obj.OOMScoreAdj = pointer.Int32(c.Int31())
 | 
								obj.OOMScoreAdj = pointer.Int32(c.Int31())
 | 
				
			||||||
			obj.ClientConnection.ContentType = "bar"
 | 
								obj.ClientConnection.ContentType = "bar"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ enableProfiling: false
 | 
				
			|||||||
healthzBindAddress: 0.0.0.0:10256
 | 
					healthzBindAddress: 0.0.0.0:10256
 | 
				
			||||||
hostnameOverride: ""
 | 
					hostnameOverride: ""
 | 
				
			||||||
iptables:
 | 
					iptables:
 | 
				
			||||||
 | 
					  localhostNodePorts: true
 | 
				
			||||||
  masqueradeAll: false
 | 
					  masqueradeAll: false
 | 
				
			||||||
  masqueradeBit: 14
 | 
					  masqueradeBit: 14
 | 
				
			||||||
  minSyncPeriod: 1s
 | 
					  minSyncPeriod: 1s
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ enableProfiling: false
 | 
				
			|||||||
healthzBindAddress: 0.0.0.0:10256
 | 
					healthzBindAddress: 0.0.0.0:10256
 | 
				
			||||||
hostnameOverride: ""
 | 
					hostnameOverride: ""
 | 
				
			||||||
iptables:
 | 
					iptables:
 | 
				
			||||||
 | 
					  localhostNodePorts: true
 | 
				
			||||||
  masqueradeAll: false
 | 
					  masqueradeAll: false
 | 
				
			||||||
  masqueradeBit: 14
 | 
					  masqueradeBit: 14
 | 
				
			||||||
  minSyncPeriod: 1s
 | 
					  minSyncPeriod: 1s
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,6 +33,9 @@ type KubeProxyIPTablesConfiguration struct {
 | 
				
			|||||||
	MasqueradeBit *int32
 | 
						MasqueradeBit *int32
 | 
				
			||||||
	// masqueradeAll tells kube-proxy to SNAT everything if using the pure iptables proxy mode.
 | 
						// masqueradeAll tells kube-proxy to SNAT everything if using the pure iptables proxy mode.
 | 
				
			||||||
	MasqueradeAll bool
 | 
						MasqueradeAll bool
 | 
				
			||||||
 | 
						// LocalhostNodePorts tells kube-proxy to allow service NodePorts to be accessed via
 | 
				
			||||||
 | 
						// localhost (iptables mode only)
 | 
				
			||||||
 | 
						LocalhostNodePorts *bool
 | 
				
			||||||
	// syncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m',
 | 
						// syncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m',
 | 
				
			||||||
	// '2h22m').  Must be greater than 0.
 | 
						// '2h22m').  Must be greater than 0.
 | 
				
			||||||
	SyncPeriod metav1.Duration
 | 
						SyncPeriod metav1.Duration
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,6 +64,9 @@ func SetDefaults_KubeProxyConfiguration(obj *kubeproxyconfigv1alpha1.KubeProxyCo
 | 
				
			|||||||
	if obj.IPTables.MinSyncPeriod.Duration == 0 {
 | 
						if obj.IPTables.MinSyncPeriod.Duration == 0 {
 | 
				
			||||||
		obj.IPTables.MinSyncPeriod = metav1.Duration{Duration: 1 * time.Second}
 | 
							obj.IPTables.MinSyncPeriod = metav1.Duration{Duration: 1 * time.Second}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if obj.IPTables.LocalhostNodePorts == nil {
 | 
				
			||||||
 | 
							obj.IPTables.LocalhostNodePorts = pointer.Bool(true)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if obj.IPVS.SyncPeriod.Duration == 0 {
 | 
						if obj.IPVS.SyncPeriod.Duration == 0 {
 | 
				
			||||||
		obj.IPVS.SyncPeriod = metav1.Duration{Duration: 30 * time.Second}
 | 
							obj.IPVS.SyncPeriod = metav1.Duration{Duration: 30 * time.Second}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ limitations under the License.
 | 
				
			|||||||
package v1alpha1
 | 
					package v1alpha1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"k8s.io/utils/pointer"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,7 +28,6 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestDefaultsKubeProxyConfiguration(t *testing.T) {
 | 
					func TestDefaultsKubeProxyConfiguration(t *testing.T) {
 | 
				
			||||||
	masqBit := int32(14)
 | 
					 | 
				
			||||||
	oomScore := int32(-999)
 | 
						oomScore := int32(-999)
 | 
				
			||||||
	ctMaxPerCore := int32(32768)
 | 
						ctMaxPerCore := int32(32768)
 | 
				
			||||||
	ctMin := int32(131072)
 | 
						ctMin := int32(131072)
 | 
				
			||||||
@@ -50,8 +50,9 @@ func TestDefaultsKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
					Burst:       10,
 | 
										Burst:       10,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
 | 
									IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
 | 
				
			||||||
					MasqueradeBit: &masqBit,
 | 
										MasqueradeBit:      pointer.Int32(14),
 | 
				
			||||||
					MasqueradeAll:      false,
 | 
										MasqueradeAll:      false,
 | 
				
			||||||
 | 
										LocalhostNodePorts: pointer.Bool(true),
 | 
				
			||||||
					SyncPeriod:         metav1.Duration{Duration: 30 * time.Second},
 | 
										SyncPeriod:         metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
					MinSyncPeriod:      metav1.Duration{Duration: 1 * time.Second},
 | 
										MinSyncPeriod:      metav1.Duration{Duration: 1 * time.Second},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
@@ -85,8 +86,9 @@ func TestDefaultsKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
					Burst:       10,
 | 
										Burst:       10,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
 | 
									IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
 | 
				
			||||||
					MasqueradeBit: &masqBit,
 | 
										MasqueradeBit:      pointer.Int32(14),
 | 
				
			||||||
					MasqueradeAll:      false,
 | 
										MasqueradeAll:      false,
 | 
				
			||||||
 | 
										LocalhostNodePorts: pointer.Bool(true),
 | 
				
			||||||
					SyncPeriod:         metav1.Duration{Duration: 30 * time.Second},
 | 
										SyncPeriod:         metav1.Duration{Duration: 30 * time.Second},
 | 
				
			||||||
					MinSyncPeriod:      metav1.Duration{Duration: 1 * time.Second},
 | 
										MinSyncPeriod:      metav1.Duration{Duration: 1 * time.Second},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -237,6 +237,7 @@ func Convert_config_KubeProxyConntrackConfiguration_To_v1alpha1_KubeProxyConntra
 | 
				
			|||||||
func autoConvert_v1alpha1_KubeProxyIPTablesConfiguration_To_config_KubeProxyIPTablesConfiguration(in *v1alpha1.KubeProxyIPTablesConfiguration, out *config.KubeProxyIPTablesConfiguration, s conversion.Scope) error {
 | 
					func autoConvert_v1alpha1_KubeProxyIPTablesConfiguration_To_config_KubeProxyIPTablesConfiguration(in *v1alpha1.KubeProxyIPTablesConfiguration, out *config.KubeProxyIPTablesConfiguration, s conversion.Scope) error {
 | 
				
			||||||
	out.MasqueradeBit = (*int32)(unsafe.Pointer(in.MasqueradeBit))
 | 
						out.MasqueradeBit = (*int32)(unsafe.Pointer(in.MasqueradeBit))
 | 
				
			||||||
	out.MasqueradeAll = in.MasqueradeAll
 | 
						out.MasqueradeAll = in.MasqueradeAll
 | 
				
			||||||
 | 
						out.LocalhostNodePorts = (*bool)(unsafe.Pointer(in.LocalhostNodePorts))
 | 
				
			||||||
	out.SyncPeriod = in.SyncPeriod
 | 
						out.SyncPeriod = in.SyncPeriod
 | 
				
			||||||
	out.MinSyncPeriod = in.MinSyncPeriod
 | 
						out.MinSyncPeriod = in.MinSyncPeriod
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
@@ -250,6 +251,7 @@ func Convert_v1alpha1_KubeProxyIPTablesConfiguration_To_config_KubeProxyIPTables
 | 
				
			|||||||
func autoConvert_config_KubeProxyIPTablesConfiguration_To_v1alpha1_KubeProxyIPTablesConfiguration(in *config.KubeProxyIPTablesConfiguration, out *v1alpha1.KubeProxyIPTablesConfiguration, s conversion.Scope) error {
 | 
					func autoConvert_config_KubeProxyIPTablesConfiguration_To_v1alpha1_KubeProxyIPTablesConfiguration(in *config.KubeProxyIPTablesConfiguration, out *v1alpha1.KubeProxyIPTablesConfiguration, s conversion.Scope) error {
 | 
				
			||||||
	out.MasqueradeBit = (*int32)(unsafe.Pointer(in.MasqueradeBit))
 | 
						out.MasqueradeBit = (*int32)(unsafe.Pointer(in.MasqueradeBit))
 | 
				
			||||||
	out.MasqueradeAll = in.MasqueradeAll
 | 
						out.MasqueradeAll = in.MasqueradeAll
 | 
				
			||||||
 | 
						out.LocalhostNodePorts = (*bool)(unsafe.Pointer(in.LocalhostNodePorts))
 | 
				
			||||||
	out.SyncPeriod = in.SyncPeriod
 | 
						out.SyncPeriod = in.SyncPeriod
 | 
				
			||||||
	out.MinSyncPeriod = in.MinSyncPeriod
 | 
						out.MinSyncPeriod = in.MinSyncPeriod
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								pkg/proxy/apis/config/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								pkg/proxy/apis/config/zz_generated.deepcopy.go
									
									
									
										generated
									
									
									
								
							@@ -157,6 +157,11 @@ func (in *KubeProxyIPTablesConfiguration) DeepCopyInto(out *KubeProxyIPTablesCon
 | 
				
			|||||||
		*out = new(int32)
 | 
							*out = new(int32)
 | 
				
			||||||
		**out = **in
 | 
							**out = **in
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if in.LocalhostNodePorts != nil {
 | 
				
			||||||
 | 
							in, out := &in.LocalhostNodePorts, &out.LocalhostNodePorts
 | 
				
			||||||
 | 
							*out = new(bool)
 | 
				
			||||||
 | 
							**out = **in
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	out.SyncPeriod = in.SyncPeriod
 | 
						out.SyncPeriod = in.SyncPeriod
 | 
				
			||||||
	out.MinSyncPeriod = in.MinSyncPeriod
 | 
						out.MinSyncPeriod = in.MinSyncPeriod
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -203,7 +203,10 @@ type Proxier struct {
 | 
				
			|||||||
	// optimize for performance over debuggability.
 | 
						// optimize for performance over debuggability.
 | 
				
			||||||
	largeClusterMode bool
 | 
						largeClusterMode bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Values are as a parameter to select the interfaces where nodeport works.
 | 
						// localhostNodePorts indicates whether to generate iptables rules that
 | 
				
			||||||
 | 
						// disable NodePort services to be accessed via localhost.
 | 
				
			||||||
 | 
						localhostNodePorts bool
 | 
				
			||||||
 | 
						// Values are as a parameter to select the interfaces where nodePort works.
 | 
				
			||||||
	nodePortAddresses []string
 | 
						nodePortAddresses []string
 | 
				
			||||||
	// networkInterfacer defines an interface for several net library functions.
 | 
						// networkInterfacer defines an interface for several net library functions.
 | 
				
			||||||
	// Inject for test purpose.
 | 
						// Inject for test purpose.
 | 
				
			||||||
@@ -224,6 +227,7 @@ func NewProxier(ipt utiliptables.Interface,
 | 
				
			|||||||
	syncPeriod time.Duration,
 | 
						syncPeriod time.Duration,
 | 
				
			||||||
	minSyncPeriod time.Duration,
 | 
						minSyncPeriod time.Duration,
 | 
				
			||||||
	masqueradeAll bool,
 | 
						masqueradeAll bool,
 | 
				
			||||||
 | 
						localhostNodePorts bool,
 | 
				
			||||||
	masqueradeBit int,
 | 
						masqueradeBit int,
 | 
				
			||||||
	localDetector proxyutiliptables.LocalTrafficDetector,
 | 
						localDetector proxyutiliptables.LocalTrafficDetector,
 | 
				
			||||||
	hostname string,
 | 
						hostname string,
 | 
				
			||||||
@@ -232,9 +236,10 @@ func NewProxier(ipt utiliptables.Interface,
 | 
				
			|||||||
	healthzServer healthcheck.ProxierHealthUpdater,
 | 
						healthzServer healthcheck.ProxierHealthUpdater,
 | 
				
			||||||
	nodePortAddresses []string,
 | 
						nodePortAddresses []string,
 | 
				
			||||||
) (*Proxier, error) {
 | 
					) (*Proxier, error) {
 | 
				
			||||||
	if utilproxy.ContainsIPv4Loopback(nodePortAddresses) {
 | 
						if localhostNodePorts && utilproxy.ContainsIPv4Loopback(nodePortAddresses) {
 | 
				
			||||||
		// Set the route_localnet sysctl we need for exposing NodePorts on loopback addresses
 | 
							// Set the route_localnet sysctl we need for exposing NodePorts on loopback addresses
 | 
				
			||||||
		klog.InfoS("Setting route_localnet=1, use nodePortAddresses to filter loopback addresses for NodePorts to skip it https://issues.k8s.io/90259")
 | 
							// Refer to https://issues.k8s.io/90259
 | 
				
			||||||
 | 
							klog.InfoS("Setting route_localnet=1 to allows nodePort services can be accessed via localhost. You can set flag '--iptables-localhost-nodeports' to false  or use nodePortAddresses (--nodeport-addresses) to filter loopback addresses to change this")
 | 
				
			||||||
		if err := utilproxy.EnsureSysctl(sysctl, sysctlRouteLocalnet, 1); err != nil {
 | 
							if err := utilproxy.EnsureSysctl(sysctl, sysctlRouteLocalnet, 1); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -289,6 +294,7 @@ func NewProxier(ipt utiliptables.Interface,
 | 
				
			|||||||
		filterRules:              utilproxy.LineBuffer{},
 | 
							filterRules:              utilproxy.LineBuffer{},
 | 
				
			||||||
		natChains:                utilproxy.LineBuffer{},
 | 
							natChains:                utilproxy.LineBuffer{},
 | 
				
			||||||
		natRules:                 utilproxy.LineBuffer{},
 | 
							natRules:                 utilproxy.LineBuffer{},
 | 
				
			||||||
 | 
							localhostNodePorts:       localhostNodePorts,
 | 
				
			||||||
		nodePortAddresses:        nodePortAddresses,
 | 
							nodePortAddresses:        nodePortAddresses,
 | 
				
			||||||
		networkInterfacer:        utilproxy.RealNetwork{},
 | 
							networkInterfacer:        utilproxy.RealNetwork{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -320,6 +326,7 @@ func NewDualStackProxier(
 | 
				
			|||||||
	syncPeriod time.Duration,
 | 
						syncPeriod time.Duration,
 | 
				
			||||||
	minSyncPeriod time.Duration,
 | 
						minSyncPeriod time.Duration,
 | 
				
			||||||
	masqueradeAll bool,
 | 
						masqueradeAll bool,
 | 
				
			||||||
 | 
						localhostNodePorts bool,
 | 
				
			||||||
	masqueradeBit int,
 | 
						masqueradeBit int,
 | 
				
			||||||
	localDetectors [2]proxyutiliptables.LocalTrafficDetector,
 | 
						localDetectors [2]proxyutiliptables.LocalTrafficDetector,
 | 
				
			||||||
	hostname string,
 | 
						hostname string,
 | 
				
			||||||
@@ -331,14 +338,14 @@ func NewDualStackProxier(
 | 
				
			|||||||
	// Create an ipv4 instance of the single-stack proxier
 | 
						// Create an ipv4 instance of the single-stack proxier
 | 
				
			||||||
	ipFamilyMap := utilproxy.MapCIDRsByIPFamily(nodePortAddresses)
 | 
						ipFamilyMap := utilproxy.MapCIDRsByIPFamily(nodePortAddresses)
 | 
				
			||||||
	ipv4Proxier, err := NewProxier(ipt[0], sysctl,
 | 
						ipv4Proxier, err := NewProxier(ipt[0], sysctl,
 | 
				
			||||||
		exec, syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[0], hostname,
 | 
							exec, syncPeriod, minSyncPeriod, masqueradeAll, localhostNodePorts, masqueradeBit, localDetectors[0], hostname,
 | 
				
			||||||
		nodeIP[0], recorder, healthzServer, ipFamilyMap[v1.IPv4Protocol])
 | 
							nodeIP[0], recorder, healthzServer, ipFamilyMap[v1.IPv4Protocol])
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err)
 | 
							return nil, fmt.Errorf("unable to create ipv4 proxier: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ipv6Proxier, err := NewProxier(ipt[1], sysctl,
 | 
						ipv6Proxier, err := NewProxier(ipt[1], sysctl,
 | 
				
			||||||
		exec, syncPeriod, minSyncPeriod, masqueradeAll, masqueradeBit, localDetectors[1], hostname,
 | 
							exec, syncPeriod, minSyncPeriod, masqueradeAll, false, masqueradeBit, localDetectors[1], hostname,
 | 
				
			||||||
		nodeIP[1], recorder, healthzServer, ipFamilyMap[v1.IPv6Protocol])
 | 
							nodeIP[1], recorder, healthzServer, ipFamilyMap[v1.IPv6Protocol])
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err)
 | 
							return nil, fmt.Errorf("unable to create ipv6 proxier: %v", err)
 | 
				
			||||||
@@ -1421,23 +1428,52 @@ func (proxier *Proxier) syncProxyRules() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Finally, tail-call to the nodeports chain.  This needs to be after all
 | 
						// Finally, tail-call to the nodePorts chain.  This needs to be after all
 | 
				
			||||||
	// other service portal rules.
 | 
						// other service portal rules.
 | 
				
			||||||
	for address := range nodeAddresses {
 | 
						for address := range nodeAddresses {
 | 
				
			||||||
		if utilproxy.IsZeroCIDR(address) {
 | 
							if utilproxy.IsZeroCIDR(address) {
 | 
				
			||||||
 | 
								destinations := []string{"-m", "addrtype", "--dst-type", "LOCAL"}
 | 
				
			||||||
 | 
								if isIPv6 {
 | 
				
			||||||
 | 
									// For IPv6, Regardless of the value of localhostNodePorts is true
 | 
				
			||||||
 | 
									// or false, we should disable access to the nodePort via localhost. Since it never works and always
 | 
				
			||||||
 | 
									// cause kernel warnings.
 | 
				
			||||||
 | 
									destinations = append(destinations, "!", "-d", "::1/128")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if !proxier.localhostNodePorts && !isIPv6 {
 | 
				
			||||||
 | 
									// If set localhostNodePorts to "false"(route_localnet=0), We should generate iptables rules that
 | 
				
			||||||
 | 
									// disable NodePort services to be accessed via localhost. Since it doesn't work and causes
 | 
				
			||||||
 | 
									// the kernel to log warnings if anyone tries.
 | 
				
			||||||
 | 
									destinations = append(destinations, "!", "-d", "127.0.0.0/8")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			proxier.natRules.Write(
 | 
								proxier.natRules.Write(
 | 
				
			||||||
				"-A", string(kubeServicesChain),
 | 
									"-A", string(kubeServicesChain),
 | 
				
			||||||
				"-m", "comment", "--comment", `"kubernetes service nodeports; NOTE: this must be the last rule in this chain"`,
 | 
									"-m", "comment", "--comment", `"kubernetes service nodeports; NOTE: this must be the last rule in this chain"`,
 | 
				
			||||||
				"-m", "addrtype", "--dst-type", "LOCAL",
 | 
									destinations,
 | 
				
			||||||
				"-j", string(kubeNodePortsChain))
 | 
									"-j", string(kubeNodePortsChain))
 | 
				
			||||||
			// Nothing else matters after the zero CIDR.
 | 
					 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Ignore IP addresses with incorrect version
 | 
							// Ignore IP addresses with incorrect version
 | 
				
			||||||
		if isIPv6 && !netutils.IsIPv6String(address) || !isIPv6 && netutils.IsIPv6String(address) {
 | 
							if isIPv6 && !netutils.IsIPv6String(address) || !isIPv6 && netutils.IsIPv6String(address) {
 | 
				
			||||||
			klog.ErrorS(nil, "IP has incorrect IP version", "IP", address)
 | 
								klog.ErrorS(nil, "IP has incorrect IP version", "IP", address)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// For ipv6, Regardless of the value of localhostNodePorts is true or false, we should disallow access
 | 
				
			||||||
 | 
							// to the nodePort via lookBack address.
 | 
				
			||||||
 | 
							if isIPv6 && utilproxy.IsLoopBack(address) {
 | 
				
			||||||
 | 
								klog.ErrorS(nil, "disallow nodePort services to be accessed via ipv6 localhost address", "IP", address)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// For ipv4, When localhostNodePorts is set to false, Ignore ipv4 lookBack address
 | 
				
			||||||
 | 
							if !isIPv6 && utilproxy.IsLoopBack(address) && !proxier.localhostNodePorts {
 | 
				
			||||||
 | 
								klog.ErrorS(nil, "disallow nodePort services to be accessed via ipv4 localhost address", "IP", address)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// create nodeport rules for each IP one by one
 | 
							// create nodeport rules for each IP one by one
 | 
				
			||||||
		proxier.natRules.Write(
 | 
							proxier.natRules.Write(
 | 
				
			||||||
			"-A", string(kubeServicesChain),
 | 
								"-A", string(kubeServicesChain),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -421,6 +421,7 @@ func NewFakeProxier(ipt utiliptables.Interface) *Proxier {
 | 
				
			|||||||
		natChains:                utilproxy.LineBuffer{},
 | 
							natChains:                utilproxy.LineBuffer{},
 | 
				
			||||||
		natRules:                 utilproxy.LineBuffer{},
 | 
							natRules:                 utilproxy.LineBuffer{},
 | 
				
			||||||
		nodeIP:                   netutils.ParseIPSloppy(testNodeIP),
 | 
							nodeIP:                   netutils.ParseIPSloppy(testNodeIP),
 | 
				
			||||||
 | 
							localhostNodePorts:       true,
 | 
				
			||||||
		nodePortAddresses:        make([]string, 0),
 | 
							nodePortAddresses:        make([]string, 0),
 | 
				
			||||||
		networkInterfacer:        networkInterfacer,
 | 
							networkInterfacer:        networkInterfacer,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -3253,6 +3254,477 @@ func TestOnlyLocalLoadBalancing(t *testing.T) {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEnableLocalhostNodePortsIPv4(t *testing.T) {
 | 
				
			||||||
 | 
						ipt := iptablestest.NewFake()
 | 
				
			||||||
 | 
						fp := NewFakeProxier(ipt)
 | 
				
			||||||
 | 
						fp.localDetector = proxyutiliptables.NewNoOpLocalDetector()
 | 
				
			||||||
 | 
						fp.localhostNodePorts = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected := dedent.Dedent(`
 | 
				
			||||||
 | 
					        *filter
 | 
				
			||||||
 | 
					        :KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-EXTERNAL-SERVICES - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-FORWARD - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-PROXY-FIREWALL - [0:0]
 | 
				
			||||||
 | 
					        -A KUBE-FORWARD -m conntrack --ctstate INVALID -j DROP
 | 
				
			||||||
 | 
					        -A KUBE-FORWARD -m comment --comment "kubernetes forwarding rules" -m mark --mark 0x4000/0x4000 -j ACCEPT
 | 
				
			||||||
 | 
					        -A KUBE-FORWARD -m comment --comment "kubernetes forwarding conntrack rule" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 | 
				
			||||||
 | 
					        COMMIT
 | 
				
			||||||
 | 
					        *nat
 | 
				
			||||||
 | 
					        :KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-EXT-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-MARK-MASQ - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-POSTROUTING - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SEP-6KG6DFHVBKBK53RU - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SEP-KDGX2M2ONE25PSWH - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SVC-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SVL-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
					        -A KUBE-NODEPORTS -m comment --comment ns1/svc1:p80 -m tcp -p tcp --dport 30001 -j KUBE-EXT-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
					        -A KUBE-SERVICES -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 10.69.0.10 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
					        -A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
 | 
				
			||||||
 | 
					        -A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "masquerade LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
					        -A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "route LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
					        -A KUBE-EXT-XPGD46QRK7WJZT7O -j KUBE-SVL-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
					        -A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
 | 
				
			||||||
 | 
					        -A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
 | 
				
			||||||
 | 
					        -A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
 | 
				
			||||||
 | 
					        -A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
 | 
				
			||||||
 | 
					        -A KUBE-SEP-6KG6DFHVBKBK53RU -m comment --comment ns1/svc1:p80 -s 10.244.0.1 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
					        -A KUBE-SEP-6KG6DFHVBKBK53RU -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination 10.244.0.1:80
 | 
				
			||||||
 | 
					        -A KUBE-SEP-KDGX2M2ONE25PSWH -m comment --comment ns1/svc1:p80 -s 10.244.2.1 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
					        -A KUBE-SEP-KDGX2M2ONE25PSWH -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination 10.244.2.1:80
 | 
				
			||||||
 | 
					        -A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.0.1:80" -m statistic --mode random --probability 0.5000000000 -j KUBE-SEP-6KG6DFHVBKBK53RU
 | 
				
			||||||
 | 
					        -A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.2.1:80" -j KUBE-SEP-KDGX2M2ONE25PSWH
 | 
				
			||||||
 | 
					        -A KUBE-SVL-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.2.1:80" -j KUBE-SEP-KDGX2M2ONE25PSWH
 | 
				
			||||||
 | 
					        COMMIT
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
						svcIP := "10.69.0.10"
 | 
				
			||||||
 | 
						svcPort := 80
 | 
				
			||||||
 | 
						svcNodePort := 30001
 | 
				
			||||||
 | 
						svcPortName := proxy.ServicePortName{
 | 
				
			||||||
 | 
							NamespacedName: makeNSN("ns1", "svc1"),
 | 
				
			||||||
 | 
							Port:           "p80",
 | 
				
			||||||
 | 
							Protocol:       v1.ProtocolTCP,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						makeServiceMap(fp,
 | 
				
			||||||
 | 
							makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
 | 
				
			||||||
 | 
								svc.Spec.Type = "NodePort"
 | 
				
			||||||
 | 
								svc.Spec.ClusterIP = svcIP
 | 
				
			||||||
 | 
								svc.Spec.Ports = []v1.ServicePort{{
 | 
				
			||||||
 | 
									Name:     svcPortName.Port,
 | 
				
			||||||
 | 
									Port:     int32(svcPort),
 | 
				
			||||||
 | 
									Protocol: v1.ProtocolTCP,
 | 
				
			||||||
 | 
									NodePort: int32(svcNodePort),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						epIP1 := "10.244.0.1"
 | 
				
			||||||
 | 
						epIP2 := "10.244.2.1"
 | 
				
			||||||
 | 
						tcpProtocol := v1.ProtocolTCP
 | 
				
			||||||
 | 
						populateEndpointSlices(fp,
 | 
				
			||||||
 | 
							makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) {
 | 
				
			||||||
 | 
								eps.AddressType = discovery.AddressTypeIPv4
 | 
				
			||||||
 | 
								eps.Endpoints = []discovery.Endpoint{{
 | 
				
			||||||
 | 
									Addresses: []string{epIP1},
 | 
				
			||||||
 | 
									NodeName:  nil,
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									Addresses: []string{epIP2},
 | 
				
			||||||
 | 
									NodeName:  pointer.String(testHostname),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								eps.Ports = []discovery.EndpointPort{{
 | 
				
			||||||
 | 
									Name:     pointer.String(svcPortName.Port),
 | 
				
			||||||
 | 
									Port:     pointer.Int32(int32(svcPort)),
 | 
				
			||||||
 | 
									Protocol: &tcpProtocol,
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fp.syncProxyRules()
 | 
				
			||||||
 | 
						assertIPTablesRulesEqual(t, getLine(), true, expected, fp.iptablesData.String())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDisableLocalhostNodePortsIPv4(t *testing.T) {
 | 
				
			||||||
 | 
						ipt := iptablestest.NewFake()
 | 
				
			||||||
 | 
						fp := NewFakeProxier(ipt)
 | 
				
			||||||
 | 
						fp.localDetector = proxyutiliptables.NewNoOpLocalDetector()
 | 
				
			||||||
 | 
						fp.localhostNodePorts = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected := dedent.Dedent(`
 | 
				
			||||||
 | 
						*filter
 | 
				
			||||||
 | 
						:KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
						:KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
						:KUBE-EXTERNAL-SERVICES - [0:0]
 | 
				
			||||||
 | 
						:KUBE-FORWARD - [0:0]
 | 
				
			||||||
 | 
						:KUBE-PROXY-FIREWALL - [0:0]
 | 
				
			||||||
 | 
						-A KUBE-FORWARD -m conntrack --ctstate INVALID -j DROP
 | 
				
			||||||
 | 
						-A KUBE-FORWARD -m comment --comment "kubernetes forwarding rules" -m mark --mark 0x4000/0x4000 -j ACCEPT
 | 
				
			||||||
 | 
						-A KUBE-FORWARD -m comment --comment "kubernetes forwarding conntrack rule" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 | 
				
			||||||
 | 
						COMMIT
 | 
				
			||||||
 | 
						*nat
 | 
				
			||||||
 | 
						:KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
						:KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
						:KUBE-EXT-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
						:KUBE-MARK-MASQ - [0:0]
 | 
				
			||||||
 | 
						:KUBE-POSTROUTING - [0:0]
 | 
				
			||||||
 | 
						:KUBE-SEP-6KG6DFHVBKBK53RU - [0:0]
 | 
				
			||||||
 | 
						:KUBE-SEP-KDGX2M2ONE25PSWH - [0:0]
 | 
				
			||||||
 | 
						:KUBE-SVC-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
						:KUBE-SVL-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
						-A KUBE-NODEPORTS -m comment --comment ns1/svc1:p80 -m tcp -p tcp --dport 30001 -j KUBE-EXT-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
						-A KUBE-SERVICES -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 10.69.0.10 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
						-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL ! -d 127.0.0.0/8 -j KUBE-NODEPORTS
 | 
				
			||||||
 | 
						-A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "masquerade LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
						-A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "route LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
						-A KUBE-EXT-XPGD46QRK7WJZT7O -j KUBE-SVL-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
						-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
 | 
				
			||||||
 | 
						-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
 | 
				
			||||||
 | 
						-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
 | 
				
			||||||
 | 
						-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
 | 
				
			||||||
 | 
						-A KUBE-SEP-6KG6DFHVBKBK53RU -m comment --comment ns1/svc1:p80 -s 10.244.0.1 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
						-A KUBE-SEP-6KG6DFHVBKBK53RU -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination 10.244.0.1:80
 | 
				
			||||||
 | 
						-A KUBE-SEP-KDGX2M2ONE25PSWH -m comment --comment ns1/svc1:p80 -s 10.244.2.1 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
						-A KUBE-SEP-KDGX2M2ONE25PSWH -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination 10.244.2.1:80
 | 
				
			||||||
 | 
						-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.0.1:80" -m statistic --mode random --probability 0.5000000000 -j KUBE-SEP-6KG6DFHVBKBK53RU
 | 
				
			||||||
 | 
						-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.2.1:80" -j KUBE-SEP-KDGX2M2ONE25PSWH
 | 
				
			||||||
 | 
						-A KUBE-SVL-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.2.1:80" -j KUBE-SEP-KDGX2M2ONE25PSWH
 | 
				
			||||||
 | 
						COMMIT
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
						svcIP := "10.69.0.10"
 | 
				
			||||||
 | 
						svcPort := 80
 | 
				
			||||||
 | 
						svcNodePort := 30001
 | 
				
			||||||
 | 
						svcPortName := proxy.ServicePortName{
 | 
				
			||||||
 | 
							NamespacedName: makeNSN("ns1", "svc1"),
 | 
				
			||||||
 | 
							Port:           "p80",
 | 
				
			||||||
 | 
							Protocol:       v1.ProtocolTCP,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						makeServiceMap(fp,
 | 
				
			||||||
 | 
							makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
 | 
				
			||||||
 | 
								svc.Spec.Type = "NodePort"
 | 
				
			||||||
 | 
								svc.Spec.ClusterIP = svcIP
 | 
				
			||||||
 | 
								svc.Spec.Ports = []v1.ServicePort{{
 | 
				
			||||||
 | 
									Name:     svcPortName.Port,
 | 
				
			||||||
 | 
									Port:     int32(svcPort),
 | 
				
			||||||
 | 
									Protocol: v1.ProtocolTCP,
 | 
				
			||||||
 | 
									NodePort: int32(svcNodePort),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						epIP1 := "10.244.0.1"
 | 
				
			||||||
 | 
						epIP2 := "10.244.2.1"
 | 
				
			||||||
 | 
						tcpProtocol := v1.ProtocolTCP
 | 
				
			||||||
 | 
						populateEndpointSlices(fp,
 | 
				
			||||||
 | 
							makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) {
 | 
				
			||||||
 | 
								eps.AddressType = discovery.AddressTypeIPv4
 | 
				
			||||||
 | 
								eps.Endpoints = []discovery.Endpoint{{
 | 
				
			||||||
 | 
									Addresses: []string{epIP1},
 | 
				
			||||||
 | 
									NodeName:  nil,
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									Addresses: []string{epIP2},
 | 
				
			||||||
 | 
									NodeName:  pointer.String(testHostname),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								eps.Ports = []discovery.EndpointPort{{
 | 
				
			||||||
 | 
									Name:     pointer.String(svcPortName.Port),
 | 
				
			||||||
 | 
									Port:     pointer.Int32(int32(svcPort)),
 | 
				
			||||||
 | 
									Protocol: &tcpProtocol,
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fp.syncProxyRules()
 | 
				
			||||||
 | 
						assertIPTablesRulesEqual(t, getLine(), true, expected, fp.iptablesData.String())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDisableLocalhostNodePortsIPv4WithNodeAddress(t *testing.T) {
 | 
				
			||||||
 | 
						ipt := iptablestest.NewFake()
 | 
				
			||||||
 | 
						fp := NewFakeProxier(ipt)
 | 
				
			||||||
 | 
						fp.localDetector = proxyutiliptables.NewNoOpLocalDetector()
 | 
				
			||||||
 | 
						fp.localhostNodePorts = false
 | 
				
			||||||
 | 
						fp.networkInterfacer.InterfaceAddrs()
 | 
				
			||||||
 | 
						fp.nodePortAddresses = []string{"127.0.0.0/8"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected := dedent.Dedent(`
 | 
				
			||||||
 | 
					        *filter
 | 
				
			||||||
 | 
					        :KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-EXTERNAL-SERVICES - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-FORWARD - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-PROXY-FIREWALL - [0:0]
 | 
				
			||||||
 | 
					        -A KUBE-FORWARD -m conntrack --ctstate INVALID -j DROP
 | 
				
			||||||
 | 
					        -A KUBE-FORWARD -m comment --comment "kubernetes forwarding rules" -m mark --mark 0x4000/0x4000 -j ACCEPT
 | 
				
			||||||
 | 
					        -A KUBE-FORWARD -m comment --comment "kubernetes forwarding conntrack rule" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 | 
				
			||||||
 | 
					        COMMIT
 | 
				
			||||||
 | 
					        *nat
 | 
				
			||||||
 | 
					        :KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-EXT-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-MARK-MASQ - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-POSTROUTING - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SEP-6KG6DFHVBKBK53RU - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SEP-KDGX2M2ONE25PSWH - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SVC-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
					        :KUBE-SVL-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
					        -A KUBE-NODEPORTS -m comment --comment ns1/svc1:p80 -m tcp -p tcp --dport 30001 -j KUBE-EXT-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
					        -A KUBE-SERVICES -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d 10.69.0.10 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
					        -A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "masquerade LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
					        -A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "route LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
					        -A KUBE-EXT-XPGD46QRK7WJZT7O -j KUBE-SVL-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
					        -A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
 | 
				
			||||||
 | 
					        -A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
 | 
				
			||||||
 | 
					        -A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
 | 
				
			||||||
 | 
					        -A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
 | 
				
			||||||
 | 
					        -A KUBE-SEP-6KG6DFHVBKBK53RU -m comment --comment ns1/svc1:p80 -s 10.244.0.1 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
					        -A KUBE-SEP-6KG6DFHVBKBK53RU -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination 10.244.0.1:80
 | 
				
			||||||
 | 
					        -A KUBE-SEP-KDGX2M2ONE25PSWH -m comment --comment ns1/svc1:p80 -s 10.244.2.1 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
					        -A KUBE-SEP-KDGX2M2ONE25PSWH -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination 10.244.2.1:80
 | 
				
			||||||
 | 
					        -A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.0.1:80" -m statistic --mode random --probability 0.5000000000 -j KUBE-SEP-6KG6DFHVBKBK53RU
 | 
				
			||||||
 | 
					        -A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.2.1:80" -j KUBE-SEP-KDGX2M2ONE25PSWH
 | 
				
			||||||
 | 
					        -A KUBE-SVL-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> 10.244.2.1:80" -j KUBE-SEP-KDGX2M2ONE25PSWH
 | 
				
			||||||
 | 
					        COMMIT
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
						svcIP := "10.69.0.10"
 | 
				
			||||||
 | 
						svcPort := 80
 | 
				
			||||||
 | 
						svcNodePort := 30001
 | 
				
			||||||
 | 
						svcPortName := proxy.ServicePortName{
 | 
				
			||||||
 | 
							NamespacedName: makeNSN("ns1", "svc1"),
 | 
				
			||||||
 | 
							Port:           "p80",
 | 
				
			||||||
 | 
							Protocol:       v1.ProtocolTCP,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						makeServiceMap(fp,
 | 
				
			||||||
 | 
							makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
 | 
				
			||||||
 | 
								svc.Spec.Type = "NodePort"
 | 
				
			||||||
 | 
								svc.Spec.ClusterIP = svcIP
 | 
				
			||||||
 | 
								svc.Spec.Ports = []v1.ServicePort{{
 | 
				
			||||||
 | 
									Name:     svcPortName.Port,
 | 
				
			||||||
 | 
									Port:     int32(svcPort),
 | 
				
			||||||
 | 
									Protocol: v1.ProtocolTCP,
 | 
				
			||||||
 | 
									NodePort: int32(svcNodePort),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						epIP1 := "10.244.0.1"
 | 
				
			||||||
 | 
						epIP2 := "10.244.2.1"
 | 
				
			||||||
 | 
						tcpProtocol := v1.ProtocolTCP
 | 
				
			||||||
 | 
						populateEndpointSlices(fp,
 | 
				
			||||||
 | 
							makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) {
 | 
				
			||||||
 | 
								eps.AddressType = discovery.AddressTypeIPv4
 | 
				
			||||||
 | 
								eps.Endpoints = []discovery.Endpoint{{
 | 
				
			||||||
 | 
									Addresses: []string{epIP1},
 | 
				
			||||||
 | 
									NodeName:  nil,
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									Addresses: []string{epIP2},
 | 
				
			||||||
 | 
									NodeName:  pointer.String(testHostname),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								eps.Ports = []discovery.EndpointPort{{
 | 
				
			||||||
 | 
									Name:     pointer.String(svcPortName.Port),
 | 
				
			||||||
 | 
									Port:     pointer.Int32(int32(svcPort)),
 | 
				
			||||||
 | 
									Protocol: &tcpProtocol,
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fp.syncProxyRules()
 | 
				
			||||||
 | 
						assertIPTablesRulesEqual(t, getLine(), true, expected, fp.iptablesData.String())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEnableLocalhostNodePortsIPv6(t *testing.T) {
 | 
				
			||||||
 | 
						ipt := iptablestest.NewIPv6Fake()
 | 
				
			||||||
 | 
						fp := NewFakeProxier(ipt)
 | 
				
			||||||
 | 
						fp.localDetector = proxyutiliptables.NewNoOpLocalDetector()
 | 
				
			||||||
 | 
						fp.localhostNodePorts = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected := dedent.Dedent(`
 | 
				
			||||||
 | 
							*filter
 | 
				
			||||||
 | 
							:KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
							:KUBE-EXTERNAL-SERVICES - [0:0]
 | 
				
			||||||
 | 
							:KUBE-FORWARD - [0:0]
 | 
				
			||||||
 | 
							:KUBE-PROXY-FIREWALL - [0:0]
 | 
				
			||||||
 | 
							-A KUBE-FORWARD -m conntrack --ctstate INVALID -j DROP
 | 
				
			||||||
 | 
							-A KUBE-FORWARD -m comment --comment "kubernetes forwarding rules" -m mark --mark 0x4000/0x4000 -j ACCEPT
 | 
				
			||||||
 | 
							-A KUBE-FORWARD -m comment --comment "kubernetes forwarding conntrack rule" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 | 
				
			||||||
 | 
							COMMIT
 | 
				
			||||||
 | 
							*nat
 | 
				
			||||||
 | 
							:KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
							:KUBE-EXT-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
							:KUBE-MARK-MASQ - [0:0]
 | 
				
			||||||
 | 
							:KUBE-POSTROUTING - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SEP-LIGRYQQLSZN4UWQ5 - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SEP-XJJ5QXWGJG344QDZ - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SVC-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SVL-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
							-A KUBE-NODEPORTS -m comment --comment ns1/svc1:p80 -m tcp -p tcp --dport 30001 -j KUBE-EXT-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
							-A KUBE-SERVICES -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d fd00:ab34::20 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
							-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL ! -d ::1/128 -j KUBE-NODEPORTS
 | 
				
			||||||
 | 
							-A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "masquerade LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
							-A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "route LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
							-A KUBE-EXT-XPGD46QRK7WJZT7O -j KUBE-SVL-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
							-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
 | 
				
			||||||
 | 
							-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
 | 
				
			||||||
 | 
							-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
 | 
				
			||||||
 | 
							-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
 | 
				
			||||||
 | 
							-A KUBE-SEP-LIGRYQQLSZN4UWQ5 -m comment --comment ns1/svc1:p80 -s ff06::c1 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
							-A KUBE-SEP-LIGRYQQLSZN4UWQ5 -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination [ff06::c1]:80
 | 
				
			||||||
 | 
							-A KUBE-SEP-XJJ5QXWGJG344QDZ -m comment --comment ns1/svc1:p80 -s ff06::c2 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
							-A KUBE-SEP-XJJ5QXWGJG344QDZ -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination [ff06::c2]:80
 | 
				
			||||||
 | 
							-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> [ff06::c1]:80" -m statistic --mode random --probability 0.5000000000 -j KUBE-SEP-LIGRYQQLSZN4UWQ5
 | 
				
			||||||
 | 
							-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> [ff06::c2]:80" -j KUBE-SEP-XJJ5QXWGJG344QDZ
 | 
				
			||||||
 | 
							-A KUBE-SVL-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> [ff06::c2]:80" -j KUBE-SEP-XJJ5QXWGJG344QDZ
 | 
				
			||||||
 | 
							COMMIT
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
						svcIP := "fd00:ab34::20"
 | 
				
			||||||
 | 
						svcPort := 80
 | 
				
			||||||
 | 
						svcNodePort := 30001
 | 
				
			||||||
 | 
						svcPortName := proxy.ServicePortName{
 | 
				
			||||||
 | 
							NamespacedName: makeNSN("ns1", "svc1"),
 | 
				
			||||||
 | 
							Port:           "p80",
 | 
				
			||||||
 | 
							Protocol:       v1.ProtocolTCP,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						makeServiceMap(fp,
 | 
				
			||||||
 | 
							makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
 | 
				
			||||||
 | 
								svc.Spec.Type = "NodePort"
 | 
				
			||||||
 | 
								svc.Spec.ClusterIP = svcIP
 | 
				
			||||||
 | 
								svc.Spec.Ports = []v1.ServicePort{{
 | 
				
			||||||
 | 
									Name:     svcPortName.Port,
 | 
				
			||||||
 | 
									Port:     int32(svcPort),
 | 
				
			||||||
 | 
									Protocol: v1.ProtocolTCP,
 | 
				
			||||||
 | 
									NodePort: int32(svcNodePort),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						epIP1 := "ff06::c1"
 | 
				
			||||||
 | 
						epIP2 := "ff06::c2"
 | 
				
			||||||
 | 
						tcpProtocol := v1.ProtocolTCP
 | 
				
			||||||
 | 
						populateEndpointSlices(fp,
 | 
				
			||||||
 | 
							makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) {
 | 
				
			||||||
 | 
								eps.AddressType = discovery.AddressTypeIPv6
 | 
				
			||||||
 | 
								eps.Endpoints = []discovery.Endpoint{{
 | 
				
			||||||
 | 
									Addresses: []string{epIP1},
 | 
				
			||||||
 | 
									NodeName:  nil,
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									Addresses: []string{epIP2},
 | 
				
			||||||
 | 
									NodeName:  pointer.String(testHostname),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								eps.Ports = []discovery.EndpointPort{{
 | 
				
			||||||
 | 
									Name:     pointer.String(svcPortName.Port),
 | 
				
			||||||
 | 
									Port:     pointer.Int32(int32(svcPort)),
 | 
				
			||||||
 | 
									Protocol: &tcpProtocol,
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fp.syncProxyRules()
 | 
				
			||||||
 | 
						assertIPTablesRulesEqual(t, getLine(), true, expected, fp.iptablesData.String())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDisableLocalhostNodePortsIPv6(t *testing.T) {
 | 
				
			||||||
 | 
						ipt := iptablestest.NewIPv6Fake()
 | 
				
			||||||
 | 
						fp := NewFakeProxier(ipt)
 | 
				
			||||||
 | 
						fp.localDetector = proxyutiliptables.NewNoOpLocalDetector()
 | 
				
			||||||
 | 
						fp.localhostNodePorts = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected := dedent.Dedent(`
 | 
				
			||||||
 | 
							*filter
 | 
				
			||||||
 | 
							:KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
							:KUBE-EXTERNAL-SERVICES - [0:0]
 | 
				
			||||||
 | 
							:KUBE-FORWARD - [0:0]
 | 
				
			||||||
 | 
							:KUBE-PROXY-FIREWALL - [0:0]
 | 
				
			||||||
 | 
							-A KUBE-FORWARD -m conntrack --ctstate INVALID -j DROP
 | 
				
			||||||
 | 
							-A KUBE-FORWARD -m comment --comment "kubernetes forwarding rules" -m mark --mark 0x4000/0x4000 -j ACCEPT
 | 
				
			||||||
 | 
							-A KUBE-FORWARD -m comment --comment "kubernetes forwarding conntrack rule" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 | 
				
			||||||
 | 
							COMMIT
 | 
				
			||||||
 | 
							*nat
 | 
				
			||||||
 | 
							:KUBE-NODEPORTS - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SERVICES - [0:0]
 | 
				
			||||||
 | 
							:KUBE-EXT-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
							:KUBE-MARK-MASQ - [0:0]
 | 
				
			||||||
 | 
							:KUBE-POSTROUTING - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SEP-LIGRYQQLSZN4UWQ5 - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SEP-XJJ5QXWGJG344QDZ - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SVC-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
							:KUBE-SVL-XPGD46QRK7WJZT7O - [0:0]
 | 
				
			||||||
 | 
							-A KUBE-NODEPORTS -m comment --comment ns1/svc1:p80 -m tcp -p tcp --dport 30001 -j KUBE-EXT-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
							-A KUBE-SERVICES -m comment --comment "ns1/svc1:p80 cluster IP" -m tcp -p tcp -d fd00:ab34::20 --dport 80 -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
							-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL ! -d ::1/128 -j KUBE-NODEPORTS
 | 
				
			||||||
 | 
							-A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "masquerade LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
							-A KUBE-EXT-XPGD46QRK7WJZT7O -m comment --comment "route LOCAL traffic for ns1/svc1:p80 external destinations" -m addrtype --src-type LOCAL -j KUBE-SVC-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
							-A KUBE-EXT-XPGD46QRK7WJZT7O -j KUBE-SVL-XPGD46QRK7WJZT7O
 | 
				
			||||||
 | 
							-A KUBE-MARK-MASQ -j MARK --or-mark 0x4000
 | 
				
			||||||
 | 
							-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
 | 
				
			||||||
 | 
							-A KUBE-POSTROUTING -j MARK --xor-mark 0x4000
 | 
				
			||||||
 | 
							-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE
 | 
				
			||||||
 | 
							-A KUBE-SEP-LIGRYQQLSZN4UWQ5 -m comment --comment ns1/svc1:p80 -s ff06::c1 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
							-A KUBE-SEP-LIGRYQQLSZN4UWQ5 -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination [ff06::c1]:80
 | 
				
			||||||
 | 
							-A KUBE-SEP-XJJ5QXWGJG344QDZ -m comment --comment ns1/svc1:p80 -s ff06::c2 -j KUBE-MARK-MASQ
 | 
				
			||||||
 | 
							-A KUBE-SEP-XJJ5QXWGJG344QDZ -m comment --comment ns1/svc1:p80 -m tcp -p tcp -j DNAT --to-destination [ff06::c2]:80
 | 
				
			||||||
 | 
							-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> [ff06::c1]:80" -m statistic --mode random --probability 0.5000000000 -j KUBE-SEP-LIGRYQQLSZN4UWQ5
 | 
				
			||||||
 | 
							-A KUBE-SVC-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> [ff06::c2]:80" -j KUBE-SEP-XJJ5QXWGJG344QDZ
 | 
				
			||||||
 | 
							-A KUBE-SVL-XPGD46QRK7WJZT7O -m comment --comment "ns1/svc1:p80 -> [ff06::c2]:80" -j KUBE-SEP-XJJ5QXWGJG344QDZ
 | 
				
			||||||
 | 
							COMMIT
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
						svcIP := "fd00:ab34::20"
 | 
				
			||||||
 | 
						svcPort := 80
 | 
				
			||||||
 | 
						svcNodePort := 30001
 | 
				
			||||||
 | 
						svcPortName := proxy.ServicePortName{
 | 
				
			||||||
 | 
							NamespacedName: makeNSN("ns1", "svc1"),
 | 
				
			||||||
 | 
							Port:           "p80",
 | 
				
			||||||
 | 
							Protocol:       v1.ProtocolTCP,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						makeServiceMap(fp,
 | 
				
			||||||
 | 
							makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
 | 
				
			||||||
 | 
								svc.Spec.Type = "NodePort"
 | 
				
			||||||
 | 
								svc.Spec.ClusterIP = svcIP
 | 
				
			||||||
 | 
								svc.Spec.Ports = []v1.ServicePort{{
 | 
				
			||||||
 | 
									Name:     svcPortName.Port,
 | 
				
			||||||
 | 
									Port:     int32(svcPort),
 | 
				
			||||||
 | 
									Protocol: v1.ProtocolTCP,
 | 
				
			||||||
 | 
									NodePort: int32(svcNodePort),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						epIP1 := "ff06::c1"
 | 
				
			||||||
 | 
						epIP2 := "ff06::c2"
 | 
				
			||||||
 | 
						tcpProtocol := v1.ProtocolTCP
 | 
				
			||||||
 | 
						populateEndpointSlices(fp,
 | 
				
			||||||
 | 
							makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) {
 | 
				
			||||||
 | 
								eps.AddressType = discovery.AddressTypeIPv6
 | 
				
			||||||
 | 
								eps.Endpoints = []discovery.Endpoint{{
 | 
				
			||||||
 | 
									Addresses: []string{epIP1},
 | 
				
			||||||
 | 
									NodeName:  nil,
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									Addresses: []string{epIP2},
 | 
				
			||||||
 | 
									NodeName:  pointer.String(testHostname),
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
								eps.Ports = []discovery.EndpointPort{{
 | 
				
			||||||
 | 
									Name:     pointer.String(svcPortName.Port),
 | 
				
			||||||
 | 
									Port:     pointer.Int32(int32(svcPort)),
 | 
				
			||||||
 | 
									Protocol: &tcpProtocol,
 | 
				
			||||||
 | 
								}}
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fp.syncProxyRules()
 | 
				
			||||||
 | 
						assertIPTablesRulesEqual(t, getLine(), true, expected, fp.iptablesData.String())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestOnlyLocalNodePortsNoClusterCIDR(t *testing.T) {
 | 
					func TestOnlyLocalNodePortsNoClusterCIDR(t *testing.T) {
 | 
				
			||||||
	ipt := iptablestest.NewFake()
 | 
						ipt := iptablestest.NewFake()
 | 
				
			||||||
	fp := NewFakeProxier(ipt)
 | 
						fp := NewFakeProxier(ipt)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,6 +118,15 @@ func IsZeroCIDR(cidr string) bool {
 | 
				
			|||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsLoopBack checks if a given IP address is a loopback address.
 | 
				
			||||||
 | 
					func IsLoopBack(ip string) bool {
 | 
				
			||||||
 | 
						netIP := netutils.ParseIPSloppy(ip)
 | 
				
			||||||
 | 
						if netIP != nil {
 | 
				
			||||||
 | 
							return netIP.IsLoopback()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsProxyableIP checks if a given IP address is permitted to be proxied
 | 
					// IsProxyableIP checks if a given IP address is permitted to be proxied
 | 
				
			||||||
func IsProxyableIP(ip string) error {
 | 
					func IsProxyableIP(ip string) error {
 | 
				
			||||||
	netIP := netutils.ParseIPSloppy(ip)
 | 
						netIP := netutils.ParseIPSloppy(ip)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,9 @@ type KubeProxyIPTablesConfiguration struct {
 | 
				
			|||||||
	MasqueradeBit *int32 `json:"masqueradeBit"`
 | 
						MasqueradeBit *int32 `json:"masqueradeBit"`
 | 
				
			||||||
	// masqueradeAll tells kube-proxy to SNAT everything if using the pure iptables proxy mode.
 | 
						// masqueradeAll tells kube-proxy to SNAT everything if using the pure iptables proxy mode.
 | 
				
			||||||
	MasqueradeAll bool `json:"masqueradeAll"`
 | 
						MasqueradeAll bool `json:"masqueradeAll"`
 | 
				
			||||||
 | 
						// LocalhostNodePorts tells kube-proxy to allow service NodePorts to be accessed via
 | 
				
			||||||
 | 
						// localhost (iptables mode only)
 | 
				
			||||||
 | 
						LocalhostNodePorts *bool `json:"localhostNodePorts"`
 | 
				
			||||||
	// syncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m',
 | 
						// syncPeriod is the period that iptables rules are refreshed (e.g. '5s', '1m',
 | 
				
			||||||
	// '2h22m').  Must be greater than 0.
 | 
						// '2h22m').  Must be greater than 0.
 | 
				
			||||||
	SyncPeriod metav1.Duration `json:"syncPeriod"`
 | 
						SyncPeriod metav1.Duration `json:"syncPeriod"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -135,6 +135,11 @@ func (in *KubeProxyIPTablesConfiguration) DeepCopyInto(out *KubeProxyIPTablesCon
 | 
				
			|||||||
		*out = new(int32)
 | 
							*out = new(int32)
 | 
				
			||||||
		**out = **in
 | 
							**out = **in
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if in.LocalhostNodePorts != nil {
 | 
				
			||||||
 | 
							in, out := &in.LocalhostNodePorts, &out.LocalhostNodePorts
 | 
				
			||||||
 | 
							*out = new(bool)
 | 
				
			||||||
 | 
							**out = **in
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	out.SyncPeriod = in.SyncPeriod
 | 
						out.SyncPeriod = in.SyncPeriod
 | 
				
			||||||
	out.MinSyncPeriod = in.MinSyncPeriod
 | 
						out.MinSyncPeriod = in.MinSyncPeriod
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user