Проверка TLS своего сайта: openssl s_client и curl вместо онлайн-сканеров

0
11
Обложка статьи: Проверка TLS своего сайта: openssl s_client и curl вместо онлайн-сканеров

Онлайн-проверки TLS удобны, но они проверяют сайт снаружи, показывают не всё и не годятся для внутренних сервисов. Три команды, openssl s_client, openssl x509 и curl, отвечают на основные вопросы за минуту: действует ли сертификат и кому он выдан, какие версии протокола принимает сервер, полная ли цепочка и перенаправляется ли HTTP на HTTPS. Ниже набор проверок с ожидаемыми результатами; примеры выводов получены на настоящем сервере и показаны с заменой имён на example.com.

Статья опирается на логику направления «Сетевая безопасность» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Проверяйте только свои сервисы или с разрешения владельца. Версия OpenSSL влияет на формат вывода: примеры получены на OpenSSL 3.0.

Что должно получиться

Уровень Что это значит на практике
2. Гигиенический Публичные сервисы защищены и контролируются, правила пересматриваются; сертификаты действуют и отслеживаются

Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.

1. Сертификат: кому выдан и до какой даты

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

Ключ -servername обязателен для серверов, которые держат несколько сайтов на одном адресе (SNI). Без него вы можете увидеть сертификат по умолчанию. Пример результата:

subject=CN = example.com
issuer=C = US, O = Let's Encrypt, CN = R10
notBefore=Oct  6 16:54:32 2026 GMT
notAfter=Jan  4 16:54:31 2027 GMT
X509v3 Subject Alternative Name: 
    DNS:example.com, DNS:*.example.com

Что смотреть: имя в subject и Subject Alternative Name должно покрывать проверяемое имя, notAfter — срок действия; запас менее 14 дней означает, что автоматическое продление не работает или вот-вот сломается. Срок до окончания можно проверить автоматически: openssl x509 -checkend 1209600 -noout вернёт код 0, если сертификат действует ещё минимум 14 дней (1209600 секунд). Готовый скрипт на несколько сайтов: Python и Bash для ИБ.

2. Цепочка и доверие

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | grep -E "^New,|Verify return code|Protocol|Cipher is"
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
    Protocol  : TLSv1.3
    Verify return code: 0 (ok)

Что смотреть: Verify return code: 0 (ok) означает, что цепочка до доверенного корневого сертификата построена. Коды 20 и 21 («unable to get local issuer certificate», «unable to verify the first certificate») указывают, что сервер не отдаёт промежуточный сертификат: настройте полную цепочку (в nginx это fullchain.pem). Код 10 — сертификат просрочен, код 18 или 19 — самоподписанный. Для просмотра всех сертификатов цепочки добавьте опцию -showcerts.

3. Версии протокола

echo | openssl s_client -connect example.com:443 -servername example.com -tls1_3 2>/dev/null | grep -E "Protocol|Cipher is"
echo | openssl s_client -connect example.com:443 -servername example.com -tls1_2 2>/dev/null | grep -E "Protocol|Cipher is"
echo | openssl s_client -connect example.com:443 -servername example.com -tls1_1 2>&1 | grep -E "alert|error"

Ожидаемый результат для современного сервера:

Protocol  : TLSv1.3
Cipher is TLS_AES_128_GCM_SHA256

Protocol  : TLSv1.2
Cipher is ECDHE-RSA-AES256-GCM-SHA384

...error:0A00042E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version:...SSL alert number 70

Первая и вторая проверки показывают принятые версии и выбранные шифры, третья — отказ: сообщение tlsv1 alert protocol version означает, что сервер не поддерживает TLS 1.1, это правильно. Если TLS 1.1 или 1.0 принимается, отключите их в настройке сервера: безопасная настройка nginx. Если библиотека OpenSSL на вашей машине собрана без поддержки старых протоколов, результат отказа будет сообщением о локальной ошибке, а не ответом сервера: в таком случае проверьте другим инструментом.

Шифры, принимаемые в TLS 1.2, можно перебрать опцией -cipher; смысл — убедиться, что слабые наборы (RC4, 3DES, экспортные, без шифрования) недоступны. Для полного перебора используйте специализированные сканеры (например, testssl.sh или sslyze): они тоже запускаются локально и показывают полный отчёт.

4. HTTP, перенаправление и HSTS

curl -sI http://example.com/ | head -4
curl -sI https://example.com/ | grep -iE "^HTTP|strict-transport|^server"
HTTP/1.1 308 Permanent Redirect
Location: https://example.com/

HTTP/2 200
server: nginx
strict-transport-security: max-age=15552000

Что смотреть: HTTP перенаправляется на HTTPS кодом 301 или 308, на HTTPS присутствует HSTS, версия веб-сервера скрыта, протокол HTTP/2. Если HSTS нет, его стоит добавить после проверки работы всего сайта по HTTPS. Утечка версии в заголовке Server и заголовки X-Powered-By — повод поправить конфигурацию: убрать такие заголовки несложно, и это снижает информативность для сканеров.

5. Проверка конкретного ответа curl

curl -sv https://example.com/ -o /dev/null 2>&1 | grep -E "SSL connection|subject|expire date|issuer"
curl -s --tlsv1.2 --tls-max 1.2 -o /dev/null -w "%{http_code}\n" https://example.com/
curl -sI --resolve example.com:443:203.0.113.10 https://example.com/ | head -3

Первая команда показывает согласованный протокол, шифр и данные сертификата в выводе curl. Вторая принудительно ограничивает версию TLS: код 200 означает, что сервер принимает TLS 1.2. Третья проверяет конкретный сервер за балансировщиком или до смены DNS: --resolve подставляет нужный адрес для имени без изменения DNS.

6. Внутренние сервисы

Те же команды работают для служб на нестандартных портах: почта (-starttls smtp -connect mail.example.com:587), LDAP, базы данных с TLS. Для внутренних центров сертификации задайте корневой сертификат: openssl s_client -CAfile ca.pem -connect ..., иначе проверка покажет, что цепочка не доверена.

Типовые проблемы

Симптом Причина и что делать
Браузер доверяет, а openssl — нет (код 20 или 21) Сервер не отдаёт промежуточный сертификат, браузер дозагружает его сам. Настройте полную цепочку на сервере
Сертификат не совпадает с именем Нет SNI или не то имя в сертификате. Проверьте -servername и список имён в SAN
Сертификат продлили, а сервер показывает старый Не перезагружен веб-сервер или несколько узлов за балансировщиком. Перезагрузите службу и проверьте каждый узел (--resolve)
TLS 1.1 принимается Не отключены старые протоколы. Задайте ssl_protocols TLSv1.2 TLSv1.3 и перезагрузите
HTTP не перенаправляется Нет серверного блока на порту 80 или он отдаёт сайт. Добавьте перенаправление

Регулярная проверка

  • Раз в сутки проверяйте срок сертификатов всех сервисов и оповещайте за 14 дней: мониторинг в Zabbix или скрипт по расписанию: проверка доступности порта в Zabbix.
  • После каждого изменения конфигурации веб-сервера выполняйте проверки из статьи.
  • Включите проверку TLS в реестр активов: срок сертификатов, ответственный, способ продления: реестр ИТ-активов.

Где это в модели зрелости

Материал относится к направлению «Сетевая безопасность» (материалы направления, карта зрелости). Контроль конфигурации публичных сервисов, включая сертификаты и версии протоколов, входит в требования к уровню 2.

Как проверить

  1. Для каждого публичного сервиса сертификат действует не менее 14 дней, имя совпадает, цепочка полная (код 0).
  2. Принимаются только TLS 1.2 и 1.3, TLS 1.1 отклоняется.
  3. HTTP перенаправляется на HTTPS, на HTTPS включён HSTS.
  4. Срок сертификатов под автоматическим контролем с оповещением.

Источники

  • Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
  • Документация OpenSSL: s_client, x509: docs.openssl.org.
  • Документация curl: curl.se.
  • NIST SP 800-52 Rev. 2, Guidelines for the Selection, Configuration, and Use of TLS Implementations: csrc.nist.gov. Международная практика, не российский норматив.

Оставьте свой ответ