# HG changeset patch # User Maxim Dounin # Date 1656460065 -10800 # Node ID 9d98d524bd02a562d9cd83f4e369c7e992c5753b # Parent e210c8942a54af14ea44cfa9285784f856cec7f8 Upstream: optimized use of SSL contexts (ticket #1234). To ensure optimal use of memory, SSL contexts for proxying are now inherited from previous levels as long as relevant proxy_ssl_* directives are not redefined. Further, when no proxy_ssl_* directives are redefined in a server block, we now preserve plcf->upstream.ssl in the "http" section configuration to inherit it to all servers. Similar changes made in uwsgi, grpc, and stream proxy. diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -209,6 +209,8 @@ static char *ngx_http_grpc_ssl_password_ ngx_command_t *cmd, void *conf); static char *ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data); +static ngx_int_t ngx_http_grpc_merge_ssl(ngx_conf_t *cf, + ngx_http_grpc_loc_conf_t *conf, ngx_http_grpc_loc_conf_t *prev); static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf); #endif @@ -562,7 +564,7 @@ ngx_http_grpc_handler(ngx_http_request_t ctx->host = glcf->host; #if (NGX_HTTP_SSL) - u->ssl = (glcf->upstream.ssl != NULL); + u->ssl = glcf->ssl; if (u->ssl) { ngx_str_set(&u->schema, "grpcs://"); @@ -4463,6 +4465,10 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t #if (NGX_HTTP_SSL) + if (ngx_http_grpc_merge_ssl(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } + ngx_conf_merge_value(conf->upstream.ssl_session_reuse, prev->upstream.ssl_session_reuse, 1); @@ -4524,7 +4530,7 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t conf->grpc_values = prev->grpc_values; #if (NGX_HTTP_SSL) - conf->upstream.ssl = prev->upstream.ssl; + conf->ssl = prev->ssl; #endif } @@ -4874,17 +4880,63 @@ ngx_http_grpc_ssl_conf_command_check(ngx static ngx_int_t +ngx_http_grpc_merge_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf, + ngx_http_grpc_loc_conf_t *prev) +{ + ngx_uint_t preserve; + + if (conf->ssl_protocols == 0 + && conf->ssl_ciphers.data == NULL + && conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_verify == NGX_CONF_UNSET + && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT + && conf->ssl_trusted_certificate.data == NULL + && conf->ssl_crl.data == NULL + && conf->upstream.ssl_session_reuse == NGX_CONF_UNSET + && conf->ssl_conf_commands == NGX_CONF_UNSET_PTR) + { + if (prev->upstream.ssl) { + conf->upstream.ssl = prev->upstream.ssl; + return NGX_OK; + } + + preserve = 1; + + } else { + preserve = 0; + } + + conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); + if (conf->upstream.ssl == NULL) { + return NGX_ERROR; + } + + conf->upstream.ssl->log = cf->log; + + /* + * special handling to preserve conf->upstream.ssl + * in the "http" section to inherit it to all servers + */ + + if (preserve) { + prev->upstream.ssl = conf->upstream.ssl; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf) { ngx_pool_cleanup_t *cln; - glcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); - if (glcf->upstream.ssl == NULL) { - return NGX_ERROR; + if (glcf->upstream.ssl->ctx) { + return NGX_OK; } - glcf->upstream.ssl->log = cf->log; - if (ngx_ssl_create(glcf->upstream.ssl, glcf->ssl_protocols, NULL) != NGX_OK) { diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -236,6 +236,8 @@ static ngx_int_t ngx_http_proxy_rewrite_ ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless); #if (NGX_HTTP_SSL) +static ngx_int_t ngx_http_proxy_merge_ssl(ngx_conf_t *cf, + ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev); static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf); #endif @@ -959,7 +961,7 @@ ngx_http_proxy_handler(ngx_http_request_ ctx->vars = plcf->vars; u->schema = plcf->vars.schema; #if (NGX_HTTP_SSL) - u->ssl = (plcf->upstream.ssl != NULL); + u->ssl = plcf->ssl; #endif } else { @@ -3724,6 +3726,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t #if (NGX_HTTP_SSL) + if (ngx_http_proxy_merge_ssl(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } + ngx_conf_merge_value(conf->upstream.ssl_session_reuse, prev->upstream.ssl_session_reuse, 1); @@ -3857,7 +3863,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t conf->proxy_values = prev->proxy_values; #if (NGX_HTTP_SSL) - conf->upstream.ssl = prev->upstream.ssl; + conf->ssl = prev->ssl; #endif } @@ -4923,16 +4929,62 @@ ngx_http_proxy_ssl_conf_command_check(ng static ngx_int_t +ngx_http_proxy_merge_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf, + ngx_http_proxy_loc_conf_t *prev) +{ + ngx_uint_t preserve; + + if (conf->ssl_protocols == 0 + && conf->ssl_ciphers.data == NULL + && conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_verify == NGX_CONF_UNSET + && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT + && conf->ssl_trusted_certificate.data == NULL + && conf->ssl_crl.data == NULL + && conf->upstream.ssl_session_reuse == NGX_CONF_UNSET + && conf->ssl_conf_commands == NGX_CONF_UNSET_PTR) + { + if (prev->upstream.ssl) { + conf->upstream.ssl = prev->upstream.ssl; + return NGX_OK; + } + + preserve = 1; + + } else { + preserve = 0; + } + + conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); + if (conf->upstream.ssl == NULL) { + return NGX_ERROR; + } + + conf->upstream.ssl->log = cf->log; + + /* + * special handling to preserve conf->upstream.ssl + * in the "http" section to inherit it to all servers + */ + + if (preserve) { + prev->upstream.ssl = conf->upstream.ssl; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) { ngx_pool_cleanup_t *cln; - plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); - if (plcf->upstream.ssl == NULL) { - return NGX_ERROR; - } - - plcf->upstream.ssl->log = cf->log; + if (plcf->upstream.ssl->ctx) { + return NGX_OK; + } if (ngx_ssl_create(plcf->upstream.ssl, plcf->ssl_protocols, NULL) != NGX_OK) diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -96,6 +96,8 @@ static char *ngx_http_uwsgi_ssl_password ngx_command_t *cmd, void *conf); static char *ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data); +static ngx_int_t ngx_http_uwsgi_merge_ssl(ngx_conf_t *cf, + ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_loc_conf_t *prev); static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf); #endif @@ -668,7 +670,7 @@ ngx_http_uwsgi_handler(ngx_http_request_ if (uwcf->uwsgi_lengths == NULL) { #if (NGX_HTTP_SSL) - u->ssl = (uwcf->upstream.ssl != NULL); + u->ssl = uwcf->ssl; if (u->ssl) { ngx_str_set(&u->schema, "suwsgi://"); @@ -1865,6 +1867,10 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t #if (NGX_HTTP_SSL) + if (ngx_http_uwsgi_merge_ssl(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } + ngx_conf_merge_value(conf->upstream.ssl_session_reuse, prev->upstream.ssl_session_reuse, 1); @@ -1927,7 +1933,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t conf->uwsgi_values = prev->uwsgi_values; #if (NGX_HTTP_SSL) - conf->upstream.ssl = prev->upstream.ssl; + conf->ssl = prev->ssl; #endif } @@ -2455,17 +2461,63 @@ ngx_http_uwsgi_ssl_conf_command_check(ng static ngx_int_t +ngx_http_uwsgi_merge_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf, + ngx_http_uwsgi_loc_conf_t *prev) +{ + ngx_uint_t preserve; + + if (conf->ssl_protocols == 0 + && conf->ssl_ciphers.data == NULL + && conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR + && conf->upstream.ssl_verify == NGX_CONF_UNSET + && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT + && conf->ssl_trusted_certificate.data == NULL + && conf->ssl_crl.data == NULL + && conf->upstream.ssl_session_reuse == NGX_CONF_UNSET + && conf->ssl_conf_commands == NGX_CONF_UNSET_PTR) + { + if (prev->upstream.ssl) { + conf->upstream.ssl = prev->upstream.ssl; + return NGX_OK; + } + + preserve = 1; + + } else { + preserve = 0; + } + + conf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); + if (conf->upstream.ssl == NULL) { + return NGX_ERROR; + } + + conf->upstream.ssl->log = cf->log; + + /* + * special handling to preserve conf->upstream.ssl + * in the "http" section to inherit it to all servers + */ + + if (preserve) { + prev->upstream.ssl = conf->upstream.ssl; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf) { ngx_pool_cleanup_t *cln; - uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); - if (uwcf->upstream.ssl == NULL) { - return NGX_ERROR; + if (uwcf->upstream.ssl->ctx) { + return NGX_OK; } - uwcf->upstream.ssl->log = cf->log; - if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL) != NGX_OK) { diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -103,6 +103,8 @@ static void ngx_stream_proxy_ssl_handsha static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c); static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s); static ngx_int_t ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s); +static ngx_int_t ngx_stream_proxy_merge_ssl(ngx_conf_t *cf, + ngx_stream_proxy_srv_conf_t *conf, ngx_stream_proxy_srv_conf_t *prev); static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf); @@ -801,7 +803,7 @@ ngx_stream_proxy_init_upstream(ngx_strea #if (NGX_STREAM_SSL) - if (pc->type == SOCK_STREAM && pscf->ssl) { + if (pc->type == SOCK_STREAM && pscf->ssl_enable) { if (u->proxy_protocol) { if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) { @@ -2150,6 +2152,10 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf #if (NGX_STREAM_SSL) + if (ngx_stream_proxy_merge_ssl(cf, conf, prev) != NGX_OK) { + return NGX_CONF_ERROR; + } + ngx_conf_merge_value(conf->ssl_enable, prev->ssl_enable, 0); ngx_conf_merge_value(conf->ssl_session_reuse, @@ -2199,17 +2205,63 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf #if (NGX_STREAM_SSL) static ngx_int_t +ngx_stream_proxy_merge_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *conf, + ngx_stream_proxy_srv_conf_t *prev) +{ + ngx_uint_t preserve; + + if (conf->ssl_protocols == 0 + && conf->ssl_ciphers.data == NULL + && conf->ssl_certificate == NGX_CONF_UNSET_PTR + && conf->ssl_certificate_key == NGX_CONF_UNSET_PTR + && conf->ssl_passwords == NGX_CONF_UNSET_PTR + && conf->ssl_verify == NGX_CONF_UNSET + && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT + && conf->ssl_trusted_certificate.data == NULL + && conf->ssl_crl.data == NULL + && conf->ssl_session_reuse == NGX_CONF_UNSET + && conf->ssl_conf_commands == NGX_CONF_UNSET_PTR) + { + if (prev->ssl) { + conf->ssl = prev->ssl; + return NGX_OK; + } + + preserve = 1; + + } else { + preserve = 0; + } + + conf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); + if (conf->ssl == NULL) { + return NGX_ERROR; + } + + conf->ssl->log = cf->log; + + /* + * special handling to preserve conf->ssl + * in the "stream" section to inherit it to all servers + */ + + if (preserve) { + prev->ssl = conf->ssl; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf) { ngx_pool_cleanup_t *cln; - pscf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); - if (pscf->ssl == NULL) { - return NGX_ERROR; + if (pscf->ssl->ctx) { + return NGX_OK; } - pscf->ssl->log = cf->log; - if (ngx_ssl_create(pscf->ssl, pscf->ssl_protocols, NULL) != NGX_OK) { return NGX_ERROR; }