Latest update - 9029
This commit is contained in:
@@ -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
-1
Submodule lib/boringssl updated: 45b8d7bbd7...04b3a96452
Submodule lib/nginx-http-flv-module updated: f627b56c31...01a825c502
+1
-1
Submodule lib/ngx-fancyindex updated: f50d7b799f...cbc0d3fca4
+1
-1
Submodule lib/pcre updated: d73a949ec1...1de7291a8c
+1
-1
Submodule lib/zlib updated: 8856740263...b37f323dc5
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -1162,7 +1162,7 @@ ngx_quic_can_shutdown(ngx_connection_t *c)
|
|||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user