[Editor: NGINX now officially supports HTTP/3 with QUIC. It is available as part of NGINX 1.25.1 mainline version for open source users and NGINX Plus R30 for enterprise customers.]
[ngx_snippet name=’table-style-blog’]
We are pleased to announce that our preview implementation of NGINX support for QUIC+HTTP/3 is now available as prebuilt binary packages for two distributions:
The binaries are the latest deliverable from the quic branch of the separate nginx-quic repo which hosts the preview implementation. As has been the case since we began work on QUIC+HTTP/3 in NGINX, you can still download and build NGINX Open Source with QUIC+HTTP/3 and a choice of SSL/TLS libraries that support QUIC. While the code is labeled experimental, several community members have reported that they are successfully using nginx-quic in production.
Our main motivation for releasing prebuilt binaries is to make it faster and easier to test NGINX with QUIC+HTTP/3. The binaries eliminate the need to compile from source and can be installed using standard package management tools.
At the time of writing, the de facto standard for open source SSL/TLS, OpenSSL, does not support QUIC. We therefore build the binary distributions with a quictls library package, which is installed automatically as a dependency. We selected quictls because it currently represents the best mix of stability, compatibility, and features.
Installation instructions for the binary distribution are available at the NGINX QUIC website.
There are several new directives for configuring NGINX for QUIC+HTTP/3, but it’s easy to combine them with directives for HTTP/1.1 and HTTP/2 in existing virtual server (server{}
) configuration blocks.
For the most basic functional configuration, all you have to do is include three directives in the server{}
(and child location{}
) block:
Directive | Description |
---|---|
listen 443 quic reuseport; | Add a new The |
ssl_protocols TLSv1.3; | Include TLS 1.3 in the list of accepted protocols, as required by QUIC. (This directive probably already exists in the configuration, but add it if necessary.) To support the full range of browsers, you probably also need to include older TLS versions as well. For information about browser support for TLS 1.3, see Can I use TLS 1.3? |
add_header Alt-Svc 'h3=":$server_port"; ma=86400'; | Include this directive to have NGINX add a response header telling the browser that an upgrade to QUIC is available and which port to connect on. By convention, the port (represented here by the The value of |
Here’s a sample server{}
block:
server { # for better compatibility we recommend
# using the same port number for QUIC and TCP
listen 443 quic reuseport; # QUIC
listen 443 ssl; # TCP
ssl_certificate certs/example.com.crt;
ssl_certificate_key certs/example.com.key;
ssl_protocols TLSv1.3;
location / {
# advertise that QUIC is available on the configured port
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
#proxy_pass <upstream_group>;
#root /<root_directory>;
}
}
There are several new optional HTTP/3‑related directives and variables (not shown in the snippet), including these:
$http3
– (Variable) Set to h3
when the request is sent during an HTTP/3 session (otherwise it’s an empty string).quic_retry
– (Directive) When set to on
, tells NGINX to send a QUIC retry message back to the requester specifying the new connection ID to use, for the purpose of validating the requester’s IP address. The QUIC retry packet partially compensates for the fact that a TCP three‑way connection handshake can’t be used to validate the connection because QUIC runs over UDP.ssl_early_data
– (Directive) When set to on
, tells NGINX to accept application data in the first request sent by a client over a new TLS 1.3 connection, if there was a previous connection from that client. This is known as zero round‑trip time (0‑RTT) connection resumption. Support for the sending of “early data” is a feature of TLS 1.3 and contributes to the improved performance of QUIC+HTTP/3 by eliminating the extra round‑trip message exchanges required for a TLS handshake.
Note: 0‑RTT connection resumption can create a security risk, because the early data is subject to replay attacks if it includes an HTTP request method other than GET
. For details, see the section about TLS 1.3 in Announcing NGINX Plus R17 on our blog.
The diagram highlights how 0‑RTT connection resumption with QUIC+HTTP/3 improves performance, because the client can send an HTTP request in its first message when resuming a QUIC connection to NGINX. For TCP with TLS, in contrast, the client must perform a new TLS handshake with NGINX to establish a secure connection, at the cost of several additional roundtrips.
For information about all the new directives and variables, see the 3. Configuration section of the nginx-quic README.
As previously mentioned, one of our motivations for releasing prebuilt binaries is to make it easier to test that NGINX is handling HTTP/3 traffic correctly. For simple command‑line testing, you can build curl
with HTTP/3 support or use a prebuilt container. In addition, newer versions of most browsers support QUIC+HTTP/3.
To verify that your QUIC‑enabled site is satisfying HTTP/3 connection requests from browsers, you can use a browser’s developer tools to examine the HTTP headers returned by NGINX. The QUIC+HTTP/3 implementation is working correctly if NGINX includes the Alt-Svc
header discussed above in its response to the browser’s initial HTTP request over TCP.
At that point, a QUIC‑capable browser makes a QUIC connection on the port specified in the Alt-Svc
directive, and subsequent HTTP requests and responses are over QUIC. Another way to verify QUIC+HTTP/3 is being used is to include another add_header
directive to set the value of a custom HTTP header to the protocol captured by the $server-protocol
variable. You can track the value of the header as it changes from HTTP/1.x
before the QUIC connection is established to HTTP/3.0
when QUIC is being used.
Here’s a sample location
block where the custom HTTP header is X-protocol
:
location / { # advertise that QUIC is available on the configured port
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
# signal whether we are using QUIC+HTTP/3
add_header X-protocol $server_protocol always;
#proxy_pass <upstream_group>;
#root /<root_directory>;
}
Alternatively, there are tools like the Chrome HTTP Indicator extension which visually indicate the protocol in use. (Note that this is not an endorsement of any browser extension and you must satisfy yourself that any possible security implications of an extension are acceptable given your circumstances).
We will continue to deliver our solution for QUIC+HTTP/3 and provide more examples of NGINX optimizations in the coming weeks. In the meantime, please share the results of your own testing to help inform our decisions. You can share your feedback on the NGINX development mailing list and the #quic‑http3 channel on NGINX Community Slack.
To get updates about our work on QUIC+HTTP/3, including the next important milestone – the merge of the nginx-quic repo into the mainline NGINX Open Source branch – subscribe to the NGINX announcement mailing list.
We also encourage you to attend our upcoming webinar, Get Hands‑On with NGINX and QUIC+HTTP/3 on Wednesday, April 19, 2023:
"This blog post may reference products that are no longer available and/or no longer supported. For the most current information about available F5 NGINX products and solutions, explore our NGINX product family. NGINX is now part of F5. All previous NGINX.com links will redirect to similar NGINX content on F5.com."