proxyprotocol

package
v0.18.3 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package proxyprotocol reads the HAProxy PROXY protocol (v1 and v2) header from accepted connections and rewrites their RemoteAddr to the real client address. Mount it on a Server with Server.ModifyConnection so that middleware reading the client IP — ratelimit, waf, logger, and the X-Forwarded-* trust logic — sees the actual client instead of the L4 load balancer in front.

m := proxyprotocol.New("10.0.0.0/8") // your load balancer's range
s := parapet.NewFrontend()
s.ModifyConnection(m.ModifyConnection)

Only a connection whose immediate peer is within the trusted CIDRs may set a client address; a direct attacker outside them is passed through untouched and cannot spoof a client IP. The header is parsed lazily on the connection's first read, off the accept loop.

Index

Examples

Constants

View Source
const DefaultHeaderTimeout = 10 * time.Second

DefaultHeaderTimeout bounds how long a trusted connection has to deliver its PROXY header before the read fails.

Variables

This section is empty.

Functions

This section is empty.

Types

type Modifier

type Modifier struct {

	// Require rejects a trusted connection that does not begin with a valid
	// PROXY header (its first read fails, so the server drops it). By default a
	// trusted connection without a header is passed through with its real peer
	// address — enable Require when every connection from the load balancer is
	// guaranteed to carry the header.
	Require bool

	// HeaderTimeout bounds reading the PROXY header from a trusted connection.
	// Zero uses DefaultHeaderTimeout; a negative value disables the deadline.
	HeaderTimeout time.Duration
	// contains filtered or unexported fields
}

Modifier wraps accepted connections to honor the PROXY protocol. Create it with New and pass its ModifyConnection method to Server.ModifyConnection.

Example (Require)

Require every trusted connection to carry a PROXY header — appropriate when the balancer always prepends one. A trusted connection without a header is rejected instead of served with the balancer's address.

package main

import (
	"github.com/moonrhythm/parapet"
	"github.com/moonrhythm/parapet/pkg/proxyprotocol"
)

func main() {
	pp := proxyprotocol.New("10.0.0.0/8")
	pp.Require = true

	s := parapet.NewFrontend()
	s.ModifyConnection(pp.ModifyConnection)
}

func New

func New(trustedCIDRs ...string) *Modifier

New creates a Modifier that trusts the given load-balancer CIDRs to supply a client address via the PROXY header. It panics on an invalid CIDR, matching parapet's fail-fast trust configuration — a silently-empty trust list is a security footgun.

With no CIDRs every peer is trusted; use that only when the listener is reachable exclusively through your load balancer.

Example

Recover the real client IP behind an L4 load balancer that speaks the PROXY protocol. Only connections from the balancer's range may set a client address.

package main

import (
	"github.com/moonrhythm/parapet"
	"github.com/moonrhythm/parapet/pkg/proxyprotocol"
)

func main() {
	pp := proxyprotocol.New("10.0.0.0/8") // your load balancer's CIDR(s)

	s := parapet.NewFrontend()
	s.ModifyConnection(pp.ModifyConnection)
	// s.Use(...) the rest of the chain; ratelimit/waf/logger now see the client.
}

func (*Modifier) ModifyConnection

func (m *Modifier) ModifyConnection(c net.Conn) net.Conn

ModifyConnection wraps c so its PROXY header (if any) is parsed on first read. Pass it to Server.ModifyConnection. It performs no I/O itself, so it never blocks the accept loop.

Jump to

Keyboard shortcuts

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