Neither of above helped in my case - IP connection to http works as expected but https was redirecting to alphabetically first https virtual site. What was working witn nginx below 1.19.4 was to add null certificate to block:
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 default_server;
listen [::]:443 default_server;
ssl_certificate /etc/ssl/null.crt;
ssl_certificate_key /etc/ssl/null.key;
server_name "";
return 444;
}
Certificte can be generated with empty CN so you need no worry about fill it.
sudo openssl req -x509 -newkey rsa:2048 -days 10000 -nodes -subj "/C=US/ST=Florida/L=XXXXX/O=Foo Inc./OU=IT/CN=X" -keyout null.key -out null.crt
Then http/https returns 444 (ERR_EMPTY_RESPONSE), in different configurations https returns ERR_HTTP2_PROTOCOL_ERROR with your null certificate which is also fine to show there is nothing there.
For nginx 1.19.4 it is simpler. It introduced ssl_reject_handshake on | off
(http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_reject_handshake) you can replace certificates 'stuff' with:
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 default_server;
listen [::]:443 default_server;
ssl_reject_handshake on;
server_name "";
return 444;
}
And now you get http 444 (ERR_EMPTY_RESPONSE) and for https ERR_SSL_UNRECOGNIZED_NAME_ALERT. No null certificates are needed.
Ref.