Зачем TLS — три гарантии безопасности и что без него
В 2026 году замок в адресной строке браузера — это норма. Любой публичный сайт идёт через HTTPS, любой API использует TLS. Поисковики наказывают сайты без HTTPS, а Chrome помечает их как «Not Secure». Но многие разработчики используют TLS не задумываясь, через https:// в URL — и не понимают, что именно он защищает и от каких атак.
В этом уроке разбираем, что такое TLS, какие три гарантии он даёт, и что происходит без TLS на реальных сетях. Эти знания критически важны: если вы интегрируете API, делаете backend, разворачиваете сервер — решения про TLS вы принимаете каждый день.
TLS — наследник SSL
Сначала немного истории. В 1990-х Netscape придумал SSL (Secure Sockets Layer) — протокол шифрования над TCP для своего браузера. Версии 1.0 (так и не выпущена — слишком много дыр), 2.0 (1995, быстро признана небезопасной), 3.0 (1996). В 1999 году IETF переименовала и стандартизировала — так появился TLS 1.0. Дальше: TLS 1.1 (2006), TLS 1.2 (2008, доминировал десятилетиями), TLS 1.3 (2018, текущий стандарт).
В народе термины «SSL» и «TLS» часто смешивают: «SSL-сертификат», «SSL handshake». На самом деле речь почти всегда о TLS. SSL 2.0 и 3.0 формально считаются deprecated, в производстве не используются. TLS 1.0 и 1.1 тоже deprecated с 2020 года — их выключают браузеры и сервера. Реально используются TLS 1.2 и TLS 1.3.
Три гарантии TLS
TLS даёт три фундаментальные гарантии:
- Confidentiality (конфиденциальность) — никто между клиентом и сервером не может прочитать содержимое.
- Integrity (целостность) — никто не может изменить данные по дороге незаметно.
- Authentication (аутентификация сервера) — клиент уверен, что говорит с тем сервером, к которому подключился, а не с подменным.
Каждая гарантия защищает от своего класса атак. Разберём по очереди.
Confidentiality: что без неё
Без TLS HTTP-трафик — это plain text. Открываете http://example.com/login — ваш логин и пароль летят по сети в открытом виде. Кто может прочитать?
Реальные сценарии без шифрования:
- В аэропорту атакующий поднимает fake WiFi «Free_Airport_WiFi». Кто-то подключается, заходит в почту — логин и пароль украдены.
- В большой корпоративной сети ваш сосед запускает Wireshark и читает все ваши HTTP-запросы.
- На национальном уровне государство видит всё, что вы ищете в Google (если бы google был HTTP).
TLS делает все эти атаки бесполезными. Перехваченный трафик — это случайные байты. Без ключей расшифровать невозможно (даже квантовому компьютеру с современными шифрами — займёт годы).
Как именно? TLS использует симметричное шифрование для данных (быстрое, AES-256), но ключ обменивают через асимметричное шифрование в handshake. Подробно — в следующем уроке.
Integrity: защита от tampering
Допустим, вы скачиваете обновление приложения по HTTP. Атакующий между вами и сервером может модифицировать ответ на лету: подменить .exe на свой с вирусом, изменить JS-код, который придёт в браузер.
Без TLS это тривиально. С TLS — математически невозможно.
TLS подписывает каждый отправленный блок данных через MAC (Message Authentication Code). Грубо: посылается не «байты», а «байты + криптографический хэш этих байт с секретным ключом». Получатель проверяет хэш — если изменилось хоть один бит, проверка фейлится. Соединение разрывается.
В TLS 1.3 используется AEAD (Authenticated Encryption with Associated Data) — шифрование + MAC в одном алгоритме (AES-GCM или ChaCha20-Poly1305). Это гарантирует, что любая модификация будет немедленно обнаружена.
Без integrity check много чего страшного. Например, ISP в некоторых странах внедряли рекламу в HTTP-страницы, не зная об этом. Атакующий мог инжектировать в HTML вашего банка скрипт, который крадёт пароли. С TLS — ничего этого невозможно. Tampering = разрыв соединения.
Authentication: «вы реально говорите с github.com?»
Допустим, у вас идеальная конфиденциальность и целостность. Но что, если вы подключились не к настоящему github.com, а к подменному серверу, который собирает ваши пароли?
Сценарии:
- DNS poisoning. Атакующий подменил DNS-ответ. Вы пишете
github.com, попадаете на чужой IP. - BGP hijack. На уровне маршрутизации атакующий объявил, что путь к IP GitHub’а идёт через него. Ваш трафик едет на чужой сервер.
- Compromised CA. Атакующий выпустил сертификат на
github.comчерез скомпрометированный certificate authority.
Без аутентификации все эти атаки приводят к классической MITM (Man-In-The-Middle) — атакующий принимает ваш запрос, делает свой к настоящему GitHub, проксирует ответ, по дороге читая все ваши логины и пароли.
TLS защищает через сертификаты. Когда сервер представляется как github.com, он показывает сертификат, подписанный известным Certificate Authority (CA) — доверенной организацией, чей публичный ключ предустановлен в ваш браузер/ОС.
Что валидирует браузер:
- Подпись. Каждая ступень цепочки подписана криптографически. Атакующий не может подделать без секретного ключа CA.
- Имя. Сертификат содержит
Subject Alternative Name. Браузер сверяет с доменом, на который подключились. - Срок действия. Сертификат имеет
notBeforeиnotAfter. Просроченный — отказ. - Revocation. Через OCSP / CRL проверяется, не отозван ли сертификат. (На практике многие браузеры это пропускают.)
- Trust root. Цепочка должна заканчиваться на CA, которой браузер доверяет.
Если хоть что-то не сошлось — браузер показывает страшную страницу с предупреждением. Это сделано намеренно — чтобы пользователь не мог случайно проигнорировать.
‘Я просто кликну Advanced -> Continue, и игнорирую warning’ — ужасная практика. В 99% случаев warning означает реальную атаку или серьёзную проблему с сервером. Никогда не учите пользователей делать так. Лучше потратить время и исправить причину warning’а на сервере.
Что НЕ делает TLS
Важно понять, что TLS не защищает:
-
Метаданные. TLS прячет содержимое, но не сам факт connection. Видно, что вы подключились к
github.com, по DNS-запросу и SNI (Server Name Indication в TLS handshake). Видно объём данных, тайминги. -
Конечный сервер. Если сервер взломан — TLS бесполезен, данные утекают в открытом виде с сервера. TLS защищает только канал, не endpoints.
-
Клиента от вредоносного скрипта. TLS не проверяет, что страница «безопасна». Можно по HTTPS загрузить страницу с XSS-уязвимостью.
-
Forward secrecy в TLS 1.2 с RSA key exchange. Если атакующий записал зашифрованный трафик и позже украл private key сервера — может расшифровать весь архив. В TLS 1.3 forward secrecy включён по умолчанию.
-
Целостность DNS. Резолв доменного имени в IP — отдельная стадия, и она может быть атакована. DoH (DNS over HTTPS) частично закрывает это.
-
Конфиденциальность от государства, если оно может legitimately заставить CA выдать сертификат. Это реальная политическая проблема (Kazakhstan trying to MITM HTTPS в 2019).
Mixed content — частая ошибка
Когда страница загружается по HTTPS, а внутри ссылается на http://-ресурс (картинку, скрипт, iframe) — это mixed content. Браузер:
- Для passive content (картинки) — может загрузить, но снимает «зелёный замок».
- Для active content (скрипты, iframes, AJAX) — блокирует загрузку полностью.
Причина: если HTTPS-страница может выполнить JS, загруженный по HTTP, атакующий мог бы подменить этот JS — и выполнить произвольный код в контексте HTTPS-страницы. Чёрная дыра в безопасности.
В консоли DevTools вы увидите ошибку типа Mixed Content: blocked by browser. Решение: все ресурсы грузить по HTTPS. Или использовать protocol-relative URLs (//cdn.example.com/lib.js) — браузер сам подставит схему текущей страницы.
HSTS: «всегда HTTPS, никогда HTTP»
Сервер может попросить браузер: «помни, что я всегда доступен по HTTPS, никогда не пробуй HTTP». Делается через заголовок:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
После этого браузер на год запоминает: для этого домена — только HTTPS. Даже если пользователь напишет http://example.com, браузер сам преобразует в https.
preload означает: предложить этот домен в HSTS preload list — встроенный в браузеры список «всегда HTTPS». GitHub, Google, и многие крупные сайты в нём. Это закрывает window of vulnerability при первом visit.
Без HSTS остаётся атака: пользователь пишет example.com (без схемы), браузер пробует http первым, атакующий перехватывает и не делает редирект — остаётся на http. С HSTS — сразу HTTPS.
Реальный пример: что показывает curl
# Подключиться по HTTPS с подробным выводом TLS
curl -v https://github.com 2>&1 | head -40
# Часть вывода (упрощённо):
# * Trying 140.82.112.4:443...
# * Connected to github.com (140.82.112.4) port 443
# * ALPN: offers h2,http/1.1
# * TLSv1.3 (OUT), TLS handshake, Client hello (1):
# * TLSv1.3 (IN), TLS handshake, Server hello (2):
# * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
# * TLSv1.3 (IN), TLS handshake, Certificate (11):
# * TLSv1.3 (IN), TLS handshake, CERT verify (15):
# * TLSv1.3 (IN), TLS handshake, Finished (20):
# * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
# * Server certificate:
# * subject: CN=github.com
# * start date: ...
# * expire date: ...
# * issuer: CN=DigiCert TLS RSA SHA256 2020 CA1
# * SSL certificate verify ok.
Что мы видим:
- TLS 1.3 версия
- Полный handshake (Client hello -> Server hello -> Certificate -> …)
- Cipher: AES-128-GCM
- Subject CN=github.com (тот домен, к которому подключались)
- Issuer: DigiCert (intermediate CA)
- Проверка прошла:
verify ok
Это и есть «здоровый» TLS-обмен. Если что-то не так — увидите ошибку с подробностями.
Попробуй сам
# 1. Сравнить HTTP vs HTTPS
curl -v http://httpbin.org/get 2>&1 | head -10
curl -v https://httpbin.org/get 2>&1 | head -20
# Видно, что для HTTPS добавляется TLS-handshake
# 2. Посмотреть TLS-сертификат сервера
openssl s_client -connect github.com:443 -servername github.com 2>/dev/null < /dev/null | grep -A 1 'subject\|issuer\|verify'
# 3. Посмотреть, какие TLS-версии поддерживает сервер
openssl s_client -connect example.com:443 -tls1_2 2>&1 | grep -E 'Protocol|Cipher'
openssl s_client -connect example.com:443 -tls1_3 2>&1 | grep -E 'Protocol|Cipher'
# 4. Попробовать подключиться к серверу с устаревшим TLS
openssl s_client -connect example.com:443 -tls1 2>&1 | head -5
# Сервер должен отказать -- TLS 1.0 deprecated
# 5. Bad certificate -- посмотрите страницы тестирования
# https://badssl.com/ -- сайт со списком намеренно сломанных TLS-сертификатов
# expired.badssl.com -- просроченный
# wrong.host.badssl.com -- неверное имя host
# self-signed.badssl.com -- самоподписанный
# Попробуйте открыть в Chrome -- увидите страшные warnings
# 6. SSL Labs analysis
# https://www.ssllabs.com/ssltest/ -- введите домен, получите подробный отчёт о TLS:
# - какие версии TLS поддерживаются
# - какие cipher suites
# - какие сертификаты в цепочке
# - какие уязвимости (BEAST, POODLE, Heartbleed)
# - общая оценка A-F
Что вы должны вынести
- TLS — стандарт шифрования веб-трафика. В 2026 году актуальны TLS 1.2 и TLS 1.3.
- Три гарантии: confidentiality (никто не читает), integrity (никто не меняет), authentication (вы говорите с правильным сервером).
- Без TLS HTTP-трафик читается любым на пути. Это не теория — реальные атаки происходят каждый день в открытых WiFi.
- Authentication работает через сертификаты + цепочка доверия CA.
- TLS не защищает метаданные (DNS, SNI), не защищает endpoint, не заменяет XSS-фильтры.
- HSTS — механизм «всегда HTTPS», защищает от downgrade-атак.
- Mixed content (HTTP-ресурсы на HTTPS-странице) блокируется браузером — надо устранять.