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
9 changes: 5 additions & 4 deletions lib/multiplexer/proxyline.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,12 +585,13 @@ func (p *ProxyLine) ResolveSource() net.Addr {
return &p.Source
}

tlvs, err := p.getTeleportTLVs()
if err != nil {
return &p.Source
if tlvs, err := p.getTeleportTLVs(); err == nil {
if tlvs.originalAddress != nil {
return tlvs.originalAddress
}
}

return tlvs.originalAddress
return &p.Source
}

func getTLSCerts(ca types.CertAuthority) [][]byte {
Expand Down
88 changes: 88 additions & 0 deletions lib/multiplexer/wrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,91 @@ func TestPROXYEnabledListener_Accept(t *testing.T) {
})
}
}

func TestWrapperConn(t *testing.T) {
const proto = "tcp"
const listenAddr = "127.0.0.1:0"
listener, err := net.Listen(proto, listenAddr)
require.NoError(t, err)
t.Cleanup(func() { listener.Close() })

connCh := make(chan net.Conn)
errCh := make(chan error)
go func() {
conn, err := listener.Accept()
if err != nil {
errCh <- err
return

}

connCh <- conn
}()

_, err = net.Dial(proto, listener.Addr().String())
require.NoError(t, err)

var c net.Conn
select {
case c = <-connCh:
case err := <-errCh:
require.NoError(t, err, "Received error while trying to accept connection")
case <-time.After(time.Millisecond * 500):
require.Fail(t, "Time out while accepting connection")
}

// Without a proxy line the RemoteAddr should just be a passthru to the underlying
// net.Conn
connNoProxy := Conn{
Conn: c,
protocol: ProtoProxy,
}
require.Equal(t, c.RemoteAddr().String(), connNoProxy.RemoteAddr().String())

// With a proxy line, the RemoteAddr should return the source address
// present in the proxy line. This test case also guards against a
// regression where genuine class E source addresses in a ProxyLine were
// being ignored in favor of a nil original address in the TLVs
classEAddr := net.TCPAddr{
IP: []byte{classEPrefix, 0, 0, 1},
}

connWithProxy := Conn{
Conn: c,
protocol: ProtoProxy,
proxyLine: &ProxyLine{
Protocol: proto,
Source: classEAddr,
},
}
require.Equal(t, classEAddr.String(), connWithProxy.RemoteAddr().String())

// With a downgraded proxy line , the RemoteAddr should return the original
// source address present in the TLVs.
downgradeAddr := net.TCPAddr{
IP: []byte{192, 168, 0, 1},
}
tlvs, err := MarshalTLVs([]TLV{
{
Type: PP2Type(PP2TeleportSubtypeOriginalAddr),
Value: []byte(downgradeAddr.String()),
},
})
require.NoError(t, err)
connWithDowngrade := Conn{
Conn: c,
protocol: ProtoProxy,
proxyLine: &ProxyLine{
Protocol: proto,
Source: classEAddr,
TLVs: []TLV{
{
Type: PP2TypeTeleport,
Value: tlvs,
},
},
},
}

require.Equal(t, downgradeAddr.String(), connWithDowngrade.RemoteAddr().String())
}
3 changes: 2 additions & 1 deletion lib/service/servicecfg/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ type ProxyConfig struct {
// PROXYProtocolMode controls behavior related to unsigned PROXY protocol headers.
PROXYProtocolMode multiplexer.PROXYProtocolMode

// PROXYAllowDowngrade
// PROXYAllowDowngrade controls whether or not pseudo IPv4 downgrading is allowed for
// IPv6 sources communicating with IPv4 destinations.
PROXYAllowDowngrade bool

// WebAddr is address for web portal of the proxy
Expand Down
Loading