HTTPS - это обычный HTTP, те же запросы и те же страницы, только переданные через зашифрованный туннель под названием TLS. Ещё до того, как передан первый байт страницы, браузер и сервер договариваются о секретном ключе, который никто из наблюдающих за сетью не сможет вычислить, а сервер с помощью сертификата доказывает, что он действительно тот сайт, имя которого вы набрали. После этого любой, кто находится между вами и сервером, видит лишь то, что вы подключились к определённому адресу, и примерно сколько данных прошло в каждую сторону. Страницы, формы, пароли и cookie он не видит и не может ничего изменить, не разорвав соединение.
В этом вся идея. Дальше в статье разбирается, как устроена каждая часть, что замок обещает и чего не обещает, и почему HTTPS нужен даже сайту, которому нечего скрывать.
HTTP и HTTPS: что на самом деле меняется#
Обычный HTTP - это текст, который передаётся открыто. Запрос страницы входа в сети выглядит точно так же, как его написал браузер:
POST /login HTTP/1.1Host: shop.example.comContent-Type: application/x-www-form-urlencodedemail=anna%40example.com&password=herring-barrel-42Каждое устройство, через которое проходит этот пакет, - роутер в кафе, сетевая коробка в отеле, интернет-провайдер, любая машина на пути, - может его прочитать, сохранить или переписать. Переписывание - не теория: провайдеры и публичные точки доступа годами вставляли в страницы по HTTP рекламу, скрипты слежки и баннеры вроде "вы приближаетесь к лимиту трафика".
HTTPS меняет транспорт и ничего выше него:
| HTTP | HTTPS | |
|---|---|---|
| Порт по умолчанию | 80 | 443 |
| Схема в URL | http:// | https:// |
| В сети | Читаемый текст | Зашифрованные записи |
| Личность сервера | Не проверяется | Подтверждена сертификатом |
| Подмена данных | Незаметна | Разрывает соединение |
Приложение не меняется. Тот же серверный код, тот же HTML, те же cookie - TLS оборачивает соединение, а HTTP работает внутри, ничего не замечая. Поэтому же "SSL" и "TLS" употребляют как синонимы: SSL был исходным протоколом 1990-х, TLS - его преемник, а все версии SSL официально списаны как небезопасные. То, что сегодня называют "SSL-сертификатом", используется только с TLS, а актуальные версии - TLS 1.2 и TLS 1.3. TLS 1.0 и 1.1 признаны устаревшими в 2021 году, и современные браузеры их не принимают.
Два вида шифрования, которые он использует#
HTTPS сочетает два семейства криптографии, потому что каждое сильно там, где другое слабо.
Симметричное шифрование использует один ключ и для закрытия, и для открытия. Оно достаточно быстрое, чтобы шифровать видео в реальном времени на телефоне. Слабое место очевидно: у обеих сторон должен быть один и тот же ключ, а отправить ключ по той самой сети, которую вы пытаетесь защитить, просто так нельзя. На практике используются шифры AES в режиме GCM и ChaCha20-Poly1305; оба заодно обнаруживают любое изменение данных, так что ловят не только прослушивание, но и подмену.
Асимметричная криптография (с открытым ключом) использует пару ключей. То, что делает один ключ, может проверить или отменить только другой. Одна половина открытая и выдаётся всем, вторая закрытая и никогда не покидает сервер. Это медленно, но решает две сложные задачи: двое незнакомых людей могут договориться об общем секрете по открытой линии, а один из них может доказать, кто он, не раскрывая ничего, что можно было бы использовать повторно.
Поэтому HTTPS один раз в начале использует медленный и хитрый вид, чтобы договориться о ключе и проверить личность, а для всего остального - быстрый. Шаг договорённости называется обменом ключами; на практике это вариант Диффи - Хеллмана на эллиптических кривых, например X25519. Каждая сторона выбирает случайный секрет, отправляет значение, полученное из него, и обе стороны, объединив полученное со своим секретом, приходят к одному и тому же числу. Наблюдатель, видевший оба значения при передаче, всё равно не может его вычислить.
Стоит знать одну деталь: современный TLS после каждого соединения выбрасывает эти секреты обмена. Это называется прямой секретностью (forward secrecy), и она означает, что если закрытый ключ сервера украдут в следующем году, трафик, записанный сегодня, всё равно расшифровать не получится. В TLS 1.3 она обязательна; в старых конфигурациях, где ключ сессии шифровался напрямую ключом сертификата сервера, её не было.
Сертификаты и центры сертификации#
Одного шифрования недостаточно. Если злоумышленник сидит между вами и сервером, он может поднять идеально зашифрованное соединение с вами и другое с настоящим сервером и читать всё посередине. Обмен ключами при этом пройдёт успешно, только не с тем участником. Остановить это может сертификат.
Сертификат - это небольшой файл, который связывает открытый ключ с одним или несколькими именами. Его важные поля:
- Subject alternative names - имена хостов, для которых он действителен, например
example.comиwww.example.com, или wildcard вроде*.example.com, покрывающий один уровень поддоменов. - Открытый ключ - открытая половина пары ключей, закрытая половина которой хранится на сервере.
- Срок действия - даты "не раньше" и "не позже". Вне этого окна сертификат отклоняется.
- Издатель и подпись - какой центр ручается за эту связку и его цифровая подпись под всем перечисленным.
Главное здесь - центр. Центр сертификации (CA) - это организация, чьи открытые ключи поставляются внутри вашей операционной системы или браузера, в списке под названием корневое хранилище (root store). Mozilla, Apple, Microsoft и Google ведут каждая своё и проверяют входящие в него центры. Когда CA подписывает сертификат, он заявляет, что проверил: заявитель управляет этим именем. Для бесплатных сертификатов, которыми пользуется большинство сайтов, эта проверка автоматическая: CA просит заявителя опубликовать токен на домене и забирает его - как именно проходит эта проверка, разобрано в статье HTTPS и Let's Encrypt: как это работает.
Корневые ключи хранят офлайн и используют редко, поэтому CA подписывает ваш сертификат промежуточным ключом, а промежуточный подписан корневым. Сервер отправляет свой сертификат и промежуточный, корневой у браузера уже есть. Это и есть цепочка:
Браузер проверяет каждую подпись вверх, пока не дойдёт до корня, которому уже доверяет. Если какого-то звена нет, оно просрочено или подписано неизвестно кем, соединение отклоняется с предупреждением. Сервер, который отправляет только свой сертификат и забывает промежуточный, - классическая ошибка настройки, и она раздражает тем, что в одних браузерах всё работает (в тех, что закэшировали промежуточный сертификат с другого сайта), а в других нет.
Каждый публичный сертификат также записывается в журналы Certificate Transparency - публичные журналы, доступные только для добавления, по которым может искать любой. Браузеры требуют доказательство, что сертификат попал в журнал. В результате CA не может тихо выпустить сертификат на ваш домен кому-то другому, не оставив следа, который вы можете найти.
TLS-рукопожатие по шагам#
Когда вы открываете https://example.com, перед получением первого байта HTML происходит следующее. Описан TLS 1.3, который согласует почти каждый современный браузер и сервер; TLS 1.2 следует той же логике с одним лишним обменом.
- TCP-соединение. Браузер определяет адрес через DNS и открывает соединение с портом
443по этому адресу. (Поиск адреса разобран в статье DNS-записи: что это и как работают.) - ClientHello. Браузер отправляет поддерживаемые версии TLS и шифры, случайное значение, свою половину обмена ключами ("key share") и два важных расширения: SNI - имя хоста, которое ему нужно, чтобы сервер с множеством сайтов знал, какой сертификат предъявить, и ALPN - протоколы, на которых он может говорить, например
h2для HTTP/2. - ServerHello. Сервер выбирает версию и шифр и отправляет свою половину key share. В этот момент обе стороны могут вычислить один и тот же секрет, и всё дальше шифруется.
- Certificate. Сервер отправляет свой сертификат и цепочку промежуточных.
- CertificateVerify. Сервер подписывает своим закрытым ключом хеш всего разговора до этого момента. Это и есть доказательство личности: такую подпись мог создать только владелец закрытого ключа, соответствующего сертификату, а поскольку она охватывает случайные значения именно этого разговора, её нельзя воспроизвести из старого.
- Finished. Сервер отправляет короткое контрольное значение по всему рукопожатию, доказывающее, что при передаче ничего не изменили.
- Проверки клиента. Браузер проверяет цепочку до доверенного корня, даты, что имя в адресной строке есть в списке имён сертификата, и подпись из шага 5. Любой сбой останавливает соединение здесь, со страницей предупреждения.
- Client Finished, затем HTTP. Браузер отправляет своё сообщение Finished, а сразу за ним обычный запрос
GET- уже внутри зашифрованных записей.
Всё это стоит одного сетевого обмена до отправки запроса - примерно как один ping до сервера. Вернувшийся посетитель может возобновить прежнюю сессию и пропустить шаг с сертификатом, а TLS 1.3 при возобновлении даже позволяет отправлять данные в самом первом пакете ("0-RTT") ценой того, что эти ранние данные можно воспроизвести повторно, поэтому серверы принимают их только для запросов, которые безопасно повторять.
Настоящее рукопожатие можно посмотреть из терминала:
# Summary: protocol, cipher, certificate subject and issuer$ openssl s_client -connect example.com:443 -servername example.com -brief < /dev/null# The same from curl, with every TLS step printed$ curl -v https://example.com -o /dev/nullФлаг -servername задаёт SNI. Без него сервер с несколькими именами может отдать сертификат по умолчанию от какого-то другого сайта, и результат выглядит как сломанный сертификат, хотя на деле просто не хватает флага.
HTTP/3 меняет транспорт под собой - он работает поверх QUIC по UDP-порту 443, а не по TCP, - но рукопожатие TLS 1.3 встроено в QUIC, и описанные выше шаги всё равно происходят.
Что означает замок и чего он не означает#
Замок, а в современном Chrome нейтральный значок настроек на том же месте, означает ровно три вещи: соединение зашифровано, при передаче оно не изменено, а сервер доказал, что у него есть действующий сертификат на имя из адресной строки. Это утверждение о канале, а не о людях на другом конце.
Он не означает, что:
- Сайт честный. Фишинговая страница на
paypa1-secure-login.comполучает действующий сертификат за секунды, потому что сертификат лишь подтверждает контроль над этим конкретным именем. Читайте имя, а не значок. - Компания та, за кого себя выдаёт. Бесплатные распространённые сертификаты проверяют только домен. Более дорогие сертификаты с проверкой организации и расширенной проверкой (EV) предполагают сверку данных компании, но браузеры больше не показывают название компании в адресной строке, так что посетитель не может их отличить.
- Сайт защищён. HTTPS защищает данные при передаче. Он ничего не делает с устаревшим плагином, слабым паролем администратора или базой данных, оставленной открытой в интернет. Лучше о защите этой стороны рассказано в статье Защита WordPress: как закрыть основные дыры.
- Никто не видит, что вы заходили на сайт. Наблюдатель в сети по-прежнему видит IP-адрес сервера и, как правило, имя хоста: SNI в ClientHello отправляется в открытом виде, если только браузер и сервер оба не поддерживают Encrypted Client Hello, который пока внедряется, а DNS-запрос идёт открытым текстом, если устройство не использует зашифрованный DNS. Чего он не видит - это путь, строку запроса, заголовки, cookie и содержимое. Адрес
https://example.com/account/orders?id=4411выдаётexample.com, а остальное остаётся внутри туннеля. - Ваш работодатель или учебное заведение не может это прочитать. Корпоративные сети и некоторые антивирусы устанавливают на управляемые устройства собственный корневой сертификат и намеренно расшифровывают трафик посередине. На устройстве, которое вы не контролируете, считайте это возможным. Как это пересекается с VPN, разобрано в статье Что защищает VPN, а что нет.
HSTS: закрываем брешь первого запроса#
Даже у сайта, который перенаправляет каждый HTTP-запрос на HTTPS, есть слабый момент: самый первый запрос. Если вы набираете example.com, браузер сначала пробует http://, и этот открытый запрос могут перехватить до прихода перенаправления. Злоумышленник в той же сети wifi может ответить на него сам и бесконечно держать вас на HTTP - это атака понижения (downgrade).
HSTS (HTTP Strict Transport Security) закрывает эту брешь. Сервер один раз отправляет заголовок по HTTPS:
Strict-Transport-Security: max-age=31536000; includeSubDomainsС этого момента в течение max-age секунд - здесь это год - браузер перед отправкой переписывает каждую ссылку http:// на это имя в https:// и убирает возможность пройти дальше при предупреждении о сертификате. Первый визит всё же остаётся незащищённым, и для этого существует список preload: имена, отправленные в него, зашиваются в браузеры как доступные только по HTTPS ещё до первого визита. Некоторые целые домены верхнего уровня, например .dev и .app, входят в этот список, поэтому любой сайт под ними должен работать по HTTPS с первого дня.
HSTS - единственная возможность HTTPS, которая может закрыть вам доступ к собственному сайту, если какому-то поддомену всё ещё нужен обычный HTTP, а preload отменяется медленно. Начните с короткого max-age, убедитесь, что всё работает, и только потом увеличивайте. Настройка, а также перенаправление и очистка смешанного содержимого, с которых стоит начинать, описаны в статье HTTPS и Let's Encrypt: как это работает.
Зачем HTTPS каждому сайту#
"На моём сайте нет входа и нет платежей" - обычный довод против того, чтобы заморачиваться. Сегодня он не выдерживает критики, причём по причинам, не связанным с секретностью.
- Браузеры помечают обычный HTTP как небезопасный в адресной строке на каждой странице. Формы на страницах по HTTP получают дополнительное предупреждение, когда человек начинает вводить текст, а браузеры всё чаще сначала пробуют HTTPS и предупреждают перед возвратом к обычному HTTP.
- Подмена касается и скучных страниц. Внедрённый скрипт на статичном кулинарном блоге выполняется в браузере посетителя с теми же правами, что и ваш: он может перенаправить, майнить или показать поддельное окно входа.
- Современные возможности требуют его. Геолокация, доступ к камере и микрофону, service workers, push-уведомления, API буфера обмена и HTTP/2 в браузерах - всё это требует безопасного контекста. Браузеры используют HTTP/2 и HTTP/3 только поверх TLS, так что сайт только по HTTP ещё и застрял на более старом и медленном протоколе.
- Поисковые системы предпочитают его. Google использует HTTPS как фактор ранжирования с 2014 года. Это небольшой фактор, но он ничего не стоит.
- Данные о реферере сохраняются. Когда посетитель переходит со страницы HTTPS на страницу HTTP, браузер удаляет реферер, поэтому сайты по HTTP теряют часть аналитики.
- Сертификат бесплатный и обновляется сам. Довод о стоимости исчез, когда бесплатные автоматические сертификаты стали нормой.
На тарифах RE:NODE для приложений и сайтов всё сводится к одной DNS-записи: добавьте имя хоста в слот прокси, направьте A-запись на показанный адрес, и сертификат будет выпущен, как только имя начнёт разрешаться, и обновляется автоматически в окне 21 день. Прокси завершает TLS и передаёт вашему приложению обычный HTTP, а настоящий адрес посетителя - в X-Forwarded-For. Как это настроить и почему выпуск иногда не удаётся, описано в статье Направьте домен на сервер и добавьте SSL.
Ошибки сертификата и что они значат#
Большинство проблем с HTTPS проявляются как одна из нескольких ошибок браузера. Коды в разных браузерах отличаются, причины одинаковы.
| Chrome / Edge | Firefox | Причина |
|---|---|---|
NET::ERR_CERT_DATE_INVALID | SEC_ERROR_EXPIRED_CERTIFICATE | Срок истёк или неверные часы на устройстве |
NET::ERR_CERT_COMMON_NAME_INVALID | SSL_ERROR_BAD_CERT_DOMAIN | Имени нет в сертификате |
NET::ERR_CERT_AUTHORITY_INVALID | SEC_ERROR_UNKNOWN_ISSUER | Цепочка неполная или не вызывает доверия |
Срок истёк. Либо не удалось обновить сертификат на сайте, либо на устройстве посетителя неверные часы. Телефон или ПК с датой на несколько лет в прошлом отвергает сразу все сертификаты в интернете, и это выдаёт причину: если ломаются все сайты, проверьте часы.
Неверное имя. Сертификат выпущен на example.com, а посетитель пришёл через www.example.com, или новый поддомен направили на сервер до того, как для него выпустили сертификат. Сертификат действителен только для имён, перечисленных в нём.
Неизвестный издатель. Сервер не отправляет промежуточный сертификат, или сертификат самоподписанный. Проверьте с машины, которая никогда не заходила на этот сайт, или воспользуйтесь командой openssl выше: она показывает цепочку, которую сервер отправляет на самом деле.
Небезопасно, хотя сертификат действителен. Смешанное содержимое: страница по HTTPS, но загружает скрипт, стили или изображение по http://. Браузеры блокируют активное содержимое полностью, и страница отображается наполовину. Точный URL указан в консоли браузера.
`ERR_TOO_MANY_REDIRECTS`. Обычно это приложение за прокси, завершающим TLS: оно видит обычный HTTP на своём порту и продолжает перенаправлять на HTTPS. Приложению нужно вместо этого доверять заголовку X-Forwarded-Proto от прокси. Почему так, объясняет статья Что делает обратный прокси.
Чтобы проверить, как сайт ведёт себя снаружи, на большинство вопросов отвечают две команды:
# Does HTTP redirect to HTTPS, and to which host?$ curl -sI http://example.com | grep -iE "^(HTTP|location)"# Is HSTS set, and for how long?$ curl -sI https://example.com | grep -i strict-transport-securityFAQ#
HTTPS и SSL - это одно и то же?
В обиходе да. Технически HTTPS - это HTTP, переданный поверх TLS, а TLS заменил SSL в 1999 году. Все версии SSL теперь списаны как небезопасные, но старое название прижилось, поэтому сертификаты по-прежнему продают как "SSL-сертификаты". Работают они с TLS 1.2 и 1.3.
HTTPS замедляет сайт?
На современном оборудовании заметно нет. Рукопожатие добавляет один обмен на новом соединении и меньше на возобновлённом, а само шифрование выполняется специальными инструкциями процессора. На практике сайты по HTTPS нередко быстрее, потому что браузеры используют HTTP/2 и HTTP/3 только поверх TLS.
Видит ли мой провайдер, какие сайты я посещаю по HTTPS?
Он видит IP-адреса, к которым вы подключаетесь, и в большинстве случаев имя хоста - из ваших DNS-запросов и из поля SNI в рукопожатии. Он не видит, какие страницы вы открывали, что искали на сайте и что вводили. Зашифрованный DNS и Encrypted Client Hello сужают это ещё сильнее там, где их поддерживают обе стороны.
Как долго действует сертификат?
Бесплатные сертификаты Let's Encrypt действуют 90 дней и обновляются автоматически. Максимальный срок для любого публично доверенного сертификата в отрасли неоднократно сокращали, и в ближайшие годы он продолжит уменьшаться, поэтому ручное ежегодное обновление повсеместно уходит в прошлое.
Достаточно ли самоподписанного сертификата?
Для шифрования на закрытом тестовом сервере да. Для публичного сайта нет: ни один браузер ему не доверяет, поэтому каждый посетитель получает предупреждение на весь экран, а приучать людей нажимать "продолжить" значит подрывать проверку личности, на которой и держится HTTPS.
Нужен ли HTTPS для игрового сервера?
Для самого игрового трафика нет - Minecraft, Valheim и большинство игр используют собственные протоколы на собственных портах, а не HTTP. Он нужен для всего, что связано с игрой и открыто в вебе: сайта, просмотрщика карты, страницы пожертвований или панели.


