mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
Merge pull request #108250 from cyclinder/add_flag_in_proxy
kube-proxy: add a flag to disable nodePortOnLocalhost
This commit is contained in:
commit
d86c013b0d
@ -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
@ -52001,6 +52001,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.",
|
||||||
@ -52016,7 +52023,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
|
||||||
|
Loading…
Reference in New Issue
Block a user