У меня есть несколько серверов, работающих на одном компьютере, некоторые только с http, некоторые с http и https. Есть несколько серверных блоков, определенных в отдельных файлах, которые включены в основной файл конфигурации.
Я установил сервер «по умолчанию» для http, который будет обслуживать общую «страницу обслуживания» для запросов, которые не соответствуют никаким другим именам server_name в других файлах конфигурации. Сервер http по умолчанию работает так, как ожидалось, он использует имя_сервера «_» и появляется первым в списке включенных (поскольку я заметил, что в случае дублирования имен серверов на серверах, используется тот, который появляется первым). Это прекрасно работает.
Я ожидал бы тот же самый блок сервера (только переключение «listen 80 default_server» на «listen 443 default_server», а также вместо обслуживания страницы «return 444»), но это не так. Вместо этого кажется, что новый https-сервер по умолчанию фактически захватывает все входящие https-соединения и вызывает их сбой, хотя другие серверные блоки имеют более подходящие server_names для входящих запросов. Удаление нового https-сервера по умолчанию приведет к возобновлению частично правильного поведения: все веб-сайты с https будут загружаться правильно; но все веб-сайты без https будут перенаправлены на первый https-сервер во включаемых файлах (который, согласно документации, если не отображается «default_server», то первый появившийся блок сервера будет «default»).
Итак, мой вопрос: как правильно определить «сервер по умолчанию» в 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;
}
}
Кто-нибудь из вас видит, что здесь может быть не так?
Мне удалось настроить общий выделенный хостинг на одном 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 -t
sudo service nginx reload
Надеюсь, поможет.
У вас нет ssl_certificate или ssl_certificate_key, определенных в вашем блоке https по умолчанию. Хотя у вас нет или вам нужен настоящий ключ для этого сценария по умолчанию, вам все равно нужно его настроить, иначе у nginx будет нежелательное поведение, которое вы описываете.
Создайте самозаверяющий сертификат с общим именем * и вставьте его в свою конфигурацию, и он начнет работать так, как вы хотите.
Поведение "по умолчанию" при этой настройке будет заключаться в том, что браузер получит предупреждение о том, что сертификату нельзя доверять, если пользователь добавляет сертификат в качестве исключения, соединение будет разорвано nginx, и они увидят значение по умолчанию своего браузера. Сообщение об ошибке «не удалось подключиться».
Мы в основном хотим любой ценой избежать того, чтобы первое определение сервера в нашем файле конфигурации служило сервером для всех 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;
}
...
Чтобы подробнее рассказать об ответе Радмиллы Мустафа:
Nginx использует заголовок Host для сопоставления server_name. Он не использует TLS SNI. Это означает, что для SSL-сервера nginx должен иметь возможность принимать SSL-соединение, что сводится к наличию сертификата / ключа. Сертификат / ключ может быть любым, например самоподписанный.
Видеть документация
Следовательно, решение:
server {
server_name _;
listen 80 default_server;
listen 443 ssl default_server;
## To also support IPv6, uncomment this block
# listen [::]:80 default_server;
# listen [::]:443 ssl default_server;
ssl_certificate <path to cert>;
ssl_certificate_key <path to key>;
return 404; # or whatever
}
Всем, кто потерял из-за этого столько волос, как я (сегодня потратил на это почти весь день). Я перепробовал почти все, и единственное, что заставило его наконец работать правильно, - это эта дурацкая строка:
ssl_session_tickets off;
Опираясь на Если неответ, мой рабочий пример:
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_session_tickets off;
return 404;
}
Я понятия не имею, почему это было необходимо, единственный принцип, который я вынес из этого, заключался в том, что nginx ведет себя очень странно, когда мы не даем ему то, что он хочет.
Если вы хотите быть абсолютно уверенным, используйте отдельные IP-адреса для хостов, которые не должны отвечать по HTTPS, и хостов, которые должны. Это также решает проблему с предупреждением браузера о недопустимом сертификате.