~emersion/tlstunnel

aae358811d2df82fb744f3441e7543e0d9458136 — Simon Ser 22 days ago 1f16053
Set PROXY protocol PP2_TYPE_SSL
3 files changed, 45 insertions(+), 7 deletions(-)

M go.mod
M go.sum
M server.go
M go.mod => go.mod +1 -1
@@ 7,7 7,7 @@ require (
	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
	github.com/klauspost/cpuid v1.3.1 // indirect
	github.com/miekg/dns v1.1.31 // indirect
	github.com/pires/go-proxyproto v0.2.0
	github.com/pires/go-proxyproto v0.2.1-0.20201009121050-c24efa3e2d93
	github.com/pkg/errors v0.9.1 // indirect
	github.com/stretchr/testify v1.6.1 // indirect
	go.uber.org/multierr v1.6.0 // indirect

M go.sum => go.sum +2 -2
@@ 24,8 24,8 @@ github.com/mholt/acmez v0.1.1/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ce
github.com/miekg/dns v1.1.30/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo=
github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/pires/go-proxyproto v0.2.0 h1:WyYKlv9pkt77b+LjMvPfwrsAxviaGCFhG4KDIy1ofLY=
github.com/pires/go-proxyproto v0.2.0/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pires/go-proxyproto v0.2.1-0.20201009121050-c24efa3e2d93 h1:zJOJr+XdRZHeJ2u2M7d27G0PreBM84mXCcOSdQVC4Xc=
github.com/pires/go-proxyproto v0.2.1-0.20201009121050-c24efa3e2d93/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

M server.go => server.go +42 -4
@@ 11,6 11,7 @@ import (

	"github.com/caddyserver/certmagic"
	"github.com/pires/go-proxyproto"
	"github.com/pires/go-proxyproto/tlvparse"
)

type Server struct {


@@ 170,6 171,11 @@ func (fe *Frontend) handle(downstream net.Conn, tlsState *tls.ConnectionState) e
		if tlsState.ServerName != "" {
			tlvs = append(tlvs, authorityTLV(tlsState.ServerName))
		}
		if tlv, err := sslTLV(tlsState); err != nil {
			return fmt.Errorf("failed to set PROXY protocol header SSL TLV: %v", err)
		} else {
			tlvs = append(tlvs, tlv)
		}
		if err := h.SetTLVs(tlvs); err != nil {
			return fmt.Errorf("failed to set PROXY protocol header TLVs: %v", err)
		}


@@ 201,10 207,42 @@ func duplexCopy(a, b io.ReadWriter) error {
	return <-done
}

func authorityTLV(name string) proxyproto.TLV {
func newTLV(t proxyproto.PP2Type, v []byte) proxyproto.TLV {
	return proxyproto.TLV{
		Type:   proxyproto.PP2_TYPE_AUTHORITY,
		Length: len(name),
		Value:  []byte(name),
		Type:   t,
		Length: len(v),
		Value:  v,
	}
}

func authorityTLV(name string) proxyproto.TLV {
	return newTLV(proxyproto.PP2_TYPE_AUTHORITY, []byte(name))
}

func sslTLV(state *tls.ConnectionState) (proxyproto.TLV, error) {
	pp2ssl := tlvparse.PP2SSL{
		Client: tlvparse.PP2_BITFIELD_CLIENT_SSL, // all of our connections are TLS
		Verify: 1,                                // we haven't checked the client cert
	}

	var version string
	switch state.Version {
	case tls.VersionTLS10:
		version = "TLSv1.0"
	case tls.VersionTLS11:
		version = "TLSv1.1"
	case tls.VersionTLS12:
		version = "TLSv1.2"
	case tls.VersionTLS13:
		version = "TLSv1.3"
	}
	if version != "" {
		versionTLV := newTLV(proxyproto.PP2_SUBTYPE_SSL_VERSION, []byte(version))
		pp2ssl.TLV = append(pp2ssl.TLV, versionTLV)
	}

	// TODO: add PP2_SUBTYPE_SSL_CIPHER, PP2_SUBTYPE_SSL_SIG_ALG, PP2_SUBTYPE_SSL_KEY_ALG
	// TODO: check client-provided cert, if any

	return pp2ssl.Marshal()
}