From mdounin at mdounin.ru Mon Aug 3 09:26:58 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 3 Aug 2015 12:26:58 +0300 Subject: [PATCH] Workaround for "configuration file test failed" under OpenVZ In-Reply-To: <55B9573F.9010901@csdoc.com> References: <55B9573F.9010901@csdoc.com> Message-ID: <20150803092658.GK19190@mdounin.ru> Hello! On Thu, Jul 30, 2015 at 01:44:15AM +0300, Gena Makhomed wrote: > # HG changeset patch > # User Gena Makhomed > # Date 1437674403 14400 > # Thu Jul 23 14:00:03 2015 -0400 > # Node ID 57ac65580b5bba0cb4bb61dca9d63daec0ceb14c > # Parent 341e4303d25be159d4773b819d0ec055ba711afb > Workaround for "configuration file test failed" under OpenVZ. > > nginx configuration test failed: [...] Here is the patch with slightly updated commit log and a comment added to the code. Please take a look if it looks fine to you. # HG changeset patch # User Gena Makhomed # Date 1437674403 14400 # Thu Jul 23 14:00:03 2015 -0400 # Node ID 3096ae76ba4726a5138e9e7161428c7afea67c0f # Parent b544f8e0d9214560a6acddbb0f40db5146e9463d Workaround for "configuration file test failed" under OpenVZ. If nginx was used under OpenVZ and a container with nginx was suspended and resumed, configuration tests started to fail because of EADDRINUSE returned from listen() instead of bind(): # nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: [emerg] listen() to 0.0.0.0:80, backlog 511 failed (98: Address already in use) nginx: configuration file /etc/nginx/nginx.conf test failed With this change EADDRINUSE errors returned by listen() are handled similarly to errors returned by bind(), and configuration tests work fine in the same environment: # nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful More details about OpenVZ suspend/resume bug: https://bugzilla.openvz.org/show_bug.cgi?id=2470 diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -567,9 +567,19 @@ ngx_open_listening_sockets(ngx_cycle_t * #endif if (listen(s, ls[i].backlog) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "listen() to %V, backlog %d failed", - &ls[i].addr_text, ls[i].backlog); + err = ngx_socket_errno; + + /* + * on OpenVZ after suspend/resume EADDRINUSE + * may be returned by listen() instead of bind(), see + * https://bugzilla.openvz.org/show_bug.cgi?id=2470 + */ + + if (err != NGX_EADDRINUSE || !ngx_test_config) { + ngx_log_error(NGX_LOG_EMERG, log, err, + "listen() to %V, backlog %d failed", + &ls[i].addr_text, ls[i].backlog); + } if (ngx_close_socket(s) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, @@ -577,7 +587,15 @@ ngx_open_listening_sockets(ngx_cycle_t * &ls[i].addr_text); } - return NGX_ERROR; + if (err != NGX_EADDRINUSE) { + return NGX_ERROR; + } + + if (!ngx_test_config) { + failed = 1; + } + + continue; } ls[i].listen = 1; -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Aug 3 09:35:47 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 3 Aug 2015 12:35:47 +0300 Subject: [PATCH] Add log variables $http_all and $sent_http_all In-Reply-To: <2412f965360cdbf9d152.1438200924@jwendell> References: <2412f965360cdbf9d152.1438200924@jwendell> Message-ID: <20150803093546.GL19190@mdounin.ru> Hello! On Wed, Jul 29, 2015 at 05:15:24PM -0300, Jonh Wendell wrote: > src/http/ngx_http_header_filter_module.c | 5 + > src/http/ngx_http_request.h | 2 + > src/http/ngx_http_variables.c | 92 ++++++++++++++++++++++++++++++++ > 3 files changed, 99 insertions(+), 0 deletions(-) > > > # HG changeset patch > # User Jonh Wendell > # Date 1438199955 10800 > # Wed Jul 29 16:59:15 2015 -0300 > # Node ID 2412f965360cdbf9d15280e8ee9fa1a28a3c86ca > # Parent 341e4303d25be159d4773b819d0ec055ba711afb > Add log variables $http_all and $sent_http_all These variables names are not compatible with $http_ and $sent_http_ variables as used by nginx. > > These are meant to log the entire request and response > headers, respectively. > > There are cases when we want to log the whole request (or response) > headers, for example, when we don't know in advance the > field the client sends. Currently we must know exactly the > header fields we want to log. > > This patch adds these two variables that contains > > $http_all: all request headers as received from client > $sent_http_all: all response headers as sent to the client > > Closes #426. > > diff -r 341e4303d25b -r 2412f965360c src/http/ngx_http_header_filter_module.c > --- a/src/http/ngx_http_header_filter_module.c Thu Jul 16 14:20:48 2015 +0300 > +++ b/src/http/ngx_http_header_filter_module.c Wed Jul 29 16:59:15 2015 -0300 > @@ -608,6 +608,11 @@ > ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, > "%*s", (size_t) (b->last - b->pos), b->pos); > > + /* prepare the complete headers for eventual logging - strip out the last "\r\n" */ > + r->headers_out.final_response.len = b->last - b->pos - (sizeof(CRLF) - 1); > + r->headers_out.final_response.data = ngx_palloc(r->pool, r->headers_out.final_response.len); > + ngx_memcpy(r->headers_out.final_response.data, b->pos, r->headers_out.final_response.len); > + This doesn't looks like an acceptable solution. (Not even talking about coding style issues.) [...] > + buf = ngx_sprintf(buf, "%V: %V\r\n", &header[i].key, &header[i].value); I can't say I ike the idea of reconstructing headers. [...] -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Aug 3 09:52:05 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 3 Aug 2015 12:52:05 +0300 Subject: ngx_ext_rename_file: remove the target file if ngx_copy_file() fails In-Reply-To: <20150709141048.f42bc4b73ec7edcd661207c4@noxt.eu> References: <20150709141048.f42bc4b73ec7edcd661207c4@noxt.eu> Message-ID: <20150803095205.GM19190@mdounin.ru> Hello! On Thu, Jul 09, 2015 at 02:10:48PM +0100, Mindaugas Rasiukevicius wrote: > Hi, > > Some background: nginx 1.9.2, used as a cache, can get into the state > when it stops evicting the objects and eventually stops caching without > being able to recover. This happens when the disk is full. Consider the > following nginx.conf fragment: > > proxy_cache_path /cache/nginx levels=1:2 > keys_zone=c3:4096m max_size=8500g > inactive=30d use_temp_path=on; > proxy_temp_path /cache/nginx-tmp 1 2; > > The disk is filled because the workers have been fetching the data from > the backend faster than the cache manager is able to evict: > > $ df -h | grep cache > /dev/sdb1 8.7T 8.7T 16M 100% /cache > tmpfs 2.0G 0 2.0G 0% /cache/nginx-tmp > > Since /cache and /cache/nginx-tmp are separate mount points, nginx has to > perform copy instead of rename. The copy functions fails due to ENOSPC, > but the ngx_ext_rename_file() does not clean up the failed target. At this > point, based on ngx_http_file_cache_sh_t::size, the cache manager believes > that the 8.5 TB threshold has not been crossed and nginx fails to recover. > > Please find the patch attached. > > -- > Mindaugas > # HG changeset patch > # User Mindaugas Rasiukevicius > # Date 1436387157 -3600 > # Wed Jul 08 21:25:57 2015 +0100 > # Node ID 9c978e51bf0e9bd6fc0fc04f4016a3c5701e9912 > # Parent dcae651b2a0cbd3de2f1fd5cf5b8c72627db94fd > ngx_ext_rename_file: remove the target file if ngx_copy_file() fails. > > diff -r dcae651b2a0c -r 9c978e51bf0e src/core/ngx_file.c > --- a/src/core/ngx_file.c Tue Jul 07 16:38:49 2015 +0300 > +++ b/src/core/ngx_file.c Wed Jul 08 21:25:57 2015 +0100 > @@ -727,12 +727,11 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_ > ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, > ngx_rename_file_n " \"%s\" to \"%s\" failed", > name, to->data); > + } > > - if (ngx_delete_file(name) == NGX_FILE_ERROR) { > - ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, > - ngx_delete_file_n " \"%s\" failed", name); > - > - } > + if (ngx_delete_file(name) == NGX_FILE_ERROR) { > + ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, > + ngx_delete_file_n " \"%s\" failed", name); > } > > ngx_free(name); By calling ngx_delete_file() at this point, you do this for all errors returned by ngx_copy_file(), including cases when it wasn't able to open a destination file for some reason. This will result in additional confusing errors, and looks like a wrong approach. If you want nginx to remove a destination file, this should be done in ngx_copy_file(). -- Maxim Dounin http://nginx.org/ From gmm at csdoc.com Mon Aug 3 09:56:20 2015 From: gmm at csdoc.com (Gena Makhomed) Date: Mon, 3 Aug 2015 12:56:20 +0300 Subject: [PATCH] Workaround for "configuration file test failed" under OpenVZ In-Reply-To: <20150803092658.GK19190@mdounin.ru> References: <55B9573F.9010901@csdoc.com> <20150803092658.GK19190@mdounin.ru> Message-ID: <55BF3AC4.10501@csdoc.com> On 03.08.2015 12:26, Maxim Dounin wrote: > Here is the patch with slightly updated commit log and a comment > added to the code. Please take a look if it looks fine to you. Yes, updated version of patch is more clean and easy to understand, thank you! > # HG changeset patch > # User Gena Makhomed > # Date 1437674403 14400 > # Thu Jul 23 14:00:03 2015 -0400 > # Node ID 3096ae76ba4726a5138e9e7161428c7afea67c0f > # Parent b544f8e0d9214560a6acddbb0f40db5146e9463d > Workaround for "configuration file test failed" under OpenVZ. > > If nginx was used under OpenVZ and a container with nginx was suspended > and resumed, configuration tests started to fail because of EADDRINUSE > returned from listen() instead of bind(): > > # nginx -t > nginx: the configuration file /etc/nginx/nginx.conf syntax is ok > nginx: [emerg] listen() to 0.0.0.0:80, backlog 511 failed (98: Address already in use) > nginx: configuration file /etc/nginx/nginx.conf test failed > > With this change EADDRINUSE errors returned by listen() are handled > similarly to errors returned by bind(), and configuration tests work > fine in the same environment: > > # nginx -t > nginx: the configuration file /etc/nginx/nginx.conf syntax is ok > nginx: configuration file /etc/nginx/nginx.conf test is successful > > More details about OpenVZ suspend/resume bug: > https://bugzilla.openvz.org/show_bug.cgi?id=2470 > > diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c > --- a/src/core/ngx_connection.c > +++ b/src/core/ngx_connection.c > @@ -567,9 +567,19 @@ ngx_open_listening_sockets(ngx_cycle_t * > #endif > > if (listen(s, ls[i].backlog) == -1) { > - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, > - "listen() to %V, backlog %d failed", > - &ls[i].addr_text, ls[i].backlog); > + err = ngx_socket_errno; > + > + /* > + * on OpenVZ after suspend/resume EADDRINUSE > + * may be returned by listen() instead of bind(), see > + * https://bugzilla.openvz.org/show_bug.cgi?id=2470 > + */ > + > + if (err != NGX_EADDRINUSE || !ngx_test_config) { > + ngx_log_error(NGX_LOG_EMERG, log, err, > + "listen() to %V, backlog %d failed", > + &ls[i].addr_text, ls[i].backlog); > + } > > if (ngx_close_socket(s) == -1) { > ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, > @@ -577,7 +587,15 @@ ngx_open_listening_sockets(ngx_cycle_t * > &ls[i].addr_text); > } > > - return NGX_ERROR; > + if (err != NGX_EADDRINUSE) { > + return NGX_ERROR; > + } > + > + if (!ngx_test_config) { > + failed = 1; > + } > + > + continue; > } > > ls[i].listen = 1; > -- Best regards, Gena From mike.maccana at gmail.com Mon Aug 3 16:51:34 2015 From: mike.maccana at gmail.com (Mike MacCana) Date: Mon, 3 Aug 2015 17:51:34 +0100 Subject: [PATCH] update default ssl_ciphers value Message-ID: The current example value for ssl_ciphers in nginx (HIGH:!aNULL:!MD5) has a number of security issues, including: - Weak DH key exchange / vulnerability to logjam attack - Preferring AES-CBC instead of GCM, which causes an 'obsolete cipher suite' message in recent versions of Chrome - 128 bit AES should be preferred over 192 and 256 bit AES considering attacks that specifically affect the larger key sizes but do not affect AES 128 Users who are aware that the values presented are an issue may typically use tools like Mozilla's SSL Config Generator https://mozilla.github.io/server-side-tls/ssl-config-generator, https://cipherli.st, or various blogs that are hopefully up to date. However: - Many users will not be aware this is an issue, and may simply uncomment the example ssl config provided. - The official nginx docs at http://nginx.org/en/docs/http/configuring_https_servers.html#compatibility state 'configuring (ssl_ciphers) explicitly is generally not needed' which is incorrect. - nginx has fixed this in the past multiple times, most recently in 1.0.5, see http://nginx.org/en/docs/http/configuring_https_servers.html#compatibility : Version 1.0.5 and later: the default SSL ciphers are ?HIGH:!aNULL:!MD5?. Version 0.7.65, 0.8.20 and later: the default SSL ciphers are ?HIGH:!ADH:!MD5?. Version 0.8.19: the default SSL ciphers are ?ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM?. Version 0.7.64, 0.8.18 and earlier: the default SSL ciphers are ?ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP?. - nginx, like all software, should use secure examples The following patch matches the 'intermediate' settings in Mozilla's TLS Configurator, including IE7 upwards for wide compatibility. Note: I've used a maximum text width of 80 characters for code, per http://nginx.org/en/docs/contributing_changes.html, however it seems there is no way to keep this line short in the config file. # HG changeset patch # User Mike MacCana # Date 1438616573 -3600 # Mon Aug 03 16:42:53 2015 +0100 # Node ID 9d055a8eba96c1e49e970770a37f742744db083c # Parent b544f8e0d9214560a6acddbb0f40db5146e9463d Update SSL cipher list diff -r b544f8e0d921 -r 9d055a8eba96 conf/nginx.conf --- a/conf/nginx.conf Thu Jul 30 16:43:48 2015 -0700 +++ b/conf/nginx.conf Mon Aug 03 16:42:53 2015 +0100 @@ -105,7 +105,7 @@ # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; - # ssl_ciphers HIGH:!aNULL:!MD5; + # ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA # ssl_prefer_server_ciphers on; # location / { diff -r b544f8e0d921 -r 9d055a8eba96 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Thu Jul 30 16:43:48 2015 -0700 +++ b/src/http/modules/ngx_http_ssl_module.c Mon Aug 03 16:42:53 2015 +0100 @@ -13,8 +13,28 @@ typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +#define NGX_DEFAULT_CIPHERS "ECDHE-RSA-AES128-GCM-SHA256\ +:ECDHE-ECDSA-AES128-GCM-SHA256\ +:ECDHE-RSA-AES256-GCM-SHA384\ +:ECDHE-ECDSA-AES256-GCM-SHA384\ +:DHE-RSA-AES128-GCM-SHA256\ +:ECDHE-RSA-AES128-SHA256\ +:DHE-RSA-AES128-SHA256\ +:ECDHE-RSA-AES256-SHA384\ +:DHE-RSA-AES256-SHA384\ +:ECDHE-RSA-AES256-SHA256\ +:DHE-RSA-AES256-SHA256\ +:HIGH\ +:!aNULL\ +:!eNULL\ +:!EXPORT\ +:!DES\ +:!RC4\ +:!MD5\ +:!PSK\ +:!SRP\ +:!CAMELLIA" -#define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" #define NGX_DEFAULT_ECDH_CURVE "prime256v1" #define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1" If this patch is accepted I will also update the documentation accordingly. SSL Labs handshake test results Before: https://archive.is/PfOGL After: https://archive.is/JccUh The changes in the patch above are already widely used by Mozilla Server Side TLS users, but if further discussion is needed on prioritisation logic then the following may be helpful: - https://wiki.mozilla.org/Security/Server_Side_TLS#Prioritization_logic (used for this patch) - https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html (used for cipherli.st) - https://github.com/nodejs/node/commit/5755fc099f883293530406c423bda47414834057 (node doing the same thing recently) Thanks, Mike -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Aug 3 17:31:37 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 3 Aug 2015 20:31:37 +0300 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: References: Message-ID: <20150803173137.GO19190@mdounin.ru> Hello! On Mon, Aug 03, 2015 at 05:51:34PM +0100, Mike MacCana wrote: > The current example value for ssl_ciphers in nginx (HIGH:!aNULL:!MD5) has a > number of security issues, including: > > - Weak DH key exchange / vulnerability to logjam attack This is not really related to the cipher suite used, but rather to the DH paramters used. We may consider removing default DH parameters from nginx code instead. > - Preferring AES-CBC instead of GCM, which causes an 'obsolete cipher > suite' message in recent versions of Chrome There is no preference enforced by nginx by default. > - 128 bit AES should be preferred over 192 and 256 bit AES considering > attacks that specifically affect the larger key sizes but do not affect AES > 128 As far as I undersand, this is about related-key attacks and doesn't really affect nginx operation. The "no preference" above also applies. Overral answer: No, thanks. And even if some of the over concens were valid, the answer would be the same. The default is kept good enough to be generally usable, and it doesn't try to account for any recent cryptographic findings, nor it tries to enforce any chipher preferences on server. This approach is believed to be better in a quickly changing world assuming the administrator is not tracking recent attacks and changes the configuration accordingly. -- Maxim Dounin http://nginx.org/ From mike.maccana at gmail.com Mon Aug 3 19:51:07 2015 From: mike.maccana at gmail.com (Mike MacCana) Date: Mon, 3 Aug 2015 20:51:07 +0100 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: <20150803173137.GO19190@mdounin.ru> References: <20150803173137.GO19190@mdounin.ru> Message-ID: On Mon, Aug 3, 2015 at 6:31 PM, Maxim Dounin wrote: > > Overral answer: > > No, thanks. And even if some of the over concens were valid, the > answer would be the same. The default is kept good enough to be > generally usable, and it doesn't try to account for any recent > cryptographic findings, nor it tries to enforce any chipher > preferences on server. This approach is believed to be better in > a quickly changing world assuming the administrator is not > tracking recent attacks and changes the configuration accordingly. > Thanks for the quick response Maxim. To clarify, there's currently 3 issues regarding cipher lists in nginx : - NGX_DEFAULT_CIPHERS has insecure defaults. You mention 'there is no preference enforced by nginx by default' - are you saying NGX_DEFAULT_CIPHERS is unused? - the example configuration in the config file is insecure - documentation which incorrectly states that the example does not need to be modified > This approach is believed to be better in a quickly changing world assuming the administrator is not tracking recent attacks and changes the configuration accordingly. Should this mean 'assuming the administrator is tracking recent attacks'? Because: - If you assume the administrator is *not* tracking recent attacks then the example config should be secure. - If you assume the administrator *is* tracking recent attacks - which is a bad assumption, as many nginx users are not system administrators but rather web developers with little to no interest in ssl - then it's still beneficial to provide a more recent cipher list, as it stops nginx users having to fix the software out of the box. What specifically does nginx lose from fixing the insecure default config, shipping a more current example, and fixing the incorrect docs? Mike -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Aug 3 21:09:27 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 4 Aug 2015 00:09:27 +0300 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: References: <20150803173137.GO19190@mdounin.ru> Message-ID: <20150803210927.GS19190@mdounin.ru> Hello! On Mon, Aug 03, 2015 at 08:51:07PM +0100, Mike MacCana wrote: > On Mon, Aug 3, 2015 at 6:31 PM, Maxim Dounin wrote: > > > > > > > Overral answer: > > > > No, thanks. And even if some of the over concens were valid, the > > answer would be the same. The default is kept good enough to be > > generally usable, and it doesn't try to account for any recent > > cryptographic findings, nor it tries to enforce any chipher > > preferences on server. This approach is believed to be better in > > a quickly changing world assuming the administrator is not > > tracking recent attacks and changes the configuration accordingly. > > > > Thanks for the quick response Maxim. To clarify, there's currently 3 issues > regarding cipher lists in nginx : > > - NGX_DEFAULT_CIPHERS has insecure defaults. This is not true. See my previous message for detailed explanation on why your concerns are invalid. > You mention 'there is no > preference enforced by nginx by default' - are you saying > NGX_DEFAULT_CIPHERS is unused? Read: default for ssl_prefer_server_ciphers is off, see http://nginx.org/r/ssl_prefer_server_ciphers. > - the example configuration in the config file is insecure This is not true, see above. > - documentation which incorrectly states that the example does not need to > be modified The documentation says what's we think is a good enough strategy in general, see below for a more detailed explanation. > > This approach is believed to be better in a quickly changing world > assuming the administrator is not tracking recent attacks and changes the > configuration accordingly. > > Should this mean 'assuming the administrator is tracking recent attacks'? > Because: > - If you assume the administrator is *not* tracking recent attacks then > the example config should be secure. It is. > - If you assume the administrator *is* tracking recent attacks - which is > a bad assumption, as many nginx users are not system administrators but > rather web developers with little to no interest in ssl - then it's still > beneficial to provide a more recent cipher list, as it stops nginx users > having to fix the software out of the box. The default configuration provided is as secure as it can be, assuming the rate at which nginx is generally updated and the rate at which various new attacks tend to appear. So, unless you are closely tracking recent attacks, it's believed to be better strategy to stick with the default as provided, which usually results in better security in long term. > What specifically does nginx lose from fixing the insecure default config, > shipping a more current example, and fixing the incorrect docs? As previously said, the default is not insecure, and the documentation isn't incorrect. Moreover, the default is believed to be better than "a more current example" in a long run, as "a more current example" tends to be new very several months, and sometimes exactly opposite to a previous "more current" one. -- Maxim Dounin http://nginx.org/ From mike.maccana at gmail.com Mon Aug 3 22:53:08 2015 From: mike.maccana at gmail.com (Mike MacCana) Date: Mon, 3 Aug 2015 23:53:08 +0100 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: <20150803210927.GS19190@mdounin.ru> References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> Message-ID: Thanks for the quick response again Maxim. You make some excellent points: 1. Best practices for cipher lists change over time. 2. ssl_prefer_server_ciphers is off by default For now: how about: - We use up to date values for NGX_DEFAULT_CIPHERS - We turn on ssl_prefer_server_ciphers by default - having the server control the negotiation is recommended in every configuration guide - We add an up to date ssl_ciphers example to the default config file - Above the example, we add a comment with the point you've made above: # Security note: best practices for ssl_ciphers frequently change over time. # Check https://mozilla.github.io/server-side-tls/ssl-config-generator for more recent settings # ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256: ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384: DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE- RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256- SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256: HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA This would resolve the SSL Labs and Chrome warnings that currently show up with nginx, but make sure people configuring nginx are aware that they need to keep up to date, and shows them where they can get a more recent config. If the user is lazy and doesn't follow ssl happenings, they're still better out of the box. And actually giving them a URL to check might make them be a little more security conscious. How does that sound? -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Aug 3 23:10:13 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 4 Aug 2015 02:10:13 +0300 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> Message-ID: <20150803231013.GU19190@mdounin.ru> Hello! On Mon, Aug 03, 2015 at 11:53:08PM +0100, Mike MacCana wrote: > Thanks for the quick response again Maxim. You make some excellent points: > > 1. Best practices for cipher lists change over time. > 2. ssl_prefer_server_ciphers is off by default > > For now: how about: > - We use up to date values for NGX_DEFAULT_CIPHERS > - We turn on ssl_prefer_server_ciphers by default - having the server > control the negotiation is recommended in every configuration guide > - We add an up to date ssl_ciphers example to the default config file > - Above the example, we add a comment with the point you've made above: > > # Security note: best practices for ssl_ciphers frequently change over time. > # Check https://mozilla.github.io/server-side-tls/ssl-config-generator for > more recent settings > # ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256: > ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384: > DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE- > RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256- > SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256: > HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA > > This would resolve the SSL Labs and Chrome warnings that currently show up > with nginx, but make sure people configuring nginx are aware that they need > to keep up to date, and shows them where they can get a more recent config. > > If the user is lazy and doesn't follow ssl happenings, they're still better > out of the box. And actually giving them a URL to check might make them be > a little more security conscious. > > How does that sound? The number of false claims in your messages and the fact that you are not reading what I already wrote makes this discussion pointless, sorry. -- Maxim Dounin http://nginx.org/ From mike.maccana at gmail.com Tue Aug 4 07:59:01 2015 From: mike.maccana at gmail.com (Mike MacCana) Date: Tue, 4 Aug 2015 08:59:01 +0100 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: <20150803231013.GU19190@mdounin.ru> References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> <20150803231013.GU19190@mdounin.ru> Message-ID: Maxim I apologise if I've offended you or not understood something you wrote. My methodology was as follows: - Install nginx - Enable ssl - Run the SSL Labs scan and a current version of Chrome - Provide a patch that fixes the errors reported by those tools Do you believe the provided SSL Labs report or Chrome is in error, or that something is wrong with the testing methodology above? On Tue, Aug 4, 2015 at 12:10 AM, Maxim Dounin wrote: > Hello! > > On Mon, Aug 03, 2015 at 11:53:08PM +0100, Mike MacCana wrote: > > > Thanks for the quick response again Maxim. You make some excellent > points: > > > > 1. Best practices for cipher lists change over time. > > 2. ssl_prefer_server_ciphers is off by default > > > > For now: how about: > > - We use up to date values for NGX_DEFAULT_CIPHERS > > - We turn on ssl_prefer_server_ciphers by default - having the server > > control the negotiation is recommended in every configuration guide > > - We add an up to date ssl_ciphers example to the default config file > > - Above the example, we add a comment with the point you've made above: > > > > # Security note: best practices for ssl_ciphers frequently change over > time. > > # Check https://mozilla.github.io/server-side-tls/ssl-config-generator > for > > more recent settings > > # ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256: > > ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384: > > DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE- > > RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256- > > SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256: > > HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA > > > > This would resolve the SSL Labs and Chrome warnings that currently show > up > > with nginx, but make sure people configuring nginx are aware that they > need > > to keep up to date, and shows them where they can get a more recent > config. > > > > If the user is lazy and doesn't follow ssl happenings, they're still > better > > out of the box. And actually giving them a URL to check might make them > be > > a little more security conscious. > > > > How does that sound? > > The number of false claims in your messages and the fact that you > are not reading what I already wrote makes this discussion > pointless, sorry. > > -- > Maxim Dounin > http://nginx.org/ > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From wmark+nginx at hurrikane.de Tue Aug 4 12:54:54 2015 From: wmark+nginx at hurrikane.de (W-Mark Kubacki) Date: Tue, 4 Aug 2015 14:54:54 +0200 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> Message-ID: Do not specifiy cipher suites, one by one, by name. That's dangerous. OpenSSL knows groups! Examples for groups: - HIGH - TLSv1.2 ? and matching: - HIGH+kEECDH - HIGH+kEECDH:HIGH+kEDH:-3DES Examining their implementation, and ordering them is the task of security engineers and/or best delegated to the authors of TLS libraries. Imagine a cipher suite "falls out of fashion", or an implementation turns out to be weaker than expected, or new ones get implemented (hello CHACHA20! see you TLSv1.3!). You don't want to go through those lists (you shouldn't have used) again nor should you expect that a regular user will do this (most didn't even care enough to change the default DHparam). -- Mark 2015-08-04 0:53 GMT+02:00 Mike MacCana : > Thanks for the quick response again Maxim. You make some excellent points: > > 1. Best practices for cipher lists change over time. > 2. ssl_prefer_server_ciphers is off by default > > For now: how about: > - We use up to date values for NGX_DEFAULT_CIPHERS > - We turn on ssl_prefer_server_ciphers by default - having the server > control the negotiation is recommended in every configuration guide > - We add an up to date ssl_ciphers example to the default config file > - Above the example, we add a comment with the point you've made above: > > # Security note: best practices for ssl_ciphers frequently change over time. > # Check https://mozilla.github.io/server-side-tls/ssl-config-generator for > more recent settings > # ssl_ciphers > ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA > > This would resolve the SSL Labs and Chrome warnings that currently show up > with nginx, but make sure people configuring nginx are aware that they need > to keep up to date, and shows them where they can get a more recent config. > > If the user is lazy and doesn't follow ssl happenings, they're still better > out of the box. And actually giving them a URL to check might make them be a > little more security conscious. > > How does that sound? > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From mike.maccana at gmail.com Tue Aug 4 13:52:58 2015 From: mike.maccana at gmail.com (Mike MacCana) Date: Tue, 4 Aug 2015 14:52:58 +0100 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> Message-ID: > Examining their implementation, and ordering them is the task of security engineers Indeed. The ciphersuite ordering is directly from the Mozilla Server Side TLS project. https://mozilla.github.io/server-side-tls/ssl-config-generator/ My understanding is OpenSSLs inbuilt ciphersuite groups (per https://www.openssl.org/docs/apps/ciphers.html) aren't sufficient to implement Mozilla's rationale, see https://wiki.mozilla.org/Security/Server_Side_TLS#Prioritization_logic, hence why Mozilla specify the ciphersuites ordering explicitly. On Tue, Aug 4, 2015 at 1:54 PM, W-Mark Kubacki wrote: > Do not specifiy cipher suites, one by one, by name. That's dangerous. > OpenSSL knows groups! > > Examples for groups: > - HIGH > - TLSv1.2 > ? and matching: > - HIGH+kEECDH > - HIGH+kEECDH:HIGH+kEDH:-3DES > > Examining their implementation, and ordering them is the task of > security engineers and/or best delegated to the authors of TLS > libraries. > > Imagine a cipher suite "falls out of fashion", or an implementation > turns out to be weaker than expected, or new ones get implemented > (hello CHACHA20! see you TLSv1.3!). You don't want to go through those > lists (you shouldn't have used) again nor should you expect that a > regular user will do this (most didn't even care enough to change the > default DHparam). > > -- > Mark > > 2015-08-04 0:53 GMT+02:00 Mike MacCana : > > Thanks for the quick response again Maxim. You make some excellent > points: > > > > 1. Best practices for cipher lists change over time. > > 2. ssl_prefer_server_ciphers is off by default > > > > For now: how about: > > - We use up to date values for NGX_DEFAULT_CIPHERS > > - We turn on ssl_prefer_server_ciphers by default - having the server > > control the negotiation is recommended in every configuration guide > > - We add an up to date ssl_ciphers example to the default config file > > - Above the example, we add a comment with the point you've made above: > > > > # Security note: best practices for ssl_ciphers frequently change over > time. > > # Check https://mozilla.github.io/server-side-tls/ssl-config-generator > for > > more recent settings > > # ssl_ciphers > > > ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA > > > > This would resolve the SSL Labs and Chrome warnings that currently show > up > > with nginx, but make sure people configuring nginx are aware that they > need > > to keep up to date, and shows them where they can get a more recent > config. > > > > If the user is lazy and doesn't follow ssl happenings, they're still > better > > out of the box. And actually giving them a URL to check might make them > be a > > little more security conscious. > > > > How does that sound? > > > > > > _______________________________________________ > > nginx-devel mailing list > > nginx-devel at nginx.org > > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mallya16 at gmail.com Tue Aug 4 14:34:52 2015 From: mallya16 at gmail.com (sunil mallya) Date: Tue, 4 Aug 2015 07:34:52 -0700 Subject: Making external http calls from nginx module Message-ID: Hey folks, Can someone point a code snippet on how I could make a http call to an external service within my module. I believe I should be able to reuse some of the code in ngx_proxy but unclear about the pitfalls. Muchos Gracias, Sunil Mallya @sunilmallya -------------- next part -------------- An HTML attachment was scrubbed... URL: From serg.brester at sebres.de Tue Aug 4 15:17:19 2015 From: serg.brester at sebres.de (Sergey Brester) Date: Tue, 04 Aug 2015 17:17:19 +0200 Subject: Making external http calls from nginx module In-Reply-To: References: Message-ID: <2df4844b866b1b2592a1716bd9ce2a8d@sebres.de> Hi, You can try to use `ngx_http_subrequest` (don't know how good it works for not an nginx location (or named location)). For example see some module used that (ex.: https://github.com/sebres/nginx/blob/hg-mirror/src/http/modules/ngx_http_auth_request_module.c#L189). You can also try to use a board directive `post_action` using pure nginx-config solution, without writing own module - adding it to your location should call external service specified within (but if I'm not mistaken still unsupported/undocumented feature). Regards, sebres 04.08.2015 16:34, wrote sunil mallya: > Hey folks, > > Can someone point a code snippet on how I could make a http call to an external service within my module. I believe I should be able to reuse some of the code in ngx_proxy but unclear about the pitfalls. > > Muchos Gracias, > Sunil Mallya > > @sunilmallya > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel [1] Links: ------ [1] http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From teward at dark-net.net Tue Aug 4 15:21:06 2015 From: teward at dark-net.net (Thomas Ward) Date: Tue, 04 Aug 2015 11:21:06 -0400 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> Message-ID: <55C0D862.8070703@dark-net.net> This discussion has been done before, elsewhere, and the consensus was to stick with the defaults (for Debian and Ubuntu nginx). Effectively though, I think the point was missed by you, Mike. So let me put in my two cents. If you merely want the summary of all the text below, go to the bottom of this message and read. On 08/04/2015 09:52 AM, Mike MacCana wrote: > My understanding is OpenSSLs inbuilt ciphersuite groups (per > https://www.openssl.org/docs/apps/ciphers.html) aren't sufficient to > implement Mozilla's rationale, see > https://wiki.mozilla.org/Security/Server_Side_TLS#Prioritization_logic, hence > why Mozilla specify the ciphersuites ordering explicitly. This implies that the administrators of a given server are going to routinely check and update their config as the security battlefront changes. We aren't necessarily catering to that niche of highly-diligent server administrators, but to those that're going to stage servers and then not bother to necessarily check the ciphers that are "strong". You also assume Mozilla's rationale is the correct one. Different security engineers will give you different answers of "What is the most secure?" in practice. Mozilla's guidelines are just their guidelines, not the rule. > > On Tue, Aug 4, 2015 at 1:54 PM, W-Mark Kubacki > > wrote: > > Do not specifiy cipher suites, one by one, by name. That's dangerous. > OpenSSL knows groups! > This is good advice! OpenSSL's defaults in those groups will dynamically change as ciphers emerge or change. As such, "HIGH", "HIGH+kEECDH", etc. will always update as ciphers are deprecated, added, etc. > > > > Imagine a cipher suite "falls out of fashion", or an implementation > turns out to be weaker than expected, or new ones get implemented > (hello CHACHA20! see you TLSv1.3!). You don't want to go through those > lists (you shouldn't have used) again nor should you expect that a > regular user will do this (most didn't even care enough to change the > default DHparam). > This is also the same logic, and is VALID advice. > > > > This would resolve the SSL Labs and Chrome warnings that > currently show up > > with nginx, but make sure people configuring nginx are aware > that they need > > to keep up to date, and shows them where they can get a more > recent config. > Well, let's do a comparison, then, and I'll make my point observed, as well as the others above! Note that these PDFs here in these links are generated by Google Chrome, in case you're wondering, and stored on the same testing environment, but with the strongest set of these for ciphers/settings. These links will remain up until I destroy the EC2 box, so it'll be about six months before I get rid of them. The test system was an Ubuntu 14.04 LTS x64 OS running on an Amazon EC2 micro instance, using the nginx.org Ubuntu repository for the Mainline packages. So we're on the latest Mainline release, with a commonly used OS and OpenSSL set. The web browser used for testing is Chrome 64bit 44.0.2403.125. First, the "absolutely completely insanely you-should-be-beaten-for-this bad" configuration. This is what I have on my honeypot box, but this was not actually my honeypot. Since it's so bad, it's got Grade F. I didn't bother testing Chrome with this because I know it will complain: http://testing.hellnet.io/ssldata/SSL-Server-Test_testing.hellnet.io_TotallyBadSSL.pdf Second, the nginx defaults. The defaults won't include the dhparam of a decent size, so it gets capped to Grade B. We also have a forward secrecy error. Not bad, though. Also, Chrome isn't complaining. http://testing.hellnet.io/ssldata/SSL-Server-Test_testing.hellnet.io_NGINXDefaults.pdf Third, the nginx defaults plus a 2048-bit DH params file. Grade becomes A-. Even better, and Chrome still doesn't complain! http://testing.hellnet.io/ssldata/SSL-Server-Test_testing.hellnet.io_NGINXDefaultsPlusDHPARAM.pdf Fourth, your proposed ciphers to be set. It still gets Grade capped to B because there's no DHPARAM of a suitable size, and there's still a forward secrecy error, and Chrome's not complaining. So this didn't fix anything. http://testing.hellnet.io/ssldata/SSL-Server_Test_testing.hellnet.io_Proposed.pdf Fifth, Your same proposed cipher set, plus the 2048-bit DH params file included gets an A-, which is where the nginx defaults plus a dhparam file. Still got a forward secrecy error, and Chrome's still not complaining: http://testing.hellnet.io/ssldata/SSL-Server-Test_testing.hellnet.io_ProposedPlusDHPARAM.pdf Now let's break the aforementioned recommendations, ignore legacy support, put a 2048-bit DHPARAM into place, and only use the two cipher groups from cipherli.st. This gets an A rating, and there's no forward secrecy problems, AND Chrome doesn't complain. But, I totally remove all the aforementioned recommendations and now have to manage this effectively by myself. http://testing.hellnet.io/ssldata/SSL-Server-Test_testing.hellnet.io_CipherLi.st.pdf > > If the user is lazy and doesn't follow ssl happenings, they're > still better > > out of the box. And actually giving them a URL to check might > make them be a > > little more security conscious. > > > You fail to consider the previously stated issue of this removing the ability for OpenSSL 'supported' cipher groups to be used in this case. And since the typical user *is* lazy and would probably rather have it work out of the box, they aren't going to be checking what's 'strong' for ciphers and such. The security-conscious group are going to be on top of this anyways. The average user will not. Using a long string of specific ciphers is bad, for all the reasons that have been mentioned before (so I will not repeat those reasons here). -- So, what's the point of this mini tirade and multiple links? From my perspective, the moral of the story, and my analysis, is as follows: * One, you are ignoring the advice from multiple other individuals - advice which is actually valid. * Two, you assume Mozilla's guidelines are the rule, rather than just a guideline. That's not actually the case. * Three, your proposed cipher sets don't really add any real value to the already existing defaults. There's no value in going away from the group-based definitions to the individual ciphers, since you now have to constantly check each individual cipher to determine if it's still 'good' or not. That adds additional work to both NGINX developers to have to constantly check the 'good ciphers lists' and constantly make revisions as the SSL/TLS landscape changes. And, for sysadmin simplicity sake for the newer sysadmins not fluent in OpenSSL and cipher naming, "HIGH" indicates high strength ciphers. What does " ECDHE-RSA-AES128-GCM-SHA256" really mean to a non-fluent sysadmin? This is also one key part of the argument downstream against putting the longer cipher strings into the downstream-packaged configurations. That same argument applies here if someone's trying to understand the default cipherstring set from the documentation. Just my two cents on this. ------ Thomas -------------- next part -------------- An HTML attachment was scrubbed... URL: From mike.maccana at gmail.com Tue Aug 4 18:53:49 2015 From: mike.maccana at gmail.com (Mike MacCana) Date: Tue, 4 Aug 2015 19:53:49 +0100 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: <55C0D862.8070703@dark-net.net> References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> <55C0D862.8070703@dark-net.net> Message-ID: On Tue, Aug 4, 2015 at 4:21 PM, Thomas Ward wrote: > This discussion has been done before, elsewhere, and the consensus was to > stick with the defaults (for Debian and Ubuntu nginx). > Understood. And I appreciate that the same issue coming up repeatedly is annoying. The fastest way to fix it is to use better defaults ;^). This implies that the administrators of a given server are going to > routinely check and update their config as the security battlefront > changes. > Not at all: I mentioned earlier that I doubt most nginx users do this, and also mentioned that using a more secure defaults will help these people. > You also assume Mozilla's rationale is the correct one. > No, I attached a report which complained of specific vulnerabilities in the default set up. See https://archive.is/PfOGL from my original message. I mentioned Mozilla's cipher lists fixes the vulnerabilities, because it does (see https://archive.is/JccUh from my original message). However I do agree there are other sources which may also be appropriate fixes, which is why I also attached three different cipher rationales in my original report. Quoting the original message: > The changes in the patch above are already widely used by Mozilla Server Side TLS users, but if further discussion is needed on prioritisation logic then the following may be helpful: - https://wiki.mozilla.org/Security/Server_Side_TLS#Prioritization_logic (used for this patch) - https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html (used for cipherli.st) - https://github.com/nodejs/node/commit/5755fc099f883293530406c423bda47414834057 (node doing the same thing recently) I am very open to discussing other cipher suites that may provide a fix. > On Tue, Aug 4, 2015 at 1:54 PM, W-Mark Kubacki > wrote: > >> Do not specifiy cipher suites, one by one, by name. That's dangerous. >> OpenSSL knows groups! >> > This is good advice! OpenSSL's defaults in those groups will dynamically > change as ciphers emerge or change. As such, "HIGH", "HIGH+kEECDH", etc. > will always update as ciphers are deprecated, added, etc. > Alas there's no inbuilt OpenSSL group with 'intermediate' compatibility that passes SSL Labs with an A or higher. See below. Happy to use one if you find it. Well, let's do a comparison, then > ***Exactly***! I did this in my original message! I suspect the confusion is that people simply didn't see the 'before' and 'after' scan results attached to the patch. Now let's break the aforementioned recommendations, ignore legacy support, > put a 2048-bit DHPARAM into place, and only use the two cipher groups from > cipherli.st. This gets an A rating, and there's no forward secrecy > problems, AND Chrome doesn't complain. But, I totally remove all the > aforementioned recommendations and now have to manage this effectively by > myself. > http://testing.hellnet.io/ssldata/SSL-Server-Test_testing.hellnet.io_CipherLi.st.pdf > > > If the user is lazy and doesn't follow ssl happenings, they're still >> better >> > out of the box. And actually giving them a URL to check might make them >> be a >> > little more security conscious. >> > >> > You fail to consider the previously stated issue of this removing the > ability for OpenSSL 'supported' cipher groups to be used in this case. > Totally happy to use the cipherli.st or whatever else fixes the reported issues instead, which is why I linked to cipherli.st in the first place. However cipherli.st, like Mozilla, uses individual ciphers for it's legacy config - click 'Yes, give me a ciphersuite that works with legacy / old software.' on https://cipherli.st. > And since the typical user *is* lazy and would probably rather have it > work out of the box, they aren't going to be checking what's 'strong' for > ciphers and such. > Agreed. Using the cipherli.st 'legacy' config, rather than the high security one, would allow it to work out of the box. The cipherli.st legacy config doesn't use groups, but shipping a secure config should take precedence over the ability to use groups. Thomas you're on the right track. You're doing the same testing I did in the original patch,and linking to the same tools. I linked cipherli.st and node.js because I *don't* believe that Mozilla guidelines are the rule. There's no value in going away from the group-based definitions to the > individual ciphers, since you now have to constantly check each individual > cipher to determine if it's still 'good' or not. > The value is in passing the same scan that you and I both ran (weirdly we got slightly different results, which I'm investigating). > That adds additional work to both NGINX developers to have to constantly > check the 'good ciphers lists' and constantly make revisions as the SSL/TLS > landscape changes. > Totally agreed, I'm happy to do this work if needed. > And, for sysadmin simplicity sake for the newer sysadmins not fluent in > OpenSSL and cipher naming, "HIGH" indicates high strength ciphers. What > does " ECDHE-RSA-AES128-GCM-SHA256" really mean to a non-fluent sysadmin? > Agreed, very little. Hence: - Having better defaults for the people who don't care - Linking somewhere downstream (whether Moz or cipherli.st or elsewhere) where people who do care can get an updated ciphersuite list in the example config. Mike -------------- next part -------------- An HTML attachment was scrubbed... URL: From teward at dark-net.net Tue Aug 4 19:24:55 2015 From: teward at dark-net.net (Thomas Ward) Date: Tue, 04 Aug 2015 15:24:55 -0400 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> <55C0D862.8070703@dark-net.net> Message-ID: <55C11187.7070800@dark-net.net> You've failed to get my points, apparently. Reminds me of me three years ago before getting hacked into sobered me up. On 08/04/2015 02:53 PM, Mike MacCana wrote: > On Tue, Aug 4, 2015 at 4:21 PM, Thomas Ward > wrote: > > This discussion has been done before, elsewhere, and the consensus > was to stick with the defaults (for Debian and Ubuntu nginx). > > > Understood. And I appreciate that the same issue coming up repeatedly > is annoying. The fastest way to fix it is to use better defaults ;^). No, wrong. The current defaults are sane. "HIGH" has this definition by OpenSSL's standards: "high" encryption cipher suites. This currently means those with key lengths larger than 128 bits, and some cipher suites with 128-bit keys. What makes yours any better than that definition? > > This implies that the administrators of a given server are going > to routinely check and update their config as the security > battlefront changes. > > > Not at all: I mentioned earlier that I doubt most nginx users do this, > and also mentioned that using a more secure defaults will help these > people. You just shift the work to the developers in your proposal. That doesn't reduce overall work load, NOR does it take into account that ciphersuites change over time. Hypothetical: I come out with a brand new cipher that is tested, stabbed at, etc. and is considered "secure". It's included in OpenSSL (and others, but lets use OpenSSL for now) 1.5.0. Your cipher strings remain used in 'nginx'. 'nginx' no longer can support the new cipher (added to "HIGH" by the OpenSSL people), and now it's up to the NGINX developers to bother checking to see if the cipherstrings that are recommended change. You've done nothing to reduce workload overall - you are just making nginx developers, and frankly downstream packagers, do the work. That isn't an improvement, it's a detriment. Especially if "HIGH" adapts to include new ciphers. > > > You also assume Mozilla's rationale is the correct one. > > > No, I attached a report which complained of specific vulnerabilities > in the default set up. See https://archive.is/PfOGL from my original > message. > > I mentioned Mozilla's cipher lists fixes the vulnerabilities, because > it does (see https://archive.is/JccUh from my original message). Again, *wrong*. Unless the dh_param defaults are also being modified, which it suggests that may eventually possibly happen based on Maxim's earlier statements, the DH strength issue remains. Your patch doesn't resolve that, so you still get capped at B. > > I am very open to discussing other cipher suites that may provide a fix. What specifically do your changes fix? They don't address the DH problem, which is the only blatantly obvious 'vulnerability' that your "Before" image shows. DH parameter strength changes are the only way to fix that, and that has to be provided separately by admins, not necessarily by nginx. >> On Tue, Aug 4, 2015 at 1:54 PM, W-Mark Kubacki >> > wrote: >> >> Do not specifiy cipher suites, one by one, by name. That's >> dangerous. >> OpenSSL knows groups! >> > This is good advice! OpenSSL's defaults in those groups will > dynamically change as ciphers emerge or change. As such, "HIGH", > "HIGH+kEECDH", etc. will always update as ciphers are deprecated, > added, etc. > > > Alas there's no inbuilt OpenSSL group with 'intermediate' > compatibility that passes SSL Labs with an A or higher. See below. > Happy to use one if you find it. If I remember correctly, "Intermediate" exposes some "medium" ciphers. > > Well, let's do a comparison, then > > > ***Exactly***! I did this in my original message! > > I suspect the confusion is that people simply didn't see the 'before' > and 'after' scan results attached to the patch. "Before" vs. "After" with no details on the specific changes made. Assumptions can therefore be made you made other changes in the process, since the cipher string you proposed still uses DHE ciphers, and the default dhparam hasn't changed. > > Totally happy to use the cipherli.st or whatever > else fixes the reported issues instead, which is why I linked to > cipherli.st in the first place. You once again missed my point about "Why should we be forced to test individual ciphers rather than just rely on the groups?" > > However cipherli.st , like Mozilla, uses > individual ciphers for it's legacy config - click 'Yes, give me a > ciphersuite that works with legacy / old software.' > on https://cipherli.st. > > > And since the typical user *is* lazy and would probably rather > have it work out of the box, they aren't going to be checking > what's 'strong' for ciphers and such. > > > There's no value in going away from the group-based definitions to the > individual ciphers, since you now have to constantly check each > individual cipher to determine if it's still 'good' or not. > > The value is in passing the same scan that you and I both ran (weirdly > we got slightly different results, which I'm investigating). Consider OpenSSL versions here, you don't define your testing environment, I did. To get actually matching baselines we need to compare apples-to-apples to account for minor changes. > > > That adds additional work to both NGINX developers to have to > constantly check the 'good ciphers lists' and constantly make > revisions as the SSL/TLS landscape changes. > > > Totally agreed, I'm happy to do this work if needed. You haven't answered my initial question, nor others' questions, about how this is actually beneficial or fixes things. Why should work be included when there's no specific details? > > > And, for sysadmin simplicity sake for the newer sysadmins not > fluent in OpenSSL and cipher naming, "HIGH" indicates high > strength ciphers. What does " ECDHE-RSA-AES128-GCM-SHA256" really > mean to a non-fluent sysadmin? > > > > - Having better defaults for the people who don't care Still needs the NGINX developers to act as security engineers to determine a "sane" cipherset, when the "HIGH" cipherset, while rejecting all else, is sane for today's SSL environment at this time. > - Linking somewhere downstream (whether Moz or cipherli.st > or elsewhere) where people who do care can get an > updated ciphersuite list in the example config. Discussed downstream, ultimately rejected as a "Why should we make the users do work", especially when security-centric admins are aware of these types of sites. So once again, you haven't proved how your proposed cipherset is actually superior to the nginx defaults. I only see detriments: * Forcing nginx developers to keep this list up to date and maintained * Forcing nginx developers to have to keep tabs and constantly revise the defaults for all security vulnerabilies * Making understanding the defaults harder for non-experienced adminisitrators. Don't get me wrong, I have suggestions for changing the defaults too, mostly involving adding several negations to this, but actually defining every single cipher to use is bad practice for 'defaults'. Thomas -------------- next part -------------- An HTML attachment was scrubbed... URL: From mike.maccana at gmail.com Tue Aug 4 23:11:39 2015 From: mike.maccana at gmail.com (Mike MacCana) Date: Wed, 5 Aug 2015 00:11:39 +0100 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: <55C11187.7070800@dark-net.net> References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> <55C0D862.8070703@dark-net.net> <55C11187.7070800@dark-net.net> Message-ID: I mentioned in my last email message that I was investigating discrepancies between your results and mine: I've since confirmed I'd used ssl_dhparam from Mozilla's preferred config and not included this in the actual patch. I apologise Thomas. Thanks for including your own handshake results as it's given me something to compare against and helped move the discussion forward. With the following setup: - Adding dh_param - nginx hg revision 6217 - 'HIGH:!aNULL:!MD5' as defined in openssl 1.0.1e (too long to paste) I can get an A out of the box - see https://archive.is/fEcdv. I believe this means we're in sync: provided the user keeps openssl up to date, adding dh_param should fix the ssllabs warnings. I was trying to save nginx users some additional work, and not correctly identifying the parameter that resolved the warning was my mistake. Would nginx accept a patch to include dh_params in the example config? -------------- next part -------------- An HTML attachment was scrubbed... URL: From teward at dark-net.net Tue Aug 4 23:41:24 2015 From: teward at dark-net.net (Thomas Ward) Date: Tue, 4 Aug 2015 19:41:24 -0400 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> <55C0D862.8070703@dark-net.net> <55C11187.7070800@dark-net.net> Message-ID: <300CAEDA-F14F-4BCE-858B-DF2B02524AD2@dark-net.net> > On Aug 4, 2015, at 19:11, Mike MacCana wrote: ... > > Would nginx accept a patch to include dh_params in the example config? > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel I have it on good authority that Maxim or someone has a diff planned to change defaults so a patch for that probably won't be needed. This also wouldn't necessarily be too helpful to be in the configuration as the DH parameters need to be generated separately and stored on their own then referenced by the ssl_dhparam parameter. Inclusion in the configuration but commented out with a recommendation to set it up is what we do downstream I think, and likely would end up having to be done here so we don't get "missing file" load errors... I'll have to double check Debian and Ubuntu on that one though to determine what we do at that downstream... Thomas *Sent from my iPhone. Please excuse any typos, as they are likely to happen by accident.* From mdounin at mdounin.ru Wed Aug 5 00:45:02 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 05 Aug 2015 00:45:02 +0000 Subject: [nginx] Workaround for "configuration file test failed" under Op... Message-ID: details: http://hg.nginx.org/nginx/rev/3096ae76ba47 branches: changeset: 6218:3096ae76ba47 user: Gena Makhomed date: Thu Jul 23 14:00:03 2015 -0400 description: Workaround for "configuration file test failed" under OpenVZ. If nginx was used under OpenVZ and a container with nginx was suspended and resumed, configuration tests started to fail because of EADDRINUSE returned from listen() instead of bind(): # nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: [emerg] listen() to 0.0.0.0:80, backlog 511 failed (98: Address already in use) nginx: configuration file /etc/nginx/nginx.conf test failed With this change EADDRINUSE errors returned by listen() are handled similarly to errors returned by bind(), and configuration tests work fine in the same environment: # nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful More details about OpenVZ suspend/resume bug: https://bugzilla.openvz.org/show_bug.cgi?id=2470 diffstat: src/core/ngx_connection.c | 26 ++++++++++++++++++++++---- 1 files changed, 22 insertions(+), 4 deletions(-) diffs (43 lines): diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -567,9 +567,19 @@ ngx_open_listening_sockets(ngx_cycle_t * #endif if (listen(s, ls[i].backlog) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "listen() to %V, backlog %d failed", - &ls[i].addr_text, ls[i].backlog); + err = ngx_socket_errno; + + /* + * on OpenVZ after suspend/resume EADDRINUSE + * may be returned by listen() instead of bind(), see + * https://bugzilla.openvz.org/show_bug.cgi?id=2470 + */ + + if (err != NGX_EADDRINUSE || !ngx_test_config) { + ngx_log_error(NGX_LOG_EMERG, log, err, + "listen() to %V, backlog %d failed", + &ls[i].addr_text, ls[i].backlog); + } if (ngx_close_socket(s) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, @@ -577,7 +587,15 @@ ngx_open_listening_sockets(ngx_cycle_t * &ls[i].addr_text); } - return NGX_ERROR; + if (err != NGX_EADDRINUSE) { + return NGX_ERROR; + } + + if (!ngx_test_config) { + failed = 1; + } + + continue; } ls[i].listen = 1; From mdounin at mdounin.ru Wed Aug 5 00:47:25 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 5 Aug 2015 03:47:25 +0300 Subject: [PATCH] Workaround for "configuration file test failed" under OpenVZ In-Reply-To: <55BF3AC4.10501@csdoc.com> References: <55B9573F.9010901@csdoc.com> <20150803092658.GK19190@mdounin.ru> <55BF3AC4.10501@csdoc.com> Message-ID: <20150805004724.GZ19190@mdounin.ru> Hello! On Mon, Aug 03, 2015 at 12:56:20PM +0300, Gena Makhomed wrote: > On 03.08.2015 12:26, Maxim Dounin wrote: > > >Here is the patch with slightly updated commit log and a comment > >added to the code. Please take a look if it looks fine to you. > > Yes, updated version of patch is more clean and easy to understand, > thank you! Committed, thanks. http://hg.nginx.org/nginx/rev/3096ae76ba47 -- Maxim Dounin http://nginx.org/ From mike.maccana at gmail.com Wed Aug 5 10:25:57 2015 From: mike.maccana at gmail.com (Mike MacCana) Date: Wed, 5 Aug 2015 11:25:57 +0100 Subject: [PATCH] update default ssl_ciphers value In-Reply-To: <300CAEDA-F14F-4BCE-858B-DF2B02524AD2@dark-net.net> References: <20150803173137.GO19190@mdounin.ru> <20150803210927.GS19190@mdounin.ru> <55C0D862.8070703@dark-net.net> <55C11187.7070800@dark-net.net> <300CAEDA-F14F-4BCE-858B-DF2B02524AD2@dark-net.net> Message-ID: On Wed, Aug 5, 2015 at 12:41 AM, Thomas Ward wrote: > > > On Aug 4, 2015, at 19:11, Mike MacCana wrote: > > > Would nginx accept a patch to include dh_params in the example config? > I have it on good authority that Maxim or someone has a diff planned to > change defaults so a patch for that probably won't be needed. > Excellent, and looking forward to it. > Inclusion in the configuration but commented out with a recommendation to > set it up is what we do downstream I think, and likely would end up having > to be done here so we don't get "missing file" load errors... ? Mike -------------- next part -------------- An HTML attachment was scrubbed... URL: From mhenrion at appnexus.com Wed Aug 5 11:21:52 2015 From: mhenrion at appnexus.com (Maxime Henrion) Date: Wed, 5 Aug 2015 11:21:52 +0000 Subject: Subrequests and output filters Message-ID: Hello all, I am currently developing an nginx module in order to implement a software component in our platform. This module's responsibility is to receive upstream requests, forward them to multiple hosts (one host per pool, with N pools; we call a pool a shard), receive all the responses and aggregate them using custom application logic, and finally return an answer. At a first glance, it seems like nginx offers everything I could possibly need in order to implement that software component, but now I'm running into issues as it seems my output filter is never being invoked as I expect it to. Surely I'm doing something wrong... My module (called dispatcher) registers a post-configuration handler to setup the output body filter like so : static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t ngx_http_dispatcher_filter_init(ngx_conf_t *cf) { ngx_http_next_body_filter = ngx_http_top_body_filter; ngx_http_top_body_filter = ngx_http_dispatcher_body_filter; return NGX_OK; } The only other callbacks in the module context are those to create and merge a location configuration. They are invoked when the "dispatcher_pass" command is encountered. Here is the code for this callback : static char * ngx_http_dispatcher_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_core_loc_conf_t *clcf; ngx_http_dispatcher_loc_conf_t *dlcf; ngx_str_t *value, *url; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_dispatcher_handler; dlcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_dispatcher_module); value = cf->args->elts; url = &value[1]; dlcf->url.data = url->data; dlcf->url.len = url->len; if (dlcf->url.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"dispatcher_pass\" needs a non-empty bounce URL"); return NGX_CONF_ERROR; } return NGX_CONF_OK; } So this just setups a handler for later use, and ties some configuration information to our request. Since my handler needs the request body in order to forward those requests, it registers a body read callback : static ngx_int_t ngx_http_dispatcher_handler(ngx_http_request_t *r) { ngx_int_t rc; rc = ngx_http_read_client_request_body(r, ngx_http_dispatcher_post_read_request_body); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_DONE; } NOTE: I'm not sure whether NGX_DONE above is the correct enum value to use, but I have tried NGX_AGAIN and others as well to no avail. Then the request body handler calls into ngx_http_subrequest() to send those N requests to one of the hosts in each of the pools. The so-called "pools" are simple upstream blocks in the configuration file and I use the "proxy_pass" directive os that nginx handles peer selection. Since I cannot use ngx_http_subrequest() to send an external HTTP request, I use a dummy bounce handler defined in the configuration file like so : location /bounce { proxy_pass http://$arg_shard/bid; } So the request body handler just uses a simple HTTP parameter "shard" to direct each of those ngx_http_subrequest() to a different server pool. Finally, here is the request body handler code : static void ngx_http_dispatcher_post_read_request_body(ngx_http_request_t *r) { ngx_http_dispatcher_loc_conf_t *dlcf; ngx_http_request_t *sr; ngx_buf_t *buf; ngx_uint_t i; ngx_str_t *shard; ngx_str_t args; ngx_int_t rc; ngx_http_dispatcher_ctx_t *ctx; ngx_http_post_subrequest_t *psr; if (r->request_body == NULL || r->request_body->bufs == NULL) { ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } buf = r->request_body->bufs->buf; if (ngx_buf_size(buf) == 0) { ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "Request body is: %*s", ngx_buf_size(buf), buf->pos); ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_dispatcher_ctx_t)); if (ctx == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } // XXX Application logic code here ngx_http_set_ctx(r, ctx, ngx_http_dispatcher_module); dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dispatcher_module); shard = dlcf->shards->elts; for (i = 0; i < dlcf->shards->nelts; i++) { ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "Sending subrequest to shard %V", &shard[i]); args.len = sizeof("shard=") + shard[i].len - 1; args.data = ngx_pnalloc(r->pool, args.len + 1); if (args.data == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_sprintf(args.data, "shard=%V", &shard[i]); psr = ngx_pcalloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } psr->handler = ngx_http_dispatcher_post_subrequest; psr->data = ctx; ctx->active_requests++; rc = ngx_http_subrequest(r, &dlcf->url, &args, &sr, NULL, NGX_HTTP_SUBREQUEST_IN_MEMORY | NGX_HTTP_SUBREQUEST_WAITED); sr->header_only = 0; if (rc != NGX_OK) { ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_subrequest failed with %i", rc); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } } r->headers_out.status = 200; ngx_http_clear_content_length(r); ngx_http_clear_last_modified(r); ngx_http_clear_accept_ranges(r); r->headers_out.content_length_n = 3; rc = ngx_http_send_header(r); r->header_only = 0; ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_sender_header(r) = %i", rc); ngx_chain_t out; buf = ngx_calloc_buf(r->pool); if (buf == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } buf->start = buf->pos = (u_char *)"foo"; buf->end = buf->last = buf->start + 3; buf->last_buf = 1; buf->memory = 1; out.buf = buf; out.next = NULL; ngx_http_finalize_request(r, ngx_http_output_filter(r, &out)); } As of right now, I have simply never been able to get ateven a response body for one of those subrequests. I have verified that the subrequests are indeed being sent, and that nginx reads the response to completion (using netcat and sending an invalid response prompts a log message about an invalid HTTP response), but my output body filter is simply never being invoked, and as far as I know this is the only way I have to get at the response body here. I have not been able to use the post_subrequest callback either, and am unsure if it'd be useful in my case. My apologies for the length of this post; I have tried to be as thorough as possible while making sure not to send any confidential code... Please don't hesitate to ask for further information or details if I'm not being clear enough. Any help would be greatly appreciated! Cheers, Maxime From agentzh at gmail.com Wed Aug 5 15:19:39 2015 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Wed, 5 Aug 2015 23:19:39 +0800 Subject: Subrequests and output filters In-Reply-To: References: Message-ID: Hello! On Wed, Aug 5, 2015 at 7:21 PM, Maxime Henrion wrote: > I am currently developing an nginx module in order to implement a software component in our platform. > > This module's responsibility is to receive upstream requests, forward them to multiple hosts (one host per pool, with N pools; we call a pool a shard), receive all the responses and aggregate them using custom application logic, and finally return an answer. > Seems like it's exactly what the ngx.location.capture_multi Lua API function provided by ngx_lua does: https://github.com/openresty/lua-nginx-module#ngxlocationcapture_multi Your requirement can be done in just a few lines of Lua and the performance is assured since almost all of the heavy-lifting is done in pure C. If you insist in rolling out your own custom nginx C modules, then I suggest you dive into ngx_lua's internals to clone what is already done and proven there. Having said that, I'm still strongly against the idea of writing your own C modules after writing tens of nginx C modules in the last 6 years myself. There won't be much gain at all as compared to the ngx_lua approach. Not to mention all the development, debugging, testing, and maintenance price paid on the developer side. Well, just my 2 cents. Regards, -agentzh From vbart at nginx.com Wed Aug 5 18:40:15 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Wed, 05 Aug 2015 21:40:15 +0300 Subject: The HTTP/2 protocol implementation Message-ID: <1886089.DbgciK4D6y@vbart-workstation> I'm happy to publish the first alpha version of the HTTP/2 module. Please, follow the link to download the patch and to get instructions: - http://nginx.org/patches/http2/ You can also find additional information in the blog post: - https://www.nginx.com/blog/early-alpha-patch-http2/ Thanks for testing. wbr, Valentin V. Bartenev From mdounin at mdounin.ru Wed Aug 5 18:55:48 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 5 Aug 2015 21:55:48 +0300 Subject: Subrequests and output filters In-Reply-To: References: Message-ID: <20150805185548.GB19190@mdounin.ru> Hello! On Wed, Aug 05, 2015 at 11:21:52AM +0000, Maxime Henrion wrote: [...] > NOTE: I'm not sure whether NGX_DONE above is the correct enum > value to use, but I have tried NGX_AGAIN and others as well to > no avail. NGX_DONE is correct return code. Compare with proxy and/or dav modules code if unsure. [...] > As of right now, I have simply never been able to get ateven a > response body for one of those subrequests. I have verified that > the subrequests are indeed being sent, and that nginx reads the > response to completion (using netcat and sending an invalid > response prompts a log message about an invalid HTTP response), > but my output body filter is simply never being invoked, and as > far as I know this is the only way I have to get at the response > body here. I have not been able to use the post_subrequest > callback either, and am unsure if it'd be useful in my case. So, the problem you are facing now is that your body filter is not called, right? Most likely reason, I think, is that your module is registered at a wrong place during configuration, and that's why it's not being called. To make sure your filter is called you should register it at HTTP_AUX_FILTER_MODULES list in the config file of your module. Alternatively, you may consider using the NGX_HTTP_SUBREQUEST_IN_MEMORY flag to ngx_http_subrequest(). This will allow you to get a response body in a post subrequest callback, without writing any response body filters. See src/http/modules/ngx_http_ssi_filter_module.c for a usage example, it's used to implement the "set" parameter of the "include" SSI command (see http://nginx.org/en/docs/http/ngx_http_ssi_module.html for docs). -- Maxim Dounin http://nginx.org/ From mhenrion at appnexus.com Fri Aug 7 11:33:06 2015 From: mhenrion at appnexus.com (Maxime Henrion) Date: Fri, 7 Aug 2015 11:33:06 +0000 Subject: Subrequests and output filters In-Reply-To: <20150805185548.GB19190@mdounin.ru> References: , <20150805185548.GB19190@mdounin.ru> Message-ID: Thanks for the answer. I have tried using the NGX_HTTP_SUBREQUEST_IN_MEMORY flag and a post subrequest callback; in fact the code I copy-pasted uses those. However, I don't see how to get at the response's body from this callback. Looking at the SSI module code, the ngx_http_ssi_stub_output() post subrequest callback does some consistency checks, sets the headers if they haven't been set already, and then just calls into ngx_http_output_filter() with a buffer chain that was actually passed to it through the "data" field of the post subrequest handler structure. I'm obviously missing things here, but I don't understand how to get at that response's body still. Thanks, Maxime ________________________________________ From: nginx-devel [nginx-devel-bounces at nginx.org] on behalf of Maxim Dounin [mdounin at mdounin.ru] Sent: Wednesday, August 05, 2015 8:55 PM To: nginx-devel at nginx.org Subject: Re: Subrequests and output filters Hello! On Wed, Aug 05, 2015 at 11:21:52AM +0000, Maxime Henrion wrote: [...] > NOTE: I'm not sure whether NGX_DONE above is the correct enum > value to use, but I have tried NGX_AGAIN and others as well to > no avail. NGX_DONE is correct return code. Compare with proxy and/or dav modules code if unsure. [...] > As of right now, I have simply never been able to get ateven a > response body for one of those subrequests. I have verified that > the subrequests are indeed being sent, and that nginx reads the > response to completion (using netcat and sending an invalid > response prompts a log message about an invalid HTTP response), > but my output body filter is simply never being invoked, and as > far as I know this is the only way I have to get at the response > body here. I have not been able to use the post_subrequest > callback either, and am unsure if it'd be useful in my case. So, the problem you are facing now is that your body filter is not called, right? Most likely reason, I think, is that your module is registered at a wrong place during configuration, and that's why it's not being called. To make sure your filter is called you should register it at HTTP_AUX_FILTER_MODULES list in the config file of your module. Alternatively, you may consider using the NGX_HTTP_SUBREQUEST_IN_MEMORY flag to ngx_http_subrequest(). This will allow you to get a response body in a post subrequest callback, without writing any response body filters. See src/http/modules/ngx_http_ssi_filter_module.c for a usage example, it's used to implement the "set" parameter of the "include" SSI command (see http://nginx.org/en/docs/http/ngx_http_ssi_module.html for docs). -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From mdounin at mdounin.ru Fri Aug 7 18:00:39 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 7 Aug 2015 21:00:39 +0300 Subject: Subrequests and output filters In-Reply-To: References: <20150805185548.GB19190@mdounin.ru> Message-ID: <20150807180039.GC67578@mdounin.ru> Hello! On Fri, Aug 07, 2015 at 11:33:06AM +0000, Maxime Henrion wrote: > Thanks for the answer. > > I have tried using the NGX_HTTP_SUBREQUEST_IN_MEMORY flag and a > post subrequest callback; in fact the code I copy-pasted uses > those. However, I don't see how to get at the response's body > from this callback. Looking at the SSI module code, the > ngx_http_ssi_stub_output() post subrequest callback does some > consistency checks, sets the headers if they haven't been set > already, and then just calls into ngx_http_output_filter() with > a buffer chain that was actually passed to it through the "data" > field of the post subrequest handler structure. > > I'm obviously missing things here, but I don't understand how to > get at that response's body still. Function to look for is ngx_http_ssi_set_variable(). -- Maxim Dounin http://nginx.org/ From bondarev at amazon.com Fri Aug 7 18:12:09 2015 From: bondarev at amazon.com (Bondarev, Daniil) Date: Fri, 7 Aug 2015 18:12:09 +0000 Subject: [PATCH] Set Content-Length to 0 when proxying requests with discarded body In-Reply-To: <1438212518122.2639@amazon.com> References: <1438212518122.2639@amazon.com> Message-ID: <1438971129857.5460@amazon.com> Ping. Any comments? ________________________________________ From: nginx-devel on behalf of Bondarev, Daniil Sent: Wednesday, July 29, 2015 4:28 PM To: nginx-devel at nginx.org Subject: [PATCH] Set Content-Length to 0 when proxying requests with discarded body Hello, We have a use case where we need to discard request body before proxying request to the upstream. To do this we call ngx_http_discard_request_body, but it uses r->headers_in.content_length_n to store the amount of data nginx wants to receive next time, so it won't be 0 until nginx read all bytes from the client. So if proxy_request_buffering is set to off, nginx ends up sending non-0 Content-Length header to the upstream without a body. The following patch fixes this behavior. # HG changeset patch # User Daniil Bondarev # Date 1438119116 25200 # Node ID ddefee93b698b9261a147a08f42a07810efa2dab # Parent 341e4303d25be159d4773b819d0ec055ba711afb Set Content-Length to 0 when proxying requests with discarded body diff -r 341e4303d25b -r ddefee93b698 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Thu Jul 16 14:20:48 2015 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Tue Jul 28 14:31:56 2015 -0700 @@ -1221,6 +1221,9 @@ ctx->internal_body_length = body_len; len += body_len; + } else if (r->discard_body) { + ctx->internal_body_length = 0; + } else if (r->headers_in.chunked && r->reading_body) { ctx->internal_body_length = -1; ctx->internal_chunked = 1; _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From mhenrion at appnexus.com Fri Aug 7 18:22:25 2015 From: mhenrion at appnexus.com (Maxime Henrion) Date: Fri, 7 Aug 2015 18:22:25 +0000 Subject: Subrequests and output filters In-Reply-To: <20150807180039.GC67578@mdounin.ru> References: <20150805185548.GB19190@mdounin.ru> , <20150807180039.GC67578@mdounin.ru> Message-ID: Thanks, I see I should be using r->upstream->buffer now. However this callback never seems to be called into for me... I have some heavy log messages there that don't show. I can tell that the response was read however, as if I send random garbage nginx complains about the response not having the proper HTTP headers. Any ideas? Thanks, Maxime ________________________________________ From: nginx-devel [nginx-devel-bounces at nginx.org] on behalf of Maxim Dounin [mdounin at mdounin.ru] Sent: Friday, August 07, 2015 8:00 PM To: nginx-devel at nginx.org Subject: Re: Subrequests and output filters Hello! On Fri, Aug 07, 2015 at 11:33:06AM +0000, Maxime Henrion wrote: > Thanks for the answer. > > I have tried using the NGX_HTTP_SUBREQUEST_IN_MEMORY flag and a > post subrequest callback; in fact the code I copy-pasted uses > those. However, I don't see how to get at the response's body > from this callback. Looking at the SSI module code, the > ngx_http_ssi_stub_output() post subrequest callback does some > consistency checks, sets the headers if they haven't been set > already, and then just calls into ngx_http_output_filter() with > a buffer chain that was actually passed to it through the "data" > field of the post subrequest handler structure. > > I'm obviously missing things here, but I don't understand how to > get at that response's body still. Function to look for is ngx_http_ssi_set_variable(). -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From arut at nginx.com Fri Aug 7 20:25:20 2015 From: arut at nginx.com (Roman Arutyunyan) Date: Fri, 7 Aug 2015 13:25:20 -0700 Subject: [PATCH] Set Content-Length to 0 when proxying requests with discarded body In-Reply-To: <1438212518122.2639@amazon.com> References: <1438212518122.2639@amazon.com> Message-ID: <27C71D3A-2A8E-4CF7-8E01-6C8E2AF47784@nginx.com> Hello Daniil, > On 29 Jul 2015, at 16:28, Bondarev, Daniil wrote: > > Hello, > > We have a use case where we need to discard request body before proxying > request to the upstream. To do this we call ngx_http_discard_request_body, > but it uses r->headers_in.content_length_n to store the amount of data nginx > wants to receive next time, so it won't be 0 until nginx read all bytes from the > client. So if proxy_request_buffering is set to off, nginx ends up sending > non-0 Content-Length header to the upstream without a body. If you have no "proxy_pass_request_body off? or ?proxy_set_body ??", it?s assumed that you want your request body to be passed to the upstream. Missing body is an error and probably it?s not a good idea to silently ignore it setting zero Content-Length. > The following patch fixes this behavior. > > # HG changeset patch > # User Daniil Bondarev > # Date 1438119116 25200 > # Node ID ddefee93b698b9261a147a08f42a07810efa2dab > # Parent 341e4303d25be159d4773b819d0ec055ba711afb > Set Content-Length to 0 when proxying requests with discarded body > > diff -r 341e4303d25b -r ddefee93b698 src/http/modules/ngx_http_proxy_module.c > --- a/src/http/modules/ngx_http_proxy_module.c Thu Jul 16 14:20:48 2015 +0300 > +++ b/src/http/modules/ngx_http_proxy_module.c Tue Jul 28 14:31:56 2015 -0700 > @@ -1221,6 +1221,9 @@ > ctx->internal_body_length = body_len; > len += body_len; > > + } else if (r->discard_body) { > + ctx->internal_body_length = 0; > + > } else if (r->headers_in.chunked && r->reading_body) { > ctx->internal_body_length = -1; > ctx->internal_chunked = 1; > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- Roman Arutyunyan From mdounin at mdounin.ru Fri Aug 7 21:45:57 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 8 Aug 2015 00:45:57 +0300 Subject: Subrequests and output filters In-Reply-To: References: <20150805185548.GB19190@mdounin.ru> <20150807180039.GC67578@mdounin.ru> Message-ID: <20150807214556.GH67578@mdounin.ru> Hello! On Fri, Aug 07, 2015 at 06:22:25PM +0000, Maxime Henrion wrote: > Thanks, I see I should be using r->upstream->buffer now. However > this callback never seems to be called into for me... I have > some heavy log messages there that don't show. I can tell that > the response was read however, as if I send random garbage nginx > complains about the response not having the proper HTTP headers. > > Any ideas? Make sure you've properly provided post subrequest handler and appropriate flags to ngx_http_subrequest(). See ngx_http_ssi_include() for how it's done there. It's a bit complicated as it handles the "include" command as a whole, but I don't think there are easier examples. -- Maxim Dounin http://nginx.org/ From defan at nginx.com Tue Aug 11 09:00:41 2015 From: defan at nginx.com (Andrei Belov) Date: Tue, 11 Aug 2015 09:00:41 +0000 Subject: [nginx] Fixed typo in the error message. Message-ID: details: http://hg.nginx.org/nginx/rev/808fd1f0b94b branches: changeset: 6219:808fd1f0b94b user: Andrei Belov date: Tue Aug 11 10:28:00 2015 +0300 description: Fixed typo in the error message. diffstat: src/core/ngx_open_file_cache.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 3096ae76ba47 -r 808fd1f0b94b src/core/ngx_open_file_cache.c --- a/src/core/ngx_open_file_cache.c Thu Jul 23 14:00:03 2015 -0400 +++ b/src/core/ngx_open_file_cache.c Tue Aug 11 10:28:00 2015 +0300 @@ -128,7 +128,7 @@ ngx_open_file_cache_cleanup(void *data) if (cache->current) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, - "%ui items still leave in open file cache", + "%ui items still left in open file cache", cache->current); } From vbart at nginx.com Tue Aug 11 13:29:04 2015 From: vbart at nginx.com (Valentin Bartenev) Date: Tue, 11 Aug 2015 13:29:04 +0000 Subject: [nginx] Core: idle connections now closed only once on exiting. Message-ID: details: http://hg.nginx.org/nginx/rev/5e6142609e48 branches: changeset: 6220:5e6142609e48 user: Valentin Bartenev date: Tue Aug 11 16:28:55 2015 +0300 description: Core: idle connections now closed only once on exiting. Iterating through all connections takes a lot of CPU time, especially with large number of worker connections configured. As a result nginx processes used to consume CPU time during graceful shutdown. To mitigate this we now only do a full scan for idle connections when shutdown signal is received. Transitions of connections to idle ones are now expected to be avoided if the ngx_exiting flag is set. The upstream keepalive module was modified to follow this. diffstat: src/core/ngx_connection.c | 20 +++++++++++++++++ src/core/ngx_connection.h | 1 + src/http/modules/ngx_http_upstream_keepalive_module.c | 4 +++ src/os/unix/ngx_process_cycle.c | 19 +-------------- src/os/win32/ngx_process_cycle.c | 22 +++--------------- 5 files changed, 31 insertions(+), 35 deletions(-) diffs (146 lines): diff -r 808fd1f0b94b -r 5e6142609e48 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Tue Aug 11 10:28:00 2015 +0300 +++ b/src/core/ngx_connection.c Tue Aug 11 16:28:55 2015 +0300 @@ -1163,6 +1163,26 @@ ngx_drain_connections(void) } +void +ngx_close_idle_connections(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + ngx_connection_t *c; + + c = cycle->connections; + + for (i = 0; i < cycle->connection_n; i++) { + + /* THREAD: lock */ + + if (c[i].fd != -1 && c[i].idle) { + c[i].close = 1; + c[i].read->handler(c[i].read); + } + } +} + + ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, ngx_uint_t port) diff -r 808fd1f0b94b -r 5e6142609e48 src/core/ngx_connection.h --- a/src/core/ngx_connection.h Tue Aug 11 10:28:00 2015 +0300 +++ b/src/core/ngx_connection.h Tue Aug 11 16:28:55 2015 +0300 @@ -215,6 +215,7 @@ ngx_int_t ngx_open_listening_sockets(ngx void ngx_configure_listening_sockets(ngx_cycle_t *cycle); void ngx_close_listening_sockets(ngx_cycle_t *cycle); void ngx_close_connection(ngx_connection_t *c); +void ngx_close_idle_connections(ngx_cycle_t *cycle); ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, ngx_uint_t port); ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text); diff -r 808fd1f0b94b -r 5e6142609e48 src/http/modules/ngx_http_upstream_keepalive_module.c --- a/src/http/modules/ngx_http_upstream_keepalive_module.c Tue Aug 11 10:28:00 2015 +0300 +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c Tue Aug 11 16:28:55 2015 +0300 @@ -302,6 +302,10 @@ ngx_http_upstream_free_keepalive_peer(ng goto invalid; } + if (ngx_terminate || ngx_exiting) { + goto invalid; + } + if (ngx_handle_read_event(c->read, 0) != NGX_OK) { goto invalid; } diff -r 808fd1f0b94b -r 5e6142609e48 src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c Tue Aug 11 10:28:00 2015 +0300 +++ b/src/os/unix/ngx_process_cycle.c Tue Aug 11 16:28:55 2015 +0300 @@ -728,9 +728,6 @@ ngx_worker_process_cycle(ngx_cycle_t *cy { ngx_int_t worker = (intptr_t) data; - ngx_uint_t i; - ngx_connection_t *c; - ngx_process = NGX_PROCESS_WORKER; ngx_worker = worker; @@ -741,19 +738,6 @@ ngx_worker_process_cycle(ngx_cycle_t *cy for ( ;; ) { if (ngx_exiting) { - - c = cycle->connections; - - for (i = 0; i < cycle->connection_n; i++) { - - /* THREAD: lock */ - - if (c[i].fd != -1 && c[i].idle) { - c[i].close = 1; - c[i].read->handler(c[i].read); - } - } - ngx_event_cancel_timers(); if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel) @@ -781,8 +765,9 @@ ngx_worker_process_cycle(ngx_cycle_t *cy ngx_setproctitle("worker process is shutting down"); if (!ngx_exiting) { + ngx_exiting = 1; ngx_close_listening_sockets(cycle); - ngx_exiting = 1; + ngx_close_idle_connections(cycle); } } diff -r 808fd1f0b94b -r 5e6142609e48 src/os/win32/ngx_process_cycle.c --- a/src/os/win32/ngx_process_cycle.c Tue Aug 11 10:28:00 2015 +0300 +++ b/src/os/win32/ngx_process_cycle.c Tue Aug 11 16:28:55 2015 +0300 @@ -761,10 +761,8 @@ failed: static ngx_thread_value_t __stdcall ngx_worker_thread(void *data) { - ngx_int_t n; - ngx_uint_t i; - ngx_cycle_t *cycle; - ngx_connection_t *c; + ngx_int_t n; + ngx_cycle_t *cycle; cycle = (ngx_cycle_t *) ngx_cycle; @@ -780,19 +778,6 @@ ngx_worker_thread(void *data) while (!ngx_quit) { if (ngx_exiting) { - - c = cycle->connections; - - for (i = 0; i < cycle->connection_n; i++) { - - /* THREAD: lock */ - - if (c[i].fd != (ngx_socket_t) -1 && c[i].idle) { - c[i].close = 1; - c[i].read->handler(c[i].read); - } - } - ngx_event_cancel_timers(); if (ngx_event_timer_rbtree.root @@ -814,8 +799,9 @@ ngx_worker_thread(void *data) ngx_quit = 0; if (!ngx_exiting) { + ngx_exiting = 1; ngx_close_listening_sockets(cycle); - ngx_exiting = 1; + ngx_close_idle_connections(cycle); } } From vl at nginx.com Wed Aug 12 09:31:42 2015 From: vl at nginx.com (Vladimir Homutov) Date: Wed, 12 Aug 2015 09:31:42 +0000 Subject: [nginx] Stream: the "tcp_nodelay" directive. Message-ID: details: http://hg.nginx.org/nginx/rev/7565e056fad6 branches: changeset: 6221:7565e056fad6 user: Vladimir Homutov date: Mon Aug 10 12:14:41 2015 +0300 description: Stream: the "tcp_nodelay" directive. diffstat: src/stream/ngx_stream.h | 1 + src/stream/ngx_stream_core_module.c | 10 ++++++++++ src/stream/ngx_stream_handler.c | 19 +++++++++++++++++++ src/stream/ngx_stream_proxy_module.c | 24 ++++++++++++++++++++++-- 4 files changed, 52 insertions(+), 2 deletions(-) diffs (129 lines): diff -r 5e6142609e48 -r 7565e056fad6 src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Tue Aug 11 16:28:55 2015 +0300 +++ b/src/stream/ngx_stream.h Mon Aug 10 12:14:41 2015 +0300 @@ -132,6 +132,7 @@ typedef struct { u_char *file_name; ngx_int_t line; ngx_log_t *error_log; + ngx_flag_t tcp_nodelay; } ngx_stream_core_srv_conf_t; diff -r 5e6142609e48 -r 7565e056fad6 src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Tue Aug 11 16:28:55 2015 +0300 +++ b/src/stream/ngx_stream_core_module.c Mon Aug 10 12:14:41 2015 +0300 @@ -45,6 +45,13 @@ static ngx_command_t ngx_stream_core_co 0, NULL }, + { ngx_string("tcp_nodelay"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_core_srv_conf_t, tcp_nodelay), + NULL }, + ngx_null_command }; @@ -122,6 +129,7 @@ ngx_stream_core_create_srv_conf(ngx_conf cscf->file_name = cf->conf_file->file.name.data; cscf->line = cf->conf_file->line; + cscf->tcp_nodelay = NGX_CONF_UNSET; return cscf; } @@ -148,6 +156,8 @@ ngx_stream_core_merge_srv_conf(ngx_conf_ } } + ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); + return NGX_CONF_OK; } diff -r 5e6142609e48 -r 7565e056fad6 src/stream/ngx_stream_handler.c --- a/src/stream/ngx_stream_handler.c Tue Aug 11 16:28:55 2015 +0300 +++ b/src/stream/ngx_stream_handler.c Mon Aug 10 12:14:41 2015 +0300 @@ -23,6 +23,7 @@ static void ngx_stream_ssl_handshake_han void ngx_stream_init_connection(ngx_connection_t *c) { + int tcp_nodelay; u_char text[NGX_SOCKADDR_STRLEN]; size_t len; ngx_int_t rc; @@ -165,6 +166,24 @@ ngx_stream_init_connection(ngx_connectio } } + if (cscf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_stream_close_connection(c); + return; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } + + #if (NGX_STREAM_SSL) { ngx_stream_ssl_conf_t *sslcf; diff -r 5e6142609e48 -r 7565e056fad6 src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Tue Aug 11 16:28:55 2015 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Mon Aug 10 12:14:41 2015 +0300 @@ -478,13 +478,35 @@ ngx_stream_proxy_connect(ngx_stream_sess static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) { + int tcp_nodelay; u_char *p; ngx_connection_t *c, *pc; ngx_log_handler_pt handler; ngx_stream_upstream_t *u; + ngx_stream_core_srv_conf_t *cscf; ngx_stream_proxy_srv_conf_t *pscf; u = s->upstream; + pc = u->peer.connection; + + cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); + + if (cscf->tcp_nodelay && pc->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(pc->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(pc, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_stream_proxy_next_upstream(s); + return; + } + + pc->tcp_nodelay = NGX_TCP_NODELAY_SET; + } if (u->proxy_protocol) { if (ngx_stream_proxy_send_proxy_protocol(s) != NGX_OK) { @@ -496,8 +518,6 @@ ngx_stream_proxy_init_upstream(ngx_strea pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); - pc = u->peer.connection; - #if (NGX_STREAM_SSL) if (pscf->ssl && pc->ssl == NULL) { ngx_stream_proxy_ssl_init_connection(s); From vl at nginx.com Wed Aug 12 09:58:15 2015 From: vl at nginx.com (Vladimir Homutov) Date: Wed, 12 Aug 2015 09:58:15 +0000 Subject: [nginx] Style. Message-ID: details: http://hg.nginx.org/nginx/rev/1bd5eb20bd7c branches: changeset: 6222:1bd5eb20bd7c user: Vladimir Homutov date: Wed Aug 12 12:56:59 2015 +0300 description: Style. diffstat: src/stream/ngx_stream_proxy_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 7565e056fad6 -r 1bd5eb20bd7c src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Mon Aug 10 12:14:41 2015 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Wed Aug 12 12:56:59 2015 +0300 @@ -478,7 +478,7 @@ ngx_stream_proxy_connect(ngx_stream_sess static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) { - int tcp_nodelay; + int tcp_nodelay; u_char *p; ngx_connection_t *c, *pc; ngx_log_handler_pt handler; From joe at joeshaw.org Wed Aug 12 14:53:20 2015 From: joe at joeshaw.org (Joe Shaw) Date: Wed, 12 Aug 2015 10:53:20 -0400 Subject: Fwd: HTTP/2: Missing location header on 301 redirects In-Reply-To: References: Message-ID: Hi, I've been taking the alpha HTTP/2 support for a spin, and noticed that 301 redirects are missing the Location response header. Thus, browsers don't redirect and just show an HTML page instead. Here's the output of nginx -V: nginx version: nginx/1.9.3 built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) built with OpenSSL 1.0.2d 9 Jul 2015 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-threads --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-file-aio --with-http_v2_module --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' --with-ipv6 I'm testing using the URL https://joeshaw.org/about (which redirects to /about/). Here's the output of a HTTP/1.1 request from curl: < HTTP/1.1 301 Moved Permanently * Server nginx is not blacklisted < Server: nginx < Date: Wed, 12 Aug 2015 14:43:41 GMT < Content-Type: text/html < Content-Length: 178 < Location: https://joeshaw.org/about/ < Connection: keep-alive < Strict-Transport-Security: max-age=15768000; preload < Public-Key-Pins: pin-sha256="aBBtZy0hiXFCr7RV/RqoJoTCMHEhrwtB6IfgSPCY2sA="; pin-sha256="d6qzvu9zOKCb90Uez27xWltNsj0e1Md7GkYYkVoZwmm="; max-age=86400 < X-Frame-Options: DENY Here's the HTTP/2 output from h2i ( https://github.com/bradfitz/http2/tree/master/h2i): [FrameHeader HEADERS flags=END_HEADERS stream=1 len=284] :status = "301" server = "nginx" date = "Wed, 12 Aug 2015 14:44:31 GMT" content-type = "text/html" content-length = "178" strict-transport-security = "max-age=15768000; preload" public-key-pins = "pin-sha256=\"aBBtZy0hiXFCr7RV/RqoJoTCMHEhrwtB6IfgSPCY2sA=\"; pin-sha256=\"d6qzvu9zOKCb90Uez27xWltNsj0e1Md7GkYYkVoZwmm=\"; max-age=86400" x-frame-options = "DENY" I hope this is helpful. Thanks, Joe -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Wed Aug 12 17:24:33 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Wed, 12 Aug 2015 20:24:33 +0300 Subject: Fwd: HTTP/2: Missing location header on 301 redirects In-Reply-To: References: Message-ID: <3208642.fHfbjkEZnE@vbart-workstation> On Wednesday 12 August 2015 10:53:20 Joe Shaw wrote: > Hi, > > I've been taking the alpha HTTP/2 support for a spin, and noticed that 301 > redirects are missing the Location response header. Thus, browsers don't > redirect and just show an HTML page instead. > > Here's the output of nginx -V: > > nginx version: nginx/1.9.3 > built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) > built with OpenSSL 1.0.2d 9 Jul 2015 > TLS SNI support enabled > configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx > --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log > --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid > --lock-path=/var/run/nginx.lock > --http-client-body-temp-path=/var/cache/nginx/client_temp > --http-proxy-temp-path=/var/cache/nginx/proxy_temp > --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp > --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp > --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx > --with-http_ssl_module --with-http_realip_module > --with-http_addition_module --with-http_sub_module --with-http_dav_module > --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module > --with-http_gzip_static_module --with-http_random_index_module > --with-http_secure_link_module --with-http_stub_status_module > --with-http_auth_request_module --with-threads --with-stream > --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-file-aio > --with-http_v2_module --with-cc-opt='-g -O2 -fstack-protector > --param=ssp-buffer-size=4 -Wformat -Werror=format-security' > --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' --with-ipv6 > > I'm testing using the URL https://joeshaw.org/about (which redirects to > /about/). > > Here's the output of a HTTP/1.1 request from curl: > > < HTTP/1.1 301 Moved Permanently > * Server nginx is not blacklisted > < Server: nginx > < Date: Wed, 12 Aug 2015 14:43:41 GMT > < Content-Type: text/html > < Content-Length: 178 > < Location: https://joeshaw.org/about/ > < Connection: keep-alive > < Strict-Transport-Security: max-age=15768000; preload > < Public-Key-Pins: > pin-sha256="aBBtZy0hiXFCr7RV/RqoJoTCMHEhrwtB6IfgSPCY2sA="; > pin-sha256="d6qzvu9zOKCb90Uez27xWltNsj0e1Md7GkYYkVoZwmm="; max-age=86400 > < X-Frame-Options: DENY > > Here's the HTTP/2 output from h2i ( > https://github.com/bradfitz/http2/tree/master/h2i): > > [FrameHeader HEADERS flags=END_HEADERS stream=1 len=284] > :status = "301" > server = "nginx" > date = "Wed, 12 Aug 2015 14:44:31 GMT" > content-type = "text/html" > content-length = "178" > strict-transport-security = "max-age=15768000; preload" > public-key-pins = > "pin-sha256=\"aBBtZy0hiXFCr7RV/RqoJoTCMHEhrwtB6IfgSPCY2sA=\"; > pin-sha256=\"d6qzvu9zOKCb90Uez27xWltNsj0e1Md7GkYYkVoZwmm=\"; max-age=86400" > x-frame-options = "DENY" > > I hope this is helpful. > We are unable to reproduce the problem with a simple configuration. Could you provide your config? wbr, Valentin V. Bartenev From joe at joeshaw.org Wed Aug 12 19:17:36 2015 From: joe at joeshaw.org (Joe Shaw) Date: Wed, 12 Aug 2015 15:17:36 -0400 Subject: Fwd: HTTP/2: Missing location header on 301 redirects In-Reply-To: <3208642.fHfbjkEZnE@vbart-workstation> References: <3208642.fHfbjkEZnE@vbart-workstation> Message-ID: Hi, I've stripped out most of the SSL parameters, obfuscated a few paths and removed a few unrelated rewrite rules, but here it is: server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server ipv6only=on; server_name joeshaw.org; charset utf-8; ssl on; ssl_certificate /etc/redacted.pem; ssl_certificate_key /etc/redacted.key; root /srv/www/joeshaw.org/; index index.html; error_page 404 /404.html; location / { try_files $uri $uri/ $uri/index.html =404; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.joeshaw.org; charset utf-8; return 301 https://joeshaw.org$request_uri; } server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; server_name joeshaw.org www.joeshaw.org; charset utf-8; return 301 https://joeshaw.org$request_uri; } Hope this helps. On a related note, after I was looking at my config I realized that I probably wanted the second server clause to be the default_server (so it always redirected to my main domain regardless of what Host/:authority header was provided) and I tried swapping them. Then whenever I hit https://joeshaw.org/ I was entered into a redirection loop. It seemed like it was not checking the :authority pseudo-header and always serving from the default_server. Joe On Wed, Aug 12, 2015 at 1:24 PM, Valentin V. Bartenev wrote: > On Wednesday 12 August 2015 10:53:20 Joe Shaw wrote: > > Hi, > > > > I've been taking the alpha HTTP/2 support for a spin, and noticed that > 301 > > redirects are missing the Location response header. Thus, browsers don't > > redirect and just show an HTML page instead. > > > > Here's the output of nginx -V: > > > > nginx version: nginx/1.9.3 > > built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) > > built with OpenSSL 1.0.2d 9 Jul 2015 > > TLS SNI support enabled > > configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx > > --conf-path=/etc/nginx/nginx.conf > --error-log-path=/var/log/nginx/error.log > > --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid > > --lock-path=/var/run/nginx.lock > > --http-client-body-temp-path=/var/cache/nginx/client_temp > > --http-proxy-temp-path=/var/cache/nginx/proxy_temp > > --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp > > --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp > > --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx > --group=nginx > > --with-http_ssl_module --with-http_realip_module > > --with-http_addition_module --with-http_sub_module --with-http_dav_module > > --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module > > --with-http_gzip_static_module --with-http_random_index_module > > --with-http_secure_link_module --with-http_stub_status_module > > --with-http_auth_request_module --with-threads --with-stream > > --with-stream_ssl_module --with-mail --with-mail_ssl_module > --with-file-aio > > --with-http_v2_module --with-cc-opt='-g -O2 -fstack-protector > > --param=ssp-buffer-size=4 -Wformat -Werror=format-security' > > --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' --with-ipv6 > > > > I'm testing using the URL https://joeshaw.org/about (which redirects to > > /about/). > > > > Here's the output of a HTTP/1.1 request from curl: > > > > < HTTP/1.1 301 Moved Permanently > > * Server nginx is not blacklisted > > < Server: nginx > > < Date: Wed, 12 Aug 2015 14:43:41 GMT > > < Content-Type: text/html > > < Content-Length: 178 > > < Location: https://joeshaw.org/about/ > > < Connection: keep-alive > > < Strict-Transport-Security: max-age=15768000; preload > > < Public-Key-Pins: > > pin-sha256="aBBtZy0hiXFCr7RV/RqoJoTCMHEhrwtB6IfgSPCY2sA="; > > pin-sha256="d6qzvu9zOKCb90Uez27xWltNsj0e1Md7GkYYkVoZwmm="; max-age=86400 > > < X-Frame-Options: DENY > > > > Here's the HTTP/2 output from h2i ( > > https://github.com/bradfitz/http2/tree/master/h2i): > > > > [FrameHeader HEADERS flags=END_HEADERS stream=1 len=284] > > :status = "301" > > server = "nginx" > > date = "Wed, 12 Aug 2015 14:44:31 GMT" > > content-type = "text/html" > > content-length = "178" > > strict-transport-security = "max-age=15768000; preload" > > public-key-pins = > > "pin-sha256=\"aBBtZy0hiXFCr7RV/RqoJoTCMHEhrwtB6IfgSPCY2sA=\"; > > pin-sha256=\"d6qzvu9zOKCb90Uez27xWltNsj0e1Md7GkYYkVoZwmm=\"; > max-age=86400" > > x-frame-options = "DENY" > > > > I hope this is helpful. > > > > > We are unable to reproduce the problem with a simple configuration. > Could you provide your config? > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From djduanjiong at gmail.com Thu Aug 13 02:17:43 2015 From: djduanjiong at gmail.com (Duan Jiong) Date: Thu, 13 Aug 2015 10:17:43 +0800 Subject: stream: sub variable len after output log to the buf Message-ID: # HG changeset patch # User Duan Jiong # Date 1439431265 -28800 # Thu Aug 13 10:01:05 2015 +0800 # Node ID 1c518d211b6b1acbd3a951218d948bd5ee4bec41 # Parent 1bd5eb20bd7c25f6cff96190d3ec048e3f3ebeec stream: sub variable len after output log to the buf Otherwise, the log before will be overwrote. diff -r 1bd5eb20bd7c -r 1c518d211b6b src/stream/ngx_stream_handler.c --- a/src/stream/ngx_stream_handler.c Wed Aug 12 12:56:59 2015 +0300 +++ b/src/stream/ngx_stream_handler.c Thu Aug 13 10:01:05 2015 +0800 @@ -328,6 +328,7 @@ p = ngx_snprintf(buf, len, ", client: %V, server: %V", &s->connection->addr_text, &s->connection->listening->addr_text); + len -= p - buf; if (s->log_handler) { return s->log_handler(log, p, len); From vl at nginx.com Thu Aug 13 14:05:04 2015 From: vl at nginx.com (Vladimir Homutov) Date: Thu, 13 Aug 2015 14:05:04 +0000 Subject: [nginx] Stream: fixed potential error log buffer overrun. Message-ID: details: http://hg.nginx.org/nginx/rev/d1f94042c29c branches: changeset: 6223:d1f94042c29c user: Vladimir Homutov date: Thu Aug 13 15:55:21 2015 +0300 description: Stream: fixed potential error log buffer overrun. Found by Duan Jiong . diffstat: src/stream/ngx_stream_handler.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (16 lines): diff -r 1bd5eb20bd7c -r d1f94042c29c src/stream/ngx_stream_handler.c --- a/src/stream/ngx_stream_handler.c Wed Aug 12 12:56:59 2015 +0300 +++ b/src/stream/ngx_stream_handler.c Thu Aug 13 15:55:21 2015 +0300 @@ -328,9 +328,11 @@ ngx_stream_log_error(ngx_log_t *log, u_c p = ngx_snprintf(buf, len, ", client: %V, server: %V", &s->connection->addr_text, &s->connection->listening->addr_text); + len -= p - buf; + buf = p; if (s->log_handler) { - return s->log_handler(log, p, len); + p = s->log_handler(log, buf, len); } return p; From pluknet at nginx.com Thu Aug 13 14:08:05 2015 From: pluknet at nginx.com (Sergey Kandaurov) Date: Thu, 13 Aug 2015 14:08:05 +0000 Subject: [nginx] Core: fixed style in the error message. Message-ID: details: http://hg.nginx.org/nginx/rev/ddf35e019a80 branches: changeset: 6224:ddf35e019a80 user: Sergey Kandaurov date: Thu Aug 13 16:27:13 2015 +0300 description: Core: fixed style in the error message. diffstat: src/core/ngx_hash.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r d1f94042c29c -r ddf35e019a80 src/core/ngx_hash.c --- a/src/core/ngx_hash.c Thu Aug 13 15:55:21 2015 +0300 +++ b/src/core/ngx_hash.c Thu Aug 13 16:27:13 2015 +0300 @@ -261,7 +261,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) { ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, - "could not build the %s, you should " + "could not build %s, you should " "increase %s_bucket_size: %i", hinit->name, hinit->name, hinit->bucket_size); return NGX_ERROR; From pluknet at nginx.com Thu Aug 13 14:08:07 2015 From: pluknet at nginx.com (Sergey Kandaurov) Date: Thu, 13 Aug 2015 14:08:07 +0000 Subject: [nginx] Core: fixed potential division by zero when initializing... Message-ID: details: http://hg.nginx.org/nginx/rev/3b6d69857de2 branches: changeset: 6225:3b6d69857de2 user: Sergey Kandaurov date: Thu Aug 13 16:27:17 2015 +0300 description: Core: fixed potential division by zero when initializing hash. Found by Clang Static Analyzer. diffstat: src/core/ngx_hash.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diffs (18 lines): diff -r ddf35e019a80 -r 3b6d69857de2 src/core/ngx_hash.c --- a/src/core/ngx_hash.c Thu Aug 13 16:27:13 2015 +0300 +++ b/src/core/ngx_hash.c Thu Aug 13 16:27:17 2015 +0300 @@ -257,6 +257,14 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng ngx_uint_t i, n, key, size, start, bucket_size; ngx_hash_elt_t *elt, **buckets; + if (hinit->max_size == 0) { + ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, + "could not build %s, you should " + "increase %s_max_size: %i", + hinit->name, hinit->name, hinit->max_size); + return NGX_ERROR; + } + for (n = 0; n < nelts; n++) { if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) { From vl at nginx.com Thu Aug 13 14:10:37 2015 From: vl at nginx.com (Vladimir Homutov) Date: Thu, 13 Aug 2015 17:10:37 +0300 Subject: stream: sub variable len after output log to the buf In-Reply-To: References: Message-ID: <20150813141036.GA28293@vlpc.nginx.com> On Thu, Aug 13, 2015 at 10:17:43AM +0800, Duan Jiong wrote: > # HG changeset patch > # User Duan Jiong > # Date 1439431265 -28800 > # Thu Aug 13 10:01:05 2015 +0800 > # Node ID 1c518d211b6b1acbd3a951218d948bd5ee4bec41 > # Parent 1bd5eb20bd7c25f6cff96190d3ec048e3f3ebeec > stream: sub variable len after output log to the buf > > Otherwise, the log before will be overwrote. > > diff -r 1bd5eb20bd7c -r 1c518d211b6b src/stream/ngx_stream_handler.c > --- a/src/stream/ngx_stream_handler.c Wed Aug 12 12:56:59 2015 +0300 > +++ b/src/stream/ngx_stream_handler.c Thu Aug 13 10:01:05 2015 +0800 > @@ -328,6 +328,7 @@ > p = ngx_snprintf(buf, len, ", client: %V, server: %V", > &s->connection->addr_text, > &s->connection->listening->addr_text); > + len -= p - buf; > > if (s->log_handler) { > return s->log_handler(log, p, len); > Thank you for reporting this! Slightly modified version committed: http://hg.nginx.org/nginx/rev/d1f94042c29c From dims.main at gmail.com Fri Aug 14 10:52:06 2015 From: dims.main at gmail.com (dims) Date: Fri, 14 Aug 2015 13:52:06 +0300 Subject: http2 broke links in code Message-ID: <55CDC856.7030602@gmail.com> Default ssl configuration: When enable http2 link brokes From vbart at nginx.com Fri Aug 14 11:29:21 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 14 Aug 2015 14:29:21 +0300 Subject: http2 broke links in code In-Reply-To: <55CDC856.7030602@gmail.com> References: <55CDC856.7030602@gmail.com> Message-ID: <7826493.GSHg891eTr@vbart-workstation> On Friday 14 August 2015 13:52:06 dims wrote: > Default ssl configuration: > href="//www.domain.ru/css2/reset-min.css"> > When enable http2 link brokes > > HTTP/2 does nothing with page content. You're probably using 3-rd party modules like mod_pagespeed or something else. wbr, Valentin V. Bartenev From dims.main at gmail.com Fri Aug 14 12:02:12 2015 From: dims.main at gmail.com (dims) Date: Fri, 14 Aug 2015 15:02:12 +0300 Subject: http2 broke links in code In-Reply-To: <7826493.GSHg891eTr@vbart-workstation> References: <55CDC856.7030602@gmail.com> <7826493.GSHg891eTr@vbart-workstation> Message-ID: <55CDD8C4.5070304@gmail.com> Yes, you right, my mistake But found problem why dont work our code. We use nginx + php-fpm and variable HTTP_HOST in code Config: location ~ \.(html|php)$ { rewrite ^(.+)\.html$ $1.php break; include /etc/nginx/fastcgi_params; fastcgi_pass unix:/var/lib/nginx/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_split_path_info ^(.+\.php)(/.+)$; try_files $uri =404; } When enable http2 variable HTTP_HOST absent in phpinfo If set fastcgi_param HTTP_HOST $http_host; in phpinfo(): _SERVER["HTTP_HOST"] no value > Valentin V. Bartenev > August 14, 2015 at 2:29 PM > > HTTP/2 does nothing with page content. You're probably using 3-rd party > modules like mod_pagespeed or something else. > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Fri Aug 14 16:11:55 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 14 Aug 2015 19:11:55 +0300 Subject: http2 broke links in code In-Reply-To: <55CDD8C4.5070304@gmail.com> References: <55CDC856.7030602@gmail.com> <7826493.GSHg891eTr@vbart-workstation> <55CDD8C4.5070304@gmail.com> Message-ID: <17775296.yLfPhLL51k@vbart-workstation> On Friday 14 August 2015 15:02:12 dims wrote: > Yes, you right, my mistake > But found problem why dont work our code. > We use nginx + php-fpm and variable HTTP_HOST in code > Config: > location ~ \.(html|php)$ { > rewrite ^(.+)\.html$ $1.php break; > include /etc/nginx/fastcgi_params; > fastcgi_pass unix:/var/lib/nginx/php-fpm.sock; > fastcgi_index index.php; > fastcgi_param SCRIPT_FILENAME > $document_root$fastcgi_script_name; > fastcgi_split_path_info ^(.+\.php)(/.+)$; > try_files $uri =404; > } > > When enable http2 variable HTTP_HOST absent in phpinfo > If set fastcgi_param HTTP_HOST $http_host; in phpinfo(): > _SERVER["HTTP_HOST"] no value [...] Thanks for the report. Please, try the new patch: http://nginx.org/patches/http2/ wbr, Valentin V. Bartenev From vbart at nginx.com Fri Aug 14 16:13:23 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 14 Aug 2015 19:13:23 +0300 Subject: Fwd: HTTP/2: Missing location header on 301 redirects In-Reply-To: References: <3208642.fHfbjkEZnE@vbart-workstation> Message-ID: <3904113.IVFsGKu12T@vbart-workstation> On Wednesday 12 August 2015 15:17:36 Joe Shaw wrote: > Hi, > > I've stripped out most of the SSL parameters, obfuscated a few paths and > removed a few unrelated rewrite rules, but here it is: > > server { > listen 443 ssl http2 default_server; > listen [::]:443 ssl http2 default_server ipv6only=on; > server_name joeshaw.org; > > charset utf-8; > > ssl on; > ssl_certificate /etc/redacted.pem; > ssl_certificate_key /etc/redacted.key; > > root /srv/www/joeshaw.org/; > index index.html; > error_page 404 /404.html; > > location / { > try_files $uri $uri/ $uri/index.html =404; > } > } > > server { > listen 443 ssl http2; > listen [::]:443 ssl http2; > server_name www.joeshaw.org; > charset utf-8; > return 301 https://joeshaw.org$request_uri; > } > > server { > listen 80 default_server; > listen [::]:80 default_server ipv6only=on; > server_name joeshaw.org www.joeshaw.org; > charset utf-8; > return 301 https://joeshaw.org$request_uri; > } > > Hope this helps. > > On a related note, after I was looking at my config I realized that I > probably wanted the second server clause to be the default_server (so it > always redirected to my main domain regardless of what Host/:authority > header was provided) and I tried swapping them. Then whenever I hit > https://joeshaw.org/ I was entered into a redirection loop. It seemed like > it was not checking the :authority pseudo-header and always serving from > the default_server. > [..] Thank you for the report. Both problems should be fixed in the new version of patch: http://nginx.org/patches/http2/ wbr, Valentin V. Bartenev From joe at joeshaw.org Fri Aug 14 18:57:41 2015 From: joe at joeshaw.org (Joe Shaw) Date: Fri, 14 Aug 2015 14:57:41 -0400 Subject: Fwd: HTTP/2: Missing location header on 301 redirects In-Reply-To: <3904113.IVFsGKu12T@vbart-workstation> References: <3208642.fHfbjkEZnE@vbart-workstation> <3904113.IVFsGKu12T@vbart-workstation> Message-ID: Hi, Things are working great, thank you. Joe On Fri, Aug 14, 2015 at 12:13 PM, Valentin V. Bartenev wrote: > On Wednesday 12 August 2015 15:17:36 Joe Shaw wrote: > > Hi, > > > > I've stripped out most of the SSL parameters, obfuscated a few paths and > > removed a few unrelated rewrite rules, but here it is: > > > > server { > > listen 443 ssl http2 default_server; > > listen [::]:443 ssl http2 default_server ipv6only=on; > > server_name joeshaw.org; > > > > charset utf-8; > > > > ssl on; > > ssl_certificate /etc/redacted.pem; > > ssl_certificate_key /etc/redacted.key; > > > > root /srv/www/joeshaw.org/; > > index index.html; > > error_page 404 /404.html; > > > > location / { > > try_files $uri $uri/ $uri/index.html =404; > > } > > } > > > > server { > > listen 443 ssl http2; > > listen [::]:443 ssl http2; > > server_name www.joeshaw.org; > > charset utf-8; > > return 301 https://joeshaw.org$request_uri; > > } > > > > server { > > listen 80 default_server; > > listen [::]:80 default_server ipv6only=on; > > server_name joeshaw.org www.joeshaw.org; > > charset utf-8; > > return 301 https://joeshaw.org$request_uri; > > } > > > > Hope this helps. > > > > On a related note, after I was looking at my config I realized that I > > probably wanted the second server clause to be the default_server (so it > > always redirected to my main domain regardless of what Host/:authority > > header was provided) and I tried swapping them. Then whenever I hit > > https://joeshaw.org/ I was entered into a redirection loop. It seemed > like > > it was not checking the :authority pseudo-header and always serving from > > the default_server. > > > [..] > > Thank you for the report. > > Both problems should be fixed in the new version of patch: > http://nginx.org/patches/http2/ > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cubicdaiya at gmail.com Fri Aug 14 23:23:45 2015 From: cubicdaiya at gmail.com (Tatsuhiko Kubo) Date: Sat, 15 Aug 2015 08:23:45 +0900 Subject: HTTP/2: response is not gzip-compressed Message-ID: Hello. I have been trying patch.http2-v2_1.9.3.txt. A response does not seem to be gzip-compressed even though gzip directive is enabled. There is the configuration and how to reproduce below. # output of 'nginx -V' $ nginx -V nginx version: nginx/1.9.3 built by clang 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) built with OpenSSL 1.0.2d 9 Jul 2015 TLS SNI support enabled configure arguments: --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --with-http_stub_status_module --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-http_ssl_module --with-http_v2_module --with-openssl=../openssl-1.0.2d $ # nginx.conf worker_processes auto; events { worker_connections 1024; } http { gzip on; server { listen 443 ssl http2; ssl on; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; root html; } } # output of curl without '--http2' $ curl -H "Accept-Encoding: gzip" --insecure -I https://127.0.0.1/index.html HTTP/1.1 200 OK Server: nginx/1.9.3 Date: Fri, 14 Aug 2015 23:19:03 GMT Content-Type: text/html Last-Modified: Wed, 06 Aug 2014 17:07:04 GMT Connection: keep-alive ETag: W/"53e260b8-264" Content-Encoding: gzip $ # output of curl with '--http2' $ curl --http2 -H "Accept-Encoding: gzip" --insecure -I https://127.0.0.1/index.html HTTP/2.0 200 server:nginx/1.9.3 date:Fri, 14 Aug 2015 23:07:50 GMT content-type:text/html content-length:612 last-modified:Wed, 06 Aug 2014 17:07:04 GMT etag:"53e260b8-264" accept-ranges:bytes $ Thanks. -- Tatsuhiko Kubo From mdounin at mdounin.ru Sun Aug 16 07:53:21 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 16 Aug 2015 07:53:21 +0000 Subject: [nginx] Fixed segfault with try_files introduced by c985d90a8d1f. Message-ID: details: http://hg.nginx.org/nginx/rev/4bc94faeff66 branches: changeset: 6226:4bc94faeff66 user: Maxim Dounin date: Sun Aug 16 10:51:16 2015 +0300 description: Fixed segfault with try_files introduced by c985d90a8d1f. If alias was used in a location given by a regular expression, nginx used to do wrong thing in try_files if a location name (i.e., regular expression) was an exact prefix of URI. The following configuration triggered a segmentation fault on a request to "/mail": location ~ /mail { alias /path/to/directory; try_files $uri =404; } Reported by Per Hansson. diffstat: src/http/ngx_http_core_module.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (14 lines): diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1239,7 +1239,9 @@ ngx_http_core_try_files_phase(ngx_http_r *e.pos = '\0'; - if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) { + if (alias && alias != NGX_MAX_SIZE_T_VALUE + && ngx_strncmp(name, clcf->name.data, alias) == 0) + { ngx_memmove(name, name + alias, len - alias); path.len -= alias; } From mdounin at mdounin.ru Sun Aug 16 07:53:24 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 16 Aug 2015 07:53:24 +0000 Subject: [nginx] Fixed wrong URI after try_files in nested location (tick... Message-ID: details: http://hg.nginx.org/nginx/rev/bd55d75a1410 branches: changeset: 6227:bd55d75a1410 user: Maxim Dounin date: Sun Aug 16 10:51:34 2015 +0300 description: Fixed wrong URI after try_files in nested location (ticket #97). The following configuration with alias, nested location and try_files resulted in wrong file being used. Request "/foo/test.gif" tried to use "/tmp//foo/test.gif" instead of "/tmp/test.gif": location /foo/ { alias /tmp/; location ~ gif { try_files $uri =405; } } Additionally, rev. c985d90a8d1f introduced a regression if the "/tmp//foo/test.gif" file was found (ticket #768). Resulting URI was set to "gif?/foo/test.gif", as the code used clcf->name of current location ("location ~ gif") instead of parent one ("location /foo/"). Fix is to use r->uri instead of clcf->name in all cases in the ngx_http_core_try_files_phase() function. It is expected to be already matched and identical to the clcf->name of the right location. diffstat: src/http/ngx_http_core_module.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diffs (32 lines): diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1240,7 +1240,7 @@ ngx_http_core_try_files_phase(ngx_http_r *e.pos = '\0'; if (alias && alias != NGX_MAX_SIZE_T_VALUE - && ngx_strncmp(name, clcf->name.data, alias) == 0) + && ngx_strncmp(name, r->uri.data, alias) == 0) { ngx_memmove(name, name + alias, len - alias); path.len -= alias; @@ -1324,6 +1324,8 @@ ngx_http_core_try_files_phase(ngx_http_r } } else { + name = r->uri.data; + r->uri.len = alias + path.len; r->uri.data = ngx_pnalloc(r->pool, r->uri.len); if (r->uri.data == NULL) { @@ -1331,8 +1333,8 @@ ngx_http_core_try_files_phase(ngx_http_r return NGX_OK; } - p = ngx_copy(r->uri.data, clcf->name.data, alias); - ngx_memcpy(p, name, path.len); + p = ngx_copy(r->uri.data, name, alias); + ngx_memcpy(p, path.data, path.len); } ngx_http_set_exten(r); From erik at dubbelboer.com Sun Aug 16 09:29:52 2015 From: erik at dubbelboer.com (Erik Dubbelboer) Date: Sun, 16 Aug 2015 09:29:52 +0000 Subject: [PATCH] Allow modules to set headers_in.user Message-ID: # HG changeset patch # User Erik Dubbelboer # Date 1439715629 0 # Node ID c6f0f112eb446b7ab4bc69c9e4e594dd79ca3293 # Parent bd55d75a1410502a9b4ac6fb44ec4528437b530a Allow modules to set headers_in.user Requesting $remote_user will always call ngx_http_auth_basic_user which will always overwrite headers_in.user. Modules that specify different modes of authentication, such as Digest, can not set $remote_use without this patch. diff -r bd55d75a1410 -r c6f0f112eb44 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Sun Aug 16 10:51:34 2015 +0300 +++ b/src/http/ngx_http_core_module.c Sun Aug 16 09:00:29 2015 +0000 @@ -2049,8 +2049,13 @@ ngx_str_t auth, encoded; ngx_uint_t len; - if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) { - return NGX_DECLINED; + if (r->headers_in.user.data != NULL) { + if (r->headers_in.user.len == 0) { + return NGX_DECLINED; + } else { + /* headers_in.user is already set, don't parse again. */ + return NGX_OK; + } } if (r->headers_in.authorization == NULL) { From Markus.Linnala at cybercom.com Sun Aug 16 11:26:59 2015 From: Markus.Linnala at cybercom.com (Markus Linnala) Date: Sun, 16 Aug 2015 14:26:59 +0300 Subject: [PATCH] guard against zero length root Message-ID: # HG changeset patch # User Markus Linnala # Date 1439724126 -10800 # Sun Aug 16 14:22:06 2015 +0300 # Node ID ca63e42fe06db68c9c85ed5d4140cb682c60d300 # Parent 3b6d69857de22eb03b479223727c365e9035882b guard against zero length root diff -r 3b6d69857de2 -r ca63e42fe06d src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Thu Aug 13 16:27:17 2015 +0300 +++ b/src/http/ngx_http_core_module.c Sun Aug 16 14:22:06 2015 +0300 @@ -4476,6 +4476,14 @@ clcf->alias = alias ? clcf->name.len : 0; clcf->root = value[1]; + if (clcf->root.len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the \"%V\" value can not be empty", + &cmd->name); + + return NGX_CONF_ERROR; + } + if (!alias && clcf->root.data[clcf->root.len - 1] == '/') { clcf->root.len--; } From Markus.Linnala at cybercom.com Sun Aug 16 14:28:34 2015 From: Markus.Linnala at cybercom.com (Markus Linnala) Date: Sun, 16 Aug 2015 17:28:34 +0300 Subject: invalid config accepted because allocation patterns Message-ID: <55D09E12.6060000@cybercom.com> Sometimes nginx accepts invalid configuration. Like: <> worker_processes 1; events { worker_connections 1024; } http { map $http_host $tp_x_forwarded_for { default "a"; } log_format main '$ht $tp_x_forwarded_for'; access_log logs/access.log main; server { } } <> That is because parameter might be allocated one after another and then ngx_strncmp would compare whole set and get it wrong. Generally every line where there is ngx_strncmp(.data, , len) where length of ngx_str_t is less than len might trigger this issue. Only small configuration change can change allocation patterns and this might not work for you. I don't know if there is any other usage for this than to learn how nginx memory allocators and ngx_str_t works. If you use no-pool-nginx patch and ASAN, you'll trigger "ERROR: AddressSanitizer: heap-buffer-overflow". Right way to handle this would always check that ngx_str_t len is >= ngx_strncmp second arg before every ngx_strncmp()==0 call. Example: Breakpoint 1, ngx_http_variables_init_vars (cf=cf at entry=0x7fffffffe2b0) at src/http/ngx_http_variables.c:2538 2538 if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) { (gdb) list 2533 2534 goto next; 2535 } 2536 } 2537 2538 if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) { 2539 v[i].get_handler = ngx_http_variable_unknown_header_in; 2540 v[i].data = (uintptr_t) &v[i].name; 2541 2542 continue; (gdb) print ((ngx_http_variable_t*)cmcf->variables.elts)[i] $10 = {name = {len = 2, data = 0x5555558b96a8 "http_x_forwarded_foraccess_log"}, set_handler = 0x0, get_handler = 0x0, data = 0, flags = 0, index = 2} gdb) cont Continuing. nginx: the configuration file /data/nginx/test.conf syntax is ok nginx: configuration file /data/nginx/test.conf test is successful [Inferior 1 (process 29905) exited normally] From dims.main at gmail.com Mon Aug 17 06:21:21 2015 From: dims.main at gmail.com (dims) Date: Mon, 17 Aug 2015 09:21:21 +0300 Subject: http2 broke links in code In-Reply-To: <17775296.yLfPhLL51k@vbart-workstation> References: <55CDC856.7030602@gmail.com> <7826493.GSHg891eTr@vbart-workstation> <55CDD8C4.5070304@gmail.com> <17775296.yLfPhLL51k@vbart-workstation> Message-ID: <55D17D61.2040301@gmail.com> Thanks - work fine now! > Valentin V. Bartenev > August 14, 2015 at 7:11 PM > [...] > > Thanks for the report. > Please, try the new patch: http://nginx.org/patches/http2/ > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > dims > August 14, 2015 at 3:02 PM > Yes, you right, my mistake > But found problem why dont work our code. > We use nginx + php-fpm and variable HTTP_HOST in code > Config: > location ~ \.(html|php)$ { > rewrite ^(.+)\.html$ $1.php break; > include /etc/nginx/fastcgi_params; > fastcgi_pass unix:/var/lib/nginx/php-fpm.sock; > fastcgi_index index.php; > fastcgi_param SCRIPT_FILENAME > $document_root$fastcgi_script_name; > fastcgi_split_path_info ^(.+\.php)(/.+)$; > try_files $uri =404; > } > > When enable http2 variable HTTP_HOST absent in phpinfo > If set fastcgi_param HTTP_HOST $http_host; in phpinfo(): > _SERVER["HTTP_HOST"] no value > > Valentin V. Bartenev > August 14, 2015 at 2:29 PM > > HTTP/2 does nothing with page content. You're probably using 3-rd party > modules like mod_pagespeed or something else. > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Aug 17 11:26:58 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 17 Aug 2015 14:26:58 +0300 Subject: invalid config accepted because allocation patterns In-Reply-To: <55D09E12.6060000@cybercom.com> References: <55D09E12.6060000@cybercom.com> Message-ID: <20150817112658.GW37350@mdounin.ru> Hello! On Sun, Aug 16, 2015 at 05:28:34PM +0300, Markus Linnala wrote: > Sometimes nginx accepts invalid configuration. > > Like: > > <> > worker_processes 1; > > events { > worker_connections 1024; > } > > http { > map $http_host $tp_x_forwarded_for { > default "a"; > } > log_format main '$ht $tp_x_forwarded_for'; > access_log logs/access.log main; > server { > } > } > <> > > That is because parameter might be allocated one after another and then > ngx_strncmp would compare whole set and get it wrong. Generally every line > where there is ngx_strncmp(.data, , len) where > length of ngx_str_t is less than len might trigger this issue. > > Only small configuration change can change allocation patterns and this > might not work for you. > > I don't know if there is any other usage for this than to learn how nginx > memory allocators and ngx_str_t works. > > If you use no-pool-nginx patch and ASAN, you'll trigger "ERROR: > AddressSanitizer: heap-buffer-overflow". > > Right way to handle this would always check that ngx_str_t len is >= > ngx_strncmp second arg before every ngx_strncmp()==0 call. The ngx_strncmp() call without any additional checks is fine as long as the string tested is expected to be null-terminated (or followed by some other character known not to match). And this is the case for most uses of ngx_strncmp(), except may be some bugs. > Example: > > Breakpoint 1, ngx_http_variables_init_vars (cf=cf at entry=0x7fffffffe2b0) at > src/http/ngx_http_variables.c:2538 > 2538 if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) { > (gdb) list > 2533 > 2534 goto next; > 2535 } > 2536 } > 2537 > 2538 if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) { > 2539 v[i].get_handler = ngx_http_variable_unknown_header_in; > 2540 v[i].data = (uintptr_t) &v[i].name; > 2541 > 2542 continue; > (gdb) print ((ngx_http_variable_t*)cmcf->variables.elts)[i] > $10 = {name = {len = 2, data = 0x5555558b96a8 > "http_x_forwarded_foraccess_log"}, set_handler = 0x0, > get_handler = 0x0, data = 0, flags = 0, index = 2} > gdb) cont > Continuing. > nginx: the configuration file /data/nginx/test.conf syntax is ok > nginx: configuration file /data/nginx/test.conf test is successful > [Inferior 1 (process 29905) exited normally] This looks like a bug. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Aug 17 12:07:25 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 17 Aug 2015 15:07:25 +0300 Subject: [PATCH] guard against zero length root In-Reply-To: References: Message-ID: <20150817120725.GZ37350@mdounin.ru> Hello! On Sun, Aug 16, 2015 at 02:26:59PM +0300, Markus Linnala wrote: > # HG changeset patch > # User Markus Linnala > # Date 1439724126 -10800 > # Sun Aug 16 14:22:06 2015 +0300 > # Node ID ca63e42fe06db68c9c85ed5d4140cb682c60d300 > # Parent 3b6d69857de22eb03b479223727c365e9035882b > guard against zero length root > > diff -r 3b6d69857de2 -r ca63e42fe06d src/http/ngx_http_core_module.c > --- a/src/http/ngx_http_core_module.c Thu Aug 13 16:27:17 2015 +0300 > +++ b/src/http/ngx_http_core_module.c Sun Aug 16 14:22:06 2015 +0300 > @@ -4476,6 +4476,14 @@ > clcf->alias = alias ? clcf->name.len : 0; > clcf->root = value[1]; > > + if (clcf->root.len == 0) { > + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, > + "the \"%V\" value can not be empty", > + &cmd->name); > + > + return NGX_CONF_ERROR; > + } > + > if (!alias && clcf->root.data[clcf->root.len - 1] == '/') { > clcf->root.len--; > } The restriction introduced looks strange. It might be better idea to check clcf->root.len in the following test instead - as far as I see, this test is the only problem with an empty root. -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Mon Aug 17 13:24:20 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Mon, 17 Aug 2015 16:24:20 +0300 Subject: HTTP/2: response is not gzip-compressed In-Reply-To: References: Message-ID: <1633648.VbJ4BPl6es@vbart-workstation> On Saturday 15 August 2015 08:23:45 Tatsuhiko Kubo wrote: > Hello. > > I have been trying patch.http2-v2_1.9.3.txt. > A response does not seem to be gzip-compressed even though gzip > directive is enabled. [..] Thank you for the report. It will be fixed in the next version of the patch. wbr, Valentin V. Bartenev From xeioex at nginx.com Mon Aug 17 14:44:21 2015 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 17 Aug 2015 14:44:21 +0000 Subject: [nginx] Sub filter: support of multiple strings to replace. Message-ID: details: http://hg.nginx.org/nginx/rev/b9447fc457b4 branches: changeset: 6228:b9447fc457b4 user: Dmitry Volyntsev date: Mon Aug 17 17:42:02 2015 +0300 description: Sub filter: support of multiple strings to replace. diffstat: src/http/modules/ngx_http_sub_filter_module.c | 433 +++++++++++++++---------- 1 files changed, 257 insertions(+), 176 deletions(-) diffs (truncated from 638 to 300 lines): diff -r bd55d75a1410 -r b9447fc457b4 src/http/modules/ngx_http_sub_filter_module.c --- a/src/http/modules/ngx_http_sub_filter_module.c Sun Aug 16 10:51:34 2015 +0300 +++ b/src/http/modules/ngx_http_sub_filter_module.c Mon Aug 17 17:42:02 2015 +0300 @@ -13,6 +13,20 @@ typedef struct { ngx_str_t match; ngx_http_complex_value_t value; +} ngx_http_sub_match_t; + + +typedef struct { + ngx_uint_t min_match_len; + ngx_uint_t max_match_len; + + u_char index[257]; + u_char shift[256]; +} ngx_http_sub_tables_t; + + +typedef struct { + ngx_http_sub_tables_t *tables; ngx_hash_t types; @@ -20,17 +34,11 @@ typedef struct { ngx_flag_t last_modified; ngx_array_t *types_keys; + ngx_array_t *matches; } ngx_http_sub_loc_conf_t; -typedef enum { - sub_start_state = 0, - sub_match_state, -} ngx_http_sub_state_e; - - typedef struct { - ngx_str_t match; ngx_str_t saved; ngx_str_t looked; @@ -48,12 +56,17 @@ typedef struct { ngx_chain_t *busy; ngx_chain_t *free; - ngx_str_t sub; + ngx_str_t *sub; + ngx_uint_t applied; - ngx_uint_t state; + ngx_int_t offset; + ngx_uint_t index; } ngx_http_sub_ctx_t; +static ngx_uint_t ngx_http_sub_cmp_index; + + static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx); static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, @@ -64,6 +77,9 @@ static char * ngx_http_sub_filter(ngx_co static void *ngx_http_sub_create_conf(ngx_conf_t *cf); static char *ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child); +static void ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables, + ngx_http_sub_match_t *match, ngx_uint_t n); +static ngx_int_t ngx_http_sub_cmp_matches(const void *one, const void *two); static ngx_int_t ngx_http_sub_filter_init(ngx_conf_t *cf); @@ -144,7 +160,7 @@ ngx_http_sub_header_filter(ngx_http_requ slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - if (slcf->match.len == 0 + if (slcf->matches == NULL || r->headers_out.content_length_n == 0 || ngx_http_test_content_type(r, &slcf->types) == NULL) { @@ -156,19 +172,19 @@ ngx_http_sub_header_filter(ngx_http_requ return NGX_ERROR; } - ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len); + ctx->saved.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1); if (ctx->saved.data == NULL) { return NGX_ERROR; } - ctx->looked.data = ngx_pnalloc(r->pool, slcf->match.len); + ctx->looked.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1); if (ctx->looked.data == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); - ctx->match = slcf->match; + ctx->offset = slcf->tables->min_match_len - 1; ctx->last_out = &ctx->out; r->filter_need_in_memory = 1; @@ -194,8 +210,10 @@ ngx_http_sub_body_filter(ngx_http_reques { ngx_int_t rc; ngx_buf_t *b; + ngx_str_t *sub; ngx_chain_t *cl; ngx_http_sub_ctx_t *ctx; + ngx_http_sub_match_t *match; ngx_http_sub_loc_conf_t *slcf; ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module); @@ -242,18 +260,10 @@ ngx_http_sub_body_filter(ngx_http_reques ctx->pos = ctx->buf->pos; } - if (ctx->state == sub_start_state) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->pos; - } - b = NULL; while (ctx->pos < ctx->buf->last) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "saved: \"%V\" state: %d", &ctx->saved, ctx->state); - rc = ngx_http_sub_parse(r, ctx); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -320,20 +330,6 @@ ngx_http_sub_body_filter(ngx_http_reques ctx->last_out = &cl->next; } - if (ctx->state == sub_start_state) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->pos; - - } else { - ctx->copy_start = NULL; - ctx->copy_end = NULL; - } - - if (ctx->looked.len > (size_t) (ctx->pos - ctx->buf->pos)) { - ctx->saved.len = ctx->looked.len - (ctx->pos - ctx->buf->pos); - ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len); - } - if (rc == NGX_AGAIN) { continue; } @@ -352,19 +348,30 @@ ngx_http_sub_body_filter(ngx_http_reques slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - if (ctx->sub.data == NULL) { + if (ctx->sub == NULL) { + ctx->sub = ngx_pcalloc(r->pool, sizeof(ngx_str_t) + * slcf->matches->nelts); + if (ctx->sub == NULL) { + return NGX_ERROR; + } + } - if (ngx_http_complex_value(r, &slcf->value, &ctx->sub) + sub = &ctx->sub[ctx->index]; + + if (sub->data == NULL) { + match = slcf->matches->elts; + + if (ngx_http_complex_value(r, &match[ctx->index].value, sub) != NGX_OK) { return NGX_ERROR; } } - if (ctx->sub.len) { + if (sub->len) { b->memory = 1; - b->pos = ctx->sub.data; - b->last = ctx->sub.data + ctx->sub.len; + b->pos = sub->data; + b->last = sub->data + sub->len; } else { b->sync = 1; @@ -373,7 +380,8 @@ ngx_http_sub_body_filter(ngx_http_reques *ctx->last_out = cl; ctx->last_out = &cl->next; - ctx->once = slcf->once; + ctx->index = 0; + ctx->once = slcf->once && (++ctx->applied == slcf->matches->nelts); continue; } @@ -428,9 +436,6 @@ ngx_http_sub_body_filter(ngx_http_reques } ctx->buf = NULL; - - ctx->saved.len = ctx->looked.len; - ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len); } if (ctx->out == NULL && ctx->busy == NULL) { @@ -513,158 +518,142 @@ ngx_http_sub_output(ngx_http_request_t * static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) { - u_char *p, *last, *copy_end, ch, match; - size_t looked, i; - ngx_http_sub_state_e state; + u_char *p, *last, *pat, *pat_end, c; + ngx_str_t *m; + ngx_int_t offset, start, next, end, len, rc; + ngx_uint_t shift, i, j; + ngx_http_sub_match_t *match; + ngx_http_sub_tables_t *tables; + ngx_http_sub_loc_conf_t *slcf; + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); + tables = slcf->tables; + + offset = ctx->offset; + end = ctx->buf->last - ctx->pos; if (ctx->once) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->buf->last; - ctx->pos = ctx->buf->last; - ctx->looked.len = 0; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once"); - - return NGX_AGAIN; + /* sets start and next to end */ + offset = end + (ngx_int_t) tables->min_match_len - 1; + goto again; } - state = ctx->state; - looked = ctx->looked.len; - last = ctx->buf->last; - copy_end = ctx->copy_end; + while (offset < end) { - for (p = ctx->pos; p < last; p++) { + c = offset < 0 ? ctx->looked.data[ctx->looked.len + offset] + : ctx->pos[offset]; - ch = *p; - ch = ngx_tolower(ch); + c = ngx_tolower(c); - if (state == sub_start_state) { - - /* the tight loop */ - - match = ctx->match.data[0]; - - for ( ;; ) { - if (ch == match) { - - if (ctx->match.len == 1) { - ctx->pos = p + 1; - ctx->copy_end = p; - - return NGX_OK; - } - - copy_end = p; - ctx->looked.data[0] = *p; - looked = 1; - state = sub_match_state; - - goto match_started; - } - - if (++p == last) { - break; - } - - ch = *p; - ch = ngx_tolower(ch); - } - - ctx->state = state; - ctx->pos = p; - ctx->looked.len = looked; - ctx->copy_end = p; - - if (ctx->copy_start == NULL) { - ctx->copy_start = ctx->buf->pos; From xeioex at nginx.com Mon Aug 17 14:44:23 2015 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 17 Aug 2015 14:44:23 +0000 Subject: [nginx] Sub filter: support of variables in the strings to replace. Message-ID: details: http://hg.nginx.org/nginx/rev/2c045e5b8291 branches: changeset: 6229:2c045e5b8291 user: Dmitry Volyntsev date: Mon Aug 17 17:42:02 2015 +0300 description: Sub filter: support of variables in the strings to replace. diffstat: src/http/modules/ngx_http_sub_filter_module.c | 174 +++++++++++++++++++++---- 1 files changed, 146 insertions(+), 28 deletions(-) diffs (truncated from 318 to 300 lines): diff -r b9447fc457b4 -r 2c045e5b8291 src/http/modules/ngx_http_sub_filter_module.c --- a/src/http/modules/ngx_http_sub_filter_module.c Mon Aug 17 17:42:02 2015 +0300 +++ b/src/http/modules/ngx_http_sub_filter_module.c Mon Aug 17 17:42:02 2015 +0300 @@ -11,8 +11,14 @@ typedef struct { + ngx_http_complex_value_t match; + ngx_http_complex_value_t value; +} ngx_http_sub_pair_t; + + +typedef struct { ngx_str_t match; - ngx_http_complex_value_t value; + ngx_http_complex_value_t *value; } ngx_http_sub_match_t; @@ -26,6 +32,10 @@ typedef struct { typedef struct { + ngx_uint_t dynamic; /* unsigned dynamic:1; */ + + ngx_array_t *pairs; + ngx_http_sub_tables_t *tables; ngx_hash_t types; @@ -61,6 +71,9 @@ typedef struct { ngx_int_t offset; ngx_uint_t index; + + ngx_http_sub_tables_t *tables; + ngx_array_t *matches; } ngx_http_sub_ctx_t; @@ -155,12 +168,16 @@ static ngx_http_output_body_filter_pt static ngx_int_t ngx_http_sub_header_filter(ngx_http_request_t *r) { - ngx_http_sub_ctx_t *ctx; + ngx_str_t *m; + ngx_uint_t i, j, n; + ngx_http_sub_ctx_t *ctx; + ngx_http_sub_pair_t *pairs; + ngx_http_sub_match_t *matches; ngx_http_sub_loc_conf_t *slcf; slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - if (slcf->matches == NULL + if (slcf->pairs == NULL || r->headers_out.content_length_n == 0 || ngx_http_test_content_type(r, &slcf->types) == NULL) { @@ -172,19 +189,76 @@ ngx_http_sub_header_filter(ngx_http_requ return NGX_ERROR; } - ctx->saved.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1); + if (slcf->dynamic == 0) { + ctx->tables = slcf->tables; + ctx->matches = slcf->matches; + + } else { + pairs = slcf->pairs->elts; + n = slcf->pairs->nelts; + + matches = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_match_t) * n); + if (matches == NULL) { + return NGX_ERROR; + } + + j = 0; + for (i = 0; i < n; i++) { + matches[j].value = &pairs[i].value; + + if (pairs[i].match.lengths == NULL) { + matches[j].match = pairs[i].match.value; + j++; + continue; + } + + m = &matches[j].match; + if (ngx_http_complex_value(r, &pairs[i].match, m) != NGX_OK) { + return NGX_ERROR; + } + + if (m->len == 0) { + continue; + } + + ngx_strlow(m->data, m->data, m->len); + j++; + } + + if (j == 0) { + return ngx_http_next_header_filter(r); + } + + ctx->matches = ngx_pnalloc(r->pool, sizeof(ngx_array_t)); + if (ctx->matches == NULL) { + return NGX_ERROR; + } + + ctx->matches->elts = matches; + ctx->matches->nelts = j; + + ctx->tables = ngx_pnalloc(r->pool, sizeof(ngx_http_sub_tables_t)); + if (ctx->tables == NULL) { + return NGX_ERROR; + } + + ngx_http_sub_init_tables(ctx->tables, ctx->matches->elts, + ctx->matches->nelts); + } + + ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); + + ctx->saved.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1); if (ctx->saved.data == NULL) { return NGX_ERROR; } - ctx->looked.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1); + ctx->looked.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1); if (ctx->looked.data == NULL) { return NGX_ERROR; } - ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); - - ctx->offset = slcf->tables->min_match_len - 1; + ctx->offset = ctx->tables->min_match_len - 1; ctx->last_out = &ctx->out; r->filter_need_in_memory = 1; @@ -350,7 +424,7 @@ ngx_http_sub_body_filter(ngx_http_reques if (ctx->sub == NULL) { ctx->sub = ngx_pcalloc(r->pool, sizeof(ngx_str_t) - * slcf->matches->nelts); + * ctx->matches->nelts); if (ctx->sub == NULL) { return NGX_ERROR; } @@ -359,9 +433,9 @@ ngx_http_sub_body_filter(ngx_http_reques sub = &ctx->sub[ctx->index]; if (sub->data == NULL) { - match = slcf->matches->elts; + match = ctx->matches->elts; - if (ngx_http_complex_value(r, &match[ctx->index].value, sub) + if (ngx_http_complex_value(r, match[ctx->index].value, sub) != NGX_OK) { return NGX_ERROR; @@ -381,7 +455,7 @@ ngx_http_sub_body_filter(ngx_http_reques ctx->last_out = &cl->next; ctx->index = 0; - ctx->once = slcf->once && (++ctx->applied == slcf->matches->nelts); + ctx->once = slcf->once && (++ctx->applied == ctx->matches->nelts); continue; } @@ -527,7 +601,7 @@ ngx_http_sub_parse(ngx_http_request_t *r ngx_http_sub_loc_conf_t *slcf; slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - tables = slcf->tables; + tables = ctx->tables; offset = ctx->offset; end = ctx->buf->last - ctx->pos; @@ -554,7 +628,7 @@ ngx_http_sub_parse(ngx_http_request_t *r /* a potential match */ start = offset - (ngx_int_t) tables->min_match_len + 1; - match = slcf->matches->elts; + match = ctx->matches->elts; i = ngx_max(tables->index[c], ctx->index); j = tables->index[c + 1]; @@ -663,7 +737,7 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_ ngx_http_sub_loc_conf_t *slcf = conf; ngx_str_t *value; - ngx_http_sub_match_t *match; + ngx_http_sub_pair_t *pair; ngx_http_compile_complex_value_t ccv; value = cf->args->elts; @@ -673,15 +747,15 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_ return NGX_CONF_ERROR; } - if (slcf->matches == NULL) { - slcf->matches = ngx_array_create(cf->pool, 1, - sizeof(ngx_http_sub_match_t)); - if (slcf->matches == NULL) { + if (slcf->pairs == NULL) { + slcf->pairs = ngx_array_create(cf->pool, 1, + sizeof(ngx_http_sub_pair_t)); + if (slcf->pairs == NULL) { return NGX_CONF_ERROR; } } - if (slcf->matches->nelts == 255) { + if (slcf->pairs->nelts == 255) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "number of search patterns exceeds 255"); return NGX_CONF_ERROR; @@ -689,18 +763,34 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_ ngx_strlow(value[1].data, value[1].data, value[1].len); - match = ngx_array_push(slcf->matches); - if (match == NULL) { + pair = ngx_array_push(slcf->pairs); + if (pair == NULL) { return NGX_CONF_ERROR; } - match->match = value[1]; + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &pair->match; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (ccv.complex_value->lengths != NULL) { + slcf->dynamic = 1; + + } else { + ngx_strlow(pair->match.value.data, pair->match.value.data, + pair->match.value.len); + } ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = &value[2]; - ccv.complex_value = &match->value; + ccv.complex_value = &pair->value; if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; @@ -723,6 +813,8 @@ ngx_http_sub_create_conf(ngx_conf_t *cf) /* * set by ngx_pcalloc(): * + * conf->dynamic = 0; + * conf->pairs = NULL; * conf->tables = NULL; * conf->types = { NULL }; * conf->types_keys = NULL; @@ -739,8 +831,11 @@ ngx_http_sub_create_conf(ngx_conf_t *cf) static char * ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child) { - ngx_http_sub_loc_conf_t *prev = parent; - ngx_http_sub_loc_conf_t *conf = child; + ngx_uint_t i, n; + ngx_http_sub_pair_t *pairs; + ngx_http_sub_match_t *matches; + ngx_http_sub_loc_conf_t *prev = parent; + ngx_http_sub_loc_conf_t *conf = child; ngx_conf_merge_value(conf->once, prev->once, 1); ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0); @@ -753,11 +848,34 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } - if (conf->matches == NULL) { + if (conf->pairs == NULL) { + conf->dynamic = prev->dynamic; + conf->pairs = prev->pairs; conf->matches = prev->matches; conf->tables = prev->tables; - } else { + } else if (conf->dynamic == 0){ + pairs = conf->pairs->elts; + n = conf->pairs->nelts; + + matches = ngx_pnalloc(cf->pool, sizeof(ngx_http_sub_match_t) * n); + if (matches == NULL) { + return NGX_CONF_ERROR; From mdounin at mdounin.ru Mon Aug 17 19:32:48 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 17 Aug 2015 19:32:48 +0000 Subject: [nginx] Win32: MSVC 2015 compatibility. Message-ID: details: http://hg.nginx.org/nginx/rev/2a621245f4cf branches: changeset: 6230:2a621245f4cf user: Maxim Dounin date: Mon Aug 17 18:09:17 2015 +0300 description: Win32: MSVC 2015 compatibility. Resolved warnings about declarations that hide previous local declarations. Warnings about WSASocketA() being deprecated resolved by explicit use of WSASocketW() instead of WSASocket(). When compiling without IPv6 support, WinSock deprecated warnings are disabled to allow use of gethostbyname(). diffstat: src/http/modules/ngx_http_fastcgi_module.c | 1 - src/http/modules/ngx_http_map_module.c | 10 +++++----- src/mail/ngx_mail_core_module.c | 3 +-- src/os/win32/ngx_socket.h | 4 ++-- src/os/win32/ngx_win32_config.h | 5 +++++ src/stream/ngx_stream_core_module.c | 3 +-- src/stream/ngx_stream_proxy_module.c | 10 +++++----- 7 files changed, 19 insertions(+), 17 deletions(-) diffs (130 lines): diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -1770,7 +1770,6 @@ ngx_http_fastcgi_process_header(ngx_http #if (NGX_HTTP_CACHE) if (f->large_stderr && r->cache) { - u_char *start; ssize_t len; ngx_http_fastcgi_header_t *fh; diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c --- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c @@ -375,7 +375,7 @@ ngx_http_map_cmp_dns_wildcards(const voi static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { - ngx_int_t rc, index; + ngx_int_t rv, index; ngx_str_t *value, name; ngx_uint_t i, key; ngx_http_map_conf_ctx_t *ctx; @@ -546,19 +546,19 @@ found: value[0].data++; } - rc = ngx_hash_add_key(&ctx->keys, &value[0], var, + rv = ngx_hash_add_key(&ctx->keys, &value[0], var, (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0); - if (rc == NGX_OK) { + if (rv == NGX_OK) { return NGX_CONF_OK; } - if (rc == NGX_DECLINED) { + if (rv == NGX_DECLINED) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid hostname or wildcard \"%V\"", &value[0]); } - if (rc == NGX_BUSY) { + if (rv == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", &value[0]); } diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -434,8 +434,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - struct sockaddr *sa; - u_char buf[NGX_SOCKADDR_STRLEN]; + u_char buf[NGX_SOCKADDR_STRLEN]; sa = &ls->u.sockaddr; diff --git a/src/os/win32/ngx_socket.h b/src/os/win32/ngx_socket.h --- a/src/os/win32/ngx_socket.h +++ b/src/os/win32/ngx_socket.h @@ -21,9 +21,9 @@ typedef int socklen_t; #define ngx_socket(af, type, proto) \ - WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED) + WSASocketW(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED) -#define ngx_socket_n "WSASocket()" +#define ngx_socket_n "WSASocketW()" int ngx_nonblocking(ngx_socket_t s); int ngx_blocking(ngx_socket_t s); diff --git a/src/os/win32/ngx_win32_config.h b/src/os/win32/ngx_win32_config.h --- a/src/os/win32/ngx_win32_config.h +++ b/src/os/win32/ngx_win32_config.h @@ -21,6 +21,11 @@ #define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_DEPRECATE +/* enable gethostbyname() in msvc2015 */ +#if !(NGX_HAVE_INET6) +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#endif + /* * we need to include explicitly before because * the warning 4201 is enabled in diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -372,8 +372,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - struct sockaddr *sa; - u_char buf[NGX_SOCKADDR_STRLEN]; + u_char buf[NGX_SOCKADDR_STRLEN]; sa = &ls->u.sockaddr; 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 @@ -528,18 +528,18 @@ ngx_stream_proxy_init_upstream(ngx_strea c = s->connection; if (c->log->log_level >= NGX_LOG_INFO) { - ngx_str_t s; + ngx_str_t str; u_char addr[NGX_SOCKADDR_STRLEN]; - s.len = NGX_SOCKADDR_STRLEN; - s.data = addr; + str.len = NGX_SOCKADDR_STRLEN; + str.data = addr; - if (ngx_connection_local_sockaddr(pc, &s, 1) == NGX_OK) { + if (ngx_connection_local_sockaddr(pc, &str, 1) == NGX_OK) { handler = c->log->handler; c->log->handler = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxy %V connected to %V", - &s, u->peer.name); + &str, u->peer.name); c->log->handler = handler; } From mdounin at mdounin.ru Mon Aug 17 19:32:50 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 17 Aug 2015 19:32:50 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: http://hg.nginx.org/nginx/rev/5def760fe95e branches: changeset: 6231:5def760fe95e user: Maxim Dounin date: Mon Aug 17 18:09:20 2015 +0300 description: Updated OpenSSL used for win32 builds. Note that as of OpenSSL 1.0.0, the "ms\do_ms" script (previously documented to be used if one doesn't want to use the assembly language files) tries to use MASM. Additionally, OpenSSL 1.0.2 finally broke MASM support. To fix this, we now explicitly use "no-asm" in OpenSSL options. diffstat: misc/GNUmakefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff --git a/misc/GNUmakefile b/misc/GNUmakefile --- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -5,7 +5,7 @@ NGINX = nginx-$(VER) TEMP = tmp OBJS = objs.msvc8 -OPENSSL = openssl-1.0.1p +OPENSSL = openssl-1.0.2d ZLIB = zlib-1.2.8 PCRE = pcre-8.37 @@ -82,7 +82,7 @@ win32: --with-mail \ --with-stream \ --with-openssl=$(OBJS)/lib/$(OPENSSL) \ - --with-openssl-opt=enable-tlsext \ + --with-openssl-opt=no-asm \ --with-http_ssl_module \ --with-mail_ssl_module \ --with-stream_ssl_module \ From chris at feedmymedia.com Mon Aug 17 20:50:29 2015 From: chris at feedmymedia.com (Chris Vancoillie) Date: Mon, 17 Aug 2015 22:50:29 +0200 Subject: http2 slow loading Message-ID: Hi Herewith attached debug log for slow loading issue testing with patch v2. -------------- next part -------------- A non-text attachment was scrubbed... Name: http2log.zip Type: application/zip Size: 59977 bytes Desc: not available URL: From jaygooby at charanga.com Tue Aug 18 11:28:23 2015 From: jaygooby at charanga.com (Jay Caines-Gooby) Date: Tue, 18 Aug 2015 12:28:23 +0100 Subject: [1.8.0 stable] bug when install on old linux version Message-ID: > On May 6, 2015, at 8:42 PM, Ruslan Ermilov wrote: > > Could you verify that this patch helps you? > > diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c > --- a/src/event/modules/ngx_epoll_module.c > +++ b/src/event/modules/ngx_epoll_module.c > @@ -329,7 +329,7 @@ ngx_epoll_init(ngx_cycle_t *cycle, ngx_m > > #if (NGX_HAVE_EVENTFD) > if (ngx_epoll_notify_init(cycle->log) != NGX_OK) { > - return NGX_ERROR; > + ngx_epoll_module_ctx.actions.notify = NULL; > } > #endif I had the same problem and this patch also fixes the "eventfd() failed (38: Function not implemented)" problem for me. Linux 2.6.16.33-xenU #x86_64 GNU/Linux ./configure --with-debug \ --with-http_stub_status_module \ --with-openssl=/tmp/openssl-1.0.1p \ --with-http_ssl_module \ --with-pcre=/tmp/pcre-8.00 -- Jay Caines-Gooby http://charanga.com http://charangamusic.co.uk jaygooby at charanga.com 01273 823 900 From vbart at nginx.com Tue Aug 18 12:29:18 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Tue, 18 Aug 2015 15:29:18 +0300 Subject: http2 slow loading In-Reply-To: References: Message-ID: <3676081.i7iDT4kKiC@vbart-workstation> On Monday 17 August 2015 22:50:29 Chris Vancoillie wrote: > Hi > > Herewith attached debug log for slow loading issue testing with patch v2. The log looks incomplete, it seems you put the "error_log" directive with the debug option not in the main level of configuration, but in some level below. As a result it didn't catch all the events. Please also provide your configuration. At the first glance it more looks like some client bandwidth limitation. Could you describe your environment and how do you test it? wbr, Valentin V. Bartenev From mdounin at mdounin.ru Tue Aug 18 13:26:58 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 18 Aug 2015 13:26:58 +0000 Subject: [nginx] Perl: fixed warning about "sep" may be used uninitialized. Message-ID: details: http://hg.nginx.org/nginx/rev/5f2a0739da19 branches: changeset: 6232:5f2a0739da19 user: Maxim Dounin date: Tue Aug 18 16:26:05 2015 +0300 description: Perl: fixed warning about "sep" may be used uninitialized. diffstat: src/http/modules/perl/nginx.xs | 15 ++++++--------- 1 files changed, 6 insertions(+), 9 deletions(-) diffs (28 lines): diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -268,18 +268,15 @@ header_in(r, key) } #endif - if (hh->offset) { + ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset); - ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset); + if (*ph) { + ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len); - if (*ph) { - ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len); + goto done; + } - goto done; - } - - XSRETURN_UNDEF; - } + XSRETURN_UNDEF; multi: From mdounin at mdounin.ru Tue Aug 18 13:27:01 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 18 Aug 2015 13:27:01 +0000 Subject: [nginx] Perl: prototyping behavior explicitly specified. Message-ID: details: http://hg.nginx.org/nginx/rev/c6cc0b79a43d branches: changeset: 6233:c6cc0b79a43d user: Maxim Dounin date: Tue Aug 18 16:26:18 2015 +0300 description: Perl: prototyping behavior explicitly specified. When prototyping behavior is not explicitly specified, xsubpp emits a message to stderr asking to do so (see ticket #608). diffstat: src/http/modules/perl/nginx.xs | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -98,6 +98,9 @@ ngx_http_perl_output(ngx_http_request_t MODULE = nginx PACKAGE = nginx +PROTOTYPES: DISABLE + + void status(r, code) CODE: From bblack at wikimedia.org Tue Aug 18 14:31:19 2015 From: bblack at wikimedia.org (Brandon Black) Date: Tue, 18 Aug 2015 14:31:19 +0000 Subject: Multiple certificate support revisited Message-ID: Hi all, The Wikimedia Foundation has been running nginx-1.9.3 patched for multi-certificate support for all production TLS traffic for a few weeks now without incident, for all inbound requests to Wikipedia and other associated projects of the Foundation. We initially used the older March variant of Filipe's patches ( http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006734.html ), and last week we switched to using the April 27 variant ( http://mailman.nginx.org/pipermail/nginx-devel/2015-April/006863.html ), which is the last known public variant I'm aware of. These were in turn based on kyprizel's patch ( http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006668.html ), which was based on Rob's patch from nearly two years ago ( http://mailman.nginx.org/pipermail/nginx-devel/2013-October/004376.html ). It has a long and colorful history at this point :) We've forward-ported Filipe's Apr 27 variant onto Debian's 1.9.3-1 package. Most of the porting was trivial (offsets / whitespace / etc). There were a couple of slightly more substantial issues around the newer OCSP Stapling valid-timestamp checking, and the porting of the general multi-cert work to the newer stream modules. The ported/updated variant of the patches we're running is available here in our repo: https://github.com/wikimedia/operations-software-nginx/blob/wmf-1.9.3-1/debian/patches/ Our configuration uses a pair of otherwise-identical RSA and ECDSA keys and an external OCSP ssl_stapling_file (certs are from GlobalSign, chain/OCSP info is identical in the pair). Our typical relevant config fragment in the server section looks like this: ------------ ssl_certificate /etc/ssl/localcerts/ecc-uni.wikimedia.org.chained.crt; ssl_certificate_key /etc/ssl/private/ecc-uni.wikimedia.org.key; ssl_certificate /etc/ssl/localcerts/uni.wikimedia.org.chained.crt; ssl_certificate_key /etc/ssl/private/uni.wikimedia.org.key; ssl_stapling on; ssl_stapling_file /var/cache/ocsp/unified.ocsp; ------------- Obviously, we'd rather get this work (or something similar) upstreamed so that we don't have to maintain local patches for this indefinitely, and so that everyone else can use it easily too. I'm assuming the reason it wasn't merged in the past is there may be other issues blocking the merge that just weren't relevant to our particular configuration, or are just matters of cleanliness or implementation detail. I'd be happy to work with whoever on resolving that and getting this patchset into a merge-able state. Does anyone know what the outstanding issues were/are? Some of the past list traffic on this is a bit fragmented. Thanks, -- Brandon From mdounin at mdounin.ru Tue Aug 18 15:23:15 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 18 Aug 2015 15:23:15 +0000 Subject: [nginx] nginx-1.9.4-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/5cb7e2eed203 branches: changeset: 6234:5cb7e2eed203 user: Maxim Dounin date: Tue Aug 18 18:16:17 2015 +0300 description: nginx-1.9.4-RELEASE diffstat: docs/xml/nginx/changes.xml | 111 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 111 insertions(+), 0 deletions(-) diffs (121 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,117 @@ + + + + +????????? proxy_downstream_buffer ? proxy_upstream_buffer ? ?????? stream +???????? ?????????? proxy_buffer_size. + + +the "proxy_downstream_buffer" and "proxy_upstream_buffer" directives +of the stream module are replaced with the "proxy_buffer_size" directive. + + + + + +????????? tcp_nodelay ? ?????? stream. + + +the "tcp_nodelay" directive in the stream module. + + + + + +?????? ????? ??????? ????????? ???????? sub_filter ????????????. + + +multiple "sub_filter" directives can be used simultaneously. + + + + + +????????? sub_filter ???????????? ?????????? ? ?????? ??????. + + +variables support in the search string of the "sub_filter" directive. + + + + + +???????????? ???????????? ????? ?? ???????? ??? Linux OpenVZ.
+??????? ???????? ????????. +
+ +configuration testing might fail under Linux OpenVZ.
+Thanks to Gena Makhomed. +
+
+ + + +????? ???????????????? ?????? ??????? ???????? ????? ?????? ????????? ????????? +??? ??????? ????????? worker_connections. + + +old worker processes might hog CPU after reconfiguration +with a large number of worker_connections. + + + + + +??? ?????????? ????????????? ???????? try_files ? alias +?????? location'?, ????????? ?????????? ??????????, +? ??????? ???????? ??? ????????? segmentation fault; +?????? ????????? ? 1.7.1. + + +a segmentation fault might occur in a worker process +if the "try_files" and "alias" directives were used +inside a location given by a regular expression; +the bug had appeared in 1.7.1. + + + + + +????????? try_files ?????? ?????????? location'?, ????????? ?????????? +??????????, ???????? ???????????, ???? ?? ??????? location'? ?????????????? +????????? alias. + + +the "try_files" directive inside a nested location +given by a regular expression worked incorrectly +if the "alias" directive was used in the outer location. + + + + + +? ????????? ?????? ??? ?????????? ???-??????. + + +in hash table initialization error handling. + + + + + +nginx ?? ????????? ? Visual Studio 2015. + + +nginx could not be built with Visual Studio 2015. + + + +
+ + From mdounin at mdounin.ru Tue Aug 18 15:23:18 2015 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 18 Aug 2015 15:23:18 +0000 Subject: [nginx] release-1.9.4 tag Message-ID: details: http://hg.nginx.org/nginx/rev/79a50ebb3b89 branches: changeset: 6235:79a50ebb3b89 user: Maxim Dounin date: Tue Aug 18 18:16:17 2015 +0300 description: release-1.9.4 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -386,3 +386,4 @@ 53d850fe292f157d2fb999c52788ec1dc53c91ed 884a967c369f73ab16ea859670d690fb094d3850 release-1.9.1 3a32d6e7404a79a0973bcd8d0b83181c5bf66074 release-1.9.2 e27a215601292872f545a733859e06d01af1017d release-1.9.3 +5cb7e2eed2031e32d2e5422caf9402758c38a6ad release-1.9.4 From jimpop at gmail.com Tue Aug 18 16:08:12 2015 From: jimpop at gmail.com (Jim Popovitch) Date: Tue, 18 Aug 2015 12:08:12 -0400 Subject: [nginx] Sub filter: support of multiple strings to replace. In-Reply-To: References: Message-ID: On Mon, Aug 17, 2015 at 10:44 AM, Dmitry Volyntsev wrote: > details: http://hg.nginx.org/nginx/rev/b9447fc457b4 > branches: > changeset: 6228:b9447fc457b4 > user: Dmitry Volyntsev > date: Mon Aug 17 17:42:02 2015 +0300 > description: > Sub filter: support of multiple strings to replace. > Hello, Can you please provide an example of use. Thank you! -Jim P. From vbart at nginx.com Tue Aug 18 16:37:38 2015 From: vbart at nginx.com (Valentin V. Bartenev) Date: Tue, 18 Aug 2015 19:37:38 +0300 Subject: [nginx] Sub filter: support of multiple strings to replace. In-Reply-To: References: Message-ID: <6763033.qoqYHaK8rh@vbart-workstation> On Tuesday 18 August 2015 12:08:12 Jim Popovitch wrote: > On Mon, Aug 17, 2015 at 10:44 AM, Dmitry Volyntsev wrote: > > details: http://hg.nginx.org/nginx/rev/b9447fc457b4 > > branches: > > changeset: 6228:b9447fc457b4 > > user: Dmitry Volyntsev > > date: Mon Aug 17 17:42:02 2015 +0300 > > description: > > Sub filter: support of multiple strings to replace. > > > > Hello, > > Can you please provide an example of use. > > Thank you! > See an example in the module documentation: http://nginx.org/en/docs/http/ngx_http_sub_module.html wbr, Valentin V. Bartenev From jimpop at gmail.com Tue Aug 18 16:44:06 2015 From: jimpop at gmail.com (Jim Popovitch) Date: Tue, 18 Aug 2015 12:44:06 -0400 Subject: [nginx] Sub filter: support of multiple strings to replace. In-Reply-To: <6763033.qoqYHaK8rh@vbart-workstation> References: <6763033.qoqYHaK8rh@vbart-workstation> Message-ID: On Tue, Aug 18, 2015 at 12:37 PM, Valentin V. Bartenev wrote: > On Tuesday 18 August 2015 12:08:12 Jim Popovitch wrote: >> On Mon, Aug 17, 2015 at 10:44 AM, Dmitry Volyntsev wrote: >> > details: http://hg.nginx.org/nginx/rev/b9447fc457b4 >> > branches: >> > changeset: 6228:b9447fc457b4 >> > user: Dmitry Volyntsev >> > date: Mon Aug 17 17:42:02 2015 +0300 >> > description: >> > Sub filter: support of multiple strings to replace. >> > >> >> Hello, >> >> Can you please provide an example of use. >> >> Thank you! >> > > See an example in the module documentation: > http://nginx.org/en/docs/http/ngx_http_sub_module.html > Thanks, I am aware of that. What is missing from the docs is the format for multiple sub_filter entries. Is it: a) sub_filter "matchA" "replaceA" "matchB" "replaceB"; b) sub_filter "matchA" "replaceA" sub_filter "matchB" "replaceB" c) sub_fitler "match1" "match2" "match3" "replaceAll" d) Only 1 sub_filter allowed per location or server And then there's the issue of sub_filter_last_modified and sub_filter_once applying to all, or just the preceding or the following entry? Multiple sub_filters is a great addition, docs are unclear on usage. :-) -Jim P. From xeioex at nginx.com Tue Aug 18 16:56:14 2015 From: xeioex at nginx.com (Dmitry) Date: Tue, 18 Aug 2015 19:56:14 +0300 Subject: [nginx] Sub filter: support of multiple strings to replace. In-Reply-To: References: <6763033.qoqYHaK8rh@vbart-workstation> Message-ID: <55D363AE.4060904@nginx.com> On 18.08.2015 19:44, Jim Popovitch wrote: > On Tue, Aug 18, 2015 at 12:37 PM, Valentin V. Bartenev wrote: >> On Tuesday 18 August 2015 12:08:12 Jim Popovitch wrote: >>> On Mon, Aug 17, 2015 at 10:44 AM, Dmitry Volyntsev wrote: >>>> details: http://hg.nginx.org/nginx/rev/b9447fc457b4 >>>> branches: >>>> changeset: 6228:b9447fc457b4 >>>> user: Dmitry Volyntsev >>>> date: Mon Aug 17 17:42:02 2015 +0300 >>>> description: >>>> Sub filter: support of multiple strings to replace. >>>> >>> Hello, >>> >>> Can you please provide an example of use. >>> >>> Thank you! >>> >> See an example in the module documentation: >> http://nginx.org/en/docs/http/ngx_http_sub_module.html >> > Thanks, I am aware of that. What is missing from the docs is the > format for multiple sub_filter entries. > > Is it: > > a) sub_filter "matchA" "replaceA" "matchB" "replaceB"; > > b) sub_filter "matchA" "replaceA" > sub_filter "matchB" "replaceB" > > c) sub_fitler "match1" "match2" "match3" "replaceAll" > > d) Only 1 sub_filter allowed per location or server Only this option is applicable here. > > And then there's the issue of sub_filter_last_modified and > sub_filter_once applying to all, or just the preceding or the > following entry? sub_filter_once on; is designed to support configurations like this one: sub_filter ' ''; sub_filter ' '