Перейти к содержимому
EVI Solutions

Ошибка SSL сертификата в коде: как распознать и исправить

Средне 20 мин Обновлено:

Краткий ответ

Ошибка SSL сертификата в коде чаще всего возникает из-за истечения срока действия сертификата, недоверия к цепочке сертификатов или неверного hostname. Решается проверкой дат, обновлением хранилища CA и правильной настройкой клиента, а не отключением проверки.

Как проявляется проблема

  • Приложение выдаёт ошибку `CERT_HAS_EXPIRED` или `certificate has expired`
  • Появляется `UNABLE_TO_VERIFY_LEAF_SIGNATURE` или `self signed certificate in certificate chain`
  • `ERR_TLS_CERT_ALTNAME_INVALID` из-за неверного hostname
  • Соединение работает в браузере, но не в коде
  • Ошибка возникает только в одном окружении (например, staging)

Частые причины

Истёк срок действия сертификата

Срок действия сертификата на сервере истёк, или клиент сохранил в кэше более старую цепочку. Проверьте дату действия и обновите кэш.

Недоверенный издатель (CA)

Клиент не распознаёт CA, выдавший сертификат, что часто бывает с внутренними или самоподписанными сертификатами. Необходимо добавить CA в хранилище доверия.

Неверный hostname

Сертификат выдан для другого имени (например, `example.com` вместо `api.example.com`). Проверьте поле SAN и способ обращения клиента.

Неверная цепочка сертификатов

Сервер не отправляет полные промежуточные сертификаты, поэтому клиент не может построить цепочку до корня. Решается правильной настройкой сервера.

Неверное время на системе

Если часы на компьютере или в контейнере неверны, действительный сертификат выглядит как истёкший или ещё не вступивший в силу.

Пошаговое решение

  1. 1

    Прочитайте точное сообщение об ошибке

    В логе найдите код ошибки (например, CERT_HAS_EXPIRED, UNABLE_TO_VERIFY_LEAF_SIGNATURE, ERR_TLS_CERT_ALTNAME_INVALID). Разные коды указывают на разные причины, поэтому не пропускайте этот шаг.

  2. 2

    Проверьте дату действия сертификата

    Откройте сайт в браузере и нажмите на замок рядом с адресом, затем в деталях сертификата посмотрите дату начала и окончания действия. Или в терминале выполните openssl s_client -connect host:443 -servername host -text и посмотрите поля Not Before и Not After.

  3. 3

    Проверьте совпадение hostname

    В том же выводе openssl найдите поле Subject Alternative Name. Оно должно содержать имя, которое вы используете в коде. Если вы обращаетесь по IP-адресу, сертификат, вероятно, будет недействительным.

  4. 4

    Обновите хранилище CA в системе

    В Windows (от имени администратора) выполните certutil -generateSSTFromWU roots.sst, затем certutil -addstore root roots.sst; отдельный сертификат добавьте с помощью certutil -addstore root sertifikat.crt. Добавляйте только тот CA, которому доверяете. В Linux (Debian/Ubuntu) sudo update-ca-certificates, а в macOS дважды щёлкните по .crt, добавьте в связку ключей System и установите Always Trust для этого CA.

  5. 5

    Добавьте внутренний CA в код

    Если вы используете внутренний или самоподписанный сертификат, в коде передайте путь к файлу CA. В Node.js это опция ca в https.request или переменная NODE_EXTRA_CA_CERTS=/путь/к/ca.crt. В Python requests используйте verify='/путь/к/ca.crt'.

  6. 6

    Исправьте цепочку на сервере

    Убедитесь, что сервер отправляет полные цепочки сертификатов. В конфигурации Nginx ssl_certificate должен содержать сертификат сервера и список промежуточных сертификатов, причём сертификат сервера должен быть первым. Проверьте с помощью openssl s_client -showcerts -servername host -connect host:443.

  7. 7

    Проверьте время на системе

    В Windows (от имени администратора) w32tm /resync, в Linux timedatectl и sudo systemctl restart systemd-timesyncd. В контейнерах Docker проверьте, синхронизировано ли время с хостом.

  8. 8

    Временно обойдите проверку только при разработке

    Если нужно продолжить разработку, временно отключите проверку, но никогда в продакшене. В Node.js NODE_TLS_REJECT_UNAUTHORIZED=0 (только локально), в Python verify=False с urllib3.disable_warnings(). Обязательно удалите перед коммитом.

Если ничего не помогает: изолируйте проблему

Если ошибка сохраняется, создайте минимальный воспроизводимый пример: скрипт, который только устанавливает TLS-соединение с тем же хостом. Протестируйте его из разных сетей и на разных компьютерах. Сравните вывод openssl s_client с тем, что видит клиент. Проверьте, не перехватывают ли трафик прокси или антивирус, изменяя сертификат. В Docker проверьте, установлены ли в контейнере CA-сертификаты (пакет ca-certificates). Если проблема только в продакшене, сравните конфигурацию окружений и версии клиентов. Для сложных цепочек и mTLS используйте такие инструменты, как openssl verify и curl -v, чтобы увидеть точный поток.

Как избежать повторения

  • Регулярно проверяйте даты истечения сертификатов и устанавливайте напоминания
  • Используйте автоматическое обновление (например, Let's Encrypt) и тестируйте обновление
  • При разработке используйте `mkcert` для локальных сертификатов вместо постоянного отключения проверки
  • Никогда не коммитьте код, содержащий `rejectUnauthorized: false` или `verify=False`

Когда лучше обратиться к специалисту

Если ошибка связана с mTLS, сложными цепочками сертификатов или возникает только на продакшен-серверах, обратитесь в IT-поддержку, чтобы изолировать проблему без риска прерывания работы.

Разработка ПО и продуктов · Приложения на заказ, SaaS и MVP за 4-8 недель

Частые вопросы

Почему у меня возникает `self signed certificate in certificate chain`?

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

Безопасно ли отключать проверку сертификата в коде?

Нет, отключение проверки (`rejectUnauthorized: false` или `verify=False`) делает приложение уязвимым к атакам перехвата. Используйте его только временно при локальной разработке и никогда в продакшене.

Как проверить, какой сертификат сервер на самом деле отправляет?

Выполните `openssl s_client -connect host:443 -servername host -showcerts -text`. В выводе вы увидите все сертификаты в цепочке, а текстовая часть показывает детали сертификата сервера, включая даты действия и поля SAN.

Поделиться
Не нашли решение?ИИ-помощник работает 24/7. Опишите проблему или отправьте скриншот ошибки и получите инструкцию для вашего случая.Спросить ИИ-помощника