From 26ac1c73f0fe90c77cbad84a6b4ef5712e35ba52 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Fri, 28 Feb 2020 13:09:51 +0300 Subject: Initial QUIC support in http. --- src/http/modules/ngx_http_ssl_module.c | 27 ++++++++++++++++++++++++++- src/http/modules/ngx_http_ssl_module.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 495e628d3..693e45a1c 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -249,6 +249,13 @@ static ngx_command_t ngx_http_ssl_commands[] = { offsetof(ngx_http_ssl_srv_conf_t, early_data), NULL }, + { ngx_string("ssl_quic"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, quic), + NULL }, + ngx_null_command }; @@ -568,6 +575,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) sscf->enable = NGX_CONF_UNSET; sscf->prefer_server_ciphers = NGX_CONF_UNSET; sscf->early_data = NGX_CONF_UNSET; + sscf->quic = NGX_CONF_UNSET; sscf->buffer_size = NGX_CONF_UNSET_SIZE; sscf->verify = NGX_CONF_UNSET_UINT; sscf->verify_depth = NGX_CONF_UNSET_UINT; @@ -612,6 +620,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->early_data, prev->early_data, 0); + ngx_conf_merge_value(conf->quic, prev->quic, 0); + ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); @@ -696,6 +706,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) } } +printf("ngx_ssl_create\n"); if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } @@ -857,6 +868,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } + if (ngx_ssl_quic(cf, &conf->ssl, conf->quic) != NGX_OK) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } @@ -1141,13 +1156,15 @@ ngx_http_ssl_init(ngx_conf_t *cf) addr = port[p].addrs.elts; for (a = 0; a < port[p].addrs.nelts; a++) { +printf("ssl %d http3 %d\n", addr[a].opt.ssl, addr[a].opt.http3); - if (!addr[a].opt.ssl) { + if (!addr[a].opt.ssl && !addr[a].opt.http3) { continue; } cscf = addr[a].default_server; sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; +printf("sscf->protocols %lx\n", sscf->protocols); if (sscf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, @@ -1156,6 +1173,14 @@ ngx_http_ssl_init(ngx_conf_t *cf) cscf->file_name, cscf->line); return NGX_ERROR; } + + if (addr[a].opt.http3 && !(sscf->protocols & NGX_SSL_TLSv1_3)) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "\"ssl_protocols\" did not enable TLSv1.3 for " + "the \"listen ... http3\" directive in %s:%ui", + cscf->file_name, cscf->line); + return NGX_ERROR; + } } } diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index 26fdccfe4..310d7c737 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -21,6 +21,7 @@ typedef struct { ngx_flag_t prefer_server_ciphers; ngx_flag_t early_data; + ngx_flag_t quic; ngx_uint_t protocols; -- cgit From ef8b06b186a2f7ac25b8ee49a325c935c3e5bb9f Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Fri, 28 Feb 2020 13:09:52 +0300 Subject: Cleanup. --- src/http/modules/ngx_http_ssl_module.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 693e45a1c..8640c2211 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -706,7 +706,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) } } -printf("ngx_ssl_create\n"); if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } @@ -1156,7 +1155,6 @@ ngx_http_ssl_init(ngx_conf_t *cf) addr = port[p].addrs.elts; for (a = 0; a < port[p].addrs.nelts; a++) { -printf("ssl %d http3 %d\n", addr[a].opt.ssl, addr[a].opt.http3); if (!addr[a].opt.ssl && !addr[a].opt.http3) { continue; @@ -1164,7 +1162,6 @@ printf("ssl %d http3 %d\n", addr[a].opt.ssl, addr[a].opt.http3); cscf = addr[a].default_server; sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; -printf("sscf->protocols %lx\n", sscf->protocols); if (sscf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, -- cgit From 5aa8e519c9fecc00b3a74781716ceb66609c5661 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 18 Mar 2020 16:37:16 +0300 Subject: Moved setting QUIC methods to runtime. This allows listening to both https and http3 in the same server. Also, the change eliminates the ssl_quic directive. --- src/http/modules/ngx_http_ssl_module.c | 14 -------------- src/http/modules/ngx_http_ssl_module.h | 1 - 2 files changed, 15 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 8640c2211..4b480a006 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -249,13 +249,6 @@ static ngx_command_t ngx_http_ssl_commands[] = { offsetof(ngx_http_ssl_srv_conf_t, early_data), NULL }, - { ngx_string("ssl_quic"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_ssl_srv_conf_t, quic), - NULL }, - ngx_null_command }; @@ -575,7 +568,6 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) sscf->enable = NGX_CONF_UNSET; sscf->prefer_server_ciphers = NGX_CONF_UNSET; sscf->early_data = NGX_CONF_UNSET; - sscf->quic = NGX_CONF_UNSET; sscf->buffer_size = NGX_CONF_UNSET_SIZE; sscf->verify = NGX_CONF_UNSET_UINT; sscf->verify_depth = NGX_CONF_UNSET_UINT; @@ -620,8 +612,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->early_data, prev->early_data, 0); - ngx_conf_merge_value(conf->quic, prev->quic, 0); - ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); @@ -867,10 +857,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - if (ngx_ssl_quic(cf, &conf->ssl, conf->quic) != NGX_OK) { - return NGX_CONF_ERROR; - } - return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index 310d7c737..26fdccfe4 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -21,7 +21,6 @@ typedef struct { ngx_flag_t prefer_server_ciphers; ngx_flag_t early_data; - ngx_flag_t quic; ngx_uint_t protocols; -- cgit From ede2656c6016d240b804bbcb28b6ecd391cca5de Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 23 Mar 2020 19:26:24 +0300 Subject: Support for HTTP/3 ALPN. This is required by Chrome. --- src/http/modules/ngx_http_ssl_module.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 4b480a006..a48d3b924 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -371,7 +371,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, #if (NGX_DEBUG) unsigned int i; #endif -#if (NGX_HTTP_V2) +#if (NGX_HTTP_V2 || NGX_HTTP_V3) ngx_http_connection_t *hc; #endif #if (NGX_HTTP_V2 || NGX_DEBUG) @@ -388,15 +388,23 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, } #endif -#if (NGX_HTTP_V2) +#if (NGX_HTTP_V2 || NGX_HTTP_V3) hc = c->data; +#endif +#if (NGX_HTTP_V2) if (hc->addr_conf->http2) { srv = (unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; } else +#endif +#if (NGX_HTTP_V3) + if (hc->addr_conf->http3) { + srv = (unsigned char *) NGX_HTTP_V3_ALPN_ADVERTISE; + srvlen = sizeof(NGX_HTTP_V3_ALPN_ADVERTISE) - 1; + } else #endif { srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE; -- cgit From 80a38580bd04f499d72ab3b6f7776e275e47a2b3 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Fri, 27 Mar 2020 19:46:54 +0300 Subject: Chunked response body in HTTP/3. --- src/http/modules/ngx_http_chunked_filter_module.c | 58 ++++++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index 4d6fd3eed..87b032496 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -18,7 +18,7 @@ typedef struct { static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf); static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r, - ngx_http_chunked_filter_ctx_t *ctx); + ngx_http_chunked_filter_ctx_t *ctx, size_t size); static ngx_http_module_t ngx_http_chunked_filter_module_ctx = { @@ -106,6 +106,7 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { u_char *chunk; off_t size; + size_t n; ngx_int_t rc; ngx_buf_t *b; ngx_chain_t *out, *cl, *tl, **ll; @@ -161,29 +162,50 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) chunk = b->start; if (chunk == NULL) { - /* the "0000000000000000" is 64-bit hexadecimal string */ - chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1); +#if (NGX_HTTP_V3) + if (r->http_version == NGX_HTTP_VERSION_30) { + n = NGX_HTTP_V3_VARLEN_INT_LEN * 2; + + } else +#endif + { + /* the "0000000000000000" is 64-bit hexadecimal string */ + n = sizeof("0000000000000000" CRLF) - 1; + } + + chunk = ngx_palloc(r->pool, n); if (chunk == NULL) { return NGX_ERROR; } b->start = chunk; - b->end = chunk + sizeof("0000000000000000" CRLF) - 1; + b->end = chunk + n; } b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module; b->memory = 0; b->temporary = 1; b->pos = chunk; - b->last = ngx_sprintf(chunk, "%xO" CRLF, size); + +#if (NGX_HTTP_V3) + if (r->http_version == NGX_HTTP_VERSION_30) { + b->last = (u_char *) ngx_http_v3_encode_varlen_int(chunk, + NGX_HTTP_V3_FRAME_DATA); + b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, size); + + } else +#endif + { + b->last = ngx_sprintf(chunk, "%xO" CRLF, size); + } tl->next = out; out = tl; } if (cl->buf->last_buf) { - tl = ngx_http_chunked_create_trailers(r, ctx); + tl = ngx_http_chunked_create_trailers(r, ctx, size); if (tl == NULL) { return NGX_ERROR; } @@ -192,11 +214,12 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) *ll = tl; - if (size == 0) { - tl->buf->pos += 2; - } - - } else if (size > 0) { + } else if (size > 0 +#if (NGX_HTTP_V3) + && r->http_version != NGX_HTTP_VERSION_30 +#endif + ) + { tl = ngx_chain_get_free_buf(r->pool, &ctx->free); if (tl == NULL) { return NGX_ERROR; @@ -227,7 +250,7 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) static ngx_chain_t * ngx_http_chunked_create_trailers(ngx_http_request_t *r, - ngx_http_chunked_filter_ctx_t *ctx) + ngx_http_chunked_filter_ctx_t *ctx, size_t size) { size_t len; ngx_buf_t *b; @@ -236,6 +259,12 @@ ngx_http_chunked_create_trailers(ngx_http_request_t *r, ngx_list_part_t *part; ngx_table_elt_t *header; +#if (NGX_HTTP_V3) + if (r->http_version == NGX_HTTP_VERSION_30) { + return ngx_http_v3_create_trailers(r); + } +#endif + len = 0; part = &r->headers_out.trailers.part; @@ -288,7 +317,10 @@ ngx_http_chunked_create_trailers(ngx_http_request_t *r, b->last = b->pos; - *b->last++ = CR; *b->last++ = LF; + if (size > 0) { + *b->last++ = CR; *b->last++ = LF; + } + *b->last++ = '0'; *b->last++ = CR; *b->last++ = LF; -- cgit From b813b9ec358862a2a94868bc057420d6eca5c05d Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Tue, 21 Jul 2020 23:09:22 +0300 Subject: QUIC: added "quic" listen parameter. The parameter allows processing HTTP/0.9-2 over QUIC. Also, introduced ngx_http_quic_module and moved QUIC settings there --- src/http/modules/ngx_http_quic_module.c | 344 ++++++++++++++++++++++++++++++++ src/http/modules/ngx_http_quic_module.h | 25 +++ src/http/modules/ngx_http_ssl_module.c | 33 ++- 3 files changed, 394 insertions(+), 8 deletions(-) create mode 100644 src/http/modules/ngx_http_quic_module.c create mode 100644 src/http/modules/ngx_http_quic_module.h (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c new file mode 100644 index 000000000..d971c8d26 --- /dev/null +++ b/src/http/modules/ngx_http_quic_module.c @@ -0,0 +1,344 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Roman Arutyunyan + */ + + +#include +#include +#include + + +static ngx_int_t ngx_http_variable_quic(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_quic_add_variables(ngx_conf_t *cf); +static void *ngx_http_quic_create_srv_conf(ngx_conf_t *cf); +static char *ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, + void *child); +static char *ngx_http_quic_max_ack_delay(ngx_conf_t *cf, void *post, + void *data); +static char *ngx_http_quic_max_udp_payload_size(ngx_conf_t *cf, void *post, + void *data); + + +static ngx_conf_post_t ngx_http_quic_max_ack_delay_post = + { ngx_http_quic_max_ack_delay }; +static ngx_conf_post_t ngx_http_quic_max_udp_payload_size_post = + { ngx_http_quic_max_udp_payload_size }; +static ngx_conf_num_bounds_t ngx_http_quic_ack_delay_exponent_bounds = + { ngx_conf_check_num_bounds, 0, 20 }; +static ngx_conf_num_bounds_t ngx_http_quic_active_connection_id_limit_bounds = + { ngx_conf_check_num_bounds, 2, -1 }; + + +static ngx_command_t ngx_http_quic_commands[] = { + + { ngx_string("quic_max_idle_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.max_idle_timeout), + NULL }, + + { ngx_string("quic_max_ack_delay"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.max_ack_delay), + &ngx_http_quic_max_ack_delay_post }, + + { ngx_string("quic_max_udp_payload_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.max_udp_payload_size), + &ngx_http_quic_max_udp_payload_size_post }, + + { ngx_string("quic_initial_max_data"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.initial_max_data), + NULL }, + + { ngx_string("quic_initial_max_stream_data_bidi_local"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_bidi_local), + NULL }, + + { ngx_string("quic_initial_max_stream_data_bidi_remote"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_bidi_remote), + NULL }, + + { ngx_string("quic_initial_max_stream_data_uni"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_uni), + NULL }, + + { ngx_string("quic_initial_max_streams_bidi"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.initial_max_streams_bidi), + NULL }, + + { ngx_string("quic_initial_max_streams_uni"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.initial_max_streams_uni), + NULL }, + + { ngx_string("quic_ack_delay_exponent"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.ack_delay_exponent), + &ngx_http_quic_ack_delay_exponent_bounds }, + + { ngx_string("quic_active_migration"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.disable_active_migration), + NULL }, + + { ngx_string("quic_active_connection_id_limit"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, tp.active_connection_id_limit), + &ngx_http_quic_active_connection_id_limit_bounds }, + + { ngx_string("quic_retry"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, retry), + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_quic_module_ctx = { + ngx_http_quic_add_variables, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_http_quic_create_srv_conf, /* create server configuration */ + ngx_http_quic_merge_srv_conf, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_quic_module = { + NGX_MODULE_V1, + &ngx_http_quic_module_ctx, /* module context */ + ngx_http_quic_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_http_variable_t ngx_http_quic_vars[] = { + + { ngx_string("quic"), NULL, ngx_http_variable_quic, 0, 0, 0 }, + + ngx_http_null_variable +}; + + +static ngx_int_t +ngx_http_variable_quic(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->connection->qs) { + + v->len = 4; + v->valid = 1; + v->no_cacheable = 1; + v->not_found = 0; + v->data = (u_char *) "quic"; + return NGX_OK; + } + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_quic_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_quic_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; + } + + return NGX_OK; +} + + +static void * +ngx_http_quic_create_srv_conf(ngx_conf_t *cf) +{ + ngx_quic_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_quic_conf_t)); + if (conf == NULL) { + return NULL; + } + + /* + * set by ngx_pcalloc(): + * + * conf->tp.original_dcid = { 0, NULL }; + * conf->tp.initial_scid = { 0, NULL }; + * conf->tp.retry_scid = { 0, NULL }; + * conf->tp.stateless_reset_token = { 0 } + * conf->tp.preferred_address = NULL + */ + + conf->tp.max_idle_timeout = NGX_CONF_UNSET_MSEC; + conf->tp.max_ack_delay = NGX_CONF_UNSET_MSEC; + conf->tp.max_udp_payload_size = NGX_CONF_UNSET_SIZE; + conf->tp.initial_max_data = NGX_CONF_UNSET_SIZE; + conf->tp.initial_max_stream_data_bidi_local = NGX_CONF_UNSET_SIZE; + conf->tp.initial_max_stream_data_bidi_remote = NGX_CONF_UNSET_SIZE; + conf->tp.initial_max_stream_data_uni = NGX_CONF_UNSET_SIZE; + conf->tp.initial_max_streams_bidi = NGX_CONF_UNSET_UINT; + conf->tp.initial_max_streams_uni = NGX_CONF_UNSET_UINT; + conf->tp.ack_delay_exponent = NGX_CONF_UNSET_UINT; + conf->tp.disable_active_migration = NGX_CONF_UNSET_UINT; + conf->tp.active_connection_id_limit = NGX_CONF_UNSET_UINT; + + conf->retry = NGX_CONF_UNSET; + + return conf; +} + + +static char * +ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_quic_conf_t *prev = parent; + ngx_quic_conf_t *conf = child; + + ngx_conf_merge_msec_value(conf->tp.max_idle_timeout, + prev->tp.max_idle_timeout, 60000); + + ngx_conf_merge_msec_value(conf->tp.max_ack_delay, + prev->tp.max_ack_delay, + NGX_QUIC_DEFAULT_MAX_ACK_DELAY); + + ngx_conf_merge_size_value(conf->tp.max_udp_payload_size, + prev->tp.max_udp_payload_size, + NGX_QUIC_MAX_UDP_PAYLOAD_SIZE); + + ngx_conf_merge_size_value(conf->tp.initial_max_data, + prev->tp.initial_max_data, + 16 * NGX_QUIC_STREAM_BUFSIZE); + + ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_bidi_local, + prev->tp.initial_max_stream_data_bidi_local, + NGX_QUIC_STREAM_BUFSIZE); + + ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_bidi_remote, + prev->tp.initial_max_stream_data_bidi_remote, + NGX_QUIC_STREAM_BUFSIZE); + + ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_uni, + prev->tp.initial_max_stream_data_uni, + NGX_QUIC_STREAM_BUFSIZE); + + ngx_conf_merge_uint_value(conf->tp.initial_max_streams_bidi, + prev->tp.initial_max_streams_bidi, 16); + + ngx_conf_merge_uint_value(conf->tp.initial_max_streams_uni, + prev->tp.initial_max_streams_uni, 16); + + ngx_conf_merge_uint_value(conf->tp.ack_delay_exponent, + prev->tp.ack_delay_exponent, + NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT); + + ngx_conf_merge_uint_value(conf->tp.disable_active_migration, + prev->tp.disable_active_migration, 1); + + ngx_conf_merge_uint_value(conf->tp.active_connection_id_limit, + prev->tp.active_connection_id_limit, 2); + + ngx_conf_merge_value(conf->retry, prev->retry, 0); + + if (conf->retry) { + if (RAND_bytes(conf->token_key, sizeof(conf->token_key)) <= 0) { + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_quic_max_ack_delay(ngx_conf_t *cf, void *post, void *data) +{ + ngx_msec_t *sp = data; + + if (*sp > 16384) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"quic_max_ack_delay\" must be less than 16384"); + + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_quic_max_udp_payload_size(ngx_conf_t *cf, void *post, void *data) +{ + size_t *sp = data; + + if (*sp < NGX_QUIC_MIN_INITIAL_SIZE + || *sp > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) + { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"quic_max_udp_payload_size\" must be between " + "%d and %d", + NGX_QUIC_MIN_INITIAL_SIZE, + NGX_QUIC_MAX_UDP_PAYLOAD_SIZE); + + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h new file mode 100644 index 000000000..e744eb197 --- /dev/null +++ b/src/http/modules/ngx_http_quic_module.h @@ -0,0 +1,25 @@ + +/* + * Copyright (C) Nginx, Inc. + * Copyright (C) Roman Arutyunyan + */ + + +#ifndef _NGX_HTTP_QUIC_H_INCLUDED_ +#define _NGX_HTTP_QUIC_H_INCLUDED_ + + +#include +#include +#include + + +#define NGX_HTTP_QUIC_ALPN(s) NGX_HTTP_QUIC_ALPN_DRAFT(s) +#define NGX_HTTP_QUIC_ALPN_DRAFT(s) "\x05hq-" #s +#define NGX_HTTP_QUIC_ALPN_ADVERTISE NGX_HTTP_QUIC_ALPN(NGX_QUIC_DRAFT_VERSION) + + +extern ngx_module_t ngx_http_quic_module; + + +#endif /* _NGX_HTTP_QUIC_H_INCLUDED_ */ diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 7daa4daf2..409514821 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -402,7 +402,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, #if (NGX_DEBUG) unsigned int i; #endif -#if (NGX_HTTP_V2 || NGX_HTTP_V3) +#if (NGX_HTTP_V2 || NGX_HTTP_QUIC) ngx_http_connection_t *hc; #endif #if (NGX_HTTP_V2 || NGX_DEBUG) @@ -419,7 +419,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, } #endif -#if (NGX_HTTP_V2 || NGX_HTTP_V3) +#if (NGX_HTTP_V2 || NGX_HTTP_QUIC) hc = c->data; #endif @@ -436,6 +436,12 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, srv = (unsigned char *) NGX_HTTP_V3_ALPN_ADVERTISE; srvlen = sizeof(NGX_HTTP_V3_ALPN_ADVERTISE) - 1; } else +#endif +#if (NGX_HTTP_QUIC) + if (hc->addr_conf->quic) { + srv = (unsigned char *) NGX_HTTP_QUIC_ALPN_ADVERTISE; + srvlen = sizeof(NGX_HTTP_QUIC_ALPN_ADVERTISE) - 1; + } else #endif { srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE; @@ -1247,6 +1253,7 @@ static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf) { ngx_uint_t a, p, s; + const char *name; ngx_http_conf_addr_t *addr; ngx_http_conf_port_t *port; ngx_http_ssl_srv_conf_t *sscf; @@ -1296,26 +1303,36 @@ ngx_http_ssl_init(ngx_conf_t *cf) addr = port[p].addrs.elts; for (a = 0; a < port[p].addrs.nelts; a++) { - if (!addr[a].opt.ssl && !addr[a].opt.http3) { + if (!addr[a].opt.ssl && !addr[a].opt.quic) { continue; } + if (addr[a].opt.http3) { + name = "http3"; + + } else if (addr[a].opt.quic) { + name = "quic"; + + } else { + name = "ssl"; + } + cscf = addr[a].default_server; sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; if (sscf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " - "the \"listen ... ssl\" directive in %s:%ui", - cscf->file_name, cscf->line); + "the \"listen ... %s\" directive in %s:%ui", + name, cscf->file_name, cscf->line); return NGX_ERROR; } - if (addr[a].opt.http3 && !(sscf->protocols & NGX_SSL_TLSv1_3)) { + if (addr[a].opt.quic && !(sscf->protocols & NGX_SSL_TLSv1_3)) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "\"ssl_protocols\" did not enable TLSv1.3 for " - "the \"listen ... http3\" directive in %s:%ui", - cscf->file_name, cscf->line); + "the \"listen ... %s\" directives in %s:%ui", + name, cscf->file_name, cscf->line); return NGX_ERROR; } } -- cgit From 36f2873f6b0d8512c053935614fcc6ae9d969858 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Tue, 21 Jul 2020 23:08:39 +0300 Subject: QUIC: added "quic" listen parameter in Stream. Also, introduced ngx_stream_quic_module. --- src/http/modules/ngx_http_quic_module.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index d971c8d26..9888e2eae 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -241,6 +241,7 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) conf->tp.active_connection_id_limit = NGX_CONF_UNSET_UINT; conf->retry = NGX_CONF_UNSET; + conf->require_alpn = 1; return conf; } -- cgit From f797a8a5b5a2012b0cae9745f05386b628365cb7 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Wed, 30 Sep 2020 20:54:46 +0300 Subject: QUIC: added stateless reset support. The new "quic_stateless_reset_token_key" directive is added. It sets the endpoint key used to generate stateless reset tokens and enables feature. If the endpoint receives short-header packet that can't be matched to existing connection, a stateless reset packet is generated with a proper token. If a valid stateless reset token is found in the incoming packet, the connection is closed. Example configuration: http { quic_stateless_reset_token_key "foo"; ... } --- src/http/modules/ngx_http_quic_module.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 9888e2eae..ec70c7286 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -125,6 +125,13 @@ static ngx_command_t ngx_http_quic_commands[] = { offsetof(ngx_quic_conf_t, retry), NULL }, + { ngx_string("quic_stateless_reset_token_key"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_str_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, sr_token_key), + NULL }, + ngx_null_command }; @@ -223,8 +230,10 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) * conf->tp.original_dcid = { 0, NULL }; * conf->tp.initial_scid = { 0, NULL }; * conf->tp.retry_scid = { 0, NULL }; - * conf->tp.stateless_reset_token = { 0 } + * conf->tp.sr_token = { 0 } + * conf->tp.sr_enabled = 0 * conf->tp.preferred_address = NULL + * conf->sr_token_key = { 0, NULL } */ conf->tp.max_idle_timeout = NGX_CONF_UNSET_MSEC; @@ -304,6 +313,8 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) } } + ngx_conf_merge_str_value(conf->sr_token_key, prev->sr_token_key, ""); + return NGX_CONF_OK; } -- cgit From 0f843cfb74dd4dab7bff4d9a0f7e73b8b8cb61f0 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Thu, 1 Oct 2020 10:04:35 +0300 Subject: QUIC: moved ssl configuration pointer to quic configuration. The ssl configuration is obtained at config time and saved for future use. --- src/http/modules/ngx_http_quic_module.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index ec70c7286..34898984a 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -262,6 +262,8 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_quic_conf_t *prev = parent; ngx_quic_conf_t *conf = child; + ngx_http_ssl_srv_conf_t *sscf; + ngx_conf_merge_msec_value(conf->tp.max_idle_timeout, prev->tp.max_idle_timeout, 60000); @@ -315,6 +317,9 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->sr_token_key, prev->sr_token_key, ""); + sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); + conf->ssl = &sscf->ssl; + return NGX_CONF_OK; } -- cgit From e8277e42241a848b63d4af2a05ceec156642690c Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Tue, 15 Sep 2020 22:44:46 +0300 Subject: SSL: added the "ssl_keys_file" directive. --- src/http/modules/ngx_http_ssl_module.c | 21 +++++++++++++++++++++ src/http/modules/ngx_http_ssl_module.h | 2 ++ 2 files changed, 23 insertions(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 409514821..99dbd8ec6 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -119,6 +119,13 @@ static ngx_command_t ngx_http_ssl_commands[] = { 0, NULL }, + { ngx_string("ssl_keys_file"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, keys_file), + NULL }, + { ngx_string("ssl_dhparam"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -605,6 +612,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) * sscf->trusted_certificate = { 0, NULL }; * sscf->crl = { 0, NULL }; * sscf->ciphers = { 0, NULL }; + * sscf->keys_file = { 0, NULL }; * sscf->shm_zone = NULL; * sscf->ocsp_responder = { 0, NULL }; * sscf->stapling_file = { 0, NULL }; @@ -676,6 +684,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); + ngx_conf_merge_str_value(conf->keys_file, prev->keys_file, ""); + ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, @@ -912,6 +922,17 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } + if (conf->keys_file.len) { + + conf->ssl.keylog = ngx_conf_open_file(cf->cycle, &conf->keys_file); + + if (conf->ssl.keylog == NULL) { + return NGX_CONF_ERROR; + } + + SSL_CTX_set_keylog_callback(conf->ssl.ctx, ngx_ssl_keylogger); + } + if (conf->stapling) { if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index 98aa1be40..aab185e05 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -36,6 +36,8 @@ typedef struct { ngx_array_t *certificates; ngx_array_t *certificate_keys; + ngx_str_t keys_file; + ngx_array_t *certificate_values; ngx_array_t *certificate_key_values; -- cgit From 743cc997811336b01109f83c659a67752015ffad Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Mon, 19 Oct 2020 10:32:53 +0300 Subject: QUIC: reverted previous 3 commits. Changes were intended for the test repository. --- src/http/modules/ngx_http_ssl_module.c | 21 --------------------- src/http/modules/ngx_http_ssl_module.h | 2 -- 2 files changed, 23 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 99dbd8ec6..409514821 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -119,13 +119,6 @@ static ngx_command_t ngx_http_ssl_commands[] = { 0, NULL }, - { ngx_string("ssl_keys_file"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_ssl_srv_conf_t, keys_file), - NULL }, - { ngx_string("ssl_dhparam"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -612,7 +605,6 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) * sscf->trusted_certificate = { 0, NULL }; * sscf->crl = { 0, NULL }; * sscf->ciphers = { 0, NULL }; - * sscf->keys_file = { 0, NULL }; * sscf->shm_zone = NULL; * sscf->ocsp_responder = { 0, NULL }; * sscf->stapling_file = { 0, NULL }; @@ -684,8 +676,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); - ngx_conf_merge_str_value(conf->keys_file, prev->keys_file, ""); - ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, @@ -922,17 +912,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - if (conf->keys_file.len) { - - conf->ssl.keylog = ngx_conf_open_file(cf->cycle, &conf->keys_file); - - if (conf->ssl.keylog == NULL) { - return NGX_CONF_ERROR; - } - - SSL_CTX_set_keylog_callback(conf->ssl.ctx, ngx_ssl_keylogger); - } - if (conf->stapling) { if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index aab185e05..98aa1be40 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -36,8 +36,6 @@ typedef struct { ngx_array_t *certificates; ngx_array_t *certificate_keys; - ngx_str_t keys_file; - ngx_array_t *certificate_values; ngx_array_t *certificate_key_values; -- cgit From b19923f91bd41f17470c0d4538ba15adcc0b95e8 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Tue, 10 Nov 2020 00:32:56 +0300 Subject: QUIC: multiple versions support in ALPN. Previously, a version based on NGX_QUIC_DRAFT_VERSION was always set. Now it is taken from the negotiated QUIC version that may differ. --- src/http/modules/ngx_http_quic_module.h | 5 ++--- src/http/modules/ngx_http_ssl_module.c | 35 +++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 11 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h index e744eb197..bd4930f8a 100644 --- a/src/http/modules/ngx_http_quic_module.h +++ b/src/http/modules/ngx_http_quic_module.h @@ -14,9 +14,8 @@ #include -#define NGX_HTTP_QUIC_ALPN(s) NGX_HTTP_QUIC_ALPN_DRAFT(s) -#define NGX_HTTP_QUIC_ALPN_DRAFT(s) "\x05hq-" #s -#define NGX_HTTP_QUIC_ALPN_ADVERTISE NGX_HTTP_QUIC_ALPN(NGX_QUIC_DRAFT_VERSION) +#define NGX_HTTP_QUIC_ALPN_ADVERTISE "\x02hq" +#define NGX_HTTP_QUIC_ALPN_DRAFT_FMT "\x05hq-%02uD" extern ngx_module_t ngx_http_quic_module; diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index a2db307f7..111de479b 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -418,6 +418,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { +#if (NGX_HTTP_QUIC) + const char *fmt; +#endif unsigned int srvlen; unsigned char *srv; #if (NGX_DEBUG) @@ -452,16 +455,32 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, } else #endif -#if (NGX_HTTP_V3) - if (hc->addr_conf->http3) { - srv = (unsigned char *) NGX_HTTP_V3_ALPN_ADVERTISE; - srvlen = sizeof(NGX_HTTP_V3_ALPN_ADVERTISE) - 1; - } else -#endif #if (NGX_HTTP_QUIC) if (hc->addr_conf->quic) { - srv = (unsigned char *) NGX_HTTP_QUIC_ALPN_ADVERTISE; - srvlen = sizeof(NGX_HTTP_QUIC_ALPN_ADVERTISE) - 1; +#if (NGX_HTTP_V3) + if (hc->addr_conf->http3) { + srv = (unsigned char *) NGX_HTTP_V3_ALPN_ADVERTISE; + srvlen = sizeof(NGX_HTTP_V3_ALPN_ADVERTISE) - 1; + fmt = NGX_HTTP_V3_ALPN_DRAFT_FMT; + + } else +#endif + { + srv = (unsigned char *) NGX_HTTP_QUIC_ALPN_ADVERTISE; + srvlen = sizeof(NGX_HTTP_QUIC_ALPN_ADVERTISE) - 1; + fmt = NGX_HTTP_QUIC_ALPN_DRAFT_FMT; + } + + /* QUIC draft */ + + if (ngx_quic_version(c) > 1) { + srv = ngx_pnalloc(c->pool, sizeof("\x05h3-xx") - 1); + if (srv == NULL) { + return SSL_TLSEXT_ERR_NOACK; + } + srvlen = ngx_sprintf(srv, fmt, ngx_quic_version(c)) - srv; + } + } else #endif { -- cgit From 1be6d80089335f5f8635230f50a0ef4173ed9593 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 11 Nov 2020 11:57:50 +0000 Subject: QUIC: connection multiplexing per port. Also, connection migration within a single worker is implemented. --- src/http/modules/ngx_http_quic_module.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 34898984a..3993d4692 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -104,9 +104,9 @@ static ngx_command_t ngx_http_quic_commands[] = { offsetof(ngx_quic_conf_t, tp.ack_delay_exponent), &ngx_http_quic_ack_delay_exponent_bounds }, - { ngx_string("quic_active_migration"), + { ngx_string("quic_disable_active_migration"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, + ngx_conf_set_flag_slot, NGX_HTTP_SRV_CONF_OFFSET, offsetof(ngx_quic_conf_t, tp.disable_active_migration), NULL }, @@ -246,7 +246,7 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) conf->tp.initial_max_streams_bidi = NGX_CONF_UNSET_UINT; conf->tp.initial_max_streams_uni = NGX_CONF_UNSET_UINT; conf->tp.ack_delay_exponent = NGX_CONF_UNSET_UINT; - conf->tp.disable_active_migration = NGX_CONF_UNSET_UINT; + conf->tp.disable_active_migration = NGX_CONF_UNSET; conf->tp.active_connection_id_limit = NGX_CONF_UNSET_UINT; conf->retry = NGX_CONF_UNSET; @@ -301,8 +301,8 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) prev->tp.ack_delay_exponent, NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT); - ngx_conf_merge_uint_value(conf->tp.disable_active_migration, - prev->tp.disable_active_migration, 1); + ngx_conf_merge_value(conf->tp.disable_active_migration, + prev->tp.disable_active_migration, 0); ngx_conf_merge_uint_value(conf->tp.active_connection_id_limit, prev->tp.active_connection_id_limit, 2); -- cgit From 2fd31c8959fbae8f069d09b61f339358214e75d1 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Tue, 10 Nov 2020 19:40:00 +0000 Subject: QUIC: renamed c->qs to c->quic. --- src/http/modules/ngx_http_quic_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 3993d4692..515d6c953 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -179,7 +179,7 @@ static ngx_int_t ngx_http_variable_quic(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - if (r->connection->qs) { + if (r->connection->quic) { v->len = 4; v->valid = 1; -- cgit From 5bbc3f1967a8ac1cce0f16b428f156301b81beb9 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 11 Nov 2020 21:08:48 +0000 Subject: QUIC: generate default stateless reset token key. Previously, if quic_stateless_reset_token_key was empty or unspecified, initial stateless reset token was not generated. However subsequent tokens were generated with empty key, which resulted in error with certain SSL libraries, for example OpenSSL. Now a random 32-byte stateless reset token key is generated if none is specified in the configuration. As a result, stateless reset tokens are now generated for all server ids. --- src/http/modules/ngx_http_quic_module.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 515d6c953..ff79cdc8d 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -317,6 +317,19 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->sr_token_key, prev->sr_token_key, ""); + if (conf->sr_token_key.len == 0) { + conf->sr_token_key.len = NGX_QUIC_DEFAULT_SRT_KEY_LEN; + + conf->sr_token_key.data = ngx_pnalloc(cf->pool, conf->sr_token_key.len); + if (conf->sr_token_key.data == NULL) { + return NGX_CONF_ERROR; + } + + if (RAND_bytes(conf->sr_token_key.data, conf->sr_token_key.len) <= 0) { + return NGX_CONF_ERROR; + } + } + sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); conf->ssl = &sscf->ssl; -- cgit From eb8f476d599306507300a82b4a26d2a2476b748c Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Tue, 10 Nov 2020 20:42:45 +0000 Subject: Fixed generating chunked response after 46e3542d51b3. If trailers were missing and a chain carrying the last_buf flag had no data in it, then last HTTP/1 chunk was broken. The problem was introduced while implementing HTTP/3 response body generation. The change fixes the issue and reduces diff to the mainline nginx. --- src/http/modules/ngx_http_chunked_filter_module.c | 45 +++++++++++++---------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index 87b032496..371559e2f 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -18,7 +18,7 @@ typedef struct { static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf); static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r, - ngx_http_chunked_filter_ctx_t *ctx, size_t size); + ngx_http_chunked_filter_ctx_t *ctx); static ngx_http_module_t ngx_http_chunked_filter_module_ctx = { @@ -204,8 +204,25 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) out = tl; } +#if (NGX_HTTP_V3) + if (r->http_version == NGX_HTTP_VERSION_30) { + + if (cl->buf->last_buf) { + tl = ngx_http_v3_create_trailers(r); + if (tl == NULL) { + return NGX_ERROR; + } + + cl->buf->last_buf = 0; + + *ll = tl; + } + + } else +#endif + if (cl->buf->last_buf) { - tl = ngx_http_chunked_create_trailers(r, ctx, size); + tl = ngx_http_chunked_create_trailers(r, ctx); if (tl == NULL) { return NGX_ERROR; } @@ -214,12 +231,11 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) *ll = tl; - } else if (size > 0 -#if (NGX_HTTP_V3) - && r->http_version != NGX_HTTP_VERSION_30 -#endif - ) - { + if (size == 0) { + tl->buf->pos += 2; + } + + } else if (size > 0) { tl = ngx_chain_get_free_buf(r->pool, &ctx->free); if (tl == NULL) { return NGX_ERROR; @@ -250,7 +266,7 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) static ngx_chain_t * ngx_http_chunked_create_trailers(ngx_http_request_t *r, - ngx_http_chunked_filter_ctx_t *ctx, size_t size) + ngx_http_chunked_filter_ctx_t *ctx) { size_t len; ngx_buf_t *b; @@ -259,12 +275,6 @@ ngx_http_chunked_create_trailers(ngx_http_request_t *r, ngx_list_part_t *part; ngx_table_elt_t *header; -#if (NGX_HTTP_V3) - if (r->http_version == NGX_HTTP_VERSION_30) { - return ngx_http_v3_create_trailers(r); - } -#endif - len = 0; part = &r->headers_out.trailers.part; @@ -317,10 +327,7 @@ ngx_http_chunked_create_trailers(ngx_http_request_t *r, b->last = b->pos; - if (size > 0) { - *b->last++ = CR; *b->last++ = LF; - } - + *b->last++ = CR; *b->last++ = LF; *b->last++ = '0'; *b->last++ = CR; *b->last++ = LF; -- cgit From 49f0b0d99d70fa4e895b939a320c29df28a34fff Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Tue, 17 Nov 2020 21:12:36 +0000 Subject: HTTP/3: finalize chunked response body chain with NULL. Unfinalized chain could result in segfault. The problem was introduced in ef83990f0e25. Patch by Andrey Kolyshkin. --- src/http/modules/ngx_http_chunked_filter_module.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index 371559e2f..138369815 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -216,6 +216,9 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) cl->buf->last_buf = 0; *ll = tl; + + } else { + *ll = NULL; } } else -- cgit From 4b440cbf97af3ffe0ab31cb083fb1ce5b0fb5f89 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Fri, 27 Nov 2020 17:46:21 +0000 Subject: HTTP/3: introduced ngx_http_v3_filter. The filter is responsible for creating HTTP/3 response header and body. The change removes differences to the default branch for ngx_http_chunked_filter_module and ngx_http_header_filter_module. --- src/http/modules/ngx_http_chunked_filter_module.c | 50 ++--------------------- 1 file changed, 4 insertions(+), 46 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index 138369815..4d6fd3eed 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -106,7 +106,6 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { u_char *chunk; off_t size; - size_t n; ngx_int_t rc; ngx_buf_t *b; ngx_chain_t *out, *cl, *tl, **ll; @@ -162,68 +161,27 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) chunk = b->start; if (chunk == NULL) { + /* the "0000000000000000" is 64-bit hexadecimal string */ -#if (NGX_HTTP_V3) - if (r->http_version == NGX_HTTP_VERSION_30) { - n = NGX_HTTP_V3_VARLEN_INT_LEN * 2; - - } else -#endif - { - /* the "0000000000000000" is 64-bit hexadecimal string */ - n = sizeof("0000000000000000" CRLF) - 1; - } - - chunk = ngx_palloc(r->pool, n); + chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1); if (chunk == NULL) { return NGX_ERROR; } b->start = chunk; - b->end = chunk + n; + b->end = chunk + sizeof("0000000000000000" CRLF) - 1; } b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module; b->memory = 0; b->temporary = 1; b->pos = chunk; - -#if (NGX_HTTP_V3) - if (r->http_version == NGX_HTTP_VERSION_30) { - b->last = (u_char *) ngx_http_v3_encode_varlen_int(chunk, - NGX_HTTP_V3_FRAME_DATA); - b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, size); - - } else -#endif - { - b->last = ngx_sprintf(chunk, "%xO" CRLF, size); - } + b->last = ngx_sprintf(chunk, "%xO" CRLF, size); tl->next = out; out = tl; } -#if (NGX_HTTP_V3) - if (r->http_version == NGX_HTTP_VERSION_30) { - - if (cl->buf->last_buf) { - tl = ngx_http_v3_create_trailers(r); - if (tl == NULL) { - return NGX_ERROR; - } - - cl->buf->last_buf = 0; - - *ll = tl; - - } else { - *ll = NULL; - } - - } else -#endif - if (cl->buf->last_buf) { tl = ngx_http_chunked_create_trailers(r, ctx); if (tl == NULL) { -- cgit From a96989365676de270fbb2ad19480435ad5e86df4 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Tue, 22 Dec 2020 12:04:15 +0300 Subject: QUIC: fixed building ALPN callback without debug and http2. --- src/http/modules/ngx_http_ssl_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 111de479b..97c58e445 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -429,7 +429,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, #if (NGX_HTTP_V2 || NGX_HTTP_QUIC) ngx_http_connection_t *hc; #endif -#if (NGX_HTTP_V2 || NGX_DEBUG) +#if (NGX_HTTP_V2 || NGX_HTTP_QUIC || NGX_DEBUG) ngx_connection_t *c; c = ngx_ssl_get_connection(ssl_conn); -- cgit From 9e489d208fff35c490b43980a064c38cc8dc4f2c Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Fri, 22 Jan 2021 16:34:06 +0300 Subject: HTTP/3: refactored request parser. The change reduces diff to the default branch for src/http/ngx_http_request.c and src/http/ngx_http_parse.c. --- src/http/modules/ngx_http_quic_module.c | 37 +++++++++++++++++++++++++++++++++ src/http/modules/ngx_http_quic_module.h | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index ff79cdc8d..5314af35b 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -175,6 +175,43 @@ static ngx_http_variable_t ngx_http_quic_vars[] = { }; +ngx_int_t +ngx_http_quic_init(ngx_connection_t *c) +{ + ngx_quic_conf_t *qcf; + ngx_http_connection_t *hc, *phc; + ngx_http_core_loc_conf_t *clcf; + + hc = c->data; + + hc->ssl = 1; + + if (c->quic == NULL) { + c->log->connection = c->number; + + qcf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_quic_module); + + ngx_quic_run(c, qcf); + + return NGX_DONE; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http init quic stream"); + + phc = c->quic->parent->data; + + if (phc->ssl_servername) { + hc->ssl_servername = phc->ssl_servername; + hc->conf_ctx = phc->conf_ctx; + + clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module); + ngx_set_connection_log(c, clcf->error_log); + } + + return NGX_OK; +} + + static ngx_int_t ngx_http_variable_quic(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h index bd4930f8a..bc75dd501 100644 --- a/src/http/modules/ngx_http_quic_module.h +++ b/src/http/modules/ngx_http_quic_module.h @@ -18,7 +18,7 @@ #define NGX_HTTP_QUIC_ALPN_DRAFT_FMT "\x05hq-%02uD" -extern ngx_module_t ngx_http_quic_module; +ngx_int_t ngx_http_quic_init(ngx_connection_t *c); #endif /* _NGX_HTTP_QUIC_H_INCLUDED_ */ -- cgit From 89dda20510bf7dac952a2dc0b5f29deba376e25f Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Fri, 29 Jan 2021 15:53:47 +0300 Subject: QUIC: stateless retry. Previously, quic connection object was created when Retry packet was sent. This is neither necessary nor convenient, and contradicts the idea of retry: protecting from bad clients and saving server resources. Now, the connection is not created, token is verified cryptographically instead of holding it in connection. --- src/http/modules/ngx_http_quic_module.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 5314af35b..901d1a563 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -346,10 +346,8 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->retry, prev->retry, 0); - if (conf->retry) { - if (RAND_bytes(conf->token_key, sizeof(conf->token_key)) <= 0) { - return NGX_CONF_ERROR; - } + if (RAND_bytes(conf->token_key, sizeof(conf->token_key)) <= 0) { + return NGX_CONF_ERROR; } ngx_conf_merge_str_value(conf->sr_token_key, prev->sr_token_key, ""); -- cgit From eab61bfc22b583031b5a6f42f9c277223ce18672 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Mon, 8 Feb 2021 16:49:33 +0300 Subject: QUIC: the "quic_host_key" directive. The token generation in QUIC is reworked. Single host key is used to generate all required keys of needed sizes using HKDF. The "quic_stateless_reset_token_key" directive is removed. Instead, the "quic_host_key" directive is used, which reads key from file, or sets it to random bytes if not specified. --- src/http/modules/ngx_http_quic_module.c | 149 ++++++++++++++++++++++++++++---- 1 file changed, 133 insertions(+), 16 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 901d1a563..8106e3e0a 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -9,6 +9,8 @@ #include #include +#include + static ngx_int_t ngx_http_variable_quic(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -20,7 +22,8 @@ static char *ngx_http_quic_max_ack_delay(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_quic_max_udp_payload_size(ngx_conf_t *cf, void *post, void *data); - +static char *ngx_http_quic_host_key(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static ngx_conf_post_t ngx_http_quic_max_ack_delay_post = { ngx_http_quic_max_ack_delay }; @@ -125,11 +128,11 @@ static ngx_command_t ngx_http_quic_commands[] = { offsetof(ngx_quic_conf_t, retry), NULL }, - { ngx_string("quic_stateless_reset_token_key"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, - ngx_conf_set_str_slot, + { ngx_string("quic_host_key"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_http_quic_host_key, NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, sr_token_key), + 0, NULL }, ngx_null_command @@ -174,6 +177,8 @@ static ngx_http_variable_t ngx_http_quic_vars[] = { ngx_http_null_variable }; +static ngx_str_t ngx_http_quic_salt = ngx_string("ngx_quic"); + ngx_int_t ngx_http_quic_init(ngx_connection_t *c) @@ -270,7 +275,7 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) * conf->tp.sr_token = { 0 } * conf->tp.sr_enabled = 0 * conf->tp.preferred_address = NULL - * conf->sr_token_key = { 0, NULL } + * conf->host_key = { 0, NULL } */ conf->tp.max_idle_timeout = NGX_CONF_UNSET_MSEC; @@ -346,25 +351,39 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->retry, prev->retry, 0); - if (RAND_bytes(conf->token_key, sizeof(conf->token_key)) <= 0) { - return NGX_CONF_ERROR; - } - - ngx_conf_merge_str_value(conf->sr_token_key, prev->sr_token_key, ""); + ngx_conf_merge_str_value(conf->host_key, prev->host_key, ""); - if (conf->sr_token_key.len == 0) { - conf->sr_token_key.len = NGX_QUIC_DEFAULT_SRT_KEY_LEN; + if (conf->host_key.len == 0) { - conf->sr_token_key.data = ngx_pnalloc(cf->pool, conf->sr_token_key.len); - if (conf->sr_token_key.data == NULL) { + conf->host_key.len = NGX_QUIC_DEFAULT_HOST_KEY_LEN; + conf->host_key.data = ngx_palloc(cf->pool, conf->host_key.len); + if (conf->host_key.data == NULL) { return NGX_CONF_ERROR; } - if (RAND_bytes(conf->sr_token_key.data, conf->sr_token_key.len) <= 0) { + if (RAND_bytes(conf->host_key.data, NGX_QUIC_DEFAULT_HOST_KEY_LEN) + <= 0) + { return NGX_CONF_ERROR; } } + if (ngx_quic_derive_key(cf->log, "av_token_key", + &conf->host_key, &ngx_http_quic_salt, + conf->av_token_key, NGX_QUIC_AV_KEY_LEN) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (ngx_quic_derive_key(cf->log, "sr_token_key", + &conf->host_key, &ngx_http_quic_salt, + conf->sr_token_key, NGX_QUIC_SR_KEY_LEN) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); conf->ssl = &sscf->ssl; @@ -407,3 +426,101 @@ ngx_http_quic_max_udp_payload_size(ngx_conf_t *cf, void *post, void *data) return NGX_CONF_OK; } + + +static char * +ngx_http_quic_host_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_quic_conf_t *qcf = conf; + + u_char *buf; + size_t size; + ssize_t n; + ngx_str_t *value; + ngx_file_t file; + ngx_file_info_t fi; + + if (qcf->host_key.len) { + return "is duplicate"; + } + + buf = NULL; +#if (NGX_SUPPRESS_WARN) + size = 0; +#endif + + value = cf->args->elts; + + if (ngx_conf_full_name(cf->cycle, &value[1], 1) != NGX_OK) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&file, sizeof(ngx_file_t)); + file.name = value[1]; + file.log = cf->log; + + file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + + if (file.fd == NGX_INVALID_FILE) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, + ngx_open_file_n " \"%V\" failed", &file.name); + return NGX_CONF_ERROR; + } + + if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_fd_info_n " \"%V\" failed", &file.name); + goto failed; + } + + size = ngx_file_size(&fi); + + if (size == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" zero key size", &file.name); + goto failed; + } + + buf = ngx_pnalloc(cf->pool, size); + if (buf == NULL) { + goto failed; + } + + n = ngx_read_file(&file, buf, size, 0); + + if (n == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_read_file_n " \"%V\" failed", &file.name); + goto failed; + } + + if ((size_t) n != size) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, 0, + ngx_read_file_n " \"%V\" returned only " + "%z bytes instead of %uz", &file.name, n, size); + goto failed; + } + + qcf->host_key.data = buf; + qcf->host_key.len = n; + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + + return NGX_CONF_OK; + +failed: + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + + if (buf) { + ngx_explicit_memzero(buf, size); + } + + return NGX_CONF_ERROR; +} -- cgit From 780de6de44b066a253a455a061efb09ff8060d09 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Tue, 16 Mar 2021 13:48:28 +0300 Subject: QUIC: fixed hq ALPN id for the final draft. It was an agreement to use "hq-interop"[1] for interoperability testing. [1] https://github.com/quicwg/base-drafts/wiki/ALPN-IDs-used-with-QUIC --- src/http/modules/ngx_http_quic_module.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h index bc75dd501..21d4a40a1 100644 --- a/src/http/modules/ngx_http_quic_module.h +++ b/src/http/modules/ngx_http_quic_module.h @@ -14,7 +14,7 @@ #include -#define NGX_HTTP_QUIC_ALPN_ADVERTISE "\x02hq" +#define NGX_HTTP_QUIC_ALPN_ADVERTISE "\x0Ahq-interop" #define NGX_HTTP_QUIC_ALPN_DRAFT_FMT "\x05hq-%02uD" -- cgit From 25a74b52d14fa0e0bbac4c0d1b3e432bbb31ca97 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 22 Mar 2021 15:51:14 +0300 Subject: HTTP/3: set initial_max_streams_uni default value to 3. The maximum number of HTTP/3 unidirectional client streams we can handle is 3: control, decode and encode. These streams are never closed. --- src/http/modules/ngx_http_quic_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 8106e3e0a..5282bf4bb 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -337,7 +337,7 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) prev->tp.initial_max_streams_bidi, 16); ngx_conf_merge_uint_value(conf->tp.initial_max_streams_uni, - prev->tp.initial_max_streams_uni, 16); + prev->tp.initial_max_streams_uni, 3); ngx_conf_merge_uint_value(conf->tp.ack_delay_exponent, prev->tp.ack_delay_exponent, -- cgit From 2f5bcafdde60c722fe5cd28965613abafb451acb Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Tue, 13 Apr 2021 12:38:34 +0300 Subject: QUIC: normalize header inclusion. Stop including QUIC headers with no user-serviceable parts inside. This allows to provide a much cleaner QUIC interface. To cope with that, ngx_quic_derive_key() is now explicitly exported for v3 and quic modules. Additionally, this completely hides the ngx_quic_keys_t internal type. --- src/http/modules/ngx_http_quic_module.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 5282bf4bb..b7661b42c 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -9,8 +9,6 @@ #include #include -#include - static ngx_int_t ngx_http_variable_quic(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); -- cgit From 38773a3c1130d34715f1cce24527a10258447354 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 5 May 2021 14:53:36 +0300 Subject: HTTP/3: reference h3c directly from ngx_http_connection_t. Previously, an ngx_http_v3_connection_t object was created for HTTP/3 and then assinged to c->data instead of the generic ngx_http_connection_t object. Now a direct reference is added to ngx_http_connection_t, which is less confusing and does not require a flag for http3. --- src/http/modules/ngx_http_quic_module.c | 2 +- src/http/modules/ngx_http_quic_module.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index b7661b42c..2354dfd8b 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -201,7 +201,7 @@ ngx_http_quic_init(ngx_connection_t *c) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http init quic stream"); - phc = c->quic->parent->data; + phc = ngx_http_quic_get_connection(c); if (phc->ssl_servername) { hc->ssl_servername = phc->ssl_servername; diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h index 21d4a40a1..8cadfbb87 100644 --- a/src/http/modules/ngx_http_quic_module.h +++ b/src/http/modules/ngx_http_quic_module.h @@ -18,6 +18,10 @@ #define NGX_HTTP_QUIC_ALPN_DRAFT_FMT "\x05hq-%02uD" +#define ngx_http_quic_get_connection(c) \ + ((ngx_http_connection_t *) (c)->quic->parent->data) + + ngx_int_t ngx_http_quic_init(ngx_connection_t *c); -- cgit From d54d551e2a880c7a7691a83d212eb707eb0f82ba Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 30 Jun 2021 13:47:38 +0300 Subject: QUIC: consider max_ack_delay=16384 invalid. As per RFC 9000: Values of 2^14 or greater are invalid. --- src/http/modules/ngx_http_quic_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 2354dfd8b..d933dd1f9 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -394,7 +394,7 @@ ngx_http_quic_max_ack_delay(ngx_conf_t *cf, void *post, void *data) { ngx_msec_t *sp = data; - if (*sp > 16384) { + if (*sp >= 16384) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"quic_max_ack_delay\" must be less than 16384"); -- cgit From 6157d0b5c1b3a6be7928748df2cda19838889f4f Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Tue, 20 Jul 2021 12:37:12 +0300 Subject: QUIC: the "quic_gso" directive. The directive enables usage of UDP segmentation offloading by quic. By default, gso is disabled since it is not always operational when detected (depends on interface configuration). --- src/http/modules/ngx_http_quic_module.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index d933dd1f9..ab84583f2 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -126,6 +126,13 @@ static ngx_command_t ngx_http_quic_commands[] = { offsetof(ngx_quic_conf_t, retry), NULL }, + { ngx_string("quic_gso"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_quic_conf_t, gso_enabled), + NULL }, + { ngx_string("quic_host_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_http_quic_host_key, @@ -290,6 +297,7 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) conf->tp.active_connection_id_limit = NGX_CONF_UNSET_UINT; conf->retry = NGX_CONF_UNSET; + conf->gso_enabled = NGX_CONF_UNSET; conf->require_alpn = 1; return conf; @@ -348,6 +356,7 @@ ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) prev->tp.active_connection_id_limit, 2); ngx_conf_merge_value(conf->retry, prev->retry, 0); + ngx_conf_merge_value(conf->gso_enabled, prev->gso_enabled, 0); ngx_conf_merge_str_value(conf->host_key, prev->host_key, ""); -- cgit From b93ae5d0670f265bec60cd616dd42b0ce96d8e2d Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 2 Aug 2021 15:48:21 +0300 Subject: QUIC: stream limits in "hq" mode. The "hq" mode is HTTP/0.9-1.1 over QUIC. The following limits are introduced: - uni streams are not allowed - keepalive_requests is enforced - keepalive_time is enforced In case of error, QUIC connection is finalized with 0x101 code. This code corresponds to HTTP/3 General Protocol Error. --- src/http/modules/ngx_http_quic_module.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index ab84583f2..b41c069b6 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -188,6 +188,7 @@ static ngx_str_t ngx_http_quic_salt = ngx_string("ngx_quic"); ngx_int_t ngx_http_quic_init(ngx_connection_t *c) { + uint64_t n; ngx_quic_conf_t *qcf; ngx_http_connection_t *hc, *phc; ngx_http_core_loc_conf_t *clcf; @@ -208,6 +209,40 @@ ngx_http_quic_init(ngx_connection_t *c) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http init quic stream"); +#if (NGX_HTTP_V3) + if (!hc->addr_conf->http3) +#endif + { + /* Use HTTP/3 General Protocol Error Code 0x101 for finalization */ + + if (c->quic->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { + ngx_quic_finalize_connection(c->quic->parent, 0x101, + "unexpected uni stream"); + ngx_http_close_connection(c); + return NGX_DONE; + } + + clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module); + + n = c->quic->id >> 2; + + if (n >= clcf->keepalive_requests) { + ngx_quic_finalize_connection(c->quic->parent, 0x101, + "reached maximum number of requests"); + ngx_http_close_connection(c); + return NGX_DONE; + } + + if (ngx_current_msec - c->quic->parent->start_time + > clcf->keepalive_time) + { + ngx_quic_finalize_connection(c->quic->parent, 0x101, + "reached maximum time for requests"); + ngx_http_close_connection(c); + return NGX_DONE; + } + } + phc = ngx_http_quic_get_connection(c); if (phc->ssl_servername) { -- cgit From 2765b63216fab23040aa83731ffd7d767cf0fa31 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Wed, 29 Sep 2021 15:01:53 +0300 Subject: Fixed mismerge of ssl_reject_handshake in 71b7453fb11f. In particular, this fixes rejecting "listen .. quic|http3" configurations without TLSv1.3 configured. --- src/http/modules/ngx_http_ssl_module.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index efbc4594c..dbb5905df 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -1385,14 +1385,23 @@ ngx_http_ssl_init(ngx_conf_t *cf) sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; if (sscf->certificates) { + + if (addr[a].opt.quic && !(sscf->protocols & NGX_SSL_TLSv1_3)) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "\"ssl_protocols\" must enable TLSv1.3 for " + "the \"listen ... %s\" directive in %s:%ui", + name, cscf->file_name, cscf->line); + return NGX_ERROR; + } + continue; } if (!sscf->reject_handshake) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " - "the \"listen ... ssl\" directive in %s:%ui", - cscf->file_name, cscf->line); + "the \"listen ... %s\" directive in %s:%ui", + name, cscf->file_name, cscf->line); return NGX_ERROR; } @@ -1417,14 +1426,6 @@ ngx_http_ssl_init(ngx_conf_t *cf) name, cscf->file_name, cscf->line); return NGX_ERROR; } - - if (addr[a].opt.quic && !(sscf->protocols & NGX_SSL_TLSv1_3)) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "\"ssl_protocols\" did not enable TLSv1.3 for " - "the \"listen ... %s\" directives in %s:%ui", - name, cscf->file_name, cscf->line); - return NGX_ERROR; - } } } -- cgit From dab6035d68f3dd3f212393635c193c7aefea0d65 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Wed, 29 Sep 2021 15:01:59 +0300 Subject: HTTP/3: fixed segfault when using SSL certificates with variables. A QUIC connection doesn't have c->log->data and friends initialized to sensible values. Yet, a request can be created in the certificate callback with such an assumption, which leads to a segmentation fault due to null pointer dereference in ngx_http_free_request(). The fix is to adjust initializing the QUIC part of a connection such that it has all of that in place. Further, this appends logging error context for unsuccessful QUIC handshakes: - cannot load certificate .. while handling frames - SSL_do_handshake() failed .. while sending frames --- src/http/modules/ngx_http_quic_module.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index b41c069b6..ce13a223f 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -198,8 +198,6 @@ ngx_http_quic_init(ngx_connection_t *c) hc->ssl = 1; if (c->quic == NULL) { - c->log->connection = c->number; - qcf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_quic_module); ngx_quic_run(c, qcf); -- cgit From 0572c2a69f4edef04e3babdb6f9ef18ff52a9619 Mon Sep 17 00:00:00 2001 From: Vladimir Homutov Date: Wed, 3 Nov 2021 13:36:21 +0300 Subject: QUIC: connections with wrong ALPN protocols are now rejected. Previously, it was not enforced in the stream module. Now, since b9e02e9b2f1d it is possible to specify protocols. Since ALPN is always required, the 'require_alpn' setting is now obsolete. --- src/http/modules/ngx_http_quic_module.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index ce13a223f..9e6d17ead 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -331,7 +331,6 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) conf->retry = NGX_CONF_UNSET; conf->gso_enabled = NGX_CONF_UNSET; - conf->require_alpn = 1; return conf; } -- cgit From 50dd9ba7e85a8d4eeecaad8776f83adc607fd132 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Thu, 11 Nov 2021 19:07:00 +0300 Subject: QUIC: reject streams which we could not create. The reasons why a stream may not be created by server currently include hitting worker_connections limit and memory allocation error. Previously in these cases the entire QUIC connection was closed and all its streams were shut down. Now the new stream is rejected and existing streams continue working. To reject an HTTP/3 request stream, RESET_STREAM and STOP_SENDING with H3_REQUEST_REJECTED error code are sent to client. HTTP/3 uni streams and Stream streams are not rejected. --- src/http/modules/ngx_http_quic_module.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 9e6d17ead..323ee2ead 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -314,6 +314,7 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) * conf->tp.sr_enabled = 0 * conf->tp.preferred_address = NULL * conf->host_key = { 0, NULL } + * cong->stream_reject_code_uni = 0; */ conf->tp.max_idle_timeout = NGX_CONF_UNSET_MSEC; @@ -331,6 +332,8 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) conf->retry = NGX_CONF_UNSET; conf->gso_enabled = NGX_CONF_UNSET; + conf->stream_close_code = NGX_HTTP_V3_ERR_NO_ERROR; + conf->stream_reject_code_bidi = NGX_HTTP_V3_ERR_REQUEST_REJECTED; return conf; } -- cgit From bfa2d1d59932b9983e3a694ed651bc4fe349edc5 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 17 Nov 2021 18:49:48 +0300 Subject: HTTP/3: fixed compilation with QUIC, but without HTTP/3. --- src/http/modules/ngx_http_quic_module.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c index 323ee2ead..9470df60e 100644 --- a/src/http/modules/ngx_http_quic_module.c +++ b/src/http/modules/ngx_http_quic_module.c @@ -332,8 +332,10 @@ ngx_http_quic_create_srv_conf(ngx_conf_t *cf) conf->retry = NGX_CONF_UNSET; conf->gso_enabled = NGX_CONF_UNSET; +#if (NGX_HTTP_V3) conf->stream_close_code = NGX_HTTP_V3_ERR_NO_ERROR; conf->stream_reject_code_bidi = NGX_HTTP_V3_ERR_REQUEST_REJECTED; +#endif return conf; } -- cgit From 7e7e552a10b9e5d0fd94b1a657061253ccac709e Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Thu, 2 Dec 2021 13:59:09 +0300 Subject: HTTP/3: adjusted ALPN macro names to align with 61abb35bb8cf. --- src/http/modules/ngx_http_quic_module.h | 2 +- src/http/modules/ngx_http_ssl_module.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h index 8cadfbb87..3b96fcc47 100644 --- a/src/http/modules/ngx_http_quic_module.h +++ b/src/http/modules/ngx_http_quic_module.h @@ -14,7 +14,7 @@ #include -#define NGX_HTTP_QUIC_ALPN_ADVERTISE "\x0Ahq-interop" +#define NGX_HTTP_QUIC_ALPN_PROTO "\x0Ahq-interop" #define NGX_HTTP_QUIC_ALPN_DRAFT_FMT "\x05hq-%02uD" diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index f2a85f12e..afeb68462 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -455,15 +455,15 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, if (hc->addr_conf->quic) { #if (NGX_HTTP_V3) if (hc->addr_conf->http3) { - srv = (unsigned char *) NGX_HTTP_V3_ALPN_ADVERTISE; - srvlen = sizeof(NGX_HTTP_V3_ALPN_ADVERTISE) - 1; + srv = (unsigned char *) NGX_HTTP_V3_ALPN_PROTO; + srvlen = sizeof(NGX_HTTP_V3_ALPN_PROTO) - 1; fmt = NGX_HTTP_V3_ALPN_DRAFT_FMT; } else #endif { - srv = (unsigned char *) NGX_HTTP_QUIC_ALPN_ADVERTISE; - srvlen = sizeof(NGX_HTTP_QUIC_ALPN_ADVERTISE) - 1; + srv = (unsigned char *) NGX_HTTP_QUIC_ALPN_PROTO; + srvlen = sizeof(NGX_HTTP_QUIC_ALPN_PROTO) - 1; fmt = NGX_HTTP_QUIC_ALPN_DRAFT_FMT; } -- cgit From 731915a0c5e90b79d3cca1a4b0a3c33e1f77631c Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 6 Dec 2021 13:02:36 +0300 Subject: HTTP/3: merged ngx_http_quic_module into ngx_http_v3_module. --- src/http/modules/ngx_http_quic_module.c | 570 -------------------------------- src/http/modules/ngx_http_quic_module.h | 28 -- src/http/modules/ngx_http_ssl_module.c | 15 +- 3 files changed, 6 insertions(+), 607 deletions(-) delete mode 100644 src/http/modules/ngx_http_quic_module.c delete mode 100644 src/http/modules/ngx_http_quic_module.h (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_quic_module.c b/src/http/modules/ngx_http_quic_module.c deleted file mode 100644 index 9470df60e..000000000 --- a/src/http/modules/ngx_http_quic_module.c +++ /dev/null @@ -1,570 +0,0 @@ - -/* - * Copyright (C) Nginx, Inc. - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include - - -static ngx_int_t ngx_http_variable_quic(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_quic_add_variables(ngx_conf_t *cf); -static void *ngx_http_quic_create_srv_conf(ngx_conf_t *cf); -static char *ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, - void *child); -static char *ngx_http_quic_max_ack_delay(ngx_conf_t *cf, void *post, - void *data); -static char *ngx_http_quic_max_udp_payload_size(ngx_conf_t *cf, void *post, - void *data); -static char *ngx_http_quic_host_key(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - -static ngx_conf_post_t ngx_http_quic_max_ack_delay_post = - { ngx_http_quic_max_ack_delay }; -static ngx_conf_post_t ngx_http_quic_max_udp_payload_size_post = - { ngx_http_quic_max_udp_payload_size }; -static ngx_conf_num_bounds_t ngx_http_quic_ack_delay_exponent_bounds = - { ngx_conf_check_num_bounds, 0, 20 }; -static ngx_conf_num_bounds_t ngx_http_quic_active_connection_id_limit_bounds = - { ngx_conf_check_num_bounds, 2, -1 }; - - -static ngx_command_t ngx_http_quic_commands[] = { - - { ngx_string("quic_max_idle_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.max_idle_timeout), - NULL }, - - { ngx_string("quic_max_ack_delay"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.max_ack_delay), - &ngx_http_quic_max_ack_delay_post }, - - { ngx_string("quic_max_udp_payload_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.max_udp_payload_size), - &ngx_http_quic_max_udp_payload_size_post }, - - { ngx_string("quic_initial_max_data"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.initial_max_data), - NULL }, - - { ngx_string("quic_initial_max_stream_data_bidi_local"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_bidi_local), - NULL }, - - { ngx_string("quic_initial_max_stream_data_bidi_remote"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_bidi_remote), - NULL }, - - { ngx_string("quic_initial_max_stream_data_uni"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.initial_max_stream_data_uni), - NULL }, - - { ngx_string("quic_initial_max_streams_bidi"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.initial_max_streams_bidi), - NULL }, - - { ngx_string("quic_initial_max_streams_uni"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.initial_max_streams_uni), - NULL }, - - { ngx_string("quic_ack_delay_exponent"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.ack_delay_exponent), - &ngx_http_quic_ack_delay_exponent_bounds }, - - { ngx_string("quic_disable_active_migration"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.disable_active_migration), - NULL }, - - { ngx_string("quic_active_connection_id_limit"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, tp.active_connection_id_limit), - &ngx_http_quic_active_connection_id_limit_bounds }, - - { ngx_string("quic_retry"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, retry), - NULL }, - - { ngx_string("quic_gso"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_quic_conf_t, gso_enabled), - NULL }, - - { ngx_string("quic_host_key"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_http_quic_host_key, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_quic_module_ctx = { - ngx_http_quic_add_variables, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - ngx_http_quic_create_srv_conf, /* create server configuration */ - ngx_http_quic_merge_srv_conf, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_http_quic_module = { - NGX_MODULE_V1, - &ngx_http_quic_module_ctx, /* module context */ - ngx_http_quic_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_http_variable_t ngx_http_quic_vars[] = { - - { ngx_string("quic"), NULL, ngx_http_variable_quic, 0, 0, 0 }, - - ngx_http_null_variable -}; - -static ngx_str_t ngx_http_quic_salt = ngx_string("ngx_quic"); - - -ngx_int_t -ngx_http_quic_init(ngx_connection_t *c) -{ - uint64_t n; - ngx_quic_conf_t *qcf; - ngx_http_connection_t *hc, *phc; - ngx_http_core_loc_conf_t *clcf; - - hc = c->data; - - hc->ssl = 1; - - if (c->quic == NULL) { - qcf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_quic_module); - - ngx_quic_run(c, qcf); - - return NGX_DONE; - } - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http init quic stream"); - -#if (NGX_HTTP_V3) - if (!hc->addr_conf->http3) -#endif - { - /* Use HTTP/3 General Protocol Error Code 0x101 for finalization */ - - if (c->quic->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) { - ngx_quic_finalize_connection(c->quic->parent, 0x101, - "unexpected uni stream"); - ngx_http_close_connection(c); - return NGX_DONE; - } - - clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module); - - n = c->quic->id >> 2; - - if (n >= clcf->keepalive_requests) { - ngx_quic_finalize_connection(c->quic->parent, 0x101, - "reached maximum number of requests"); - ngx_http_close_connection(c); - return NGX_DONE; - } - - if (ngx_current_msec - c->quic->parent->start_time - > clcf->keepalive_time) - { - ngx_quic_finalize_connection(c->quic->parent, 0x101, - "reached maximum time for requests"); - ngx_http_close_connection(c); - return NGX_DONE; - } - } - - phc = ngx_http_quic_get_connection(c); - - if (phc->ssl_servername) { - hc->ssl_servername = phc->ssl_servername; - hc->conf_ctx = phc->conf_ctx; - - clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module); - ngx_set_connection_log(c, clcf->error_log); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_variable_quic(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - if (r->connection->quic) { - - v->len = 4; - v->valid = 1; - v->no_cacheable = 1; - v->not_found = 0; - v->data = (u_char *) "quic"; - return NGX_OK; - } - - v->not_found = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_quic_add_variables(ngx_conf_t *cf) -{ - ngx_http_variable_t *var, *v; - - for (v = ngx_http_quic_vars; v->name.len; v++) { - var = ngx_http_add_variable(cf, &v->name, v->flags); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = v->get_handler; - var->data = v->data; - } - - return NGX_OK; -} - - -static void * -ngx_http_quic_create_srv_conf(ngx_conf_t *cf) -{ - ngx_quic_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_quic_conf_t)); - if (conf == NULL) { - return NULL; - } - - /* - * set by ngx_pcalloc(): - * - * conf->tp.original_dcid = { 0, NULL }; - * conf->tp.initial_scid = { 0, NULL }; - * conf->tp.retry_scid = { 0, NULL }; - * conf->tp.sr_token = { 0 } - * conf->tp.sr_enabled = 0 - * conf->tp.preferred_address = NULL - * conf->host_key = { 0, NULL } - * cong->stream_reject_code_uni = 0; - */ - - conf->tp.max_idle_timeout = NGX_CONF_UNSET_MSEC; - conf->tp.max_ack_delay = NGX_CONF_UNSET_MSEC; - conf->tp.max_udp_payload_size = NGX_CONF_UNSET_SIZE; - conf->tp.initial_max_data = NGX_CONF_UNSET_SIZE; - conf->tp.initial_max_stream_data_bidi_local = NGX_CONF_UNSET_SIZE; - conf->tp.initial_max_stream_data_bidi_remote = NGX_CONF_UNSET_SIZE; - conf->tp.initial_max_stream_data_uni = NGX_CONF_UNSET_SIZE; - conf->tp.initial_max_streams_bidi = NGX_CONF_UNSET_UINT; - conf->tp.initial_max_streams_uni = NGX_CONF_UNSET_UINT; - conf->tp.ack_delay_exponent = NGX_CONF_UNSET_UINT; - conf->tp.disable_active_migration = NGX_CONF_UNSET; - conf->tp.active_connection_id_limit = NGX_CONF_UNSET_UINT; - - conf->retry = NGX_CONF_UNSET; - conf->gso_enabled = NGX_CONF_UNSET; -#if (NGX_HTTP_V3) - conf->stream_close_code = NGX_HTTP_V3_ERR_NO_ERROR; - conf->stream_reject_code_bidi = NGX_HTTP_V3_ERR_REQUEST_REJECTED; -#endif - - return conf; -} - - -static char * -ngx_http_quic_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_quic_conf_t *prev = parent; - ngx_quic_conf_t *conf = child; - - ngx_http_ssl_srv_conf_t *sscf; - - ngx_conf_merge_msec_value(conf->tp.max_idle_timeout, - prev->tp.max_idle_timeout, 60000); - - ngx_conf_merge_msec_value(conf->tp.max_ack_delay, - prev->tp.max_ack_delay, - NGX_QUIC_DEFAULT_MAX_ACK_DELAY); - - ngx_conf_merge_size_value(conf->tp.max_udp_payload_size, - prev->tp.max_udp_payload_size, - NGX_QUIC_MAX_UDP_PAYLOAD_SIZE); - - ngx_conf_merge_size_value(conf->tp.initial_max_data, - prev->tp.initial_max_data, - 16 * NGX_QUIC_STREAM_BUFSIZE); - - ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_bidi_local, - prev->tp.initial_max_stream_data_bidi_local, - NGX_QUIC_STREAM_BUFSIZE); - - ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_bidi_remote, - prev->tp.initial_max_stream_data_bidi_remote, - NGX_QUIC_STREAM_BUFSIZE); - - ngx_conf_merge_size_value(conf->tp.initial_max_stream_data_uni, - prev->tp.initial_max_stream_data_uni, - NGX_QUIC_STREAM_BUFSIZE); - - ngx_conf_merge_uint_value(conf->tp.initial_max_streams_bidi, - prev->tp.initial_max_streams_bidi, 16); - - ngx_conf_merge_uint_value(conf->tp.initial_max_streams_uni, - prev->tp.initial_max_streams_uni, 3); - - ngx_conf_merge_uint_value(conf->tp.ack_delay_exponent, - prev->tp.ack_delay_exponent, - NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT); - - ngx_conf_merge_value(conf->tp.disable_active_migration, - prev->tp.disable_active_migration, 0); - - ngx_conf_merge_uint_value(conf->tp.active_connection_id_limit, - prev->tp.active_connection_id_limit, 2); - - ngx_conf_merge_value(conf->retry, prev->retry, 0); - ngx_conf_merge_value(conf->gso_enabled, prev->gso_enabled, 0); - - ngx_conf_merge_str_value(conf->host_key, prev->host_key, ""); - - if (conf->host_key.len == 0) { - - conf->host_key.len = NGX_QUIC_DEFAULT_HOST_KEY_LEN; - conf->host_key.data = ngx_palloc(cf->pool, conf->host_key.len); - if (conf->host_key.data == NULL) { - return NGX_CONF_ERROR; - } - - if (RAND_bytes(conf->host_key.data, NGX_QUIC_DEFAULT_HOST_KEY_LEN) - <= 0) - { - return NGX_CONF_ERROR; - } - } - - if (ngx_quic_derive_key(cf->log, "av_token_key", - &conf->host_key, &ngx_http_quic_salt, - conf->av_token_key, NGX_QUIC_AV_KEY_LEN) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - if (ngx_quic_derive_key(cf->log, "sr_token_key", - &conf->host_key, &ngx_http_quic_salt, - conf->sr_token_key, NGX_QUIC_SR_KEY_LEN) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); - conf->ssl = &sscf->ssl; - - return NGX_CONF_OK; -} - - -static char * -ngx_http_quic_max_ack_delay(ngx_conf_t *cf, void *post, void *data) -{ - ngx_msec_t *sp = data; - - if (*sp >= 16384) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"quic_max_ack_delay\" must be less than 16384"); - - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_http_quic_max_udp_payload_size(ngx_conf_t *cf, void *post, void *data) -{ - size_t *sp = data; - - if (*sp < NGX_QUIC_MIN_INITIAL_SIZE - || *sp > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) - { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"quic_max_udp_payload_size\" must be between " - "%d and %d", - NGX_QUIC_MIN_INITIAL_SIZE, - NGX_QUIC_MAX_UDP_PAYLOAD_SIZE); - - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_http_quic_host_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_quic_conf_t *qcf = conf; - - u_char *buf; - size_t size; - ssize_t n; - ngx_str_t *value; - ngx_file_t file; - ngx_file_info_t fi; - - if (qcf->host_key.len) { - return "is duplicate"; - } - - buf = NULL; -#if (NGX_SUPPRESS_WARN) - size = 0; -#endif - - value = cf->args->elts; - - if (ngx_conf_full_name(cf->cycle, &value[1], 1) != NGX_OK) { - return NGX_CONF_ERROR; - } - - ngx_memzero(&file, sizeof(ngx_file_t)); - file.name = value[1]; - file.log = cf->log; - - file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); - - if (file.fd == NGX_INVALID_FILE) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, - ngx_open_file_n " \"%V\" failed", &file.name); - return NGX_CONF_ERROR; - } - - if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { - ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, - ngx_fd_info_n " \"%V\" failed", &file.name); - goto failed; - } - - size = ngx_file_size(&fi); - - if (size == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" zero key size", &file.name); - goto failed; - } - - buf = ngx_pnalloc(cf->pool, size); - if (buf == NULL) { - goto failed; - } - - n = ngx_read_file(&file, buf, size, 0); - - if (n == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, - ngx_read_file_n " \"%V\" failed", &file.name); - goto failed; - } - - if ((size_t) n != size) { - ngx_conf_log_error(NGX_LOG_CRIT, cf, 0, - ngx_read_file_n " \"%V\" returned only " - "%z bytes instead of %uz", &file.name, n, size); - goto failed; - } - - qcf->host_key.data = buf; - qcf->host_key.len = n; - - if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, - ngx_close_file_n " \"%V\" failed", &file.name); - } - - return NGX_CONF_OK; - -failed: - - if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, - ngx_close_file_n " \"%V\" failed", &file.name); - } - - if (buf) { - ngx_explicit_memzero(buf, size); - } - - return NGX_CONF_ERROR; -} diff --git a/src/http/modules/ngx_http_quic_module.h b/src/http/modules/ngx_http_quic_module.h deleted file mode 100644 index 3b96fcc47..000000000 --- a/src/http/modules/ngx_http_quic_module.h +++ /dev/null @@ -1,28 +0,0 @@ - -/* - * Copyright (C) Nginx, Inc. - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_HTTP_QUIC_H_INCLUDED_ -#define _NGX_HTTP_QUIC_H_INCLUDED_ - - -#include -#include -#include - - -#define NGX_HTTP_QUIC_ALPN_PROTO "\x0Ahq-interop" -#define NGX_HTTP_QUIC_ALPN_DRAFT_FMT "\x05hq-%02uD" - - -#define ngx_http_quic_get_connection(c) \ - ((ngx_http_connection_t *) (c)->quic->parent->data) - - -ngx_int_t ngx_http_quic_init(ngx_connection_t *c); - - -#endif /* _NGX_HTTP_QUIC_H_INCLUDED_ */ diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index afeb68462..3af21178b 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -416,7 +416,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { -#if (NGX_HTTP_QUIC) +#if (NGX_HTTP_V3) const char *fmt; #endif unsigned int srvlen; @@ -424,10 +424,10 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, #if (NGX_DEBUG) unsigned int i; #endif -#if (NGX_HTTP_V2 || NGX_HTTP_QUIC) +#if (NGX_HTTP_V2 || NGX_HTTP_V3) ngx_http_connection_t *hc; #endif -#if (NGX_HTTP_V2 || NGX_HTTP_QUIC || NGX_DEBUG) +#if (NGX_HTTP_V2 || NGX_HTTP_V3 || NGX_DEBUG) ngx_connection_t *c; c = ngx_ssl_get_connection(ssl_conn); @@ -441,7 +441,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, } #endif -#if (NGX_HTTP_V2 || NGX_HTTP_QUIC) +#if (NGX_HTTP_V2 || NGX_HTTP_V3) hc = c->data; #endif @@ -451,17 +451,14 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; } else #endif -#if (NGX_HTTP_QUIC) - if (hc->addr_conf->quic) { #if (NGX_HTTP_V3) + if (hc->addr_conf->quic) { if (hc->addr_conf->http3) { srv = (unsigned char *) NGX_HTTP_V3_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_V3_ALPN_PROTO) - 1; fmt = NGX_HTTP_V3_ALPN_DRAFT_FMT; - } else -#endif - { + } else { srv = (unsigned char *) NGX_HTTP_QUIC_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_QUIC_ALPN_PROTO) - 1; fmt = NGX_HTTP_QUIC_ALPN_DRAFT_FMT; -- cgit From d84c1f7885cc898f626057c314cdae4047c5d513 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Sat, 4 Dec 2021 10:52:55 +0300 Subject: HTTP/3: http3_hq directive and NGX_HTTP_V3_HQ macro. Listen quic parameter is no longer supported. --- src/http/modules/ngx_http_ssl_module.c | 41 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 3af21178b..f43e51eac 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -417,18 +417,21 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, void *arg) { #if (NGX_HTTP_V3) - const char *fmt; + const char *fmt; #endif - unsigned int srvlen; - unsigned char *srv; + unsigned int srvlen; + unsigned char *srv; #if (NGX_DEBUG) - unsigned int i; + unsigned int i; #endif #if (NGX_HTTP_V2 || NGX_HTTP_V3) - ngx_http_connection_t *hc; + ngx_http_connection_t *hc; +#endif +#if (NGX_HTTP_V3 && NGX_HTTP_V3_HQ) + ngx_http_v3_srv_conf_t *h3scf; #endif #if (NGX_HTTP_V2 || NGX_HTTP_V3 || NGX_DEBUG) - ngx_connection_t *c; + ngx_connection_t *c; c = ngx_ssl_get_connection(ssl_conn); #endif @@ -452,16 +455,21 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, } else #endif #if (NGX_HTTP_V3) - if (hc->addr_conf->quic) { - if (hc->addr_conf->http3) { + if (hc->addr_conf->http3) { + +#if (NGX_HTTP_V3_HQ) + h3scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v3_module); + + if (h3scf->hq) { + srv = (unsigned char *) NGX_HTTP_V3_HQ_ALPN_PROTO; + srvlen = sizeof(NGX_HTTP_V3_HQ_ALPN_PROTO) - 1; + fmt = NGX_HTTP_V3_HQ_ALPN_DRAFT_FMT; + } else +#endif + { srv = (unsigned char *) NGX_HTTP_V3_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_V3_ALPN_PROTO) - 1; fmt = NGX_HTTP_V3_ALPN_DRAFT_FMT; - - } else { - srv = (unsigned char *) NGX_HTTP_QUIC_ALPN_PROTO; - srvlen = sizeof(NGX_HTTP_QUIC_ALPN_PROTO) - 1; - fmt = NGX_HTTP_QUIC_ALPN_DRAFT_FMT; } /* QUIC draft */ @@ -1317,16 +1325,13 @@ ngx_http_ssl_init(ngx_conf_t *cf) addr = port[p].addrs.elts; for (a = 0; a < port[p].addrs.nelts; a++) { - if (!addr[a].opt.ssl && !addr[a].opt.quic) { + if (!addr[a].opt.ssl && !addr[a].opt.http3) { continue; } if (addr[a].opt.http3) { name = "http3"; - } else if (addr[a].opt.quic) { - name = "quic"; - } else { name = "ssl"; } @@ -1336,7 +1341,7 @@ ngx_http_ssl_init(ngx_conf_t *cf) if (sscf->certificates) { - if (addr[a].opt.quic && !(sscf->protocols & NGX_SSL_TLSv1_3)) { + if (addr[a].opt.http3 && !(sscf->protocols & NGX_SSL_TLSv1_3)) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "\"ssl_protocols\" must enable TLSv1.3 for " "the \"listen ... %s\" directive in %s:%ui", -- cgit From 5efdec71581f9402dd7132267d68240ab2f8870b Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Wed, 26 Jan 2022 14:15:40 +0300 Subject: HTTP/3: removed draft versions support in ALPN. --- src/http/modules/ngx_http_ssl_module.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 1ecbe439f..64ad9ee2f 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -419,9 +419,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { -#if (NGX_HTTP_V3) - const char *fmt; -#endif unsigned int srvlen; unsigned char *srv; #if (NGX_DEBUG) @@ -466,23 +463,11 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, if (h3scf->hq) { srv = (unsigned char *) NGX_HTTP_V3_HQ_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_V3_HQ_ALPN_PROTO) - 1; - fmt = NGX_HTTP_V3_HQ_ALPN_DRAFT_FMT; } else #endif { srv = (unsigned char *) NGX_HTTP_V3_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_V3_ALPN_PROTO) - 1; - fmt = NGX_HTTP_V3_ALPN_DRAFT_FMT; - } - - /* QUIC draft */ - - if (ngx_quic_version(c) > 1) { - srv = ngx_pnalloc(c->pool, sizeof("\x05h3-xx") - 1); - if (srv == NULL) { - return SSL_TLSEXT_ERR_NOACK; - } - srvlen = ngx_sprintf(srv, fmt, ngx_quic_version(c)) - srv; } } else -- cgit From a36ebf7e95baebf445b0973bd270bc009b0b0e9a Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 22 Feb 2023 19:16:53 +0400 Subject: QUIC: OpenSSL compatibility layer. The change allows to compile QUIC with OpenSSL which lacks BoringSSL QUIC API. This implementation does not support 0-RTT. --- src/http/modules/ngx_http_ssl_module.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 265cb3162..62ec13cf0 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -9,6 +9,10 @@ #include #include +#if (NGX_QUIC_OPENSSL_COMPAT) +#include +#endif + typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); @@ -1317,16 +1321,22 @@ ngx_http_ssl_init(ngx_conf_t *cf) continue; } + cscf = addr[a].default_server; + sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; + if (addr[a].opt.http3) { name = "http3"; +#if (NGX_QUIC_OPENSSL_COMPAT) + if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) { + return NGX_ERROR; + } +#endif + } else { name = "ssl"; } - cscf = addr[a].default_server; - sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; - if (sscf->certificates) { if (addr[a].opt.http3 && !(sscf->protocols & NGX_SSL_TLSv1_3)) { -- cgit From 815ef96124176baef4e940c4beaec158305b368a Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 27 Feb 2023 14:00:56 +0400 Subject: HTTP/3: "quic" parameter of "listen" directive. Now "listen" directve has a new "quic" parameter which enables QUIC protocol for the address. Further, to enable HTTP/3, a new directive "http3" is introduced. The hq-interop protocol is enabled by "http3_hq" as before. Now application protocol is chosen by ALPN. Previously used "http3" parameter of "listen" is deprecated. --- src/http/modules/ngx_http_ssl_module.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 62ec13cf0..8167157e2 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -431,7 +431,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, #if (NGX_HTTP_V2 || NGX_HTTP_V3) ngx_http_connection_t *hc; #endif -#if (NGX_HTTP_V3 && NGX_HTTP_V3_HQ) +#if (NGX_HTTP_V3) ngx_http_v3_srv_conf_t *h3scf; #endif #if (NGX_HTTP_V2 || NGX_HTTP_V3 || NGX_DEBUG) @@ -459,19 +459,26 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, } else #endif #if (NGX_HTTP_V3) - if (hc->addr_conf->http3) { + if (hc->addr_conf->quic) { -#if (NGX_HTTP_V3_HQ) h3scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v3_module); - if (h3scf->hq) { + if (h3scf->enable && h3scf->enable_hq) { + srv = (unsigned char *) NGX_HTTP_V3_ALPN_PROTO + NGX_HTTP_V3_HQ_ALPN_PROTO; + srvlen = sizeof(NGX_HTTP_V3_ALPN_PROTO NGX_HTTP_V3_HQ_ALPN_PROTO) + - 1; + + } else if (h3scf->enable_hq) { srv = (unsigned char *) NGX_HTTP_V3_HQ_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_V3_HQ_ALPN_PROTO) - 1; - } else -#endif - { + + } else if (h3scf->enable || hc->addr_conf->http3) { srv = (unsigned char *) NGX_HTTP_V3_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_V3_ALPN_PROTO) - 1; + + } else { + return SSL_TLSEXT_ERR_ALERT_FATAL; } } else @@ -1317,15 +1324,15 @@ ngx_http_ssl_init(ngx_conf_t *cf) addr = port[p].addrs.elts; for (a = 0; a < port[p].addrs.nelts; a++) { - if (!addr[a].opt.ssl && !addr[a].opt.http3) { + if (!addr[a].opt.ssl && !addr[a].opt.quic) { continue; } cscf = addr[a].default_server; sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; - if (addr[a].opt.http3) { - name = "http3"; + if (addr[a].opt.quic) { + name = "quic"; #if (NGX_QUIC_OPENSSL_COMPAT) if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) { @@ -1339,7 +1346,7 @@ ngx_http_ssl_init(ngx_conf_t *cf) if (sscf->certificates) { - if (addr[a].opt.http3 && !(sscf->protocols & NGX_SSL_TLSv1_3)) { + if (addr[a].opt.quic && !(sscf->protocols & NGX_SSL_TLSv1_3)) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "\"ssl_protocols\" must enable TLSv1.3 for " "the \"listen ... %s\" directive in %s:%ui", -- cgit From 4d472cd792cc9699e014995c9f41c3e3e048e975 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Fri, 24 Mar 2023 19:49:50 +0400 Subject: HTTP/3: fixed OpenSSL compatibility layer initialization. SSL context is not present if the default server has neither certificates nor ssl_reject_handshake enabled. Previously, this led to null pointer dereference before it would be caught with configuration checks. Additionally, non-default servers with distinct SSL contexts need to initialize compatibility layer in order to complete a QUIC handshake. --- src/http/modules/ngx_http_ssl_module.c | 40 ++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 8167157e2..d92ec403e 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -56,6 +56,10 @@ static char *ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data); static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf); +#if (NGX_QUIC_OPENSSL_COMPAT) +static ngx_int_t ngx_http_ssl_quic_compat_init(ngx_conf_t *cf, + ngx_http_conf_addr_t *addr); +#endif static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = { @@ -1328,14 +1332,11 @@ ngx_http_ssl_init(ngx_conf_t *cf) continue; } - cscf = addr[a].default_server; - sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; - if (addr[a].opt.quic) { name = "quic"; #if (NGX_QUIC_OPENSSL_COMPAT) - if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) { + if (ngx_http_ssl_quic_compat_init(cf, &addr[a]) != NGX_OK) { return NGX_ERROR; } #endif @@ -1344,6 +1345,9 @@ ngx_http_ssl_init(ngx_conf_t *cf) name = "ssl"; } + cscf = addr[a].default_server; + sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; + if (sscf->certificates) { if (addr[a].opt.quic && !(sscf->protocols & NGX_SSL_TLSv1_3)) { @@ -1391,3 +1395,31 @@ ngx_http_ssl_init(ngx_conf_t *cf) return NGX_OK; } + + +#if (NGX_QUIC_OPENSSL_COMPAT) + +static ngx_int_t +ngx_http_ssl_quic_compat_init(ngx_conf_t *cf, ngx_http_conf_addr_t *addr) +{ + ngx_uint_t s; + ngx_http_ssl_srv_conf_t *sscf; + ngx_http_core_srv_conf_t **cscfp, *cscf; + + cscfp = addr->servers.elts; + for (s = 0; s < addr->servers.nelts; s++) { + + cscf = cscfp[s]; + sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; + + if (sscf->certificates || sscf->reject_handshake) { + if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) { + return NGX_ERROR; + } + } + } + + return NGX_OK; +} + +#endif -- cgit From 2ce3eeeeb76318e414b62d399da70872d2de23d8 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Thu, 11 May 2023 13:22:10 +0400 Subject: HTTP/3: removed "http3" parameter of "listen" directive. The parameter has been deprecated since c851a2ed5ce8. --- src/http/modules/ngx_http_ssl_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index c0d6bae06..d2ca475d3 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -477,7 +477,7 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, srv = (unsigned char *) NGX_HTTP_V3_HQ_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_V3_HQ_ALPN_PROTO) - 1; - } else if (h3scf->enable || hc->addr_conf->http3) { + } else if (h3scf->enable) { srv = (unsigned char *) NGX_HTTP_V3_ALPN_PROTO; srvlen = sizeof(NGX_HTTP_V3_ALPN_PROTO) - 1; -- cgit