proxyproto

package module
v0.0.0-...-666ea95 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 16, 2020 License: Apache-2.0 Imports: 13 Imported by: 0

README

DO NOT USE - Temporary Fork

Wait until https://github.com/pires/go-proxyproto/pull/9 is merged. This fork will be deleted.

go-proxyproto

Build 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 (TODO)
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())
}

Documentation

http://godoc.org/github.com/pires/go-proxyproto

Documentation

Overview

Package proxyproto implements Proxy Protocol (v1 and v2) parser and writer, as per specification: http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt

Index

Constants

View Source
const (
	UNSPEC       = '\x00'
	TCPv4        = '\x11'
	UDPv4        = '\x12'
	TCPv6        = '\x21'
	UDPv6        = '\x22'
	UnixStream   = '\x31'
	UnixDatagram = '\x32'
)
View Source
const (
	// Section 2.2
	PP2_TYPE_ALPN           PP2Type = 0x01
	PP2_TYPE_AUTHORITY              = 0x02
	PP2_TYPE_CRC32C                 = 0x03
	PP2_TYPE_NOOP                   = 0x04
	PP2_TYPE_SSL                    = 0x20
	PP2_SUBTYPE_SSL_VERSION         = 0x21
	PP2_SUBTYPE_SSL_CN              = 0x22
	PP2_SUBTYPE_SSL_CIPHER          = 0x23
	PP2_SUBTYPE_SSL_SIG_ALG         = 0x24
	PP2_SUBTYPE_SSL_KEY_ALG         = 0x25
	PP2_TYPE_NETNS                  = 0x30

	// Section 2.2.7, reserved types
	PP2_TYPE_MIN_CUSTOM     = 0xE0
	PP2_TYPE_MAX_CUSTOM     = 0xEF
	PP2_TYPE_MIN_EXPERIMENT = 0xF0
	PP2_TYPE_MAX_EXPERIMENT = 0xF7
	PP2_TYPE_MIN_FUTURE     = 0xF8
	PP2_TYPE_MAX_FUTURE     = 0xFF

	// Amazon's extension
	PP2_TYPE_AWS            = 0xEA
	PP2_SUBTYPE_AWS_VPCE_ID = 0x01

	// pp2_tlv_ssl.client  bit fields
	PP2_BITFIELD_CLIENT_SSL       uint8 = 0x01
	PP2_BITFIELD_CLIENT_CERT_CONN       = 0x02
	PP2_BITFIELD_CLIENT_CERT_SESS       = 0x04
)
View Source
const (
	CRLF      = "\r\n"
	SEPARATOR = " "
)
View Source
const (
	LOCAL = '\x20'
	PROXY = '\x21'
)

Variables

View Source
var (
	// Protocol
	SIGV1 = []byte{'\x50', '\x52', '\x4F', '\x58', '\x59'}
	SIGV2 = []byte{'\x0D', '\x0A', '\x0D', '\x0A', '\x00', '\x0D', '\x0A', '\x51', '\x55', '\x49', '\x54', '\x0A'}

	ErrCantReadProtocolVersionAndCommand    = errors.New("Can't read proxy protocol version and command")
	ErrCantReadAddressFamilyAndProtocol     = errors.New("Can't read address family or protocol")
	ErrCantReadLength                       = errors.New("Can't read length")
	ErrCantResolveSourceUnixAddress         = errors.New("Can't resolve source Unix address")
	ErrCantResolveDestinationUnixAddress    = errors.New("Can't resolve destination Unix address")
	ErrNoProxyProtocol                      = errors.New("Proxy protocol signature not present")
	ErrUnknownProxyProtocolVersion          = errors.New("Unknown proxy protocol version")
	ErrUnsupportedProtocolVersionAndCommand = errors.New("Unsupported proxy protocol version and command")
	ErrUnsupportedAddressFamilyAndProtocol  = errors.New("Unsupported address family and protocol")
	ErrInvalidLength                        = errors.New("Invalid length")
	ErrInvalidAddress                       = errors.New("Invalid address")
	ErrInvalidPortNumber                    = errors.New("Invalid port number")
)
View Source
var (
	ErrTruncatedTLV    = errors.New("Truncated TLV")
	ErrMalformedTLV    = errors.New("Malformed TLV Value")
	ErrIncompatibleTLV = errors.New("Incompatible TLV type")
)

Functions

func AWSVPECID

func AWSVPECID(tlvs []TLV) (string, bool)

AWSVPCEID returns the first AWS VPC ID in the TLV if it exists and is well-formed and a bool indicating one was found.

Types

type AddressFamilyAndProtocol

type AddressFamilyAndProtocol byte

AddressFamilyAndProtocol represents address family and transport protocol.

func (AddressFamilyAndProtocol) IsDatagram

func (ap AddressFamilyAndProtocol) IsDatagram() bool

IsDatagram returns true if the transport protocol is UDP or DGRAM (SOCK_DGRAM), false otherwise.

func (AddressFamilyAndProtocol) IsIPv4

func (ap AddressFamilyAndProtocol) IsIPv4() bool

IsIPv4 returns true if the address family is IPv4 (AF_INET4), false otherwise.

func (AddressFamilyAndProtocol) IsIPv6

func (ap AddressFamilyAndProtocol) IsIPv6() bool

IsIPv6 returns true if the address family is IPv6 (AF_INET6), false otherwise.

func (AddressFamilyAndProtocol) IsStream

func (ap AddressFamilyAndProtocol) IsStream() bool

IsStream returns true if the transport protocol is TCP or STREAM (SOCK_STREAM), false otherwise.

func (AddressFamilyAndProtocol) IsUnix

func (ap AddressFamilyAndProtocol) IsUnix() bool

IsUnix returns true if the address family is UNIX (AF_UNIX), false otherwise.

func (AddressFamilyAndProtocol) IsUnspec

func (ap AddressFamilyAndProtocol) IsUnspec() bool

IsUnspec returns true if the transport protocol or address family is unspecified, false otherwise.

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is used to wrap and underlying connection which may be speaking the Proxy Protocol. If it is, the RemoteAddr() will return the address of the client instead of the proxy address.

func NewConn

func NewConn(conn net.Conn, timeout time.Duration) *Conn

NewConn is used to wrap a net.Conn that may be speaking the proxy protocol into a proxyproto.Conn

func (*Conn) Close

func (p *Conn) Close() error

Close wraps original conn.Close

func (*Conn) LocalAddr

func (p *Conn) LocalAddr() net.Addr

LocalAddr returns the address of the server if the proxy protocol is being used, otherwise just returns the address of the socket server.

func (*Conn) Read

func (p *Conn) Read(b []byte) (int, error)

Read is check for the proxy protocol header when doing the initial scan. If there is an error parsing the header, it is returned and the socket is closed.

func (*Conn) RemoteAddr

func (p *Conn) RemoteAddr() net.Addr

RemoteAddr returns the address of the client if the proxy protocol is being used, otherwise just returns the address of the socket peer.

func (*Conn) SetDeadline

func (p *Conn) SetDeadline(t time.Time) error

SetDeadline wraps original conn.SetDeadline

func (*Conn) SetReadDeadline

func (p *Conn) SetReadDeadline(t time.Time) error

SetReadDeadline wraps original conn.SetReadDeadline

func (*Conn) SetWriteDeadline

func (p *Conn) SetWriteDeadline(t time.Time) error

SetWriteDeadline wraps original conn.SetWriteDeadline

func (*Conn) Write

func (p *Conn) Write(b []byte) (int, error)

Write wraps original conn.Write

type Header struct {
	Version            byte
	Command            ProtocolVersionAndCommand
	TransportProtocol  AddressFamilyAndProtocol
	SourceAddress      net.IP
	DestinationAddress net.IP
	SourcePort         uint16
	DestinationPort    uint16
	// contains filtered or unexported fields
}

Header is the placeholder for proxy protocol header.

func Read

func Read(reader *bufio.Reader) (*Header, error)

Read identifies the proxy protocol version and reads the remaining of the header, accordingly.

If proxy protocol header signature is not present, the reader buffer remains untouched and is safe for reading outside of this code.

If proxy protocol header signature is present but an error is raised while processing the remaining header, assume the reader buffer to be in a corrupt state. Also, this operation will block until enough bytes are available for peeking.

func ReadTimeout

func ReadTimeout(reader *bufio.Reader, timeout time.Duration) (*Header, error)

ReadTimeout acts as Read but takes a timeout. If that timeout is reached, it's assumed there's no proxy protocol header.

func (*Header) EqualTo

func (header *Header) EqualTo(otherHeader *Header) bool

EqualTo returns true if headers are equivalent, false otherwise. Deprecated: use EqualsTo instead. This method will eventually be removed.

func (*Header) EqualsTo

func (header *Header) EqualsTo(otherHeader *Header) bool

EqualsTo returns true if headers are equivalent, false otherwise.

func (*Header) Format

func (header *Header) Format() ([]byte, error)

Format renders a proxy protocol header in a format to write over the wire.

func (*Header) LocalAddr

func (header *Header) LocalAddr() net.Addr

LocalAddr returns the address of the local endpoint of the connection.

func (*Header) RemoteAddr

func (header *Header) RemoteAddr() net.Addr

RemoteAddr returns the address of the remote endpoint of the connection.

func (*Header) TLVs

func (header *Header) TLVs() ([]TLV, error)

TLVs returns the TLVs stored into this header, if they exist. TLVs are optional for v2 of the protocol.

func (*Header) WriteTo

func (header *Header) WriteTo(w io.Writer) (int64, error)

WriteTo renders a proxy protocol header in a format and writes it to an io.Writer.

type Listener

type Listener struct {
	Listener           net.Listener
	ProxyHeaderTimeout time.Duration
}

Listener is used to wrap an underlying listener, whose connections may be using the HAProxy Proxy Protocol. If the connection is using the protocol, the RemoteAddr() will return the correct client address.

Optionally define ProxyHeaderTimeout to set a maximum time to receive the Proxy Protocol Header. Zero means no timeout.

func (*Listener) Accept

func (p *Listener) Accept() (net.Conn, error)

Accept waits for and returns the next connection to the listener.

func (*Listener) Addr

func (p *Listener) Addr() net.Addr

Addr returns the underlying listener's network address.

func (*Listener) Close

func (p *Listener) Close() error

Close closes the underlying listener.

type PP2SSL

type PP2SSL struct {
	Client uint8 // The <client> field is made of a bit field from the following values,
	// indicating which element is present: PP2_BITFIELD_CLIENT_SSL,
	// PP2_BITFIELD_CLIENT_CERT_CONN, PP2_BITFIELD_CLIENT_CERT_SESS
	Verify uint32 // Verify will be zero if the client presented a certificate
	// and it was successfully verified, and non-zero otherwise.
	TLV []TLV
}

2.2.5. The PP2_TYPE_SSL type and subtypes

struct pp2_tlv_ssl {
        uint8_t  client;
        uint32_t verify;
        struct pp2_tlv sub_tlv[0];
};

func SSL

func SSL(tlvs []TLV) (PP2SSL, bool)

SSL returns the first PP2SSL if it exists and is well formed as well as bool indicating if it was found.

func (PP2SSL) ClientCN

func (s PP2SSL) ClientCN() (string, bool)

ClientCN returns the string representation (in UTF8) of the Common Name field (OID: 2.5.4.3) of the client certificate's Distinguished Name and whether that extension exists.

func (PP2SSL) ClientCertConn

func (s PP2SSL) ClientCertConn() bool

ClientCertConn indicates that the client provided a certificate over the current connection.

func (PP2SSL) ClientCertSess

func (s PP2SSL) ClientCertSess() bool

ClientCertSess indicates that the client provided a certificate at least once over the TLS session this connection belongs to.

func (PP2SSL) ClientSSL

func (s PP2SSL) ClientSSL() bool

ClientSSL indicates that the client connected over SSL/TLS. When true, SSLVersion will return the version.

func (PP2SSL) SSLVersion

func (s PP2SSL) SSLVersion() (string, bool)

SSLVersion returns the US-ASCII string representation of the TLS version and whether that extension exists.

func (PP2SSL) Verified

func (s PP2SSL) Verified() bool

Verified is true if the client presented a certificate and it was successfully verified

type PP2Type

type PP2Type byte

PP2Type is the proxy protocol v2 type

func (PP2Type) AWS

func (p PP2Type) AWS() bool

AWS is true if the type is the AWS extension

func (PP2Type) App

func (p PP2Type) App() bool

App is true if the type is reserved for application specific data, see section 2.2.7

func (PP2Type) Experiment

func (p PP2Type) Experiment() bool

Experiment is true if the type is reserved for temporary experimental use by application developers, see section 2.2.7

func (PP2Type) Future

func (p PP2Type) Future() bool

Future is true is the type is reserved for future use, see section 2.2.7

func (PP2Type) Registered

func (p PP2Type) Registered() bool

Registered is true if the type is registered in the spec, see section 2.2

func (PP2Type) SSL

func (p PP2Type) SSL() bool

SSL is true if the type is SSL

func (PP2Type) Spec

func (p PP2Type) Spec() bool

Spec is true if the type is covered by the spec, see section 2.2 and 2.2.7

type ProtocolVersionAndCommand

type ProtocolVersionAndCommand byte

ProtocolVersionAndCommand represents proxy protocol version and command.

func (ProtocolVersionAndCommand) IsLocal

func (pvc ProtocolVersionAndCommand) IsLocal() bool

IsLocal returns true if the protocol version is \x2 and command is LOCAL, false otherwise.

func (ProtocolVersionAndCommand) IsProxy

func (pvc ProtocolVersionAndCommand) IsProxy() bool

IsProxy returns true if the protocol version is \x2 and command is PROXY, false otherwise.

func (ProtocolVersionAndCommand) IsUnspec

func (pvc ProtocolVersionAndCommand) IsUnspec() bool

IsUnspec returns true if the protocol version or command is unspecified, false otherwise.

type TLV

type TLV struct {
	Type   PP2Type
	Length int
	Value  []byte
}

TLV is a uninterpreted Type-Length-Value for V2 protocol, see section 2.2

func (TLV) AWSVPCEID

func (t TLV) AWSVPCEID() (string, error)

AWSVPCEID returns the vpc-id of an AWS VPC extension TLV or errors with ErrIncompatibleTLV or ErrMalformedTLV if it's the wrong TLV type or has a malformed VPC ID (containing chars other than 0-9, a-z, -)

func (TLV) AWSVPCEType

func (t TLV) AWSVPCEType() bool

AWSVPCEType is true if the TLV is an AWS extension with VPCE subtype

func (TLV) SSL

func (t TLV) SSL() (PP2SSL, error)

SSL returns the pp2_tlv_ssl from section 2.2.5 or errors with ErrIncompatibleTLV or ErrMalformedTLV

func (TLV) SSLType

func (t TLV) SSLType() bool

SSLType is true if the TLV is type SSL

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL