NGINX использует первый ssl server_block, который он может найти по умолчанию
Итак, я удалил мой стандартный vhost config из /etc/nginx/sites-available/
, поскольку мне не нужно перехватывать пользователей, обращающихся к несуществующему поддомену (Debian 9).
Проблема: при вызове случайного субдомена с помощью https, например https://abc.example.com
NGINX применяет поведение по умолчанию и использует первый listen 443
блок сервера он может найти в моих файлах конфигурации. Это означает, что, когда пользователь по ошибке получает доступ к поддельному поддомену с помощью https, вместо того, чтобы получить ошибку 404 (как при вызове https://abc.amazon.com/ или https://abc.google.com/), он получит красный восклицательный знак и certificate name missmatch
ошибка (хром (NET::ERR_CERT_COMMON_NAME_INVALID
)), что куда страшнее, чем понятная ошибка 404.
Вопрос: есть ли способ отключить это поведение nginx по умолчанию, используя первый найденный блок ssl-сервера?
О, И: Даже при воссоздании vhost по умолчанию (я скопировал его резервную копию), NGINX демонстрирует то же поведение при доступе к случайному поддомену с https. Также Firefox будет использовать мой порт 80
блок сервера для перенаправления любого трафика с http на https://www.example.com$request_uri;
, Chrome перенаправляет http на https при вызове случайного субдомена, но сохраняет субдомен (правило, которое я никогда не определял). Вот мои 2 файла конфигурации в /etc/nginx/sites-available/
Я сейчас использую.
по умолчанию (конфигурация, обновление)
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 404;
}
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
return 444;
}
www.example.com (config)
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
include /etc/nginx/snippets/letsencrypt.conf;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_dhparam /etc/letsencrypt/live/example.com/dh.pem;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8;
add_header X-Frame-Options "SAMEORIGIN";
add_header x-xss-protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_dhparam /etc/letsencrypt/live/example.com/dh.pem;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8;
add_header X-Frame-Options "SAMEORIGIN";
add_header x-xss-protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/www.example.com;
index index.php;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location / {
try_files $uri $uri/ =404;
}
}
РЕДАКТИРОВАТЬ: Это мои записи DNS:
(HOST) * (TYPE) A (DESTINATION) MYIP
(HOST) @ (TYPE) A (DESTINATION) MYIP
and some more for ftp, mail etc
Как мне изменить указанный выше DNS, чтобы он включал только мои субдомены (imap,webmail,www,smtp)? Кроме того, какова цель следующей предварительно сконфигурированной строки? Должен ли я изменить его на imap.example.com, чтобы он работал правильно? (У меня нет почтового поддомена)
(HOST) @ (TYPE) MX (MX) 10 (DESTINATION) mail.example.com
2 ответа
... пользователь по ошибке получает доступ к ложному поддомену с помощью https ... он получит красный восклицательный знак и ошибку несоответствия имени сертификата (chrome (NET::ERR_CERT_COMMON_NAME_INVALID)), что гораздо страшнее, чем понятная ошибка 404.
Вопрос: есть ли способ отключить это поведение nginx по умолчанию, используя первый найденный блок ssl-сервера?
Проблема, которую вы пытаетесь решить, на самом деле не вызвана тем, что nginx по умолчанию использует первый блок сервера.
Вместо этого проблема заключается в том, что у вас либо нет сертификата, соответствующего (суб) домену, который запрашивал клиент, либо вы не настроили nginx для предоставления этого сертификата, если клиент получил доступ к этому конкретному поддомену. Это означает, что nginx не сможет предоставить клиенту сертификат, который фактически соответствует (суб) домену, к которому клиент получил доступ.
Поскольку существует существенное требование, чтобы сертификат сервера действительно совпадал с URL-адресом, во всех случаях клиент потерпит неудачу с некоторым пугающим сообщением об ошибке: либо потому, что субъект (ы) в сертификате не соответствуют URL-адресу, либо потому, что сертификат не выдан доверенным центром сертификации (как в случае использования самозаверяющего сертификата для блока по умолчанию) или потому что сервер просто закрывает соединение, если клиент пытается получить доступ к домену, который не настроен (как это возможно с другими веб-серверами),
Я использую следующую конфигурацию для моего SSL-хоста по умолчанию:
server {
listen 443 ssl default_server;
ssl_certificate /path/to/self-signed.crt;
ssl_certificate_key /path/to/key;
return 444;
}
return 444
это специальный код возврата nginx, который немедленно закрывает соединение.
Клиенты увидят сообщение об ошибке о проблемах подключения. Это лучшее, что можно сделать, когда нет подходящего сертификата для домена.