SSL contexts reuse across locations
Pavel Pautov
P.Pautov at F5.com
Tue Jun 28 05:26:38 UTC 2022
Hi,
The patch seems fine and is somewhat similar to what I've posted before.
I guess, the copy-paste can be addressed some time later by someone else.
> -----Original Message-----
> From: Maxim Dounin <mdounin at mdounin.ru>
> Sent: Saturday, June 25, 2022 22:48
> To: Pavel Pautov via nginx-devel <nginx-devel at nginx.org>
> Subject: Re: SSL contexts reuse across locations
>
> EXTERNAL MAIL: nginx-devel-bounces at nginx.org
>
> Hello!
>
> On Sat, Jun 25, 2022 at 01:02:21AM +0000, Pavel Pautov via nginx-devel wrote:
>
> > > -----Original Message-----
> > > From: Maxim Dounin <mdounin at mdounin.ru>
> > > Sent: Thursday, June 16, 2022 18:51
> > >
> > > Hello!
> > >
> > > On Thu, Jun 16, 2022 at 08:26:48AM +0000, Pavel Pautov via nginx-devel
> wrote:
> > >
> > > > Looks like, we've made a full circle then... I've replied to
> > > > that suggestion already and in last e-mail (with patch) I note
> > > > that moving additional logic into the ngx_http_proxy_set_ssl()
> > > > has its own drawbacks, but I can certainly move more stuff into
> > > > it.
> > > >
> > > > So do you envision something like "ngx_http_proxy_set_ssl(cf,
> > > > conf, prev, reuse_ssl)"? As previously we've established that
> > > > directives merging stays out of ngx_http_proxy_set_ssl (and
> > > > reuse_ssl calculation has to happen before it).
> > >
> > > I don't think further attempts to explain how to write readable
> > > code worth the effort.
> >
> > Too bad.
>
> Yes, that's unfortunate. You may want to consider asking more
> experienced developers in your company for mentorship.
>
> > > Please see the patch below. Review and testing appreciated.
> >
> > The patch seems to contradict some previously discussed points.
> > For example, it can actually increase memory usage in certain
> > configurations (say, when proxy_ssl_* directives in location
> > override server level directives or when proxy_pass
> > "https://..." is absent). Or you don't consider this an issue
> > anymore?
>
> Quoting the very first review:
>
> : Also, it should be a good idea to avoid creating SSL contexts if
> : there is no SSL proxying configured. Or, at very least, make sure
> : only one context at the http level is used in such cases, so
> : configurations with many servers won't suddenly blow up.
>
> The patch tries to be in line with this, and create at most one
> proxy SSL context as long as no SSL proxying is configured (it
> fails to do so though, see below). If proxy SSL settings are
> redefined at some level, this redefinition adds an SSL context,
> and this behaviour is something one might expect from the explicit
> proxy_ssl_* directives in the configuration.
>
> > More importantly, it doesn't really solve the use case from
> > #1234, i.e. http level proxy_ssl_* directives with many servers
> > (as by default http level values are remain unset and thus are
> > not equal to server level values).
>
> My bad, mostly focused on the location level and missed that it is
> not possible to properly compare http and server level settings
> after the merge.
>
> Updated patch below, with additional function called just before
> the merge of particular directives. The resulting codes tries to
> be close to ngx_http_proxy_set_ssl(), where the relevant settings
> are used to create SSL contexts, to be self-explanatory.
>
> Additionally, the patch now avoids creating SSL contexts if there
> are no SSL proxying configured. This seems to complicate things
> insignificantly given the new code layout, though ensures that
> configurations with "proxy_ssl_verify on;" at http or stream level
> without proxy_ssl_trusted_certificate set at the same level, as
> seen in stream_proxy_ssl_verify.t, won't blow up.
>
> > Also, you effectively compare some directives by value (instead
> > of checking the presence), so it might be surprising to the user
> > that repeating some directives on inner level increases memory
> > consumption and repeating others doesn't.
>
> I don't think this is an issue. SSL contexts can be inherited
> from the previous level if proxy_ssl_* directives are not
> redefined; if any of them are redefined, this can result in an
> additional SSL context. While there are settings which does not
> create additional SSL contexts even if set to a different value
> (such as proxy_ssl_server_name), the only guarantee we are willing
> to provide is that inherited settings will result in optimal
> memory usage.
>
> Either way, this is irrelevant with the updated patch.
>
> > My last patch already addresses all of above...
>
> Except you've failed to make it readable.
>
> > Also, it would be nice to avoid all this copy-paste
>
> As already explained, upstream SSL settings are protocol-specific
> in the current design, as well as upstream SSL context creation.
> While introducing some shared part is possible, it does not seem
> to worth the effort, especially given the existing
> protocol-specific difference.
>
> > and have the same optimization in the stream module.
>
> Given there are no locations in the stream module, I don't think
> this is an issue there, or at least no more than server-side SSL
> contexts. On the other hand, it is trivial to add the same
> optimization to the stream module, and good from the code
> consistency point of view. Added.
>
> > > # HG changeset patch
> > > # User Maxim Dounin <mdounin at mdounin.ru>
> > > # Date 1655429915 -10800
> > > # Fri Jun 17 04:38:35 2022 +0300
> > > # Node ID e4a0eeb3edba037f0d090023a2242bda2f8dcb03
> > > # Parent e23a385cd0ec866a3eb1d8c9c956991e1ed50d78
> > > Upstream: optimized use of SSL contexts (ticket #1234).
> > [...]
> > >
> > > #if (NGX_HTTP_SSL)
> > > - u->ssl = (glcf->upstream.ssl != NULL);
> > > + u->ssl = glcf->ssl;
> >
> > I like this change, with it additional 'shared_ssl' pointer can
> > be removed from my patch.
>
> Well, "shared_ssl" shouldn't have been added in the first place.
>
> Updated patch below. Review and testing appreciated.
>
> # HG changeset patch
> # User Maxim Dounin <mdounin at mdounin.ru>
> # Date 1656218606 -10800
> # Sun Jun 26 07:43:26 2022 +0300
> # Node ID f45142380cee37e71dab76d77ead279cf9b2f4e9
> # Parent fecd73db563fb64108f7669eca419badb2aba633
> 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)
> {
[...]
More information about the nginx-devel
mailing list