Конфигурации SSL NGINX иногда указывают на неверный домен с несколькими виртуальными хостами.

Вопрос или проблема

Вопрос:
Я запускаю сервер NGINX с примерно 150 конфигурациями виртуальных хостов. Иногда клиенты сообщают, что их SSL-сертификат неверен, и их домен указывает на SSL-сертификат другого клиента, что не является ожидаемым поведением.

Вот моя текущая настройка:

Файлы конфигураций автоматически создаются в /etc/nginx/sites-enabled/ и имеют случайные имена.
Чтобы гарантировать, что конфигурация по умолчанию загружается первой, я переименовал ее в 0000-default. Эта конфигурация по умолчанию использует самоподписанный сертификат.
Другие конфигурации доменов управляются Certbot/Letsencrypt и имеют правильные SSL-сертификаты.

Конфигурация 0000-default:

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                try_files $uri $uri/ =404;
        }
}

server {
        listen 443 default_server ssl;

        ssl_certificate /etc/nginx/snippets/ssl/self_cert.pem;
        ssl_certificate_key /etc/nginx/snippets/ssl/self_key.pem;

        return 301 http://$host;
}

Пример конфигурации клиента:

server {
    server_name sub.example.com;

    location = /.well-known/security.txt {
        alias /etc/nginx/snippets/security.txt;
    }

    location /branded_placeholder {
        root /etc/nginx/snippets;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/dslkfjaldk.php;
    }

    location / {
        if ($request_uri = "/") {
            return 301 https://$host/branded_placeholder;
        }
        proxy_pass http://backend_dslkfjaldk;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }

    listen 443 ssl; # управляется Certbot
    ssl_certificate /etc/letsencrypt/live/sub.example.com/fullchain.pem; # управляется Certbot
    ssl_certificate_key /etc/letsencrypt/live/sub.example.com/privkey.pem; # управляется Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # управляется Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # управляется Certbot
}

server {
    if ($host = sub.example.com) {
        return 301 https://$host$request_uri;
    }
    server_name sub.example.com;
    listen 80;
    return 404; # управляется Certbot
}

Проблема:
Иногда, при доступе к домену, отображается неправильный SSL-сертификат. Например, домен может указывать на домен другого клиента. Это происходит периодически и кажется случайным, но это вызывает значительные проблемы для моих клиентов.

Что я пробовал:

Убедился, что конфигурация сервера по умолчанию загружается первой, переименовав ее в 0000-default. Проверил порядок конфигурационных файлов.

Мои вопросы:

Почему NGINX иногда выдает неправильный SSL-сертификат для определенных доменов?

Как я могу гарантировать, что NGINX постоянно выдает правильный SSL-сертификат для каждого домена?

Есть ли лучший способ настроить сервер по умолчанию в комбинации с Certbot/Let’s Encrypt, чтобы избежать этой проблемы?

Дополнительная информация:

Я использую Certbot для управления SSL-сертификатами.
Сервер работает на NGINX под управлением Debian 12.

Ответ или решение

Понимание проблемы неправильной конфигурации SSL в NGINX

Проблема, с которой вы столкнулись — случайная подача неверных SSL-сертификатов для ваших клиентов — может вызывать путаницу и недовольство. Давайте разберем причины возникновения этой проблемы и поймем, как её можно устранить.

Причины проблемы

  1. Приоритет конфигураций: NGINX использует подход «первый совпадение» для определения, какой блок server обрабатывать во время установки соединения. Убедитесь, что блоки server с поддержкой SSL настроены корректно и имеют соответствующий порядок.

  2. Дефолтный сервер: Использование блока default_server для проксирования с 443 порта может привести к ситуации, когда клиент не получает ожидаемый сертификат, так как NGINX может не различить серверные блоки из-за плохой конфигурации.

  3. Неправильный возврат по умолчанию: Ваш текущий конфиг 0000-default с самоподписанным сертификатом может вызываться при запросах к несуществующим доменам. Это означает, что если клиент подключается к несуществующему домену, он может получить ответ с неверным сертификатом.

  4. Ошибки в конфигурации Certbot: Если Certbot не корректно настроен для обновления конфигурации после обновления сертификатов, это также может привести к тому, что старые или неверные сертификаты будут продолжать использоваться.

Рекомендации по исправлению проблемы

  1. Проверка конфигурации NGINX: Используйте команду nginx -t, чтобы убедиться, что конфигурация корректна. Это поможет выявить ошибки в конфигурации, которые могут повлиять на подачу сертификатов.

  2. Управление приоритетами серверов: Убедитесь, что блоки для ваших доменов с SSL имеют указание listen в правильной последовательности. Например, задайте их как listen 443 ssl; перед другими блоками.

  3. Улучшите обработку запросов на 80 порту: Обеспечьте, чтобы у каждого из ваших доменов был соответствующий конфиг на 80 порту, который правильно перенаправляет на HTTPS. Рассмотрите возможность использования return 301 https://$host$request_uri; для всех ваших доменов.

  4. Проверка обновлений Certbot: Регулярно ожидайте интеграцию вашего настройки с Certbot. Проверьте, чтобы у вас была последняя версия Certbot, и убедитесь, что межсерверные соединения обновляются корректно.

  5. Пересмотрите конфигурацию блоков SSL: Убедитесь, что SSL-сертификаты правильно ссылаются на каждый конкретный домен, без дублирования server_name.

Пример исправленной конфигурации для сервера:

server {
    listen 80;
    server_name sub.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name sub.example.com;

    ssl_certificate /etc/letsencrypt/live/sub.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub.example.com/privkey.pem;

    location / {
        # Ваши настройки
    }
}

Заключение

Следуя вышеупомянутым рекомендациям, вы сможете значительно снизить вероятность возникновения ошибок при подаче SSL-сертификатов для ваших клиентов. Для достижения наилучшего результата, тестируйте конфигурацию на каждом этапе и ведите журнал изменений для возможного анализа причин возникновения ошибок в будущем. Это позволит вам обеспечивать надежность и безопасность для всех ваших пользователей и клиентов.

Оцените материал
Добавить комментарий

Капча загружается...