Categorygithub.com/pires/go-proxyproto
modulepackage
0.8.0
Repository: https://github.com/pires/go-proxyproto.git
Documentation: pkg.go.dev

# README

go-proxyproto

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.

Installation

$ go get -u github.com/pires/go-proxyproto

Usage

Client

package main

import (
	"io"
	"log"
	"net"

	proxyproto "github.com/pires/go-proxyproto"
)

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

func main() {
	// Dial some proxy listener e.g. https://github.com/mailgun/proxyproto
	target, err := net.ResolveTCPAddr("tcp", "127.0.0.1:2319")
	chkErr(err)

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

	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("10.1.1.1"),
			Port: 1000,
		},
		DestinationAddr: &net.TCPAddr{
			IP:   net.ParseIP("20.2.2.2"),
			Port: 2000,
		},
	}
	// After the connection was created write the proxy headers first
	_, err = header.WriteTo(conn)
	chkErr(err)
	// Then your data... e.g.:
	_, err = io.WriteString(conn, "HELO")
	chkErr(err)
}

Server

package main

import (
	"log"
	"net"

	proxyproto "github.com/pires/go-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"

	"github.com/pires/go-proxyproto"
)

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

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

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

	server.Serve(proxyListener)
}

Special notes

AWS

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.

# Packages

No description provided by the author
No description provided by the author
No description provided by the author

# Functions

HeaderProxyFromAddrs creates a new PROXY header from a source and a destination address.
IgnoreProxyHeaderNotOnInterface retuns a ConnPolicyFunc which can be used to decide whether to use or ignore PROXY headers depending on the connection being made on a specific interface.
JoinTLVs joins multiple Type-Length-Value records.
LaxWhiteListPolicy returns a PolicyFunc which decides whether the upstream ip is allowed to send a proxy header based on a list of allowed IP addresses and IP ranges.
MustLaxWhiteListPolicy returns a LaxWhiteListPolicy but will panic if one of the provided IP addresses or IP ranges is invalid.
MustStrictWhiteListPolicy returns a StrictWhiteListPolicy but will panic if one of the provided IP addresses or IP ranges is invalid.
NewConn is used to wrap a net.Conn that may be speaking the proxy protocol into a proxyproto.Conn.
Read identifies the proxy protocol version and reads the remaining of the header, accordingly.
ReadTimeout acts as Read but takes a timeout.
SetReadHeaderTimeout sets the readHeaderTimeout for a connection when passed as option to NewConn().
SkipProxyHeaderForCIDR returns a PolicyFunc which can be used to accept a connection from a skipHeaderCIDR without requiring a PROXY header, e.g.
SplitTLVs splits the Type-Length-Value vector, returns the vector or an error.
StrictWhiteListPolicy returns a PolicyFunc which decides whether the upstream ip is allowed to send a proxy header based on a list of allowed IP addresses and IP ranges.
ValidateHeader adds given validator for proxy headers to a connection when passed as option to NewConn().
WithPolicy adds given policy to a connection when passed as option to NewConn().

# Constants

IGNORE address from PROXY header, but accept connection.
LOCAL represents the LOCAL command in v2 or UNKNOWN transport in v1, in which case no address information is expected.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Section 2.2.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Section 2.2.7, reserved types.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
PROXY represents the PROXY command in v2 or transport is not UNKNOWN in v1, in which case valid local/remote address and port information is expected.
REJECT connection when PROXY header is sent Note: even though the first read on the connection returns an error if a PROXY header is present, subsequent reads do not.
REQUIRE connection to send PROXY header, reject if not present Note: even though the first read on the connection returns an error if a PROXY header is not present, subsequent reads do not.
SKIP accepts a connection without requiring the PROXY header Note: an example usage can be found in the SkipProxyHeaderForCIDR function.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
USE address from PROXY header.

# Variables

DefaultReadHeaderTimeout is how long header processing waits for header to be read from the wire, if Listener.ReaderHeaderTimeout is not set.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
ErrInvalidUpstream should be returned when an upstream connection address is not trusted, and therefore is invalid.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Protocol.
No description provided by the author

# Structs

Conn is used to wrap and underlying connection which may be speaking the Proxy Protocol.
ConnPolicyOptions contains the remote and local addresses of a connection.
Header is the placeholder for proxy protocol header.
Listener is used to wrap an underlying listener, whose connections may be using the HAProxy Proxy Protocol.
TLV is a uninterpreted Type-Length-Value for V2 protocol, see section 2.2.

# Type aliases

AddressFamilyAndProtocol represents address family and transport protocol.
ConnPolicyFunc can be used to decide whether to trust the PROXY info based on connection policy options.
Policy defines how a connection with a PROXY header address is treated.
PolicyFunc can be used to decide whether to trust the PROXY info from upstream.
PP2Type is the proxy protocol v2 type.
ProtocolVersionAndCommand represents the command in proxy protocol v2.
Validator receives a header and decides whether it is a valid one In case the header is not deemed valid it should return an error.