Вопрос: Правильная настройка сервера nginx по умолчанию для https


У меня несколько серверов, работающих на одной машине, некоторые с http только, некоторые с http и https. Существует несколько серверных блоков, определенных в отдельных файлах, которые включены в основной файл конфигурации.

Я установил «по умолчанию» сервер для http, который будет обслуживать общую «страницу обслуживания» для запросов, которые не соответствуют ни одному из других имен сервера в других файлах конфигурации. Сервер по умолчанию http работает так, как ожидалось, он использует имя_сервера «_», и он появляется первым в списке включений (поскольку я заметил, что в случае дублирования имен сервера на серверах используется первый, который появляется первым). Это отлично работает.

Я бы ожидал такой же точный серверный блок (только переключение «listen 80 default_server» на «слушать 443 default_server», а также вместо того, чтобы обслуживать страницу «return 444»), но это не так. Вместо этого кажется, что новый https-сервер по умолчанию фактически захватывает все входящие соединения https и приводит к их провалу, хотя другие серверные блоки имеют более подходящие имена серверов для входящих запросов. Удаление нового https-сервера по умолчанию приведет к возобновлению полурефлекторного поведения: сайты с https будут загружены правильно; но веб-сайты без https будут перенаправлены на первый https-сервер в включаемых файлах (что, согласно документам, если не отображается «default_server», тогда первый серверный блок будет отображаться «по умолчанию»).

Итак, мой вопрос: каков правильный способ определения «сервера по умолчанию» в nginx для соединений ssl? Почему, когда я явно устанавливаю «default_server», он становится жадным и захватывает все соединения, тогда как когда я неявно разрешаю nginx решать «сервер по умолчанию», он работает так, как я ожидал бы (с неправильным сервером, установленным по умолчанию, и другими реальными серверами вести себя правильно)?

Вот мои «серверы по умолчанию». Http работает без нарушения работы других серверов. Https разбивает другие серверы и потребляет все.

server {
    listen 443 ssl default_server;
    server_name _;

    access_log /var/log/nginx/maintenance.access.log;
    error_log /var/log/nginx/maintenance.error.log error;

    return 444;
}

server {
    listen *:80 default_server;
    server_name _;
    charset utf-8;

    access_log /var/log/nginx/maintenance.access.log;
    error_log /var/log/nginx/maintenance.error.log error;

    root /home/path/to/templates;

    location / {
        return 503;
    }

    error_page 503 @maintenance;

    location @maintenance {
        rewrite ^(.*)$ /maintenance.html break;
    }
}

Кто-нибудь из вас видит, что здесь может быть не так?


51
2018-02-26 22:29


Источник




Ответы:


У вас нет ssl_certificate или ssl_certificate_key, определенных в вашем блоке https по умолчанию. Хотя у вас нет или требуется реальный ключ для этого сценария по умолчанию, вам все равно нужно его настроить, иначе nginx будет иметь нежелательное поведение, которое вы описываете.

Создайте самозаверяющий сертификат с общим именем * и включите его в свою конфигурацию, и он начнет работать так, как вы хотите.

Поведение «по умолчанию» в этой настройке будет состоять в том, что браузер получит предупреждение о том, что сертификат не может быть доверен, если пользователь добавит сертификат в качестве исключения, соединение будет удалено nginx, и они будут видеть, что их браузер по умолчанию Сообщение об ошибке «не удалось подключиться».


18
2018-02-27 16:27



Я пробовал это, но он по-прежнему не работает: все запросы ssl на IP переходят на мой другой узел ssl. Что-нибудь еще я мог попробовать? - Michael Härtl


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

Это не может быть достигнуто декларативно для 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;
    }

    ...

13
2017-07-02 00:12



не могли бы вы объяснить, что listen [::]:443 ssl http2; делает? У меня возникли проблемы с поиском документации. - Andrew Brown
Кажется, я нашел его, просто нужно было знать, что искать. IPV4 и IPV6. - Andrew Brown


Мне удалось настроить общий выделенный хостинг на одном IP-адресе с nginx. HTTP по умолчанию и HTTPS, обслуживающие 404 для входящих доменов.

1 - создать зону по умолчанию

Поскольку nginx загружает vhosts в порядке ascii, вы должны создать 00-default файл / символическая ссылка в ваш /etc/nginx/sites-enabled,

2 - Заполните зону по умолчанию

Заполните 00-default с vhosts по умолчанию. Вот зона, которую я использую:

server {
    server_name _;
    listen       80  default_server;
    return       404;
}


server {
    listen 443 ssl;
    server_name _;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    return       404;
}

3 - Создайте собственный сертификат, тест и перезагрузку

Вам нужно будет создать самоподписанный сертификат в /etc/nginx/ssl/nginx.crt,

Создайте самозаверяющий сертификат по умолчанию: sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

Просто напоминание :

  • Проверьте конфигурацию nginx перед перезагрузкой / перезапуском: nginx -t
  • Перезагрузите пользоваться: sudo service nginx reload

Надеюсь, поможет.


8
2018-04-24 11:52



Не разрешает браузеру предупреждение о посещении небезопасного сайта. - gdbj
Не может быть разрешен, так как catch-all должен соответствовать любым доменам. SSL не может подменять все домены. Представьте себе, что если вы подменяете адрес google.fr на своем сервере, вы сможете аутентифицировать ваш сервер как google.fr. Это была бы серьезная проблема безопасности :( - Ifnot
Я думаю, это имеет смысл. К сожалению, в Chrome у вас появилось страшное предупреждение, прежде чем просмотреть страницу 404, которая хуже того, что сервер просто отклонил трафик. Делает вид, что сервер неправильно настроен. - gdbj


Чтобы подробнее рассказать о решении Радмиллы Мустафы:

Nginx использует заголовок «Host» для сопоставления имен серверов. Он не использует SNI TLS. Это означает, что для сервера SSL nginx должен иметь возможность принимать SSL-соединение, которое сводится к наличию сертификата / ключа. Сертификат / ключ может быть любым, например. самозаверяющими.

Видеть документация

Следовательно, решение:

server {
    server_name _;
    listen 80 default_server;
    listen 443 ssl default_server;
    ssl_certificate <path to cert>;
    ssl_certificate_key <path to key>;
    return 404; # or whatever
}

3
2018-03-30 21:17



Я чувствую, что это должен быть принятый ответ. Большое спасибо. - aggregate1166877


Если вы хотите быть абсолютно уверены, то используйте отдельные IP-адреса для хостов, которые не должны отвечать на HTTPS и хосты, которые должны. Это также устраняет проблему предупреждения браузера «недействительный сертификат».


1
2018-02-27 13:19