Назад | Перейти на главную страницу

Nginx SNI и Letsencrypt на FreeBSD; Неверный сертификат?

У меня есть VPS с 14 доменами, и я настраиваю Letkencrypt для автоматического получения отдельного сертификата для каждого домена со всеми включенными поддоменами. Итак, у меня есть 14 сертификатов. Очевидно, что объединение всех доменов в один сертификат не вариант, потому что скоро я достигну максимального количества доменов / субдоменов 100 на сертификат для Letsencrypt.

Итак, я был счастлив в течение месяца, пока не обнаружил, что nginx обслуживает неправильные сертификаты для всех доменов, кроме одного (того, который он автоматически выбирает - или, я установлю - в качестве сервера по умолчанию для порта 443). После большой головной боли я обнаружил, что каждый сертификат SSL должен иметь свой собственный IP-адрес, а не общий. Затем я обнаружил, что для решения этой проблемы используется SNI.

$ nginx -V
TLS SNI support enabled

Так что сделайте длинную историю короче; Проблема в том, независимо от того, что я делаю Nginx упорно служить неправильный сертификат:

$ 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

И не поймите меня неправильно, настоящие сертификаты - это то, чем они должны быть:

$ 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

Итак, допустим, у нас есть два домена alpha.com и omega.com. Как бы вы настроили nginx с поддержкой SNI для обслуживания правильного сертификата SSL для каждого?

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;
}

Спасибо

ОБНОВИТЬ: Это был исходный конфиг:

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;
}

Похоже, @AlexeyTen был прав. Добавление следующего серверного блока решило проблему:

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
}

Моя ошибка: поскольку * - это подстановочный знак, я думал, что * .learnmyway.net также разрешит learnmyway.net. Кажется, я ошибался.