8

I have an Nginx instance using SNI to serve multiple HTTPS domains from a single IP.

The only glitch with the setup is that Nginx responds with the first (acting as default) domain whenever a URL for the bare IP of the server, or a domain listed at that IP for which there is no corresponding HTTPS server block, is requested. In this case I would much prefer to simply return a standard 403 Forbidden -- I would set up a default server block to do this but I can't see a way around client certificate mismatch warnings.

(How c|C)an I configure Nginx to reject requests to such unknown/undefined domains without needing to specify a particular ssl certificate which will upset browsers? (i.e. I need Nginx to reject the request with a 403 prior to upsetting the client with a "bad" cert - from the client's POV this should be identical to the case where no HTTPS server block is defined at all.)

Carlton Gibson
  • 215
  • 2
  • 6
  • Does this answer your question? [Nginx. How do I reject request to unlisted ssl virtual server?](https://serverfault.com/questions/373929/nginx-how-do-i-reject-request-to-unlisted-ssl-virtual-server) – Josh Kelley Feb 24 '21 at 16:53

2 Answers2

9

This Question quite similar to the one I answered yesterday: nginx and SNI: is it possible to automatically resolve SSL certificate by domain name

It is not possible to reject the connection before the user sees a bad certificate message in his browser. By the time Nginx might return an HTTP 403 answer, the SSL handshake is over and to complete the handshake the browser must accept the provided certificate. You can only reject the connection after the user accepted the certificate by setting up a default server:

server {
    listen 433 default_server ssl;
    ssl_certificate       common.crt;
    ssl_certificate_key   common.key;
    return 403;
}

However, most recent browsers support Server Name Indication and if you have a certificate set for each vhost, it's quite unlikely for a normal user to see that message.

It might be possible to reject connections without valid hostname indicated by SSL with iptables but that is probably quite tricky and would not be conform to any standards at all.

Updated information: It is possible to return 444 to abort the tcp connection immediately before a certificate error is shown.

xblax
  • 316
  • 2
  • 7
  • Using SNI, you could theoretically abort the connection when there is no certificate for the given domain name, which would be still better than displaying a cert error. Do you know how to do this? – Yogu Oct 28 '14 at 00:12
  • 1
    Yes, I found out it's possible to `return 444` to abort the tcp connection before a cert error is shown. – xblax Oct 30 '14 at 20:11
  • @xblax Could you also tell us HOW to return 444 before a certificate is shown? Ideally I wouldn't waste resources on a handshake for a request to a server_name I don't know. SNI should reveal the requested name before even decrypting the request. – Static Storm Sep 20 '19 at 17:03
  • @xblax Like so: `server { listen 80; server_name ...; return 444; } – KajMagnus Sep 28 '20 at 19:59
  • 1
    @xblax And, with HTTPS, you can add something like this: `listen 433 ssl; ssl_certificate /etc/nginx/some-ssl-cert.pem; ssl_certificate_key /etc/nginx/some-ssl-cert.key; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ` The cert won't actually get used — Nginx aborts the connection, early, and I didn't see any certificate error — instead, there's this error: *"This site can’t be reached ... webpage at https://... might be temporarily down or it may have moved permanently to a new web address. ERR_HTTP2_PROTOCOL_ERROR"*. But without those `ssl_...` lines, Nginx didn't want to start. – KajMagnus Sep 28 '20 at 20:10
  • @xblax, does'nt work for me in HTTPS... As expected, the connection is aborted due to 444 (with an ERR_HTTP2_PROTOCOL_ERROR), but AFTER the browser displayed a certificate error... – David Oct 18 '21 at 20:39
0

If your domains are subdomains of the same master (*.example.com) you could use a wildcard certificate. Failing that, I don't think you can supply any cert the browser will be happy with.

Chris Nava
  • 1,147
  • 1
  • 7
  • 9
  • Hi Chris. I appreciate the wildcard point but it's not really what I'm asking. Yes, the browser isn't going to like any cert BUT is there any way of rejecting the connection based on the requested server name? (I'm suspecting not, but this seems the place to ask... :) – Carlton Gibson Jan 23 '11 at 09:44
  • Untested assumption -> You'll need to supply a valid cert or the browser will consider the connection unsafe. The browser will therefore not act on any redirect you send it until the user allows an override. The only way I can think of to automatically perform the override is to provide a valid cert. :-( – Chris Nava Jan 24 '11 at 04:23