proxyprotocol

package module
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: May 1, 2019 License: MIT Imports: 8 Imported by: 4

README

go-proxyprotocol

GoDoc Go Report Card Build Status

Golang package `github.com/c0va23/go-proxyprotocol' provide receiver for HA ProxyProtocol v1 and v2.

This package provides a wrapper for the interface net.Listener, which extracts remote and local address of the connection from the headers in the format HA proxyprotocol.

Usage example

package main

import (
	"fmt"
	"log"
	"net"
	"net/http"

	"github.com/c0va23/go-proxyprotocol"
)

func main() {
	rawList, _ := net.Listen("tcp", ":8080")

	list := proxyprotocol.
        NewDefaultListener(rawList).
        WithLogger(proxyprotocol.LoggerFunc(log.Printf))

	http.Serve(list, http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		log.Printf("Remote Addr: %s, URI: %s", req.RemoteAddr, req.RequestURI)
		fmt.Fprintf(res, "Hello, %s!\n", req.RemoteAddr)
	}))
}

DefaultListener try parse proxyprotocol v1 and v2 header. If header signature not recognized, then used raw connection.

If you want to use only proxy protocol V1 or v2 headers, you can initialize the listener as follows:

list := proxyprotocol.NewListener(rawList, proxyprotocol.TextHeaderParserBuilder)

Implementation status

Human-readable header format (Version 1)
  • UNKNOWN
  • IPv4
  • IPv6
Binary header format (version 2)
  • Unspec
  • TCP over IPv4
  • TCP over IPv6
  • UDP over IPv4
  • UDP over IPv6
  • Unix Stream
  • Unix Datagram

Documentation

Overview

Package proxyprotocol implement receiver for HA Proxy Protocol V1 and V2.

Proxy Protocol spec http://www.haproxy.org/download/2.0/doc/proxy-protocol.txt

This package provides a wrapper for the interface net.Listener, which extracts remote and local address of the connection from the headers in the format HA proxy protocol.

Index

Constants

View Source
const (
	BinaryVersion2    byte = 0x20
	BinaryVersionMask byte = 0xF0
)

BinaryVersion2 bits

View Source
const (
	BinaryCommandLocal byte = 0x00
	BinaryCommandProxy byte = 0x01
	BinaryCommandMask  byte = 0x0F
)

Commands

View Source
const (
	BinaryAFUnspec byte = 0x00
	BinaryAFInet   byte = 0x10
	BinaryAFInet6  byte = 0x20
	BinaryAFUnix   byte = 0x30
	BinaryAFMask   byte = 0xF0
)

Address families

View Source
const (
	BinaryTPUnspec byte = 0x00
	BinaryTPStream byte = 0x01
	BinaryTPDgram  byte = 0x02
	BinaryTPMask   byte = 0x0F
)

Transport protocols

View Source
const (
	TLVTypeNoop byte = 0x04
)

TLV types

Variables

View Source
var (
	BinarySignature    = []byte{0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A}
	BinarySignatureLen = len(BinarySignature)
)

BinarySignature is magic prefix for proxyprotocol Binary

View Source
var (
	BinaryProtocolUnspec       = BinaryAFUnspec | BinaryTPUnspec
	BinaryProtocolTCPoverIPv4  = BinaryAFInet | BinaryTPStream
	BinaryProtocolUDPoverIPv4  = BinaryAFInet | BinaryTPDgram
	BinaryProtocolTCPoverIPv6  = BinaryAFInet6 | BinaryTPStream
	BinaryProtocolUDPoverIPv6  = BinaryAFInet6 | BinaryTPDgram
	BinaryProtocolUnixStream   = BinaryAFUnix | BinaryTPStream
	BinaryProtocolUnixDatagram = BinaryAFUnix | BinaryTPDgram
)

Protocol variants

View Source
var (
	ErrUnknownVersion       = errors.New("unknown version")
	ErrUnknownCommand       = errors.New("unknown command")
	ErrUnexpectedAddressLen = errors.New("unexpected address length")
)

Errors

View Source
var (
	ErrInvalidSignature = errors.New("invalid signature")
	ErrUnknownProtocol  = errors.New("unknown protocol")
)

Shared HeaderParser errors

View Source
var (
	TextSignature = []byte("PROXY")
	TextSeparator = " "
	TextCR        = byte('\r')
	TextLF        = byte('\n')
	TextCRLF      = []byte{TextCR, TextLF}
)

TextSignature is prefix for proxyprotocol v1

View Source
var (
	TextProtocolIPv4    = "TCP4"
	TextProtocolIPv6    = "TCP6"
	TextProtocolUnknown = "UNKNOWN"
)

TextProtocol list

View Source
var (
	ErrInvalidAddressList = errors.New("invalid address list")
	ErrInvalidIP          = errors.New("invalid IP")
	ErrInvalidPort        = errors.New("invalid port")
)

Text protocol errors

View Source
var BinaryHeaderParserBuilder = HeaderParserBuilderFunc(func(logger Logger) HeaderParser {
	return NewBinaryHeaderParser(logger)
})

BinaryHeaderParserBuilder build BinaryHeaderParser

View Source
var (
	BinaryPortLen = 2
)

Expected address length

DefaultFallbackHeaderParserBuilder build FallbackHeaderParserBuilder with default HeaderParserList (TextHeaderParser, BinaryHeaderParser, StubHeaderParser)

View Source
var ErrInvalidHeader = errors.New("invalid header")

ErrInvalidHeader returned by FallbackHeaderParser when all headerParsers return ErrInvalidSignature

View Source
var StubHeaderParserBuilder = HeaderParserBuilderFunc(func(logger Logger) HeaderParser {
	return NewStubHeaderParser()
})

StubHeaderParserBuilder build StubHeaderParser

View Source
var TextHeaderParserBuilder = HeaderParserBuilderFunc(func(logger Logger) HeaderParser {
	return NewTextHeaderParser(logger)
})

TextHeaderParserBuilder build TextHeaderParser

Functions

func NewConn

func NewConn(conn net.Conn, logger Logger, headerParser HeaderParser, trustedAddr bool) net.Conn

NewConn create wrapper on net.Conn.

Types

type BinaryHeaderParser

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

BinaryHeaderParser parse proxyprotocol header from Reader

func NewBinaryHeaderParser

func NewBinaryHeaderParser(logger Logger) BinaryHeaderParser

NewBinaryHeaderParser construct BinaryHeaderParser

func (BinaryHeaderParser) Parse

func (parser BinaryHeaderParser) Parse(buf *bufio.Reader) (*Header, error)

Parse buffer

type Conn

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

Conn is wrapper on net.Conn with RemoteAddr() override.

On first call Read() or RemoteAddr() parse proxyprotocol header and store local and remote addresses.

func (*Conn) LocalAddr

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

LocalAddr proxy to conn.LocalAddr

func (*Conn) Read

func (conn *Conn) Read(buf []byte) (int, error)

Read on first call parse proxyprotocol header.

If header parser return error, then error stored and returned. Otherwise call Read on source connection.

Following calls of Read function check parse header error. If error not nil, then error returned. Otherwise called source "conn.Read".

func (*Conn) RemoteAddr

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

RemoteAddr on first call parse proxyprotocol header.

If header parser return header, then return source address from header. Otherwise return original source address.

type FallbackHeaderParser

type FallbackHeaderParser struct {
	Logger        Logger
	HeaderParsers []HeaderParser
}

FallbackHeaderParser iterate over HeaderParser until parser not return nil error.

func NewFallbackHeaderParser

func NewFallbackHeaderParser(logger Logger, headerParsers ...HeaderParser) FallbackHeaderParser

NewFallbackHeaderParser create new instance of FallbackHeaderParser

func (FallbackHeaderParser) Parse

func (parser FallbackHeaderParser) Parse(buf *bufio.Reader) (*Header, error)

Parse iterate over headerParsers call Parse().

If any parser return not nil or not ErrInvalidSignature error, then return its error.

If any parser return nil error, then return header.

If all parsers return error ErrInvalidSignature, then return ErrInvalidHeader.

type FallbackHeaderParserBuilder

type FallbackHeaderParserBuilder []HeaderParserBuilder

FallbackHeaderParserBuilder build FallbackHeaderParser

func NewFallbackHeaderParserBuilder

func NewFallbackHeaderParserBuilder(
	headerParserBuilders ...HeaderParserBuilder,
) FallbackHeaderParserBuilder

NewFallbackHeaderParserBuilder construct FallbackHeaderParserBuilder

func (FallbackHeaderParserBuilder) Build

func (headerParserBuilders FallbackHeaderParserBuilder) Build(logger Logger) HeaderParser

Build FallbackHeaderParser from headerParserBuilders

type FallbackLogger

type FallbackLogger struct {
	Logger
}

FallbackLogger wrap Logger or nil

func (FallbackLogger) Printf

func (wrapper FallbackLogger) Printf(format string, v ...interface{})

Printf call Printf on inner logger if it not nil

type Header struct {
	SrcAddr net.Addr
	DstAddr net.Addr
}

Header struct represent header parsing result

type HeaderParser

type HeaderParser interface {
	Parse(readBuf *bufio.Reader) (*Header, error)
}

HeaderParser describe interface for header parsers

type HeaderParserBuilder

type HeaderParserBuilder interface {
	Build(Logger) HeaderParser
}

HeaderParserBuilder build HeaderParser's

type HeaderParserBuilderFunc

type HeaderParserBuilderFunc func(logger Logger) HeaderParser

HeaderParserBuilderFunc wrap builder func into HeaderParserBuilder

func (HeaderParserBuilderFunc) Build

func (funcBuilder HeaderParserBuilderFunc) Build(logger Logger) HeaderParser

Build implement HeaderParserBuilder for build func

type Listener

Listener implement net.Listener

func NewDefaultListener

func NewDefaultListener(listener net.Listener) Listener

NewDefaultListener construct proxyprotocol.Listener from other net.Listener with DefaultFallbackHeaderParserBuilder.

func NewListener

func NewListener(listener net.Listener, headerParserBuilder HeaderParserBuilder) Listener

NewListener construct Listener

func (Listener) Accept

func (listener Listener) Accept() (net.Conn, error)

Accept implement net.Listener.Accept().

When listener have SourceChecker, then check source address. If source checker return error, then return error. If source checker return false, then return raw connection.

Otherwise connection wrapped into Conn with header parser.

func (Listener) WithHeaderParserBuilder

func (listener Listener) WithHeaderParserBuilder(headerParserBuilder HeaderParserBuilder) Listener

WithHeaderParserBuilder copy Listener and set HeaderParserBuilder. Can be used to disable or reorder HeaderParser's.

func (Listener) WithLogger

func (listener Listener) WithLogger(logger Logger) Listener

WithLogger copy Listener and set Logger

func (Listener) WithSourceChecker

func (listener Listener) WithSourceChecker(sourceChecker SourceChecker) Listener

WithSourceChecker copy Listener and set SourceChecker

type Logger

type Logger interface {
	Printf(format string, v ...interface{})
}

Logger interface

type LoggerFunc

type LoggerFunc func(format string, v ...interface{})

LoggerFunc wrap Printf-like function into proxyprotocol.Logger

func (LoggerFunc) Printf

func (logf LoggerFunc) Printf(format string, v ...interface{})

Printf call inner Printf-link function

type SourceChecker

type SourceChecker func(net.Addr) (bool, error)

SourceChecker check trusted address

type StubHeaderParser

type StubHeaderParser struct{}

StubHeaderParser always return nil Header

func NewStubHeaderParser

func NewStubHeaderParser() StubHeaderParser

NewStubHeaderParser construct StubHeaderParser

func (StubHeaderParser) Parse

func (parser StubHeaderParser) Parse(*bufio.Reader) (*Header, error)

Parse always return nil, nil

type TextHeaderParser

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

TextHeaderParser for proxyprotocol v1

func NewTextHeaderParser

func NewTextHeaderParser(logger Logger) TextHeaderParser

NewTextHeaderParser construct TextHeaderParser

func (TextHeaderParser) Parse

func (parser TextHeaderParser) Parse(buf *bufio.Reader) (*Header, error)

Parse proxyprotocol v1 header

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

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