0

I have a VPS with 14 domains and I setup letskencrypt to automatically retrieve a separate certificate for each domain with all sub-domains included. So, I have 14 certs. Obviously, putting all domains in one cert is not an option because soon I'll hit the maximum 100 domain/sub-domain per cert for Letsencrypt.

So, I was happy for a month until I found out that nginx serves wrong certs for all domains except one (the one that it automatically picks up - or, I'll set - as the default server for port 443). After a lot of headache I found out that each SSL cert must have its own IP not a shared one. Then also I found out there is SNI as a workaround for this issue.

$ nginx -V
TLS SNI support enabled

So make the long story short; The problem is no matter what I do nginx stubbornly serve's the wrong cert:

$ curl --insecure -v https://babaei.net 2>&1 | awk 'BEGIN { cert=0 } /^\* Server certificate:/ { cert=1 } /^\*/ { if (cert) print }'
* Server certificate:
*  subject: CN=babaei.net
*  start date: Aug 28 13:30:00 2016 GMT
*  expire date: Nov 26 13:30:00 2016 GMT
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Connection #0 to host babaei.net left intact

$ curl --insecure -v https://learnmyway.net 2>&1 | awk 'BEGIN { cert=0 } /^\* Server certificate:/ { cert=1 } /^\*/ { if (cert) print }'
* Server certificate:
*  subject: CN=babaei.net
*  start date: Aug 28 13:30:00 2016 GMT
*  expire date: Nov 26 13:30:00 2016 GMT
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Connection #0 to host learnmyway.net left intact

$ curl --insecure -v https://3rr0r.org 2>&1 | awk 'BEGIN { cert=0 } /^\* Server certificate:/ { cert=1 } /^\*/ { if (cert) print }'
* Server certificate:
*  subject: CN=babaei.net
*  start date: Aug 28 13:30:00 2016 GMT
*  expire date: Nov 26 13:30:00 2016 GMT
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Connection #0 to host 3rr0r.org left intact

And, don't get me wrong the actual certs are what they are supposed to be:

$ openssl x509 -noout -subject -in /path/to/certs/babaei.net.pem
subject= /CN=babaei.net

$ openssl x509 -noout -subject -in /path/to/certs/learnmyway.net.pem
subject= /CN=learnmyway.net

$ openssl x509 -noout -subject -in /path/to/certs/3rr0r.org.pem
subject= /CN=3rr0r.org

So, let's say we have two domains alpha.com and omega.com. How would you configure SNI enabled nginx to serve the right SSL cert for each?

server {
  server_tokens  off;

  listen  443 ssl http2;
  listen  [::]:443 ssl http2;
  server_name  www.alpha.com;

  ssl  on;
  ssl_certificate  /path/to/alpha.com/cert.pem;
  ssl_certificate_key /path/to/alpha.com/key.pem;
}

server {
  server_tokens  off;

  listen  443 ssl http2;
  listen  [::]:443 ssl http2;
  server_name  www.omega.com;

  ssl  on;
  ssl_certificate  /path/to/omega.com/cert.pem;
  ssl_certificate_key /path/to/omega.com/key.pem;
}

Thanks

UPDATE: This was the original config:

server {
    server_tokens   off;

    listen          80;
    listen          [::]:80;
    server_name     learnmyway.net;

    location / {
        return 301 https://www.$server_name$request_uri;  # enforce https / www
    }

    # Error Pages
    include /path/to/snippets/error;

    # Anti-DDoS
    include /path/to/snippets/anti-ddos;

    # letsencrypt acme challenges
    include /path/to/snippets/letsencrypt-acme-challenge;
}

server {
    server_tokens   off;

    listen          80;
    listen          [::]:80;
    server_name     *.learnmyway.net;

    location / {
        return 301 https://$host$request_uri;  # enforce https
    }

    # Error Pages
    include /path/to/snippets/error;

    # Anti-DDoS
    include /path/to/snippets/anti-ddos;

    # letsencrypt acme challenges
    include /path/to/snippets/letsencrypt-acme-challenge;
}


server {
    server_tokens   off;

    listen          443 ssl http2;
    listen          [::]:443 ssl http2;
    server_name     www.learnmyway.net;

    # Hardened SSL
    include                 /path/to/snippets/hardened-ssl;
    ssl_certificate         /path/to/certs/learnmyway.net.pem;
    ssl_certificate_key     /path/to/keys/learnmyway.net.pem;
    ssl_trusted_certificate /path/to/certs/learnmyway.net.pem;

    #error_log      /path/to/learnmyway.net/log/www_error_log;
    #access_log     /path/to/learnmyway.net/log/www_access_log;

    root            /path/to/learnmyway.net/www/;
    index           index.html;

    # Error Pages
    include         /path/to/snippets/error;

    # Anti-DDoS
    include         /path/to/snippets/anti-ddos;

    # letsencrypt acme challenges
    include /path/to/snippets/letsencrypt-acme-challenge;

    # Compression
    include         /path/to/snippets/compression;

    # Static Resource Caching
    include         /path/to/snippets/static-resource-caching;
}
9
  • 1
    Do you have server blocks for all of your domains?
    – Alexey Ten
    Aug 29, 2016 at 9:36
  • Right. Show the actual nginx configuration for these domains. Aug 29, 2016 at 9:36
  • 1
    In your config you don't need ssl on; directives and SHOULD add alpha.com and omega.com names to corresponding server_name directives. Oherwise request to omega.com (without www) will end up in first server block.
    – Alexey Ten
    Aug 29, 2016 at 9:37
  • 1
    It was solved? I don't see your answer below! Sep 4, 2016 at 14:39
  • 1
    @MichaelHampton the answer was in the update section. But to avoid confusion as you asked I did add it as an answer. Sep 5, 2016 at 17:06

1 Answer 1

1

Looks like @AlexeyTen was right. Adding the following server block solved the issue:

server {
    server_tokens   off;

    listen          443 ssl http2;
    listen          [::]:443 ssl http2;
    server_name     learnmyway.net;

    # Hardened SSL
    include                 /path/to/snippets/hardened-ssl;
    ssl_certificate         /path/to/certs/learnmyway.net.pem;
    ssl_certificate_key     /path/to/keys/learnmyway.net.pem;
    ssl_trusted_certificate /path/to/certs/learnmyway.net.pem;

    return 301 https://www.$server_name$request_uri;  # enforce www
}

My mistake: Since * is a wildcard character, I thought *.learnmyway.net will resolve learnmyway.net, too. It seems I was wrong.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .