Opened 2 years ago

Closed 2 years ago

#1694 closed defect (invalid)

Prefer SNI name to Host header when selecting server block

Reported by: cHYzZQo@… Owned by:
Priority: minor Milestone:
Component: nginx-core Version:
Keywords: Cc:
uname -a:
nginx -V: nginx version: nginx/1.10.3 (Ubuntu)
built with OpenSSL 1.0.2g 1 Mar 2016
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/ --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads


Let's say I have a config file that looks like this.

server {
    listen 7002 ssl;
    ssl on;

    ssl_client_certificate /path-to-client-ca.pem;
    ssl_verify_client on;

    ssl_certificate /path-to-cert/server.crt;
    ssl_certificate_key /path-to-key/server.key;

    location / {
        proxy_pass http://client-cer-proxy:50001;
server {
    listen 7002 ssl;
    ssl on;
    ssl_certificate /path-to-another-cert/server.crt;
    ssl_certificate_key /path-to-another-key/server.key;
    location / {
        proxy_pass http://no-client-proxy:50001;


If I make a request to this server with an sni of but a host header of The SSL handshake happens as I would expect, i'm required to provide a client certificate. Assuming that handshake is successful when it comes time to actually serve the request it uses the server block instead proxing the request to http://no-client-proxy:50001 instead of http://client-cer-proxy:50001.

Is that expected? It seems to me that once the ssl handshake happens the rest of the request should be processed by the same server block. and if it can't be then it should send a 429 Misdirected Request rather than switching server blocks.

I tested this with 1.10.3 and 1.13.6. A quick look through the code didn't turn up any changes in more recent versions but I'm happy to test again if it will help.

Change History (1)

comment:1 by Maxim Dounin, 2 years ago

Resolution: invalid
Status: newclosed

In theory, you are right. SNI was designed to be used with the only one name, and requesting different names over a connection which uses SNI is not correct. Quoting RFC 6066:

If the server_name is established in the TLS session handshake, the client SHOULD NOT
attempt to request a different server name at the application layer.

But in practice, SPDY introduced so-called "connection reuse", which effectively uses a connection with an established SNI for request to different application-level names. And it is followed by HTTP/2 connection reuse, which does the same: a HTTP/2 client can request a different host over an already established connection.

The 421 (Misdirected Request) status code, also introduced by HTTP/2 RFC, is expected to be used only when such a connection reuse is not possible due to server limitations. In nginx, 421 is returned when a client tries to request a server protected with client SSL certificates over a connection established to a different server.

Note: See TracTickets for help on using tickets.