Opened 21 months ago
Last modified 19 months ago
#2455 closed defect
nginx doesn't close http/2 connection on error '400' (redirected) — at Version 2
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-core | Version: | 1.23.x |
Keywords: | Cc: | RuStrannik@… | |
uname -a: | Linux server.example.com 4.19.0 #1 SMP Tue Jan 25 12:49:12 MSK 2022 x86_64 GNU/Linux | ||
nginx -V: |
nginx version: nginx/1.23.1
built by gcc 8.3.0 (Debian 8.3.0-6) built with OpenSSL 1.1.1d 10 Sep 2019 (running with OpenSSL 1.1.1n 15 Mar 2022) TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --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-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.23.1/debian/debuild-base/nginx-1.23.1=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie' |
Description (last modified by )
Problem: when built-in error '400' redirected to custom handler, and used incorrect request method, nginx does not perform any actions, just hangs keeping connection open.
Expected behaviour: error handler redirected and either connection closed without response (case A) of specified response returned and connection closed as well (case B).
Server config:
server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; include snippets/snakeoil.conf; error_page 400 /drop; #error_page 400 =200 /drop; # makes no difference # Case 'A' location = /drop { return 444; } # Case 'B' #location = /drop { return 200 "error\n"; } # doesn't work either location / { return 200 "server ok!\n"; } }
Request to cause issue:
curl --request "whatever" --insecure -v https://123.123.123.123
Output:
* Trying 123.123.123.123:443... * Connected to 123.123.123.123 (123.123.123.123) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=localhost.localdomain * start date: Nov 16 00:53:58 2020 GMT * expire date: Nov 14 00:53:58 2030 GMT * issuer: CN=localhost.localdomain * SSL certificate verify result: self signed certificate (18), continuing anyway. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x55b42a177fe0) > whatever / HTTP/2 > Host: 123.123.123.123 > user-agent: curl/7.74.0 > accept: */* > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing * Connection state changed (MAX_CONCURRENT_STREAMS == 128)! <now hangs here infinitely>
UPD: fixed typos and removed unrelated condition.
Change History (2)
comment:1 by , 21 months ago
Status: | new → accepted |
---|
comment:2 by , 21 months ago
Description: | modified (diff) |
---|
Thank you for posting patch so quickly.
Can confirm, 'return 200' actually works on 'nginx/1.23.1', my bad, sorry.
Was also testing this issue on a different server with 'nginx/1.22.0' and 'return 200' does not work there.
Regarding the configuring error pages, I wanted to minimize server exposure and minimize resources spent on processing requests from scripts and scanners, especially to malformed ones, as there is absolutely no value in doing that.
Have not tested patched and recompiled nginx yet.
Thanks for reporting this, looks like another variant of #274, which was missed in 1812f1d79d84.
I don't see any issues with
return 200 ...
though, it works fine in my tests and is expected to work fine. Could you please re-check if you are indeed seeing any issues with it?The following patch should fix the issue with
return 444
:Review and testing appreciated.
Disclaimer: please note that configuring error pages for 400 (Bad Request) errors is generally a bad idea, it's known to cause various issues due to lack of otherwise required request properties.