Add support for the PROXY protocol
This commit is contained in:
parent
f64eb89cee
commit
e3ac31414f
|
@ -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
1
go.mod
|
@ -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
2
go.sum
|
@ -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=
|
||||
|
|
5
main.go
5
main.go
|
@ -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":
|
||||
|
|
37
server.go
37
server.go
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue