Шифрование само по себе ничего не гарантирует: можно идеально зашифровать разговор с мошенником. Поэтому в рукопожатии сервер предъявляет сертификат — документ, в котором сказано: «ключ такой-то принадлежит сайту такому-то», и подпись того, кто это проверил. Замок в адресной строке означает, что браузер проверил этот документ и подпись под ним. Посмотрим, что именно он проверяет — на сертификате этого сайта.

Это восьмая часть цикла «Что происходит, когда открываешь сайт».

Что прислал сервер

$ echo | openssl s_client -connect alekseychikun.ru:443 -servername alekseychikun.ru
Certificate chain
 0 s:CN=alekseychikun.ru
   i:C=US, O=Let's Encrypt, CN=YR2
   a:PKEY: RSA, 4096 (bit); sigalg: sha256WithRSAEncryption
   v:NotBefore: Sep 30 17:48:20 2026 GMT; NotAfter: Dec 29 17:48:19 2026 GMT
 1 s:C=US, O=Let's Encrypt, CN=YR2
   i:C=US, O=ISRG, CN=Root YR
   v:NotBefore: Sep  3 00:00:00 2025 GMT; NotAfter: Sep  2 23:59:59 2028 GMT
 2 s:C=US, O=ISRG, CN=Root YR
…
Verify return code: 0 (ok)

s: — кому выдан сертификат (subject), i: — кто его подписал (issuer). Сертификат сайта подписан промежуточным центром Let’s Encrypt «YR2», тот — корневым «Root YR». Каждая строка цепочки подписана следующей.

сайт CN=alekseychikun.ru 30.09 → 29.12.2026 RSA 4096 промежуточный Let’s Encrypt YR2 до 02.09.2028 корневой ISRG Root в хранилище ОС или браузера подписалподписал Сервер присылает свой сертификат и промежуточные. Доверенный корень — только из хранилища.
Цепочка доверия: браузер идёт от сертификата сайта к корню, проверяя подпись на каждом шаге.

Почему не подписывают сразу корнем

Закрытый ключ корневого центра — самое ценное, что у центра есть: если он утечёт, придётся менять доверие во всех браузерах мира. Поэтому корень хранят отключённым от сети и используют редко — только чтобы подписать промежуточные сертификаты. А сертификаты сайтов каждый день выдают промежуточные. Утечёт промежуточный ключ — его отзовут и выпустят новый, корень останется.

Что проверяет браузер

  1. Имя. Адрес в строке должен быть в списке имён сертификата. Смотрят не на CN, а на поле Subject Alternative Name: у этого сайта там alekseychikun.ru и www.alekseychikun.ru. Зайдёте на третье имя — будет ошибка, даже если сервер тот же;
  2. Срок. Текущее время между NotBefore и NotAfter. Отсюда же классическая ошибка с неправильными часами на компьютере: сертификаты «ещё не действуют» у всех сайтов сразу;
  3. Подписи по цепочке вплоть до корня, которому браузер доверяет. Корни лежат в хранилище операционной системы или браузера — от сервера корень браузер не принимает: иначе любой мог бы прислать «свой корень»;
  4. Подпись рукопожатия (CertificateVerify из прошлой части): сервер доказывает, что у него есть закрытый ключ от предъявленного сертификата. Без этого сертификат можно было бы просто скопировать — он же публичный;
  5. Не отозван ли и записан ли в публичные журналы прозрачности (Certificate Transparency). Каждый выпущенный сертификат попадает в открытые журналы, и подделку можно обнаружить.

90 дней — это нормально

Сертификат этого сайта выпущен 30 сентября и действует до 29 декабря — ровно 90 дней. Let’s Encrypt выдаёт короткие сертификаты специально: их продлевает автоматика, и утёкший ключ перестаёт работать быстро. У нас продлением занимается сам прокси, за месяц до конца срока. Обратная сторона — если автоматика сломалась, узнаете вы об этом через считаные недели, и лучше раньше: заведите проверку срока по расписанию.

# сколько дней осталось
end=$(echo | openssl s_client -connect example.ru:443 -servername example.ru 2>/dev/null \
      | openssl x509 -noout -enddate | cut -d= -f2)
echo $(( ( $(date -d "$end" +%s) - $(date +%s) ) / 86400 )) дней

Неполная цепочка: браузер работает, скрипты — нет

Частая поломка: сервер присылает только сертификат сайта, без промежуточного. Браузеры это часто прощают — они запоминают промежуточные сертификаты с других сайтов или докачивают их по ссылке из сертификата. А curl, Python, Node и интеграции между серверами — нет, они честно падают с ошибкой проверки. Выглядит как «у нас всё открывается, а у партнёров интеграция не работает».

# сколько сертификатов присылает сервер — должно быть 2 и больше
echo | openssl s_client -connect example.ru:443 -servername example.ru -showcerts 2>/dev/null | grep -c 'BEGIN CERTIFICATE'

Подключать в сервер надо файл fullchain (сертификат и промежуточные), а не голый сертификат. При покупном сертификате промежуточный скачивается по ссылке из поля Authority Information Access самого сертификата.

Почему замок не значит «сайт честный»

Сертификат Let’s Encrypt подтверждает одно: тот, кто его получил, управляет этим доменом. Не то, что за доменом стоит настоящая компания, и не то, что сайт не мошеннический. Фишинговый сайт на похожем имени получит такой же замок за пару минут. Замок — про то, что разговор с этим именем никто не подслушивает и не подменяет. А имя проверяйте глазами.

Сайт открывается в браузере, а интеграции падают на сертификате?

Пришлите адрес — проверю цепочку, сроки и имена и подскажу, какой файл подключить.

· полезно?
АЧ
Алексей Чикун веб-разработчик, команда TRIOHEAD

Делаю сайты и сервисы целиком: от вёрстки до сервера. Пишу о том, что проверил на своих проектах.

Комментарии

// загружаю комментарии…

Комментарии публикуются после проверки. Ссылки и HTML не принимаются.