1
1
Fork 0
mirror of https://git.sr.ht/~emersion/tlstunnel synced 2024-05-11 22:06:07 +02:00

Add support for the PROXY protocol

This commit is contained in:
Simon Ser 2020-09-09 14:52:41 +02:00
parent f64eb89cee
commit e3ac31414f
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
5 changed files with 47 additions and 1 deletions

View File

@ -4,6 +4,7 @@ A TLS reverse proxy.
- Automatic TLS with Let's Encrypt
- Route incoming connections to backends using Server Name Indication
- Support for the [PROXY protocol]
Example configuration:
@ -14,3 +15,5 @@ Example configuration:
## License
MIT
[PROXY protocol]: https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt

1
go.mod
View File

@ -5,4 +5,5 @@ go 1.15
require (
github.com/caddyserver/certmagic v0.11.2
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/pires/go-proxyproto v0.1.3
)

2
go.sum
View File

@ -195,6 +195,8 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pires/go-proxyproto v0.1.3 h1:2XEuhsQluSNA5QIQkiUv8PfgZ51sNYIQkq/yFquiSQM=
github.com/pires/go-proxyproto v0.1.3/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

View File

@ -98,7 +98,10 @@ func parseBackend(backend *Backend, d *Directive) error {
return fmt.Errorf("failed to parse backend URI %q: %v", backendURI, err)
}
// TODO: +proxy to use the PROXY protocol
if strings.HasSuffix(u.Scheme, "+proxy") {
u.Scheme = strings.TrimSuffix(u.Scheme, "+proxy")
backend.Proxy = true
}
switch u.Scheme {
case "", "tcp":

View File

@ -9,6 +9,7 @@ import (
"net"
"github.com/caddyserver/certmagic"
"github.com/pires/go-proxyproto"
)
type Server struct {
@ -152,12 +153,20 @@ func (fe *Frontend) handle(downstream net.Conn) error {
}
defer upstream.Close()
if be.Proxy {
h := proxyHeader(downstream.RemoteAddr(), downstream.LocalAddr())
if _, err := h.WriteTo(upstream); err != nil {
return fmt.Errorf("failed to write PROXY protocol header: %v", err)
}
}
return duplexCopy(upstream, downstream)
}
type Backend struct {
Network string
Address string
Proxy bool
}
func duplexCopy(a, b io.ReadWriter) error {
@ -172,3 +181,31 @@ func duplexCopy(a, b io.ReadWriter) error {
}()
return <-done
}
func proxyHeader(sourceAddr, destAddr net.Addr) *proxyproto.Header {
h := proxyproto.Header{
Version: 2,
Command: proxyproto.PROXY,
}
switch sourceAddr := sourceAddr.(type) {
case *net.TCPAddr:
destAddr, ok := destAddr.(*net.TCPAddr)
if !ok {
break
}
if localIP4 := sourceAddr.IP.To4(); len(localIP4) == net.IPv4len {
h.TransportProtocol = proxyproto.TCPv4
} else if len(sourceAddr.IP) == net.IPv6len {
h.TransportProtocol = proxyproto.TCPv6
} else {
break
}
h.SourceAddress = sourceAddr.IP
h.DestinationAddress = destAddr.IP
h.SourcePort = uint16(sourceAddr.Port)
h.DestinationPort = uint16(destAddr.Port)
}
return &h
}