NGINX.COM
Web Server Load Balancing with NGINX Plus

[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.]

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:

  • Red Hat Enterprise Linux 9 and binary‑compatible variants
  • Ubuntu 22.04

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.

Configuring NGINX for QUIC+HTTP/3

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 listen directive with the quic parameter to tell NGINX to listen for HTTP/3 connections on the same port as for HTTP/1.1 and HTTP/2, here 443.

The reuseport parameter is required for correct operation when there are multiple NGINX worker processes. It enables the kernel to distribute incoming HTTP/3 connections among them.

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 $server_port variable) is the same as used for TLS with HTTP/1.1 and HTTP/2.

The value of ma is the number of seconds the client can safely assume NGINX is accepting HTTP/3 traffic over UDP; after that time the client needs to revert to TCP. The value specified here is equivalent to 24 hours.

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.

Diagram comparing the messages needed for HTTP connection resumption for TCP+TLS versus QUIC

For information about all the new directives and variables, see the 3. Configuration section of the nginx-quic README.

Testing NGINX with QUIC+HTTP/3

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).

What’s Next

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.

Watch the Webinar

We also encourage you to attend our upcoming webinar, Get Hands‑On with NGINX and QUIC+HTTP/3 on Wednesday, April 19, 2023:

Hero image

Learn how to deploy, configure, manage, secure, and monitor your Kubernetes Ingress controller with NGINX to deliver apps and APIs on-premises and in the cloud.



About The Author

Robert Haynes

Technical Marketing Manager

About F5 NGINX

F5, Inc. is the company behind NGINX, the popular open source project. We offer a suite of technologies for developing and delivering modern applications. Together with F5, our combined solution bridges the gap between NetOps and DevOps, with multi-cloud application services that span from code to customer.

Learn more at nginx.com or join the conversation by following @nginx on Twitter.