# HTTP transport, TLS, HTTP/2 and HTTP/3 RustProxy distinguishes **frontend** client protocols from the **upstream** protocol used to contact an application. Selecting HTTP/3 on a listener does not require an HTTP/3 backend. ## Frontend listeners - **HTTP/1.1:** default plaintext HTTP and standard Upgrade-based WebSocket support where enabled. - **HTTPS / HTTP/2:** TLS listeners may negotiate HTTP/2 and HTTP/1.1. Settings include H2 idle/connection-drain controls. - **HTTP/3 (QUIC):** optional UDP transport on an enabled TLS frontend, using the listener certificate and supported H3 settings. The host firewall/NAT must pass UDP on the actual HTTPS port, not only TCP/443. Browsers can fall back to H2/H1 when H3 is unavailable. - **H2C:** explicit cleartext HTTP/2 capability only where the listener or upstream policy enables it; it is not ordinary browser HTTPS. Transport settings attach to **named listeners**, and a Vhost must select the appropriate listener IDs. Addresses locked by CLI/systemd startup cannot be rewritten from the panel. Changing a listener bind or startup-owned TLS option may require a restart. ### Saving HTTP/3 settings - **Immediately after a successful panel save:** H2/H1 TLS responses use the saved `alt_svc_max_age` (`Alt-Svc`), provided a matching UDP listener was actually bound at startup. Origin `Alt-Svc` never passes through. The value `0` publishes `ma=0`. - **Disabling H3 on a Vhost or an existing listener:** new H1/H2 responses publish `Alt-Svc: clear` to remove the browser's cached alternative service. A browser may keep an established QUIC connection until it closes; `clear` does not forcibly terminate it. - **For new QUIC connections only:** updates to `max_concurrent_bidistream`, `max_concurrent_unistream`, `max_idle_timeout` and reductions to `max_concurrent_connections` are applied without restart. Existing QUIC connections keep their negotiated limits. If no existing UDP socket matches the saved listener address, no H3 is advertised or accepted on the old address. - **Restart needed:** UDP listener enable/disable, changing IP/port/TLS properties, UDP socket buffer sizes, changes to H1/H2 listener settings and increasing `max_concurrent_connections` above the startup bound. The live listener status continues to show `restart_required` for these cases. After a restart, the new connection cap can take effect. ### QUIC UDP socket buffers (0.34.3) The HTTP/3 settings of each TLS listener include: | Parameter | Default | Accepted values | Takes effect | |---|---:|---|---| | `udp_receive_buffer_bytes` | 4194304 (4 MiB) | `0` (OS default) or 65536–16777216 | On listener restart | | `udp_send_buffer_bytes` | 4194304 (4 MiB) | `0` (OS default) or 65536–16777216 | On listener restart | Use **Settings → HTTP/3** to edit these as whole MiB values (0–16); the JSON API stores bytes. No global `net.core.*_default` adjustment is necessary: RustProxy explicitly sets its own socket options. An OS limit may still clamp the request. Linux doubles `setsockopt(SO_RCVBUF / SO_SNDBUF)` values for bookkeeping; RustProxy targets the final effective size shown as `rb`/`tb` in `ss`. For a 4 MiB target on Debian/Linux, if the default `net.core.rmem_max` or `net.core.wmem_max` prevents reaching the target, set adequate socket *maxima* after reviewing host memory constraints, for example: ```bash sudo sysctl -w net.core.rmem_max=8388608 sudo sysctl -w net.core.wmem_max=8388608 sudo systemctl restart rustproxy.service sudo ss -uapm | grep -A1 rust-proxy ``` Read the `HTTP/3 UDP effective socket buffers` startup log message. `ss` should show approximately `rb4194304,tb4194304` (or larger if the OS adjusts values) when the requested size is granted. Changes to the OS maxima alone do not resize an existing socket; the configured buffer size is applied when a QUIC listener starts. High default/maxima for every program are not recommended as a substitute for explicit per-socket configuration. No specific throughput gain is guaranteed; compare H2/H3 at matched traffic before/after. ## Backend protocol selection | Backend mode | HTTPS origin | Plain HTTP origin | |---|---|---| | `http1` | HTTP/1.1 | HTTP/1.1 | | `auto` | ALPN H2 or H1 | HTTP/1.1 | | Legacy `http2` | Compatible ALPN H2/H1 | H2C | | Strict `h2` | Requires H2 | Requires H2C | WebSockets normally use HTTP/1.1 Upgrade. HTTP/2/HTTP/3 client requests can still reach HTTP/1.1 backends when the selected bridge/path is supported; do not assume the frontend and origin protocol always match. HTTP/2 GOAWAY, H3 stream cancellation and retries are constrained to safe lifecycle cases. Use backend protocol telemetry and logs when diagnosing negotiation. ## TLS and trust Public HTTPS requires a correct certificate with hostname coverage. Administration TLS is separate. Backend `https://` encrypts traffic, but **upstream certificate verification is opt-in by default** in the current backend model; enable it and specify CA/name where needed. Private/loopback addresses and routing to a local RustProxy listener require explicit risk overrides. ## Timeouts, request bodies and streaming Idle/read/connect/response-header timeouts and backend connection pools are configurable. A response may stream after its headers have arrived; response-header metrics are not full-body duration. WebSockets and Streams have separate idle lifetimes and should be tested with the actual application. RustProxy rejects suspicious ambiguous request targets rather than normalizing them into potentially unsafe backend paths. ## Troubleshooting - **HTTPS works but H3 does not:** check UDP firewall/NAT, listener H3 enablement, TLS certificate, network middleboxes and actual browser negotiation. - **502 / protocol error to backend:** verify origin supports selected `auto`, `http2`, `h2` or H2C mode and the correct TLS hostname/verification policy. - **WebSocket disconnects:** enable websocket forwarding in the Vhost and ensure idle limits/proxy/backend are compatible. - **Unexpected HTTP→HTTPS redirect:** inspect Vhost `force_ssl`, selected listeners and actual public scheme. For listener configuration see [Configuration](CONFIGURATION.md); for safer deployment see [Security](SECURITY.md).