Skip to content

Commit

Permalink
Provide client address information in transport request (#25993)
Browse files Browse the repository at this point in the history
If client address information is missing in dial request, we take it from the ssh connection.
It's needed for correctly propagating IP information of users
 connecting to auth server through proxy tunnel listener.
  • Loading branch information
AntonAM committed May 10, 2023
1 parent b229bdf commit 2e94ecc
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 14 deletions.
29 changes: 15 additions & 14 deletions lib/reversetunnel/agentpool.go
Expand Up @@ -552,20 +552,21 @@ func (p *AgentPool) getVersion(ctx context.Context) (string, error) {
// transport creates a new transport instance.
func (p *AgentPool) transport(ctx context.Context, channel ssh.Channel, requests <-chan *ssh.Request, conn sshutils.Conn) *transport {
return &transport{
closeContext: ctx,
component: p.Component,
localClusterName: p.LocalCluster,
kubeDialAddr: p.KubeDialAddr,
authClient: p.Client,
reverseTunnelServer: p.ReverseTunnelServer,
server: p.Server,
emitter: p.Client,
sconn: conn,
channel: channel,
requestCh: requests,
log: p.log,
authServers: p.LocalAuthAddresses,
proxySigner: p.PROXYSigner,
closeContext: ctx,
component: p.Component,
localClusterName: p.LocalCluster,
kubeDialAddr: p.KubeDialAddr,
authClient: p.Client,
reverseTunnelServer: p.ReverseTunnelServer,
server: p.Server,
emitter: p.Client,
sconn: conn,
channel: channel,
requestCh: requests,
log: p.log,
authServers: p.LocalAuthAddresses,
proxySigner: p.PROXYSigner,
forwardClientAddress: true,
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/reversetunnel/srv.go
Expand Up @@ -688,6 +688,7 @@ func (s *server) handleTransport(sconn *ssh.ServerConn, nch ssh.NewChannel) {
localClusterName: s.ClusterName,
emitter: s.Emitter,
proxySigner: s.proxySigner,
sconn: sconn,
}
go t.start()
}
Expand Down
24 changes: 24 additions & 0 deletions lib/reversetunnel/transport.go
Expand Up @@ -177,6 +177,12 @@ type transport struct {

// proxySigner is used to sign PROXY headers and securely propagate client IP information
proxySigner multiplexer.PROXYHeaderSigner

// forwardClientAddress indicates whether we should take into account ClientSrcAddr/ClientDstAddr on incoming
// dial request. If false, we ignore those fields and take address from the parent ssh connection. It allows
// preventing users connecting to the proxy tunnel listener spoofing their address; but we are still able to
// correctly propagate client address in reverse tunnel agents of nodes/services.
forwardClientAddress bool
}

// start will start the transporting data over the tunnel. This function will
Expand Down Expand Up @@ -214,6 +220,24 @@ func (p *transport) start() {
p.reply(req, false, []byte(err.Error()))
return
}

if !p.forwardClientAddress {
// This shouldn't happen in normal operation. Either malicious user or misconfigured client.
if dreq.ClientSrcAddr != "" || dreq.ClientDstAddr != "" {
p.log.Warnf("Received unexpected dial request with client source address %q, "+
"client destination address %q, when they should be empty.", dreq.ClientSrcAddr, dreq.ClientDstAddr)
}

// Make sure address fields are overwritten.
if p.sconn != nil {
dreq.ClientSrcAddr = p.sconn.RemoteAddr().String()
dreq.ClientDstAddr = p.sconn.LocalAddr().String()
} else {
dreq.ClientSrcAddr = ""
dreq.ClientDstAddr = ""
}
}

p.log.Debugf("Received out-of-band proxy transport request for %v [%v], from %v.", dreq.Address, dreq.ServerID, dreq.ClientSrcAddr)

// directAddress will hold the address of the node to dial to, if we don't
Expand Down

0 comments on commit 2e94ecc

Please sign in to comment.