Skip to content
← Все статьи

Неполная цепочка SSL-сертификата: как найти и исправить incomplete chain

Неполная цепочка SSL-сертификата: как найти и исправить incomplete chain

Incomplete certificate chain — это ситуация, когда сервер отдаёт только собственный листовой сертификат, без промежуточных (intermediate). Настольные браузеры часто умеют «дотягивать» цепочку из своего кеша, но мобильные клиенты, старые библиотеки, curl, Java-приложения и API документацию-клиенты этого не делают — и отваливаются с ошибкой «unable to get local issuer certificate». В статье разберём, как диагностировать проблему и правильно собрать fullchain.

Почему цепочка важна

Цепочка доверия — это иерархия сертификатов от вашего листового до корневого CA, которому доверяет клиент. Обычно она выглядит так:

Root CA (встроен в trust store клиента)
  └─ Intermediate CA 1
      └─ Intermediate CA 2 (опционально)
          └─ Leaf (ваш сертификат на example.com)

Клиент должен суметь дойти от вашего листового сертификата до какого-то корневого, которому он доверяет. Если сервер не отдаёт intermediate — клиент не может построить путь. Root CA в цепочке отправлять не обязательно (и не рекомендуется) — клиенты его и так знают.

Симптомы неполной цепочки

Диагностика

Первая проверка:

openssl s_client -connect example.com:443 -servername example.com -showcerts < /dev/null 2>/dev/null \
    | grep "^-\|^ *s:\|^ *i:"

Правильный вывод должен содержать минимум две записи s: (subject) и i: (issuer):

s:CN=example.com
i:C=US, O=Let's Encrypt, CN=R3
s:C=US, O=Let's Encrypt, CN=R3
i:C=US, O=Internet Security Research Group, CN=ISRG Root X1

Если есть только один блок s:/i: — цепочка неполная. Также протестируйте через SSL Checker enterno.io или SSL Labs — они чётко скажут «chain issues».

Исправление: собрать fullchain.pem

Для Let's Encrypt всё уже готово — используйте fullchain.pem, он уже содержит leaf + intermediate:

# Правильно
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

# Неправильно (только leaf)
ssl_certificate /etc/letsencrypt/live/example.com/cert.pem;

Для коммерческих CA вы получаете архив с несколькими файлами: cert.crt (ваш), intermediate.crt, иногда root.crt. Объедините leaf и intermediate в правильном порядке:

cat cert.crt intermediate.crt > fullchain.crt
# Ваш leaf — первым, intermediate — вторым
# root НЕ добавляйте

Если intermediate несколько, порядок: leaf → intermediate ближе к leaf → intermediate выше → и т.д. Перепутали порядок — клиент всё равно получит ошибку.

Конфигурация в nginx и Apache

nginx:

ssl_certificate     /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;

Apache:

SSLCertificateFile      /etc/apache2/certs/cert.crt
SSLCertificateKeyFile   /etc/apache2/certs/privkey.key
SSLCertificateChainFile /etc/apache2/certs/intermediate.crt
# Или (Apache 2.4.8+) leaf+intermediate в одном файле:
SSLCertificateFile      /etc/apache2/certs/fullchain.pem

После изменений: nginx -t && systemctl reload nginx / apachectl configtest && systemctl reload apache2.

Где взять intermediate, если его потеряли

Все современные CA публикуют intermediate-сертификаты. Способы получить:

  1. Сайт CA: у Let's Encrypt — letsencrypt.org/certificates, у Sectigo, DigiCert — аналогичные страницы.
  2. AIA (Authority Information Access): внутри сертификата есть URL на intermediate. Достанем его:
    openssl x509 -in cert.crt -noout -text | grep "CA Issuers"
    # CA Issuers - URI:http://r3.i.lencr.org/
    curl http://r3.i.lencr.org/ | openssl x509 -inform DER -out intermediate.pem
  3. crt.sh: найдите свой сертификат на crt.sh, там будет ссылка на issuer.

Автоматизация и предотвращение

Связанные проблемы

Если исправили цепочку, но ошибки остались, посмотрите:

Часто задаваемые вопросы

Включать ли root CA в fullchain.pem?

Нет. Клиент и так имеет его в trust store. Отправка root увеличивает размер handshake и ничего не добавляет.

Что делать с cross-signed intermediate для старых Android?

Используйте «long chain» от Let's Encrypt, где intermediate подписан старым DST Root CA X3. По умолчанию certbot использует короткую цепочку с ISRG Root X1 — для Android < 7.1.1 нужно форсировать --preferred-chain "ISRG Root X1".

Почему Chrome работает, а Python requests — нет?

Chrome может дотянуть intermediate из кеша AIA Fetching. Python requests использует certifi bundle, который содержит только root. Нужен полный fullchain на сервере.

Как быстро проверить с мобильного?

Используйте онлайн-сервис или сторонний SSL/TLS проверку-проверщик, который не использует ваш десктопный кеш. SSL Checker enterno.io проверяет из своего окружения — это эквивалентно «чистому клиенту».

Заключение

Incomplete chain — тихая проблема: на десктопе не видно, а мобильные пользователи и API-интеграции ломаются. Правильное решение — один раз собрать корректный fullchain.pem и поставить автомониторинг целостности. SSL Checker от enterno.io проверит цепочку за 15 секунд, а Monitors будет делать это каждые 5 минут круглосуточно. Также см. ошибки даты сертификата и handshake failed.

Path validation — RFC 5280, §6. Let's Encrypt chains — letsencrypt.org/certificates. Тест — SSL Labs.

Проверьте ваш сайт прямо сейчас

Проверить →
Другие статьи: SSL
SSL
Бесплатный SSL через Let's Encrypt: установка certbot за 10 минут
15.04.2026 · 10 просм.
SSL
Wildcard vs SAN-сертификат: когда какой выбрать в 2026
15.04.2026 · 8 просм.
SSL
Слабые cipher suites: как найти и отключить небезопасные шифры TLS
15.04.2026 · 8 просм.
SSL
Mixed Content: как найти и исправить HTTP-ресурсы на HTTPS-сайте
15.04.2026 · 8 просм.