Need help with go-proxyproto?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

199 Stars 65 Forks Apache License 2.0 151 Commits 9 Opened issues


A Go library implementation of the PROXY protocol, versions 1 and 2.

Services available


Need anything else?

Contributors list


Actions Status Coverage Status Go Report Card

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



package main

import ( "io" "log" "net"

proxyproto ""


func chkErr(err error) { if err != nil { log.Fatalf("Error: %s", err.Error()) } }

func main() { // Dial some proxy listener e.g. target, err := net.ResolveTCPAddr("tcp", "") chkErr(err)

conn, err := net.DialTCP("tcp", nil, target)

defer conn.Close()

// Create a proxyprotocol header or use HeaderProxyFromAddrs() if you
// have two conn's
header := &proxyproto.Header{
    Version:            1,
    Command:            proxyproto.PROXY,
    TransportProtocol:  proxyproto.TCPv4,
    SourceAddr: &net.TCPAddr{
        IP:   net.ParseIP(""),
        Port: 1000,
    DestinationAddr: &net.TCPAddr{
        IP:   net.ParseIP(""),
        Port: 2000,
// After the connection was created write the proxy headers first
_, err = header.WriteTo(conn)
// Then your data... e.g.:
_, err = io.WriteString(conn, "HELO")



package main

import ( "log" "net"

proxyproto ""


func main() { // Create a listener addr := "localhost:9876" list, err := net.Listen("tcp", addr) if err != nil { log.Fatalf("couldn't listen to %q: %q\n", addr, err.Error()) }

// Wrap listener in a proxyproto listener
proxyListener := &proxyproto.Listener{Listener: list}
defer proxyListener.Close()

// Wait for a connection and accept it
conn, err := proxyListener.Accept()
defer conn.Close()

// Print connection details
if conn.LocalAddr() == nil {
    log.Fatal("couldn't retrieve local address")
log.Printf("local address: %q", conn.LocalAddr().String())

if conn.RemoteAddr() == nil {
    log.Fatal("couldn't retrieve remote address")
log.Printf("remote address: %q", conn.RemoteAddr().String())


HTTP Server

package main

import ( "net" "net/http" "time"



func main() { server := http.Server{ Addr: ":8080", }

ln, err := net.Listen("tcp", server.Addr)
if err != nil {

proxyListener := &proxyproto.Listener{
    Listener:          ln,
    ReadHeaderTimeout: 10 * time.Second,
defer proxyListener.Close()



Special notes


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

has the value
. You need to contact AWS support to change it to
, instead.

Just to be clear, you need this fix only if your server is designed to speak first.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.