-- Leo's gemini proxy

-- Connecting to michaelnordmeyer.com:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini;lang=en-US

Enabling HTTP/3 (QUIC) on nginx


I decided to enable experimental HTTP/3 support for nginx, after it was mainlined at the end of May, and because most mainstream browsers support HTTP/3. It is quite easy, if you know how to handle the tiny nginx footgun, the `add_header` directive.


First, you have to check if your nginx version > 1.25 has been built with HTTP/3 support. The one from nginx’s repository obviously has. `nginx -V` has to report `--with-http_v3_module`. Also make sure to allow port 443/UDP in your firewall.


To turn on HTTP/3 support, add to the `http` context of `nginx.conf`, if you want to enable it for the whole server. Otherwise add to the appropriate `server` context:


## NGX_HTTP_V3_MODULE https://nginx.org/en/docs/http/ngx_http_v3_module.html

http3 on;
http3_hq on;
quic_retry on;


## NGX_HTTP_SSL_MODULE https://nginx.org/en/docs/http/ngx_http_ssl_module.html

# Speeds-up HTTP/3.
# Requests sent within early data are subject to replay attacks.
# To protect against such attacks at the application layer, the $ssl_early_data variable should be used.
# https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
ssl_early_data on;

ssl_protocols TLSv1.2 TLSv1.3;

TLSv1.3 has to be turned on as well. Notice the reply attack possibility, if nginx proxies your app.


In the appropriate `server` context, add the following to enable the announcement of HTTP/3 support, and replace the old HTTP/2 listen directives for HTTPS connections:


listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic;
listen [::]:443 quic;

add_header Alt-Svc 'h3=":$server_port"; ma=86400' always;

The maximum age is set to the default 864000 seconds, which is 24 hours


Optionally add another header, if you want to see the used protocol in the response.


add_header X-protocol $server_protocol always;

This is pretty straight-forward, but you have to be aware of the innocuous `add_header` directive. It can be put in the context of `http`, `server`, `location`, and `if` in `location`. “These directives are inherited from the previous configuration level if and only if there are no add_header directives defined on the current level”, to quote the nginx docs.


That means, putting them in the central `http` context in `nginx.conf` will eventually fail, because you should always add `Content-Security-Policy` header to your sites, which might be different for different sites, and therefore have to be added to `server` contexts.


So, put all your `add_header` directives in your respective server contexts, preferably by using one or more `include`, and include in every `location` where you have to add extra headers.


To test if your site has HTTP/3 support, go to


HTTP/3 Check

-- Response ended

-- Page fetched on Tue May 21 12:20:43 2024