How to tell nginx to serve https only for one vhost-managed domain?

I have an ec2 instance running ubuntu and nginx 0.8.4, with vhosts serving several different domains using http but one using SSL/https.

Secure domain configuration:

server {
    listen 443 ssl;
    server_name "securedomain.tld";

    ssl_certificate     /etc/nginx/certs/securedomain.tld.crt;
    ssl_certificate_key /etc/nginx/certs/securedomain.tld.key;

    if ($host != $server_name) {
        return 444; # this won't work because HTTPS communication has 
                    # been already started, warning message is displayed
    }

    // ...
}

Unsecure domain configuration:

server {
    listen 80; 
    server_name "unsecuredomain.tld";

    // ...
}

Right now the domain served using https is catching up all the https trafic, for all managed domains… that means that https://unsecuredomain.tld/ will display a warning and actually serve the contents from securedomain.tld :(

Question is, is there a way to prevent nginx from serving all unsecure domains served using https? eg by specifying that you only want to accept https connections for a given requested host…

Hint: an ec2 instance cannot have more than one IP affected.


In short: nope. As far as nginx is concerned, you've told it that all connections to port 443 are SSL connections for that vhost, and it's just doing what you told it. By the time it can see the Host: header in the request, the SSL negotiation has been done (absent SNI, which is really only going to help if you've got certs for all your domains and are being hit by an SNI-aware browser).


The SSL mismatch warning is unpreventable without a second IP address or some sort of proxy setup, as womble notes.

If you want to prevent unsecuredomain.tld content from being served over SSL, you should use something like the following in the securedomain.tld SSL vhost definition instead of what you have:

if ($host != $server_name) {
    rewrite ^(.*)$ http://unsecuredomain.tld permanent;
}

and just bounce them out, instead of throwing up a different HTTP error after they've already received the browser warning and chosen to continue.