HTTP/3, pf and port redirection

I serve a website with Caddy from within a VNET jail. Instead of allowing the Caddy user (www) to bind to port 443, I use a redirect rule in pf:

Code:
pass in quick on $ext_if proto tcp from $lan_net to ($ext_if) port 443 rdr-to $caddyjail port 8443

Caddy supports HTTP/3 by default, and sends the following Alt-Svc header, pointing to the same port it listens on:

Code:
alt-svc: h3=":8443"; ma=2592000

But opening this UDP port in pf will not work when testing with curl ( --http3-only); the handshake times out. I need to redirect UDP, too:

Code:
pass in quick on $ext_if proto {tcp, udp} from $lan_net to ($ext_if) port 443 rdr-to $caddyjail port 8443

This works with curl. But it gets stranger: Safari succeeds using HTTP/3 without opening UDP port 443 (i.e. it seems to use port 8443 directly, based on the Alt-Svc header), but also with the second variant (UDP port 443 open, port 8443 closed).

Chrome and Firefox stick with HTTP/2, regardless of which UDP port is opened (443, 8443 or both).

So my questions are:
  • Why does curl ignore the port hint in the Alt-Svc header?
  • Why do two major browser ignore the Alt-Svc header altogether?
The webserver runs in my LAN, so delivery is fast (below 50ms). Could this be a factor for Chrome and Firefox?
 
Back
Top