[PATCH] Keepalive: add new option "keepalive_ssl_respect_sni"

geniuss99 geniuss.dev at gmail.com
Thu Mar 11 18:28:49 UTC 2021


 src/http/modules/ngx_http_upstream_keepalive_module.c |  42 +++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)


# HG changeset patch
# User geniuss99 <geniuss.dev at gmail.com>
# Date 1615484979 -10800
#      Thu Mar 11 20:49:39 2021 +0300
# Node ID ed1348e8e25381b3b1a2540289effcf7ccec6fd6
# Parent  0215ec9aaa8af6036c62e1db676c9b0cc1d5fca4
Keepalive: add new option "keepalive_ssl_respect_sni".

This option allows handling the following usecase:
1. proxy https requests with different hostnames to server with same ip;
2. use cache of upstream connections via keepalive option in upstream module;
3. reuse connection from keepalive pool only if ip and servername used during
   handshake with upstream match hostname from downstream request.

When this option is turned on not only the ip address of upstream server is
taken into account upon connection search but also servername used during
handshake procedure.

diff -r 0215ec9aaa8a -r ed1348e8e253 src/http/modules/ngx_http_upstream_keepalive_module.c
--- a/src/http/modules/ngx_http_upstream_keepalive_module.c	Thu Mar 11 09:58:45 2021 +0300
+++ b/src/http/modules/ngx_http_upstream_keepalive_module.c	Thu Mar 11 20:49:39 2021 +0300
@@ -15,6 +15,10 @@
     ngx_uint_t                         requests;
     ngx_msec_t                         timeout;
 
+#if (NGX_HTTP_SSL)
+    ngx_flag_t                         ssl_respect_sni;
+#endif
+
     ngx_queue_t                        cache;
     ngx_queue_t                        free;
 
@@ -49,6 +53,7 @@
 #if (NGX_HTTP_SSL)
     ngx_event_set_peer_session_pt      original_set_session;
     ngx_event_save_peer_session_pt     original_save_session;
+    ngx_str_t                          *http_request_server;
 #endif
 
 } ngx_http_upstream_keepalive_peer_data_t;
@@ -100,6 +105,16 @@
       offsetof(ngx_http_upstream_keepalive_srv_conf_t, requests),
       NULL },
 
+#if (NGX_HTTP_SSL)
+
+    { ngx_string("keepalive_ssl_respect_sni"),
+      NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_upstream_keepalive_srv_conf_t, ssl_respect_sni),
+      NULL },
+
+#endif
       ngx_null_command
 };
 
@@ -152,6 +167,10 @@
     ngx_conf_init_msec_value(kcf->timeout, 60000);
     ngx_conf_init_uint_value(kcf->requests, 100);
 
+#if (NGX_HTTP_SSL)
+    ngx_conf_init_value(kcf->ssl_respect_sni, 0);
+#endif
+
     if (kcf->original_init_upstream(cf, us) != NGX_OK) {
         return NGX_ERROR;
     }
@@ -217,6 +236,8 @@
     kp->original_save_session = r->upstream->peer.save_session;
     r->upstream->peer.set_session = ngx_http_upstream_keepalive_set_session;
     r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session;
+
+    kp->http_request_server = &r->headers_in.server;
 #endif
 
     return NGX_OK;
@@ -232,6 +253,10 @@
     ngx_int_t          rc;
     ngx_queue_t       *q, *cache;
     ngx_connection_t  *c;
+#if (NGX_HTTP_SSL)
+    ngx_int_t         *ssl_respect_sni;
+    const char        *ssl_server_name;
+#endif
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                    "get keepalive peer");
@@ -248,6 +273,10 @@
 
     cache = &kp->conf->cache;
 
+#if (NGX_HTTP_SSL)
+    ssl_respect_sni = &kp->conf->ssl_respect_sni;
+#endif
+
     for (q = ngx_queue_head(cache);
          q != ngx_queue_sentinel(cache);
          q = ngx_queue_next(q))
@@ -259,6 +288,15 @@
                          item->socklen, pc->socklen)
             == 0)
         {
+#if (NGX_HTTP_SSL)
+            /* check if server_name from ssl connection corresponds to requested host */
+            if (*ssl_respect_sni == 1 && c->ssl != NULL && c->ssl->connection != NULL && c->ssl->handshaked) {
+                ssl_server_name = SSL_get_servername(c->ssl->connection, TLSEXT_NAMETYPE_host_name);
+                if (ssl_server_name != NULL && ngx_strncasecmp(kp->http_request_server->data, (u_char*) ssl_server_name, ngx_strlen(ssl_server_name)) != 0) {
+                    continue;
+                }
+            }
+#endif
             ngx_queue_remove(q);
             ngx_queue_insert_head(&kp->conf->free, q);
 
@@ -516,6 +554,10 @@
     conf->timeout = NGX_CONF_UNSET_MSEC;
     conf->requests = NGX_CONF_UNSET_UINT;
 
+#if (NGX_HTTP_SSL)
+    conf->ssl_respect_sni = NGX_CONF_UNSET;
+#endif
+
     return conf;
 }
 


More information about the nginx-devel mailing list