#2463 closed defect (invalid)

ssl_reject_handshake allows some connections through

Reported by: thestinger@… Owned by:
Priority: minor Milestone:
Component: nginx-core Version: 1.21.x
Keywords: Cc:
uname -a: Linux 0-network 6.1.14-1-lts #1 SMP PREEMPT_DYNAMIC Sat, 25 Feb 2023 11:02:38 +0000 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.22.1
built with OpenSSL 3.0.7 1 Nov 2022 (running with OpenSSL 3.0.8 7 Feb 2023)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/bin/nginx --pid-path=/run/nginx.pid --lock-path=/run/lock/nginx.lock --user=http --group=http --http-log-path=/var/log/nginx/access.log --error-log-path=stderr --http-client-body-temp-path=/var/lib/nginx/client-body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-cc-opt='-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fstack-clash-protection -fcf-protection -flto=auto' --with-ld-opt='-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -flto=auto' --with-compat --with-debug --with-file-aio --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_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-pcre-jit --with-stream --with-stream_geoip_module --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads

Description

We've noticed a small number of connections somehow making it past ssl_reject_handshake.

This is an example caused by a censys.io bot scanning the whole IPv4 space:

Mar 05 14:32:59 0-network nginx[47606]: 2023/03/05 14:32:59 [error] 47606#47606: *4121615 directory index of "/var/empty/" is forbidden, client: 167.248.133.117, server: , request: "GET / HTTP/1.1", host: "51.79.54.68:443"
Mar 05 14:32:59 0-network nginx[47606]: 4121615 167.248.133.117 - TLSv1.3 HTTP/1.1 51.79.54.68 GET "/" 403 41 146/304 0.000 "-" "-"

We mostly see this happening with these bots scanning for vulnerabilities. I expect that it's easy enough to replicate by just having a server with a similar configuration with a public IPv4 address.

If I run curl https://51.79.54.68/ --http1.1 myself, I get the expected tlsv1 unrecognized name error. I've also tried openssl s_client -connect 51.79.54.68:443 and gnutls-cli 51.79.54.68:443. No luck bypassing ssl_reject_handshake myself.

server {

listen 443 default_server ssl backlog=4096;
listen [::]:443 default_server ssl backlog=4096;
ssl_reject_handshake on;

}

This issue is happening across each of our sites. Here's one of the configurations, corresponding to the server with the logs above:

https://github.com/GrapheneOS/grapheneos.network/blob/main/nginx/nginx.conf

We have much simpler configurations without any use of proxy_pass, etc. where this is happening too.

I'm guessing that most people are not using nginx with OpenSSL 3.x yet and that it's an OpenSSL 3.x bug or compatibility issue. I don't know enough about how nginx implements this feature to know if the bug is in nginx or OpenSSL.

Change History (2)

comment:1 by thestinger@…, 21 months ago

Meant to mark the version as 1.22.x. Seems I can't change it now.

comment:2 by Maxim Dounin, 21 months ago

Resolution: invalid
Status: newclosed

The ssl_reject_handshake directive prevents handshakes in the context of the given server block at the SSL level, but HTTP requests still can reach the server if SSL handshake happens in the different server. For example, HTTP/2 explicitly defines cases when connections connections can be reused for requests to a different SNI name. Further, this is how Domain fronting works.

If you want nginx to reject requests at the HTTP level as well, consider adding this to your nginx configuration. For example, something like

server {
    listen 443 ssl;
    ssl_reject_handshake on;
    return 404;
}

might be a good solution.

Note: See TracTickets for help on using tickets.