Latest update - 9029

This commit is contained in:
2023-02-26 16:32:22 +09:00
parent aeed7a64b5
commit 82a6cbb09e
11 changed files with 168 additions and 36 deletions
+143 -17
View File
@@ -2,12 +2,13 @@ Experimental QUIC support for nginx
----------------------------------- -----------------------------------
1. Introduction 1. Introduction
2. Installing 2. Building from sources
3. Configuration 3. Configuration
4. Clients 4. Directives
5. Troubleshooting 5. Clients
6. Contributing 6. Troubleshooting
7. Links 7. Contributing
8. Links
1. Introduction 1. Introduction
@@ -51,7 +52,16 @@ Experimental QUIC support for nginx
+ Lost packets are detected and retransmitted properly + Lost packets are detected and retransmitted properly
+ Clients may migrate to new address + Clients may migrate to new address
2. Installing 2. Building from sources
The build is configured using the configure command.
Refer to http://nginx.org/en/docs/configure.html for details.
When configuring nginx, it's possible to 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
A library that provides QUIC support is required to build nginx, there A library that provides QUIC support is required to build nginx, there
are several of those available on the market: are several of those available on the market:
@@ -85,12 +95,6 @@ Experimental QUIC support for nginx
--with-cc-opt="-I../libressl/build/include" \ --with-cc-opt="-I../libressl/build/include" \
--with-ld-opt="-L../libressl/build/lib" --with-ld-opt="-L../libressl/build/lib"
When configuring nginx, it's possible to 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
3. Configuration 3. Configuration
The HTTP "listen" directive got a new option "http3" which enables The HTTP "listen" directive got a new option "http3" which enables
@@ -174,7 +178,129 @@ Example configuration:
} }
} }
4. Clients 4. Directives
Syntax: quic_bpf on | off;
Default: quic_bpf off;
Context: main
Enables routing of QUIC packets using eBPF.
When enabled, this allows to support QUIC connection migration.
The directive is only supported on Linux 5.7+.
Syntax: quic_retry on | off;
Default: quic_retry off;
Context: http | stream, server
Enables the QUIC Address Validation feature. This includes:
- sending a new token in a Retry packet or a NEW_TOKEN frame
- validating a token received in the Initial packet
Syntax: quic_gso on | off;
Default: quic_gso off;
Context: http | stream, server
Enables sending in optimized batch mode using segmentation offloading.
Optimized sending is only supported on Linux featuring UDP_SEGMENT.
Syntax: quic_mtu size;
Default: quic_mtu 65527;
Context: http | stream, server
Sets the QUIC max_udp_payload_size transport parameter value.
This is the maximum UDP payload that we are willing to receive.
Syntax: quic_host_key file;
Default: -
Context: http | stream, server
Specifies a file with the secret key used to encrypt stateless reset and
address validation tokens. By default, a randomly generated key is used.
Syntax: quic_active_connection_id_limit number;
Default: quic_active_connection_id_limit 2;
Context: http | stream, server
Sets the QUIC active_connection_id_limit transport parameter value.
This is the maximum number of connection IDs we are willing to store.
Syntax: quic_timeout time;
Default: quic_timeout 60s;
Context: stream, server
Defines a timeout used to negotiate the QUIC idle timeout.
In the http module, it is taken from the keepalive_timeout directive.
Syntax: quic_stream_buffer_size size;
Default: quic_stream_buffer_size 64k;
Context: stream, server
Syntax: http3_stream_buffer_size size;
Default: http3_stream_buffer_size 64k;
Context: http, server
Sets buffer size for reading and writing of the QUIC STREAM payload.
The buffer size is used to calculate initial flow control limits
in the following QUIC transport parameters:
- initial_max_data
- initial_max_stream_data_bidi_local
- initial_max_stream_data_bidi_remote
- initial_max_stream_data_uni
Syntax: http3_max_concurrent_pushes number;
Default: http3_max_concurrent_pushes 10;
Context: http, server
Limits the maximum number of concurrent push requests in a connection.
Syntax: http3_max_concurrent_streams number;
Default: http3_max_concurrent_streams 128;
Context: http, server
Sets the maximum number of concurrent HTTP/3 streams in a connection.
Syntax: http3_push uri | off;
Default: http3_push off;
Context: http, server, location
Pre-emptively sends (pushes) a request to the specified uri along with
the response to the original request. Only relative URIs with absolute
path will be processed, for example:
http3_push /static/css/main.css;
The uri value can contain variables.
Several http3_push directives can be specified on the same configuration
level. The off parameter cancels the effect of the http3_push directives
inherited from the previous configuration level.
Syntax: http3_push_preload on | off;
Default: http3_push_preload off;
Context: http, server, location
Enables automatic conversion of preload links specified in the “Link”
response header fields into push requests.
Syntax: http3_hq on | off;
Default: http3_hq off;
Context: http, server
Enables HTTP/0.9 protocol negotiation used in QUIC interoperability tests.
5. Clients
* Browsers * Browsers
@@ -201,7 +327,7 @@ Example configuration:
"nghttp3/ngtcp2 client" "quic" "nghttp3/ngtcp2 client" "quic"
5. Troubleshooting 6. Troubleshooting
Here are some tips that may help to identify problems: Here are some tips that may help to identify problems:
@@ -231,16 +357,16 @@ Example configuration:
#define NGX_QUIC_DEBUG_ALLOC #define NGX_QUIC_DEBUG_ALLOC
#define NGX_QUIC_DEBUG_CRYPTO #define NGX_QUIC_DEBUG_CRYPTO
6. Contributing 7. Contributing
Please refer to Please refer to
http://nginx.org/en/docs/contributing_changes.html http://nginx.org/en/docs/contributing_changes.html
7. Links 8. Links
[1] https://datatracker.ietf.org/doc/html/rfc9000 [1] https://datatracker.ietf.org/doc/html/rfc9000
[2] https://datatracker.ietf.org/doc/html/rfc9114 [2] https://datatracker.ietf.org/doc/html/rfc9114
[3] https://mailman.nginx.org/mailman3/lists/nginx-devel.nginx.org/ [3] https://mailman.nginx.org/mailman/listinfo/nginx-devel
[4] https://boringssl.googlesource.com/boringssl/ [4] https://boringssl.googlesource.com/boringssl/
[5] https://www.libressl.org/ [5] https://www.libressl.org/
[6] https://github.com/quictls/openssl [6] https://github.com/quictls/openssl
+1 -4
View File
@@ -33,9 +33,6 @@ static int ngx_ssl_new_client_session(ngx_ssl_conn_t *ssl_conn,
#ifdef SSL_READ_EARLY_DATA_SUCCESS #ifdef SSL_READ_EARLY_DATA_SUCCESS
static ngx_int_t ngx_ssl_try_early_data(ngx_connection_t *c); static ngx_int_t ngx_ssl_try_early_data(ngx_connection_t *c);
#endif #endif
#if (NGX_DEBUG)
static void ngx_ssl_handshake_log(ngx_connection_t *c);
#endif
static void ngx_ssl_handshake_handler(ngx_event_t *ev); static void ngx_ssl_handshake_handler(ngx_event_t *ev);
#ifdef SSL_READ_EARLY_DATA_SUCCESS #ifdef SSL_READ_EARLY_DATA_SUCCESS
static ssize_t ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf, static ssize_t ngx_ssl_recv_early(ngx_connection_t *c, u_char *buf,
@@ -2053,7 +2050,7 @@ ngx_ssl_try_early_data(ngx_connection_t *c)
#if (NGX_DEBUG) #if (NGX_DEBUG)
static void void
ngx_ssl_handshake_log(ngx_connection_t *c) ngx_ssl_handshake_log(ngx_connection_t *c)
{ {
char buf[129], *s, *d; char buf[129], *s, *d;
+3
View File
@@ -323,6 +323,9 @@ ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool,
ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
#if (NGX_DEBUG)
void ngx_ssl_handshake_log(ngx_connection_t *c);
#endif
ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size);
ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size); ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size);
ssize_t ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit); ssize_t ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl, off_t limit);
+2 -2
View File
@@ -644,7 +644,7 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
if (len < min_payload) { if (len < min_payload) {
ngx_memset(p, NGX_QUIC_FT_PADDING, min_payload - len); ngx_memset(p, NGX_QUIC_FT_PADDING, min_payload - len);
len = min_payload; len = min_payload;
} }
pkt.payload.data = src; pkt.payload.data = src;
pkt.payload.len = len; pkt.payload.len = len;
@@ -1254,7 +1254,7 @@ ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
if (len < (ssize_t) min_payload) { if (len < (ssize_t) min_payload) {
ngx_memset(src + len, NGX_QUIC_FT_PADDING, min_payload - len); ngx_memset(src + len, NGX_QUIC_FT_PADDING, min_payload - len);
len = min_payload; len = min_payload;
} }
pkt.payload.data = src; pkt.payload.data = src;
pkt.payload.len = len; pkt.payload.len = len;
+13 -7
View File
@@ -190,7 +190,7 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
SSL_get0_alpn_selected(ssl_conn, &alpn_data, &alpn_len); SSL_get0_alpn_selected(ssl_conn, &alpn_data, &alpn_len);
if (alpn_len == 0) { if (alpn_len == 0) {
qc->error = 0x100 + SSL_AD_NO_APPLICATION_PROTOCOL; qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL);
qc->error_reason = "unsupported protocol in ALPN extension"; qc->error_reason = "unsupported protocol in ALPN extension";
ngx_log_error(NGX_LOG_INFO, c->log, 0, ngx_log_error(NGX_LOG_INFO, c->log, 0,
@@ -301,6 +301,7 @@ ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
} }
qc->error = NGX_QUIC_ERR_CRYPTO(alert); qc->error = NGX_QUIC_ERR_CRYPTO(alert);
qc->error_reason = "handshake failed";
return 1; return 1;
} }
@@ -422,8 +423,15 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data)
sslerr); sslerr);
if (sslerr != SSL_ERROR_WANT_READ) { if (sslerr != SSL_ERROR_WANT_READ) {
if (c->ssl->handshake_rejected) {
ngx_connection_error(c, 0, "handshake rejected");
ERR_clear_error();
return NGX_ERROR;
}
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed"); ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed");
qc->error_reason = "handshake failed";
return NGX_ERROR; return NGX_ERROR;
} }
} }
@@ -440,11 +448,9 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data)
return NGX_OK; return NGX_OK;
} }
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, #if (NGX_DEBUG)
"quic ssl cipher:%s", SSL_get_cipher(ssl_conn)); ngx_ssl_handshake_log(c);
#endif
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic handshake completed successfully");
c->ssl->handshaked = 1; c->ssl->handshaked = 1;
+1 -1
View File
@@ -1162,7 +1162,7 @@ ngx_quic_can_shutdown(ngx_connection_t *c)
return NGX_DECLINED; return NGX_DECLINED;
} }
} }
} }
return NGX_OK; return NGX_OK;
} }