Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions lib/reversetunnel/agentpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,20 +556,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,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 @@ -201,6 +207,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