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

Nginx один ip и несколько ssl сертификатов

Пример случая. У меня есть веб-сервер с одним IPV4-адресом. Я размещаю около 50 веб-сайтов, и только два из них имеют ssl-сертификаты. Я настроил vhosts для 2 веб-сайтов ssl, и все в порядке, за исключением одной большой проблемы - если я посещаю другие 48 сайтов с префиксом https: // (у них нет сертификатов ssl), я вижу свой последний веб-сайт с сертификатом SSL .

Можно ли запретить префикс https на сайтах без SSL? Или есть только одно решение - использовать выделенные IP-адреса. Если у меня есть выделенный IP-адрес, я использую следующую конфигурацию:

server {
        listen 111.222.333.444:443 ssl;
}

Таким образом, если я использую https на веб-сайте без SSL, ничего не произойдет.

Nginx использует «сервер по умолчанию», который выбирает для обслуживания страниц, когда нет другого ближайшего совпадения. Если вы не указали используемый по умолчанию сервер, я считаю, что он использует первый из найденных (который в вашем случае является одним из ваших HTTPS-сайтов). Таким образом, вы должны иметь возможность создать сервер vhost по умолчанию с вашим IPv4-адресом для TLS (вы больше используете только TLS, а не SSL, верно?) И заставить его прослушивать IP-адрес, который будет улавливать случайные запросы HTTPS. Возможно, вам также потребуется добавить туда элемент server_name для ваших 48 незащищенных сайтов, но он может работать и без этого.

#Your catch-all HTTPS server:
server {
  listen 104.218.234.204:443 default_server;
  server_name ruel.in ruel.pro;
  root /var/www/ruel.pro;
  index index.html;
  ssl on;
  ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
  ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
  ssl_dhparam /etc/ssl/private/dhparams_4096.pem;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
}

#Regular HTTP server
server {
  listen ruel.in:80;
  server_name ruel.in;
  root /var/www/ruel.in;
  index index.php index.html index.htm;
  ...
}

#Regular HTTP server
server {
  listen ruel.pro:80;
  server_name ruel.pro;
  root /var/www/ruel.pro;
  index index.php index.html index.htm;
  ...
}

#Your HTTPS server
server {
  listen dallas.ruhnet.net:443 ssl;
  server_name dallas.ruhnet.net;
  ...
}

Другая альтернатива - продолжайте и настройте их все с помощью HTTPS! В проекте Let's Encrypt (https://www.letsencrypt.org) вы можете бесплатно получить доверенные сертификаты для всех остальных сайтов. И это довольно просто.

Я знаком с проблемой.

Мы в основном хотим любой ценой избежать того, чтобы первое определение сервера в нашем файле конфигурации служило сервером для всех SSL-соединений. Мы все знаем, что он это делает (в отличие от http и использования конфигурации default_server, которая хорошо работает).

Это не может быть достигнуто декларативно в Nginx для SSL (пока), поэтому мы должны закодировать это с помощью IF ...

Переменная $host это имя хоста из строки запроса или заголовка http. Переменная $server_name - это имя серверного блока, в котором мы сейчас находимся.

Итак, если эти два не равны, вы обслужили этот блок сервера SSL для другого хоста, поэтому он должен быть заблокирован.

Мы можем реализовать это в каждом серверном блоке (конечно, с общим включением).

Код не содержит конкретных ссылок на IP-адреса или имена серверов, поэтому его можно легко повторно использовать для других конфигураций сервера без изменений.

Пример:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ###
    ### Section: SSL

    #
    ## Check if this certificate is really served for this server_name
    ##   http://serverfault.com/questions/578648/properly-setting-up-a-default-nginx-server-for-https
    if ($host != $server_name) {
        #return 404 "this is an invalid request";
        return       444;
    }

    # ...