Documentation
¶
Overview ¶
Package edgeproxy is the chassis side of the trusted-edge contract:
trusted edge | PROXY v2 (+ AUTHORITY, SSL, ALPN TLVs) → TCP inlet
An edge that terminates TLS in front of the chassis (Caddy today) has already seen everything an inlet would learn from its own handshake — the real client address, the SNI hostname, the negotiated ALPN and TLS version. It hands them over in the PROXY protocol header it writes before the first byte of the stream, and this package is the one place that header is accepted and read.
The trust boundary is the peer address: a header is REQUIRED from the operator's trusted CIDRs and never honoured from anyone else (their connection is served as-is, header bytes and all). So a parsed header is proof the connection came through the front door, and its contents are chassis facts, not client input.
An HTTP head behind HTTP proxies gets the same fact from the same boundary, in a header instead (clientip.go): X-Forwarded-For counts only when the socket peer is one of those CIDRs.
Leaf package: no chassis imports, so any head (imap, tcp, web, …) can use it.
Index ¶
Constants ¶
const DefaultHeaderTimeout = 5 * time.Second
DefaultHeaderTimeout bounds how long a trusted peer may take to send its header. The edge writes it with the first packet; anything slower is a broken or hostile peer holding a socket open.
Variables ¶
var ErrNoHeader = errors.New("edgeproxy: trusted peer sent no valid PROXY header")
ErrNoHeader is Read's answer for a trusted peer that sent no (or an unparseable) PROXY header. The stream is unusable — every read on it fails — so the caller closes.
Functions ¶
func Fronted ¶
Fronted reports whether a trusted edge presented a PROXY header on conn — the cheap form of Read for heads that only need the yes/no.
func ParseTrusted ¶
ParseTrusted turns operator entries (CIDRs, or bare IPs meaning /32 or /128) into networks. Blank entries are dropped; entries that parse as neither come back in bad so the caller decides whether that is a warning (imap, web) or a refusal to start (tcp).
An entry may itself hold several, separated by commas or spaces. A list flag read from one environment variable arrives split one way or the other depending on who wrote it, and the wrong guess used to leave "a,b" as one unparseable entry — a trust list that silently trusted nobody.
func Wrap ¶
Wrap makes ln accept a PROXY header (v1 or v2) from trusted peers: REQUIRE from inside trusted, SKIP for everyone else — their connection is handed back untouched and a header they send is just stream bytes. Wrap BEFORE tls.NewListener: the header precedes the handshake. headerTimeout <= 0 means DefaultHeaderTimeout. With no trusted networks ln is returned as is.
Types ¶
type Clients ¶
type Clients struct {
// contains filtered or unexported fields
}
Clients resolves the client address of HTTP requests for one trust list. The zero value and nil trust nobody: the client is the socket peer.
func NewClients ¶
NewClients builds a resolver from operator entries (--web-trusted-proxies; see ParseTrusted for the forms). Unparseable entries come back in bad and are not trusted.
func (*Clients) IP ¶
IP returns the address of the client that sent r, without a port.
- The peer is not a trusted proxy (or none are configured): the peer. X-Forwarded-For is not read.
- The peer is a trusted proxy: the first X-Forwarded-For address from the right that is not a trusted proxy.
- Every address in it is a trusted proxy — the request began inside, say one app calling another: the leftmost, the one that began it.
- The header is missing, or the address a proxy recorded cannot be read ("unknown", an obfuscated node name): the peer. Nothing to the left of an unreadable hop is trustworthy, and the proxy's own address is the conservative key for a throttle — shared, never forgeable.
type Facts ¶
type Facts struct {
Present bool
// The real client and the address it dialled, from the header. The
// wrapped conn's RemoteAddr/LocalAddr already report these too.
ClientIP string
ClientPort int
LocalIP string
LocalPort int
Authority string // PP2_TYPE_AUTHORITY: the hostname the client asked for (SNI), raw
ALPN string // PP2_TYPE_ALPN
TLS bool // PP2_TYPE_SSL says the client leg was TLS
TLSVersion string // PP2_SUBTYPE_SSL_VERSION, in crypto/tls spelling ("TLS 1.3")
}
Facts is what a trusted edge said about one connection. The zero value (Present false) means nobody vouched for it: an untrusted peer, an unwrapped listener, or the edge's own LOCAL health probe.