A Go library implementation of the PROXY protocol, versions 1 and 2, which provides, as per specification:
(...) a convenient way to safely transport connection information such as a client's address across multiple layers of NAT or TCP proxies. It is designed to require little changes to existing components and to limit the performance impact caused by the processing of the transported information.
This library is to be used in one of or both proxy clients and proxy servers that need to support said protocol. Both protocol versions, 1 (text-based) and 2 (binary-based) are supported.
$ go get -u github.com/pires/go-proxyproto
The fastest way to get started is the runnable programs under
examples/ and the API examples on
pkg.go.dev:
| Goal | Where to look |
|---|---|
| Minimal client | examples/client |
| Minimal server | examples/server |
| HTTP server | examples/httpserver |
| Server + client over TLS (PROXY header before TLS) | examples/tlsserver, examples/tlsclient |
Listener options: timeout, buffer size, policy, validation |
ExampleListener_* |
NewConn options |
ExampleNewConn_* |
| PROXY over TLS, both wrapping orders | ExampleListener_tls, ExampleListener_tlsHeaderInsideTLS |
Use the full runnable examples above for complete programs. The core API shape is small:
header := proxyproto.HeaderProxyFromAddrs(1, sourceAddr, destinationAddr)
_, err := header.WriteTo(conn) // write the PROXY header before application data
See examples/client for a complete TCP client.
proxyListener := &proxyproto.Listener{Listener: ln}
conn, err := proxyListener.Accept()
// conn.RemoteAddr() now reports the client address from the PROXY header, when present.
See examples/server for a complete TCP server. For HTTP/1
and HTTP/2, see examples/httpserver, which uses
helper/http2 so one server can accept proxied HTTP/1 and HTTP/2
connections.
When combining the PROXY protocol with TLS, choose the wrapping order based on where the upstream puts the PROXY header relative to the TLS handshake:
tls.NewListener(&proxyproto.Listener{Listener: l}, tlsConfig).&proxyproto.Listener{Listener: tls.NewListener(l, tlsConfig)}.In both cases conn.RemoteAddr() reports the client carried by the PROXY
header. Runnable code lives in examples/tlsserver and
examples/tlsclient; the API examples
ExampleListener_tls
and
ExampleListener_tlsHeaderInsideTLS
show both orderings.
AWS Network Load Balancer (NLB) does not push the PPV2 header until the client starts sending the data. This is a problem if your server speaks first. e.g. SMTP, FTP, SSH etc.
By default, NLB target group attribute proxy_protocol_v2.client_to_server.header_placement has the value on_first_ack_with_payload. You need to contact AWS support to change it to on_first_ack, instead.
Just to be clear, you need this fix only if your server is designed to speak first.
$ claude mcp add go-proxyproto \
-- python -m otcore.mcp_server <graph>