From 3eea0d14052d2b00d2191ea1833164896cc3ff51 Mon Sep 17 00:00:00 2001 From: Michael Beaumont Date: Thu, 30 Jan 2020 17:43:47 +0100 Subject: [PATCH] kube-proxy: Only open ipv4 sockets for ipv4 clusters --- pkg/proxy/iptables/proxier.go | 24 ++++++++++++++++-------- pkg/proxy/iptables/proxier_test.go | 2 +- pkg/proxy/ipvs/proxier.go | 26 +++++++++++++++++--------- pkg/proxy/ipvs/proxier_test.go | 2 +- pkg/proxy/util/port.go | 2 +- 5 files changed, 36 insertions(+), 20 deletions(-) diff --git a/pkg/proxy/iptables/proxier.go b/pkg/proxy/iptables/proxier.go index 3d6ac101e5c..e7237ffe450 100644 --- a/pkg/proxy/iptables/proxier.go +++ b/pkg/proxy/iptables/proxier.go @@ -241,8 +241,8 @@ type Proxier struct { type listenPortOpener struct{} // OpenLocalPort holds the given local port open. -func (l *listenPortOpener) OpenLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) { - return openLocalPort(lp) +func (l *listenPortOpener) OpenLocalPort(lp *utilproxy.LocalPort, isIPv6 bool) (utilproxy.Closeable, error) { + return openLocalPort(lp, isIPv6) } // Proxier implements proxy.Provider @@ -1043,7 +1043,7 @@ func (proxier *Proxier) syncProxyRules() { klog.V(4).Infof("Port %s was open before and is still needed", lp.String()) replacementPortsMap[lp] = proxier.portsMap[lp] } else { - socket, err := proxier.portMapper.OpenLocalPort(&lp) + socket, err := proxier.portMapper.OpenLocalPort(&lp, isIPv6) if err != nil { msg := fmt.Sprintf("can't open %s, skipping this externalIP: %v", lp.String(), err) @@ -1212,7 +1212,7 @@ func (proxier *Proxier) syncProxyRules() { klog.V(4).Infof("Port %s was open before and is still needed", lp.String()) replacementPortsMap[lp] = proxier.portsMap[lp] } else if svcInfo.Protocol() != v1.ProtocolSCTP { - socket, err := proxier.portMapper.OpenLocalPort(&lp) + socket, err := proxier.portMapper.OpenLocalPort(&lp, isIPv6) if err != nil { klog.Errorf("can't open %s, skipping this nodePort: %v", lp.String(), err) continue @@ -1612,7 +1612,7 @@ func writeBytesLine(buf *bytes.Buffer, bytes []byte) { buf.WriteByte('\n') } -func openLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) { +func openLocalPort(lp *utilproxy.LocalPort, isIPv6 bool) (utilproxy.Closeable, error) { // For ports on node IPs, open the actual port and hold it, even though we // use iptables to redirect traffic. // This ensures a) that it's safe to use that port and b) that (a) stays @@ -1628,17 +1628,25 @@ func openLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) { var socket utilproxy.Closeable switch lp.Protocol { case "tcp": - listener, err := net.Listen("tcp", net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port))) + network := "tcp4" + if isIPv6 { + network = "tcp6" + } + listener, err := net.Listen(network, net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port))) if err != nil { return nil, err } socket = listener case "udp": - addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port))) + network := "udp4" + if isIPv6 { + network = "udp6" + } + addr, err := net.ResolveUDPAddr(network, net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port))) if err != nil { return nil, err } - conn, err := net.ListenUDP("udp", addr) + conn, err := net.ListenUDP(network, addr) if err != nil { return nil, err } diff --git a/pkg/proxy/iptables/proxier_test.go b/pkg/proxy/iptables/proxier_test.go index 95418f1cc23..8528fc8e2de 100644 --- a/pkg/proxy/iptables/proxier_test.go +++ b/pkg/proxy/iptables/proxier_test.go @@ -335,7 +335,7 @@ type fakePortOpener struct { // OpenLocalPort fakes out the listen() and bind() used by syncProxyRules // to lock a local port. -func (f *fakePortOpener) OpenLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) { +func (f *fakePortOpener) OpenLocalPort(lp *utilproxy.LocalPort, isIPv6 bool) (utilproxy.Closeable, error) { f.openPorts = append(f.openPorts, lp) return nil, nil } diff --git a/pkg/proxy/ipvs/proxier.go b/pkg/proxy/ipvs/proxier.go index 83c9a01b3b1..a0f5fb5bdd0 100644 --- a/pkg/proxy/ipvs/proxier.go +++ b/pkg/proxy/ipvs/proxier.go @@ -1145,6 +1145,7 @@ func (proxier *Proxier) syncProxyRules() { klog.Errorf("Failed to cast serviceInfo %q", svcName.String()) continue } + isIPv6 := utilnet.IsIPv6(svcInfo.ClusterIP()) protocol := strings.ToLower(string(svcInfo.Protocol())) // Precompute svcNameString; with many services the many calls // to ServicePortName.String() show up in CPU profiles. @@ -1236,7 +1237,7 @@ func (proxier *Proxier) syncProxyRules() { klog.V(4).Infof("Port %s was open before and is still needed", lp.String()) replacementPortsMap[lp] = proxier.portsMap[lp] } else { - socket, err := proxier.portMapper.OpenLocalPort(&lp) + socket, err := proxier.portMapper.OpenLocalPort(&lp, isIPv6) if err != nil { msg := fmt.Sprintf("can't open %s, skipping this externalIP: %v", lp.String(), err) @@ -1425,13 +1426,12 @@ func (proxier *Proxier) syncProxyRules() { // We do not start listening on SCTP ports, according to our agreement in the // SCTP support KEP } else if svcInfo.Protocol() != v1.ProtocolSCTP { - socket, err := proxier.portMapper.OpenLocalPort(&lp) + socket, err := proxier.portMapper.OpenLocalPort(&lp, isIPv6) if err != nil { klog.Errorf("can't open %s, skipping this nodePort: %v", lp.String(), err) continue } if lp.Protocol == "udp" { - isIPv6 := utilnet.IsIPv6(svcInfo.ClusterIP()) conntrack.ClearEntriesForPort(proxier.exec, lp.Port, isIPv6, v1.ProtocolUDP) } replacementPortsMap[lp] = socket @@ -2122,11 +2122,11 @@ func writeBytesLine(buf *bytes.Buffer, bytes []byte) { type listenPortOpener struct{} // OpenLocalPort holds the given local port open. -func (l *listenPortOpener) OpenLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) { - return openLocalPort(lp) +func (l *listenPortOpener) OpenLocalPort(lp *utilproxy.LocalPort, isIPv6 bool) (utilproxy.Closeable, error) { + return openLocalPort(lp, isIPv6) } -func openLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) { +func openLocalPort(lp *utilproxy.LocalPort, isIPv6 bool) (utilproxy.Closeable, error) { // For ports on node IPs, open the actual port and hold it, even though we // use ipvs to redirect traffic. // This ensures a) that it's safe to use that port and b) that (a) stays @@ -2142,17 +2142,25 @@ func openLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) { var socket utilproxy.Closeable switch lp.Protocol { case "tcp": - listener, err := net.Listen("tcp", net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port))) + network := "tcp4" + if isIPv6 { + network = "tcp6" + } + listener, err := net.Listen(network, net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port))) if err != nil { return nil, err } socket = listener case "udp": - addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port))) + network := "udp4" + if isIPv6 { + network = "udp6" + } + addr, err := net.ResolveUDPAddr(network, net.JoinHostPort(lp.IP, strconv.Itoa(lp.Port))) if err != nil { return nil, err } - conn, err := net.ListenUDP("udp", addr) + conn, err := net.ListenUDP(network, addr) if err != nil { return nil, err } diff --git a/pkg/proxy/ipvs/proxier_test.go b/pkg/proxy/ipvs/proxier_test.go index d83c191b9db..e5d4175af97 100644 --- a/pkg/proxy/ipvs/proxier_test.go +++ b/pkg/proxy/ipvs/proxier_test.go @@ -67,7 +67,7 @@ type fakePortOpener struct { // OpenLocalPort fakes out the listen() and bind() used by syncProxyRules // to lock a local port. -func (f *fakePortOpener) OpenLocalPort(lp *utilproxy.LocalPort) (utilproxy.Closeable, error) { +func (f *fakePortOpener) OpenLocalPort(lp *utilproxy.LocalPort, isIPv6 bool) (utilproxy.Closeable, error) { f.openPorts = append(f.openPorts, lp) return nil, nil } diff --git a/pkg/proxy/util/port.go b/pkg/proxy/util/port.go index 2706f067fde..bb8de546ae0 100644 --- a/pkg/proxy/util/port.go +++ b/pkg/proxy/util/port.go @@ -51,7 +51,7 @@ type Closeable interface { // PortOpener is an interface around port opening/closing. // Abstracted out for testing. type PortOpener interface { - OpenLocalPort(lp *LocalPort) (Closeable, error) + OpenLocalPort(lp *LocalPort, isIPv6 bool) (Closeable, error) } // RevertPorts is closing ports in replacementPortsMap but not in originalPortsMap. In other words, it only