rpxy behind rpxy-l4 #585
|
I'm trying to set up rpxy as "all-the-HTTP" TLS terminating server. Unfortunately, I must multiplex protocols on port 443, so I decided to use rpxy-l4 to do that. On the other hand I need to keep original client IPs for rpxy, so I decided to proxy Web traffic from rpxy-l4 using HAProxy PROXY protocol. To do so, I've enabled it in prxy's & l4 configuration: [experimental.tcp_recv_proxy_protocol]
trusted_proxies = ["127.0.0.1/32", "::1/128"][protocols."https"]
protocol = "tls"
target = ["localhost:2443"]
alpn = ["http/1.1", "acme-tls/1"]
tcp_send_proxy_protocol = "v2"On the third hand, I need to redirect all the plain HTTP to HTTPS, so to do that I need to have some server listening on TCP/80. I'm wonder how could I implement that with rpxy-l4/rpxy tandem? The first idea was to make rpxy-l4 to listen on TCP/443 (HTTPS) and UDP/443 (HTTP/3) and proxy to rpxy using PROXY protocol, and make rpxy to terminate TLS, renew ACME certs, and listen on TCP/80 for plain HTTP (on it's own) (with the sole purpose of redirecting to HTTPS). Unfortunately, this doesn't make it. Three problems there.
listen_port = 80
listen_port_tls = 2443
listen_address_v4 = ['127.0.0.1', 'a.b.c.d'] # a.b.c.d is real IP here
listen_address_v6 = ['::1', 'cafe:babe::1'] # as well IPv6 hereThis make rpxy to listen on localhost and public IP as well, while it needs to listen on public IPs only for plain HTTP on TCP/80. This compromises security as it enlarges attack surface. (Still I can ensure security through firewall, but...)
# TODO: Is it nice to have multiple listen ports?
listen_port = 443I'm wonder if this is ever achievable? What do you think? Some options I've thought about:
The problem that I'm thinking plain HTTP is required for ACME to work. Is that correct? I'm not much familiar with TLS-ALPN-01 challenge.
Any considerations are appreciated. 😊 |
Replies: 1 comment 4 replies
|
Thanks for the detailed writeup. You've already mapped the problem space accurately, down to reading the First the ACME concern, because I think it dissolves most of the tension: rpxy does not need plain HTTP on :80 for certificate issuance or renewal. It uses TLS-ALPN-01 (RFC 8737), not HTTP-01, which is exactly what the On the two rpxy limitations you hit (PROXY-protocol expectation and the shared listen address): I did look at per-listener configuration for these earlier and decided against it, and I'm not planning to add it for now, though if the internal architecture is ever reworked, it's something I'd revisit at that point. The reasoning behind that decision: That leaves the redirect, and my recommendation is one of two shapes:
On why I'd prefer two instances over a multi-port rpxy-l4: for TCP the difference is mostly config-table bookkeeping, since each accepted connection is an independent spliced pair. The real cost is on the UDP/QUIC side. UDP has no connection, so rpxy-l4 keeps its own flow table keyed on (client src, listen socket) -> upstream socket in order to demux return datagrams back to the correct client and the correct listener. Adding multiple listen ports multiplies that state along the listen-socket dimension. Socket lifecycle, timeouts, cleanup, and return-path demux all grow with it, which is a meaningful increase in live state and bug surface inside a single process. Splitting into separate instances collapses that dimension to a constant per process and lets OS process isolation handle the separation for free. Since rpxy-l4 is purely L4 and shares no cross-port state (no TLS termination, no cert cache — those live in rpxy), a second instance costs only one more config file and one more process; a systemd template unit makes the operational overhead negligible. That trade is clearly favorable for a 443+80 setup. Multi-port would only begin to pay off with many listen ports, which is not rpxy-l4's target shape. In short: keep rpxy on localhost behind rpxy-l4 with PROXY protocol, let TLS-ALPN-01 handle ACME on :443, and either drop :80 or give it its own rpxy-l4 instance. |
Thanks for the detailed writeup. You've already mapped the problem space accurately, down to reading the
listen_portTODO in rpxy-l4, so let me address each point directly.First the ACME concern, because I think it dissolves most of the tension: rpxy does not need plain HTTP on :80 for certificate issuance or renewal. It uses TLS-ALPN-01 (RFC 8737), not HTTP-01, which is exactly what the
acme-tls/1entry in your rpxy-l4alpnlist is for. The challenge completes entirely over :443: the ACME CA opens a TLS connection negotiating theacme-tls/1ALPN, and rpxy answers with a self-signed certificate carrying the key-authorization digest. In your topology this works as-is. rpxy-l4 sees theacm…