2020-04-28 23:16:13 +08:00
|
|
|
Experimental QUIC support for nginx
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
1. Introduction
|
|
|
|
2. Installing
|
|
|
|
3. Configuration
|
|
|
|
4. Clients
|
|
|
|
5. Troubleshooting
|
2020-05-25 23:37:43 +08:00
|
|
|
6. Contributing
|
|
|
|
7. Links
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
1. Introduction
|
|
|
|
|
|
|
|
This is an experimental QUIC [1] / HTTP/3 [2] support for nginx.
|
|
|
|
|
|
|
|
The code is developed in a separate "quic" branch available
|
|
|
|
at https://hg.nginx.org/nginx-quic. Currently it is based
|
2021-05-28 18:45:09 +08:00
|
|
|
on nginx mainline 1.21.x. We merge new nginx releases into
|
2020-10-22 19:55:15 +08:00
|
|
|
this branch regularly.
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
The project code base is under the same BSD license as nginx.
|
|
|
|
|
2020-10-22 19:55:15 +08:00
|
|
|
The code is currently at a beta level of quality and should not
|
2020-04-28 23:16:13 +08:00
|
|
|
be used in production.
|
|
|
|
|
|
|
|
We are working on improving HTTP/3 support with the goal of
|
|
|
|
integrating it to the main NGINX codebase. Expect frequent
|
|
|
|
updates of this code and don't rely on it for whatever purpose.
|
|
|
|
|
|
|
|
We'll be grateful for any feedback and code submissions however
|
|
|
|
we don't bear any responsibilities for any issues with this code.
|
|
|
|
|
|
|
|
You can always contact us via nginx-devel mailing list [3].
|
|
|
|
|
|
|
|
What works now:
|
|
|
|
|
2021-05-28 18:45:09 +08:00
|
|
|
Currently we support IETF-QUIC draft-29 through final RFC documents.
|
2020-06-23 16:57:00 +08:00
|
|
|
Earlier drafts are NOT supported as they have incompatible wire format.
|
2020-04-28 23:16:13 +08:00
|
|
|
|
2020-10-22 19:55:15 +08:00
|
|
|
nginx should be able to respond to HTTP/3 requests over QUIC and
|
2020-04-28 23:16:13 +08:00
|
|
|
it should be possible to upload and download big files without errors.
|
|
|
|
|
|
|
|
+ The handshake completes successfully
|
|
|
|
+ One endpoint can update keys and its peer responds correctly
|
2020-05-14 22:22:29 +08:00
|
|
|
+ 0-RTT data is being received and acted on
|
2020-04-28 23:16:13 +08:00
|
|
|
+ Connection is established using TLS Resume Ticket
|
2020-05-14 21:33:46 +08:00
|
|
|
+ A handshake that includes a Retry packet completes successfully
|
2020-04-28 23:16:13 +08:00
|
|
|
+ Stream data is being exchanged and ACK'ed
|
|
|
|
+ An H3 transaction succeeded
|
|
|
|
+ One or both endpoints insert entries into dynamic table and
|
|
|
|
subsequently reference them from header blocks
|
2020-08-21 19:55:32 +08:00
|
|
|
+ Version Negotiation packet is sent to client with unknown version
|
|
|
|
+ Lost packets are detected and retransmitted properly
|
2021-04-29 20:35:02 +08:00
|
|
|
+ Clients may migrate to new address
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
Not (yet) supported features:
|
|
|
|
|
2020-08-21 19:55:32 +08:00
|
|
|
- Explicit Congestion Notification (ECN) as specified in quic-recovery [5]
|
2020-04-28 23:16:13 +08:00
|
|
|
- A connection with the spin bit succeeds and the bit is spinning
|
|
|
|
- Structured Logging
|
|
|
|
|
|
|
|
Since the code is experimental and still under development,
|
|
|
|
a lot of things may not work as expected, for example:
|
|
|
|
|
|
|
|
- Flow control mechanism is basic and intended to avoid CPU hog and make
|
|
|
|
simple interactions possible
|
|
|
|
|
2021-05-28 18:45:09 +08:00
|
|
|
- Not all protocol requirements are strictly followed; some of checks are
|
2020-04-28 23:16:13 +08:00
|
|
|
omitted for the sake of simplicity of initial implementation
|
|
|
|
|
|
|
|
2. Installing
|
|
|
|
|
|
|
|
You will need a BoringSSL [4] library that provides QUIC support
|
|
|
|
|
2020-04-30 20:59:14 +08:00
|
|
|
$ hg clone -b quic https://hg.nginx.org/nginx-quic
|
2020-04-28 23:16:13 +08:00
|
|
|
$ cd nginx-quic
|
2022-01-13 21:56:07 +08:00
|
|
|
$ ./auto/configure --with-debug --with-http_v3_module \
|
|
|
|
--with-cc-opt="-I../boringssl/include" \
|
|
|
|
--with-ld-opt="-L../boringssl/build/ssl \
|
2020-04-30 20:47:43 +08:00
|
|
|
-L../boringssl/build/crypto"
|
2020-04-28 23:16:13 +08:00
|
|
|
$ make
|
|
|
|
|
2022-01-13 21:56:07 +08:00
|
|
|
Alternatively, nginx can be configured with QuicTLS [9]
|
|
|
|
|
|
|
|
$ ./auto/configure --with-debug --with-http_v3_module \
|
|
|
|
--with-cc-opt="-I../quictls/build/include" \
|
|
|
|
--with-ld-opt="-L../quictls/build/lib"
|
|
|
|
|
2020-07-22 18:45:34 +08:00
|
|
|
When configuring nginx, you can enable QUIC and HTTP/3 using the
|
|
|
|
following new configuration options:
|
|
|
|
|
|
|
|
--with-http_v3_module - enable QUIC and HTTP/3
|
|
|
|
--with-stream_quic_module - enable QUIC in Stream
|
|
|
|
|
2020-04-28 23:16:13 +08:00
|
|
|
3. Configuration
|
|
|
|
|
2021-12-04 15:52:55 +08:00
|
|
|
The HTTP "listen" directive got a new option "http3" which enables
|
|
|
|
HTTP/3 over QUIC on the specified port.
|
2020-07-22 18:45:34 +08:00
|
|
|
|
|
|
|
The Stream "listen" directive got a new option "quic" which enables
|
|
|
|
QUIC as client transport protocol instead of TCP or plain UDP.
|
2020-04-28 23:16:13 +08:00
|
|
|
|
2020-07-22 18:45:34 +08:00
|
|
|
Along with "http3" or "quic", you also have to specify "reuseport"
|
|
|
|
option [6] to make it work properly with multiple workers.
|
2020-04-28 23:16:13 +08:00
|
|
|
|
2020-05-23 19:41:08 +08:00
|
|
|
To enable address validation:
|
|
|
|
|
|
|
|
quic_retry on;
|
|
|
|
|
|
|
|
To enable 0-RTT:
|
|
|
|
|
|
|
|
ssl_early_data on;
|
|
|
|
|
|
|
|
Make sure that TLS 1.3 is configured which is required for QUIC:
|
|
|
|
|
|
|
|
ssl_protocols TLSv1.3;
|
|
|
|
|
2021-07-23 16:25:16 +08:00
|
|
|
To enable GSO (Generic Segmentation Offloading):
|
|
|
|
|
|
|
|
quic_gso on;
|
|
|
|
|
2021-12-06 20:19:54 +08:00
|
|
|
To limit maximum packet size:
|
|
|
|
|
|
|
|
quic_mtu <size>;
|
|
|
|
|
|
|
|
To set host key for various tokens:
|
|
|
|
|
|
|
|
quic_host_key <filename>;
|
|
|
|
|
|
|
|
|
2021-07-23 16:25:16 +08:00
|
|
|
By default this Linux-specific optimization [8] is disabled.
|
|
|
|
Enable if your network interface is configured to support GSO.
|
|
|
|
|
2020-07-28 20:53:42 +08:00
|
|
|
A number of directives were added that configure HTTP/3:
|
|
|
|
|
2021-12-06 20:19:54 +08:00
|
|
|
http3_stream_buffer_size
|
2020-07-28 20:53:42 +08:00
|
|
|
http3_max_concurrent_pushes
|
2021-12-06 20:19:54 +08:00
|
|
|
http3_max_concurrent_streams
|
2020-07-28 20:53:42 +08:00
|
|
|
http3_push
|
|
|
|
http3_push_preload
|
2021-12-04 15:52:55 +08:00
|
|
|
http3_hq (requires NGX_HTTP_V3_HQ macro)
|
2020-07-28 20:53:42 +08:00
|
|
|
|
2021-12-01 16:02:17 +08:00
|
|
|
In http, an additional variable is available: $http3.
|
|
|
|
The value of $http3 is "h3" for HTTP/3 connections,
|
|
|
|
"hq" for hq connections, or an empty string otherwise.
|
|
|
|
|
|
|
|
In stream, an additional variable is available: $quic.
|
2020-04-28 23:16:13 +08:00
|
|
|
The value of $quic is "quic" if QUIC connection is used,
|
2021-05-31 16:54:47 +08:00
|
|
|
or an empty string otherwise.
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
Example configuration:
|
|
|
|
|
|
|
|
http {
|
|
|
|
log_format quic '$remote_addr - $remote_user [$time_local] '
|
|
|
|
'"$request" $status $body_bytes_sent '
|
2021-12-07 21:07:47 +08:00
|
|
|
'"$http_referer" "$http_user_agent" "$http3"';
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
access_log logs/access.log quic;
|
|
|
|
|
|
|
|
server {
|
|
|
|
# for better compatibility it's recommended
|
|
|
|
# to use the same port for quic and https
|
|
|
|
listen 8443 http3 reuseport;
|
|
|
|
listen 8443 ssl;
|
|
|
|
|
|
|
|
ssl_certificate certs/example.com.crt;
|
|
|
|
ssl_certificate_key certs/example.com.key;
|
|
|
|
ssl_protocols TLSv1.3;
|
|
|
|
|
|
|
|
location / {
|
|
|
|
# required for browsers to direct them into quic port
|
2021-05-31 16:54:47 +08:00
|
|
|
add_header Alt-Svc 'h3=":8443"; ma=86400';
|
2020-04-28 23:16:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
4. Clients
|
|
|
|
|
|
|
|
* Browsers
|
|
|
|
|
2021-03-07 05:23:23 +08:00
|
|
|
Known to work: Firefox 80+ and Chrome 85+ (QUIC draft 29+)
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
Beware of strange issues: sometimes browser may decide to ignore QUIC
|
|
|
|
Cache clearing/restart might help. Always check access.log and
|
|
|
|
error.log to make sure you are using HTTP/3 and not TCP https.
|
|
|
|
|
|
|
|
+ to enable QUIC in Firefox, set the following in 'about:config':
|
|
|
|
network.http.http3.enabled = true
|
|
|
|
|
|
|
|
+ to enable QUIC in Chrome, enable it on command line and force it
|
|
|
|
on your site:
|
|
|
|
|
2020-09-11 15:56:05 +08:00
|
|
|
$ ./chrome --enable-quic --quic-version=h3-29 \
|
2020-04-28 23:16:13 +08:00
|
|
|
--origin-to-force-quic-on=example.com:8443
|
|
|
|
|
|
|
|
* Console clients
|
|
|
|
|
|
|
|
Known to work: ngtcp2, firefox's neqo and chromium's console clients:
|
|
|
|
|
|
|
|
$ examples/client 127.0.0.1 8443 https://example.com:8443/index.html
|
|
|
|
|
|
|
|
$ ./neqo-client https://127.0.0.1:8443/
|
|
|
|
|
|
|
|
$ chromium-build/out/my_build/quic_client http://example.com:8443 \
|
2020-09-11 15:56:05 +08:00
|
|
|
--quic_version=h3-29 \
|
2020-04-28 23:16:13 +08:00
|
|
|
--allow_unknown_root_cert \
|
|
|
|
--disable_certificate_verification
|
|
|
|
|
|
|
|
|
|
|
|
If you've got it right, in the access log you should see something like:
|
|
|
|
|
|
|
|
127.0.0.1 - - [24/Apr/2020:11:27:29 +0300] "GET / HTTP/3" 200 805 "-"
|
2021-05-31 16:54:47 +08:00
|
|
|
"nghttp3/ngtcp2 client" "quic"
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
|
|
|
|
5. Troubleshooting
|
|
|
|
|
|
|
|
Here are some tips that may help you to identify problems:
|
|
|
|
|
2020-10-22 19:55:15 +08:00
|
|
|
+ Ensure you are building with proper SSL library that supports QUIC
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
+ Ensure you are using the proper SSL library in runtime
|
|
|
|
(`nginx -V` will show you what you are using)
|
|
|
|
|
|
|
|
+ Ensure your client is actually sending QUIC requests
|
|
|
|
(see "Clients" section about browsers and cache)
|
|
|
|
|
|
|
|
We recommend to start with simple console client like ngtcp2
|
|
|
|
to ensure you've got server configured properly before trying
|
2020-05-22 23:16:34 +08:00
|
|
|
with real browsers that may be very picky with certificates,
|
2020-04-28 23:16:13 +08:00
|
|
|
for example.
|
|
|
|
|
|
|
|
+ Build nginx with debug support [7] and check your debug log.
|
|
|
|
It should contain all details about connection and why it
|
|
|
|
failed. All related messages contain "quic " prefix and can
|
|
|
|
be easily filtered out.
|
|
|
|
|
|
|
|
+ If you want to investigate deeper, you may want to enable
|
2021-06-25 17:41:58 +08:00
|
|
|
additional debugging in src/event/quic/ngx_event_quic_connection.h:
|
2020-04-28 23:16:13 +08:00
|
|
|
|
|
|
|
#define NGX_QUIC_DEBUG_PACKETS
|
|
|
|
#define NGX_QUIC_DEBUG_FRAMES
|
2020-12-02 03:11:01 +08:00
|
|
|
#define NGX_QUIC_DEBUG_ALLOC
|
2020-04-28 23:16:13 +08:00
|
|
|
#define NGX_QUIC_DEBUG_CRYPTO
|
|
|
|
|
2020-05-25 23:37:43 +08:00
|
|
|
6. Contributing
|
|
|
|
|
|
|
|
If you are willing to contribute, please refer to
|
|
|
|
http://nginx.org/en/docs/contributing_changes.html
|
|
|
|
|
|
|
|
7. Links
|
2020-04-28 23:16:13 +08:00
|
|
|
|
2021-05-28 18:45:09 +08:00
|
|
|
[1] https://datatracker.ietf.org/doc/html/rfc9000
|
|
|
|
[2] https://datatracker.ietf.org/doc/html/draft-ietf-quic-http
|
2020-04-28 23:16:13 +08:00
|
|
|
[3] https://mailman.nginx.org/mailman/listinfo/nginx-devel
|
|
|
|
[4] https://boringssl.googlesource.com/boringssl/
|
2021-05-28 18:45:09 +08:00
|
|
|
[5] https://datatracker.ietf.org/doc/html/rfc9002
|
2020-04-28 23:16:13 +08:00
|
|
|
[6] https://nginx.org/en/docs/http/ngx_http_core_module.html#listen
|
|
|
|
[7] https://nginx.org/en/docs/debugging_log.html
|
2021-07-23 16:25:16 +08:00
|
|
|
[8] http://vger.kernel.org/lpc_net2018_talks/willemdebruijn-lpc2018-udpgso-paper-DRAFT-1.pdf
|
2022-01-13 21:56:07 +08:00
|
|
|
[9] https://github.com/quictls/openssl
|