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

NGINX использует первый ssl server_block, который может найти по умолчанию

Итак, я удалил свою конфигурацию vhost по умолчанию из /etc/nginx/sites-available/, поскольку мне не нужно отлавливать пользователей, обращающихся к несуществующему поддомену (Debian 9).

Проблема: При вызове случайного поддомена с https, например. https://abc.example.com, NGINX применит поведение по умолчанию и будет использовать первый listen 443 server-block он может найти в моих файлах конфигурации. Это означает, что, когда пользователь по ошибке обращается к ложному поддомену с https, вместо того, чтобы получить ошибку 404 (например, при вызове abc.amazon.com или abc.google.com), он получит красный восклицательный знак и certificate name missmatch ошибка (хром (NET::ERR_CERT_COMMON_NAME_INVALID)), что куда страшнее понятной ошибки 404.
Вопрос: Есть ли способ отключить это поведение nginx по умолчанию при использовании первого серверного блока ssl, который он может найти?
ОН, И: Даже при воссоздании виртуального хоста по умолчанию (я скопировал его резервную копию), 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 (конфигурация)

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

... пользователь по ошибке получает доступ к ложному поддомену с 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, который немедленно закрывает соединение.

Клиенты увидят сообщение об ошибке о проблемах с подключением. Это лучшее, что можно сделать, когда для домена нет подходящего сертификата.