Проблема первого запроса
Допустим, сайт поддерживает HTTPS и перенаправляет на него всех, кто пришёл по HTTP. Казалось бы, всё в порядке. Но самый первый запрос пользователь отправляет по открытому HTTP, если просто набрал адрес без схемы. Именно в этот момент злоумышленник в сети, например в открытом Wi-Fi, может перехватить запрос и подсунуть поддельную страницу без шифрования. Эту технику называют понижением защиты, SSL stripping.
HSTS, HTTP Strict Transport Security, закрывает эту дыру. Сайт сообщает браузеру: в течение заданного срока ходи ко мне только по HTTPS, даже если пользователь или ссылка просит HTTP. Браузер запоминает это правило и сам переписывает адреса, не отправляя незащищённый запрос.
Как выглядит заголовок
Сайт отправляет в ответе по HTTPS заголовок Strict-Transport-Security. Обязательный параметр max-age задаёт срок в секундах, например 31536000 соответствует году. Необязательный includeSubDomains распространяет правило на все поддомены, а preload означает согласие попасть в предзагруженный список.
Важный нюанс: заголовок принимается только по защищённому соединению. Если получить его по HTTP, браузер проигнорирует, ведь его мог вставить любой посредник. Ещё одно следствие: пока браузер помнит правило, он отказывается открывать сайт, если сертификат недействителен, и не даёт нажать кнопку «всё равно продолжить». Это сделано намеренно, чтобы пользователь не отключил защиту по привычке.
О базовой схеме защищённого соединения можно прочитать на странице про HTTPS.
Preload-список
Остаётся щель: самый первый визит на сайт, когда браузер ещё не получил заголовок. Чтобы закрыть её, разработчики браузеров ведут общий предзагруженный список доменов, для которых HTTPS требуется с самого начала. Домен подаётся в этот список по заявке, при условии что заголовок содержит длинный max-age, includeSubDomains и preload, а сайт целиком работает по HTTPS.
Удалить домен из списка можно, но процесс медленный: обновление доходит до пользователей вместе с новыми версиями браузеров, поэтому нужно подходить к этому осознанно. Для крупных сервисов это норма, для небольшого личного сайта часто достаточно обычного HSTS.
Риски неверной настройки
Главный риск связан с тем, что ошибка сохраняется у пользователей на весь срок max-age. Если вы включили HSTS с includeSubDomains на год, а затем обнаружили, что один поддомен работает только по HTTP или у него просрочен сертификат, посетители не смогут открыть его вообще. Быстро откатить это невозможно.
Поэтому рекомендуют вводить постепенно. Начните с короткого срока, например нескольких минут, затем увеличьте до дня, недели и только после проверки всех поддоменов ставьте месяцы. Заранее убедитесь, что автоматическое продление сертификатов работает, ведь после включения HSTS просроченный сертификат приводит к полному отказу открытия, а не к предупреждению.
Настройку упрощает автоматика вроде Let's Encrypt.
Как проверить у себя: HSTS
В инструментах разработчика браузера откройте вкладку «Сеть», выберите основной запрос к сайту и найдите заголовок Strict-Transport-Security в ответе. В командной строке достаточно curl -sI с адресом сайта по протоколу HTTPS и поиска строки. Онлайн-проверки покажут срок и статус в preload-списке.
Если нужно сбросить запомненное правило для тестового домена, в Chrome есть служебная страница управления политиками безопасности, а в Firefox можно очистить сохранённые данные сайта. Учтите, что HSTS защищает только от понижения до HTTP. Он не проверяет честность сайта и не заменяет корректный сертификат.
HSTS и поддомены на практике
Опция includeSubDomains полезна и опасна одновременно. Она защищает все поддомены, включая забытые, и закрывает кражу cookie через незащищённый соседний поддомен. Но включать её можно, только когда каждый поддомен, в том числе внутренние панели и тестовые стенды, работает по HTTPS с действительным сертификатом. Перед включением составьте список всех имён из DNS и проверьте каждое. Отдельный вопрос — почтовые и служебные хосты: правило действует на веб-запросы, но неожиданно затрагивает то, что открывают браузером. Разумно начать с основного домена и расширять охват постепенно.