feat: support PROXY protocol v1 and v2 - #283
Conversation
There was a problem hiding this comment.
🔵 Needs a closer look
It introduces security-sensitive listener-wrapping and connection-admission behavior that warrants final human review despite tests and documentation updates.
Pull request overview
This PR adds first-class PROXY protocol v1/v2 support to the HTTP module by introducing explicit, per-listener configuration (plain HTTP vs HTTPS) and wrapping TCP listeners so client addresses can be derived from trusted PROXY headers before HTTP/TLS processing.
Changes:
- Introduces
proxy_protocolconfiguration for plain HTTP and HTTPS (with requiredtrusted_proxiesand default 5s header read timeout) plus schema/README documentation. - Adds a dedicated
servers/proxyprotocolwrapper built ongithub.com/pires/go-proxyprotowith validation and strict peer/header enforcement behavior. - Adds unit + integration tests covering header parsing, timeouts, untrusted peers, HTTP/HTTPS behavior, WebSockets, and PHP
REMOTE_ADDRpropagation.
File summaries
| File | Description |
|---|---|
| tests/proxy_protocol_test.go | End-to-end integration coverage (HTTP/HTTPS/h2c) verifying PROXY header behavior and address propagation. |
| tests/go.mod | Adds transitive module dependency bookkeeping for the test module. |
| tests/go.sum | Adds checksum entries for the new dependency in the test module. |
| servers/proxyprotocol/proxyprotocol.go | New PROXY protocol config + listener wrapper implementation and validation. |
| servers/proxyprotocol/proxyprotocol_test.go | Unit tests for config validation, header parsing/rewrites, timeouts, and trusted-peer enforcement. |
| servers/proxyprotocol/http_test.go | Behavior tests validating rejection semantics and compatibility with HTTP/TLS/WebSocket flows. |
| servers/https/https.go | Wraps the HTTPS listener with PROXY protocol support before ServeTLS and ensures listener closure on setup failures. |
| servers/https/https_test.go | Adds regression test ensuring listeners are closed on setup errors across proxy-protocol modes. |
| servers/https/config.go | Adds ssl.proxy_protocol config field and validates it against TLS/ACME enablement. |
| servers/https/config_test.go | Tests defaulting/validation for ssl.proxy_protocol, including default timeout behavior. |
| servers/http11/http.go | Wraps the plain HTTP listener with PROXY protocol support before serving. |
| schema.json | Adds proxy_protocol schema definitions and dependency constraints for plain HTTP + SSL. |
| README.md | Documents configuration, strict trust model, TLS ordering, and behavior notes/limits. |
| go.mod | Adds github.com/pires/go-proxyproto v0.15.0 dependency. |
| go.sum | Adds checksum entries for the new dependency. |
| config/config.go | Adds http.proxy_protocol to config and validates/initializes it during defaults init. |
Review details
- Files reviewed: 14/16 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #283 +/- ##
==========================================
+ Coverage 87.61% 88.34% +0.72%
==========================================
Files 28 29 +1
Lines 1292 1347 +55
==========================================
+ Hits 1132 1190 +58
+ Misses 160 157 -3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Summary
closes: roadrunner-server/roadrunner#937.
http.proxy_protocolandhttp.ssl.proxy_protocolsettings, with mandatory explicittrusted_proxiesIPs/CIDRs and a 5s default header timeout.go-proxyprotov0.15.0 for v1/v2 parsing. Accept TCP4/TCP6 metadata and valid UNKNOWN/LOCAL headers; leave TLVs opaque rather than treating them as TLS or authentication state.Scope
HTTP/1.1, h2c, HTTPS HTTP/2, and existing Go-middleware WebSocket upgrades retain their behavior. Omitted sections leave their listeners unchanged. FastCGI, HTTP/3, and CertMagic's temporary ACME challenge listeners are not wrapped; the ACME-configured application HTTPS listener is supported.
The README documents strict health-check requirements, connection-wide identity, forwarding-header trust, v1 fragmentation behavior, and the parser's 4096-byte v2 payload limit. RoadRunner's dependency bump and bundled schema update can follow the HTTP module release.