Nginx ходит к upstream по HTTPS: включаем SNI и проверку сертификата

Внешний HTTPS сайта работает, но после перевода backend на HTTPS Nginx возвращает 502. Клиентский сертификат сайта не объясняет эту ошибку: между Nginx и backend создаётся отдельное TLS-соединение. У него собственные имя сервера, доверенные центры и параметры проверки.

Опишите идентичность backend отдельно

upstream backend_tls {
    server 10.20.0.15:8443;
}

server {
    listen 8080;
    server_name app.example;
    location / {
        proxy_pass https://backend_tls;
        proxy_ssl_server_name on;
        proxy_ssl_name backend.internal.example;
        proxy_ssl_verify on;
        proxy_ssl_trusted_certificate /etc/nginx/backend-ca.pem;
        proxy_set_header Host backend.internal.example;
    }
}

Это фрагмент контекста http для учебной проверки входа по 8080. TLS-терминация внешнего входа настраивается отдельно. Группа upstream задаёт сетевой адрес. proxy_ssl_name задаёт имя, по которому проверяется сертификат backend и которое передаётся как SNI при включённом server_name.

Host относится к HTTP после завершения TLS. Его значение может отличаться от TLS-имени, если этого требует контракт приложения. В простом примере они совпадают. Одна настройка Host не заменяет SNI: выбор сертификата на backend происходит раньше обработки HTTP-заголовков.

Задайте доверие явно

В стандартной конфигурации proxy_ssl_verify выключен. Само наличие https в proxy_pass не означает проверенную подлинность upstream. Включите проверку и укажите утверждённый набор CA. Конечный сертификат backend должен содержать backend.internal.example, быть действующим и иметь пригодную цепочку.

Проверьте глубину цепочки proxy_ssl_verify_depth под используемый центр и сертификаты. Если она недостаточна для вашей иерархии, проверка может завершиться ошибкой при правильном корне. Не увеличивайте значение произвольно вместо изучения фактической цепочки: сначала получите её с того же сетевого участка.

Разберите причину 502 по журналу

Ошибка handshake, несовпадение имени и невозможность проверить издателя — разные ситуации. Сопоставьте запись error log со временем внешнего запроса. Затем выполните строгую проверку backend с машины Nginx, задав нужное server name и CA. Это поможет отделить серверную цепочку от параметров самого прокси.

openssl s_client -connect 10.20.0.15:8443 -servername backend.internal.example -verify_hostname backend.internal.example -CAfile /etc/nginx/backend-ca.pem -verify_return_error

Например, сообщение о несовпадении имени при сертификате на backend.internal.example может появиться, если Nginx проверяет имя группы backend_tls. Сетевое соединение здесь уже возможно, поэтому менять IP не требуется: задайте ожидаемую идентичность через proxy_ssl_name. Если строгий вызов тоже отвергает имя, проверьте SAN самого сертификата и правильность выбранного backend.

Другой результат — невозможность построить цепочку до доверенного издателя. Сравните присланные intermediate с CA-файлом и утверждённой иерархией организации. Исправлением будет полноценная цепочка на backend либо правильный набор доверия у Nginx. Выключение verify лишь скроет причину и лишит второй участок проверки подлинности.

Если прямое соединение с указанным именем и CA работает, проверьте фактически применённую конфигурацию Nginx. Возможно, запрос попадает в другой location или унаследовал иное значение. Если backend требует mTLS, дополнительно нужны клиентские сертификат и ключ прокси; это отдельная аутентификация, которую приведённый пример не задаёт.

Перед применением проверьте конфигурацию через nginx -t. После согласованного включения выполните запрос к внешнему входу и подтвердите обращение к нужному backend. На тестовом стенде полезно проверить, что заведомо неподходящее имя приводит к отказу: так видно, что проверка upstream действительно включена.

Разбирайте каждый сетевой участок сервиса отдельно. Откройте программу Linux и Bash для DevOps-инженеров. Практика сети, DNS и HTTP поможет связать параметры клиента, прокси и приложения в последовательную диагностику.

Ещё по теме

Продолжить на практике

  • Linux и Bash для DevOps-инженеров ↗

    Linux для работы с серверами: процессы, права, systemd, сеть, диски и логи. Автоматизируйте повседневные задачи на Bash и разберите типичные сбои сервиса — от занятого порта до переполненного диска.