Commit 9bc99a0c authored by Brad Davidson's avatar Brad Davidson Committed by Brad Davidson

Ensure remotedialer kubelet connections use kubelet bind address

Signed-off-by: 's avatarBrad Davidson <brad.davidson@rancher.com> (cherry picked from commit eb8bd158) Signed-off-by: 's avatarBrad Davidson <brad.davidson@rancher.com>
parent 979d8f8f
...@@ -136,8 +136,8 @@ require ( ...@@ -136,8 +136,8 @@ require (
github.com/rancher/dynamiclistener v0.3.6 github.com/rancher/dynamiclistener v0.3.6
github.com/rancher/lasso v0.0.0-20230830164424-d684fdeb6f29 github.com/rancher/lasso v0.0.0-20230830164424-d684fdeb6f29
github.com/rancher/permissions v0.0.0-20240523180510-4001d3d637f7 github.com/rancher/permissions v0.0.0-20240523180510-4001d3d637f7
github.com/rancher/remotedialer v0.3.0 github.com/rancher/remotedialer v0.4.1
github.com/rancher/wharfie v0.5.3 github.com/rancher/wharfie v0.6.4
github.com/rancher/wrangler v1.1.1 github.com/rancher/wrangler v1.1.1
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/rootless-containers/rootlesskit v1.0.1 github.com/rootless-containers/rootlesskit v1.0.1
......
...@@ -38,6 +38,7 @@ import ( ...@@ -38,6 +38,7 @@ import (
var ( var (
endpointDebounceDelay = time.Second endpointDebounceDelay = time.Second
defaultDialer = net.Dialer{}
) )
type agentTunnel struct { type agentTunnel struct {
...@@ -45,6 +46,7 @@ type agentTunnel struct { ...@@ -45,6 +46,7 @@ type agentTunnel struct {
cidrs cidranger.Ranger cidrs cidranger.Ranger
ports map[string]bool ports map[string]bool
mode string mode string
kubeletAddr string
kubeletPort string kubeletPort string
startTime time.Time startTime time.Time
} }
...@@ -82,6 +84,7 @@ func Setup(ctx context.Context, config *daemonconfig.Node, proxy proxy.Proxy) er ...@@ -82,6 +84,7 @@ func Setup(ctx context.Context, config *daemonconfig.Node, proxy proxy.Proxy) er
cidrs: cidranger.NewPCTrieRanger(), cidrs: cidranger.NewPCTrieRanger(),
ports: map[string]bool{}, ports: map[string]bool{},
mode: config.EgressSelectorMode, mode: config.EgressSelectorMode,
kubeletAddr: config.AgentConfig.ListenAddress,
kubeletPort: fmt.Sprint(ports.KubeletPort), kubeletPort: fmt.Sprint(ports.KubeletPort),
startTime: time.Now().Truncate(time.Second), startTime: time.Now().Truncate(time.Second),
} }
...@@ -186,7 +189,7 @@ func (a *agentTunnel) setKubeletPort(ctx context.Context, apiServerReady <-chan ...@@ -186,7 +189,7 @@ func (a *agentTunnel) setKubeletPort(ctx context.Context, apiServerReady <-chan
return false, nil return false, nil
} }
a.kubeletPort = kubeletPort a.kubeletPort = kubeletPort
logrus.Infof("Tunnel authorizer set Kubelet Port %s", a.kubeletPort) logrus.Infof("Tunnel authorizer set Kubelet Port %s", net.JoinHostPort(a.kubeletAddr, a.kubeletPort))
return true, nil return true, nil
}) })
} }
...@@ -390,7 +393,7 @@ func (a *agentTunnel) authorized(ctx context.Context, proto, address string) boo ...@@ -390,7 +393,7 @@ func (a *agentTunnel) authorized(ctx context.Context, proto, address string) boo
logrus.Debugf("Tunnel authorizer checking dial request for %s", address) logrus.Debugf("Tunnel authorizer checking dial request for %s", address)
host, port, err := net.SplitHostPort(address) host, port, err := net.SplitHostPort(address)
if err == nil { if err == nil {
if a.isKubeletPort(proto, host, port) { if a.isKubeletOrStreamPort(proto, host, port) {
return true return true
} }
if ip := net.ParseIP(host); ip != nil { if ip := net.ParseIP(host); ip != nil {
...@@ -448,7 +451,7 @@ func (a *agentTunnel) connect(rootCtx context.Context, waitGroup *sync.WaitGroup ...@@ -448,7 +451,7 @@ func (a *agentTunnel) connect(rootCtx context.Context, waitGroup *sync.WaitGroup
go func() { go func() {
for { for {
// ConnectToProxy blocks until error or context cancellation // ConnectToProxy blocks until error or context cancellation
err := remotedialer.ConnectToProxy(ctx, wsURL, nil, auth, ws, onConnect) err := remotedialer.ConnectToProxyWithDialer(ctx, wsURL, nil, auth, ws, a.dialContext, onConnect)
connected = false connected = false
if err != nil && !errors.Is(err, context.Canceled) { if err != nil && !errors.Is(err, context.Canceled) {
logrus.WithField("url", wsURL).WithError(err).Error("Remotedialer proxy error; reconnecting...") logrus.WithField("url", wsURL).WithError(err).Error("Remotedialer proxy error; reconnecting...")
...@@ -471,7 +474,21 @@ func (a *agentTunnel) connect(rootCtx context.Context, waitGroup *sync.WaitGroup ...@@ -471,7 +474,21 @@ func (a *agentTunnel) connect(rootCtx context.Context, waitGroup *sync.WaitGroup
} }
} }
// isKubeletPort returns true if the connection is to a reserved TCP port on a loopback address. // isKubeletOrStreamPort returns true if the connection is to a reserved TCP port on a loopback address.
func (a *agentTunnel) isKubeletPort(proto, host, port string) bool { func (a *agentTunnel) isKubeletOrStreamPort(proto, host, port string) bool {
return proto == "tcp" && (host == "127.0.0.1" || host == "::1") && (port == a.kubeletPort || port == daemonconfig.StreamServerPort) return proto == "tcp" && (host == "127.0.0.1" || host == "::1") && (port == a.kubeletPort || port == daemonconfig.StreamServerPort)
} }
// dialContext dials a local connection on behalf of the remote server. If the
// connection is to the kubelet port on the loopback address, the kubelet is dialed
// at its configured bind address. Otherwise, the connection is dialed normally.
func (a *agentTunnel) dialContext(ctx context.Context, network, address string) (net.Conn, error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return nil, err
}
if a.isKubeletOrStreamPort(network, host, port) && port == a.kubeletPort {
address = net.JoinHostPort(a.kubeletAddr, port)
}
return defaultDialer.DialContext(ctx, network, address)
}
...@@ -3,7 +3,6 @@ package control ...@@ -3,7 +3,6 @@ package control
import ( import (
"bufio" "bufio"
"context" "context"
"fmt"
"io" "io"
"net" "net"
"net/http" "net/http"
...@@ -197,7 +196,6 @@ func (t *TunnelServer) dialBackend(ctx context.Context, addr string) (net.Conn, ...@@ -197,7 +196,6 @@ func (t *TunnelServer) dialBackend(ctx context.Context, addr string) (net.Conn,
if err != nil { if err != nil {
return nil, err return nil, err
} }
loopback := t.config.Loopback(true)
var nodeName string var nodeName string
var toKubelet, useTunnel bool var toKubelet, useTunnel bool
...@@ -224,14 +222,17 @@ func (t *TunnelServer) dialBackend(ctx context.Context, addr string) (net.Conn, ...@@ -224,14 +222,17 @@ func (t *TunnelServer) dialBackend(ctx context.Context, addr string) (net.Conn,
useTunnel = true useTunnel = true
} }
// Always dial kubelet via the loopback address.
if toKubelet {
addr = fmt.Sprintf("%s:%s", loopback, port)
}
// If connecting to something hosted by the local node, don't tunnel // If connecting to something hosted by the local node, don't tunnel
if nodeName == t.config.ServerNodeName { if nodeName == t.config.ServerNodeName {
useTunnel = false useTunnel = false
if toKubelet {
// Dial local kubelet at the configured bind address
addr = net.JoinHostPort(t.config.BindAddress, port)
}
} else if toKubelet {
// Dial remote kubelet via the loopback address, the remotedialer client
// will ensure that it hits the right local address.
addr = net.JoinHostPort(t.config.Loopback(false), port)
} }
if useTunnel { if useTunnel {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment