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 ¶
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)
}
Output:
func New ¶
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.
}
Output: