Skip to content

Commit

Permalink
Implement support for the PROXY protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
tsipinakis committed Mar 31, 2022
1 parent 625361f commit e03b685
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 3 deletions.
3 changes: 3 additions & 0 deletions config/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ type SSHConfig struct {
// See https://tools.ietf.org/html/rfc4253#page-4 section 4.2. Protocol Version Exchange
// The trailing CR and LF characters should NOT be added to this string.
ServerVersion SSHServerVersion `json:"serverVersion" yaml:"serverVersion" default:"SSH-2.0-ContainerSSH"`
// AllowedProxies is a list of IP addresses or CIDR ranges that are allowed to use the
// PROXY protocol to override the connection originator IP address.
AllowedProxies []string `json:"allowedProxies" yaml:"allowedProxies"`
// Ciphers are the ciphers offered to the client.
Ciphers SSHCipherList `json:"ciphers" yaml:"ciphers" default:"[\"[email protected]\",\"[email protected]\",\"[email protected]\",\"aes256-ctr\",\"aes192-ctr\",\"aes128-ctr\"]" comment:"SSHCipher suites to use"`
// KexAlgorithms are the key exchange algorithms offered to the client.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/mitchellh/mapstructure v1.4.3
github.com/opencontainers/image-spec v1.0.2
github.com/oschwald/geoip2-golang v1.5.0
github.com/pires/go-proxyproto v0.6.1
github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw=
github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
1 change: 1 addition & 0 deletions internal/sshserver/Server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/containerssh/libcontainerssh/service"
"github.com/stretchr/testify/assert"
"golang.org/x/crypto/ssh"
"github.com/pires/go-proxyproto"
)

//region Tests
Expand Down
22 changes: 19 additions & 3 deletions internal/sshserver/serverImpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
messageCodes "github.com/containerssh/libcontainerssh/message"
"github.com/containerssh/libcontainerssh/service"
"golang.org/x/crypto/ssh"
"github.com/pires/go-proxyproto"
)

type serverImpl struct {
Expand Down Expand Up @@ -54,11 +55,20 @@ func (s *serverImpl) RunWithLifecycle(lifecycle service.Lifecycle) error {
Control: s.socketControl,
}

useProxy := len(s.cfg.AllowedProxies) > 0

netListener, err := listenConfig.Listen(lifecycle.Context(), "tcp", s.cfg.Listen)
if err != nil {
s.lock.Unlock()
return messageCodes.Wrap(err, messageCodes.ESSHStartFailed, "failed to start SSH server on %s", s.cfg.Listen)
}
if useProxy {
policy := proxyproto.MustStrictWhiteListPolicy(s.cfg.AllowedProxies)
netListener = &proxyproto.Listener{
Listener: netListener,
Policy: policy,
}
}
s.listenSocket = netListener
s.lock.Unlock()
if err := s.handler.OnReady(); err != nil {
Expand All @@ -84,7 +94,13 @@ func (s *serverImpl) RunWithLifecycle(lifecycle service.Lifecycle) error {
break
}
s.wg.Add(1)
go s.handleConnection(tcpConn)
logger := s.logger
if useProxy {
proxyConn := tcpConn.(*proxyproto.Conn)
proxyIp := proxyConn.Raw().RemoteAddr()
logger = logger.WithLabel("fromProxy", proxyIp.(*net.TCPAddr).IP.String())
}
go s.handleConnection(logger, tcpConn)
}
lifecycle.Stopping()
s.shuttingDown = true
Expand Down Expand Up @@ -501,10 +517,10 @@ func (s *serverImpl) createPasswordCallback(
return passwordCallback
}

func (s *serverImpl) handleConnection(conn net.Conn) {
func (s *serverImpl) handleConnection(logger log.Logger, conn net.Conn) {
addr := conn.RemoteAddr().(*net.TCPAddr)
connectionID := GenerateConnectionID()
logger := s.logger.
logger = logger.
WithLabel("remoteAddr", addr.IP.String()).
WithLabel("connectionId", connectionID)
handlerNetworkConnection, err := s.handler.OnNetworkConnection(*addr, connectionID)
Expand Down

0 comments on commit e03b685

Please sign in to comment.