Як налаштувати HSTS і не заблокувати собі доступ
Поетапний, зворотний план впровадження Strict-Transport-Security, який покращує приватність, не перетворюючи один невдалий сертифікат на простій.
Зміст
- HSTS простий, доки перестає бути простим
- Що насправді робить заголовок HSTS
- Сценарії блокування, яких слід уникати
- 1. Забутий субдомен не готовий до HTTPS
- 2. Сертифікат прострочується
- 3. Staging або внутрішні інструменти живуть під production-доменом
- 4. Preload сприймають як звичайний прапорець
- Безпечний план впровадження
- Крок 1: Проведіть аудит кожного hostname, який ви контролюєте
- Крок 2: Виправте HTTPS перед додаванням HSTS
- Крок 3: Почніть із дуже короткого max-age
- Крок 4: Збільшуйте поступово
- Крок 5: Додавайте includeSubDomains лише після реального аудиту
- Крок 6: Ставтеся до preload як до окремого проєкту
- Приклади конфігурації
- Nginx
- Apache
- CDN або edge-платформа
- Як безпечно скасувати HSTS
- Checklist для тестування перед випуском
- Аргумент HSTS на користь приватності
HSTS простий, доки перестає бути простим
HTTP Strict Transport Security, зазвичай скорочено HSTS, повідомляє браузерам: «для цього сайту завжди використовуйте HTTPS». Щойно браузер отримує цей заголовок через дійсне HTTPS-з’єднання, він запам’ятовує правило на вказаний вами час.
Це корисно. Це запобігає атакам із пониженням протоколу, зменшує кількість випадкових небезпечних запитів і прибирає незручний момент, коли користувач вводить example.com і на мить торкається звичайного HTTP перед перенаправленням.
Але це також липке правило. Якщо ви опублікуєте неправильну політику HSTS, браузери можуть продовжувати застосовувати її ще довго після того, як ви приберете заголовок із сервера. Саме так команди блокують собі доступ: не зовсім до власної адмінпанелі, а до браузерів користувачів, субдоменів, staging-систем, застарілих кінцевих точок і забутих сервісів, які не готові до примусового HTTPS.
Мета не в тому, щоб уникати HSTS. Мета — розгортати його як міграцію, а не як перемикач.
Що насправді робить заголовок HSTS
Типовий заголовок HSTS виглядає так:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Він має три важливі частини:
max-age: як довго, у секундах, браузер має примусово використовувати HTTPS для цього хоста.includeSubDomains: чи поширюється правило також на кожен субдомен.preload: сигнал, що ви хочете додати домен до списків preload у браузерах.
Браузер довіряє цьому заголовку лише тоді, коли отримує його через дійсний HTTPS. Якщо сертифікат недійсний, прострочений або не відповідає хосту, браузер не повинен приймати нову політику HSTS з такої відповіді.
Після збереження політики майбутні спроби відвідати http://example.com браузер оновлює до https://example.com ще до надсилання запиту. У цьому й полягає виграш для приватності: небезпечний запит ніколи не залишає пристрій.
Сценарії блокування, яких слід уникати
Більшість збоїв HSTS спричиняє не основний сайт. Вони трапляються на краях.
1. Забутий субдомен не готовий до HTTPS
includeSubDomains звучить охайно, але це абсолютне правило. Якщо встановити його на example.com, воно застосовується до:
www.example.comapi.example.comold-crm.example.comprinter-setup.example.comstaging.example.com- будь-чого іншого під цим доменом
Якщо будь-який із цих хостів не може обслуговувати дійсний HTTPS, користувачі з кешованою політикою HSTS не зможуть дістатися до нього через HTTP.
2. Сертифікат прострочується
Без HSTS користувачі іноді проходять далі попри попередження про сертифікат. Це не є доброю практикою безпеки, але так трапляється.
З HSTS сучасні браузери не дають легко обійти помилки сертифіката для цього хоста. У цьому й сенс. Це також означає, що поновлення сертифікатів має бути нудним, монітореним і протестованим процесом.
3. Staging або внутрішні інструменти живуть під production-доменом
Розміщення внутрішніх інструментів під *.example.com може стати болючим, щойно батьківський домен почне використовувати includeSubDomains. Якщо ці інструменти використовують самопідписані сертифікати, приватні центри сертифікації, старі конфігурації TLS або взагалі не мають HTTPS, HSTS швидко виявить цей компроміс.
Це одна з причин, чому багато команд тримають внутрішні та експериментальні системи під окремим доменом із власною політикою безпеки.
4. Preload сприймають як звичайний прапорець
HSTS preload — це не просто ще одна директива. Це означає, що ваш домен може постачатися всередині браузерів як HTTPS-only ще до того, як будь-який користувач відвідає ваш сайт.
Це закриває прогалину «першого відвідування», але скасувати це значно складніше. Видалення зі списків preload може доходити до користувачів тижнями або місяцями, залежно від циклів випуску браузерів. Preload доречний для стабільних, зрілих доменів. Він не доречний для сайту, який досі з’ясовує свій інвентар субдоменів.
Безпечний план впровадження
Крок 1: Проведіть аудит кожного hostname, який ви контролюєте
Перш ніж встановлювати includeSubDomains, перелічіть кожен hostname під доменом. DNS-записи — це початок, але не вся картина. Перевірте конфігурації CDN, панелі хостингу, hostname, пов’язані з email, старі маркетингові інструменти, storage buckets і внутрішню документацію.
Для кожного hostname дайте відповіді:
- Він обслуговує HTTP, HTTPS чи обидва?
- HTTPS-сертифікат дійсний і поновлюється автоматично?
- HTTP чисто перенаправляється на HTTPS?
- Він має бути публічним?
- Він досі потрібен?
Якщо ваша команда вже має звички налагодження production-заголовків, це природно стає поруч із перевірками перенаправлень і заголовків. Ми описували цей процес у невеликому наборі інструментів для налагодження перенаправлень і HTTP-заголовків у production.
Крок 2: Виправте HTTPS перед додаванням HSTS
HSTS не робить зламане налаштування HTTPS безпечним. Він лише робить HTTPS обов’язковим.
Перед увімкненням перевірте:
- TLS-сертифікати покривають правильні hostname.
- Сертифікати поновлюються автоматично.
- HTTP перенаправляється на HTTPS одним чистим переходом, де це можливо.
- Канонічні перенаправлення хоста послідовні, наприклад з non-
wwwнаwwwабо навпаки. - Ресурси застосунку не залежать від небезпечних URL
http://.
Змішаний контент трапляється рідше, ніж раніше, але він досі з’являється в старих темах CMS, фрагментах аналітики, вбудованих медіа та жорстко прописаних шляхах до зображень.
Крок 3: Почніть із дуже короткого max-age
Не починайте з одного року. Почніть із п’яти хвилин:
Strict-Transport-Security: max-age=300
Розгорніть це лише на hostname, який тестуєте, зазвичай на канонічному production-сайті. Поки що не додавайте includeSubDomains.
Потім протестуйте в реальних браузерах і через командний рядок:
curl -I https://example.com
Ви маєте побачити рівно один заголовок Strict-Transport-Security. Дубльовані заголовки HSTS від app server і CDN — поширене джерело плутанини. Браузери зазвичай застосовують ефективну політику, але людям, які налагоджують інцидент, неоднозначність не потрібна.
Крок 4: Збільшуйте поступово
Якщо нічого не ламається, збільшуйте тривалість поетапно:
Strict-Transport-Security: max-age=86400
Потім:
Strict-Transport-Security: max-age=604800
Потім, можливо:
Strict-Transport-Security: max-age=2592000
Практичний графік такий:
- 5 хвилин
- 1 день
- 1 тиждень
- 1 місяць
- 6 місяців або 1 рік
За поспіх призів не дають. Уся суть поетапного впровадження — дати моніторингу, inbox підтримки та крайовим випадкам час повідомити вам, що пропустив ваш checklist.
Крок 5: Додавайте includeSubDomains лише після реального аудиту
Коли кожен публічний субдомен готовий до HTTPS, можна розглянути:
Strict-Transport-Security: max-age=31536000; includeSubDomains
У цей момент варто бути консервативними. Якщо одному застарілому сервісу досі потрібен HTTP, не додавайте includeSubDomains до батьківського домену. Або мігруйте цей сервіс, або перенесіть його на інший домен, або прийміть, що ваша політика HSTS наразі має залишатися вужчою.
Заголовки безпеки мають відображати реальність. Їх не слід використовувати як мотиваційні плакати для інфраструктури, яку ви сподіваєтеся колись мати.
Крок 6: Ставтеся до preload як до окремого проєкту
Розглядайте preload лише тоді, коли виконано все нижче:
- Домен і всі субдомени підтримують дійсний HTTPS.
- HTTP перенаправляється на HTTPS.
- Заголовок HSTS використовує
max-ageщонайменше 31536000 секунд. - Заголовок містить
includeSubDomains. - Заголовок містить
preload. - Ви впевнені, що вам не знадобиться звичайний HTTP ніде під цим доменом.
Заголовок, готовий до preload, виглядає так:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Подання до списку preload — це довгострокове зобов’язання. Якщо сайт є campaign microsite, тимчасовим доменом продукту або доменом із нечіткими межами власності, пропустіть це.
Приклади конфігурації
Nginx
Використовуйте always, щоб заголовок надсилався також у відповідях із помилками:
add_header Strict-Transport-Security "max-age=300" always;
Після стабілізації впровадження:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Apache
З увімкненим mod_headers:
Header always set Strict-Transport-Security "max-age=300"
Пізніше:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
CDN або edge-платформа
Якщо ваш CDN встановлює заголовки відповідей, краще керувати HSTS в одному місці. Не встановлюйте одну політику на origin і іншу на edge, якщо не маєте дуже чіткої причини.
Також перевірте, чи CDN застосовує заголовки до перенаправлень, кешованих помилок і кастомних сторінок помилок. Production-сайт — це не лише його відповідь 200 OK.
Як безпечно скасувати HSTS
Якщо потрібно вимкнути HSTS, надішліть:
Strict-Transport-Security: max-age=0
Але є нюанс: браузер має успішно дістатися сайту через дійсний HTTPS, щоб отримати цей заголовок. Якщо сам HTTPS зламаний, користувачі з кешованою політикою HSTS не зможуть отримати інструкцію, яка її очистить.
Тож звичайний порядок відновлення такий:
- Відновіть дійсний HTTPS.
- Віддавайте
Strict-Transport-Security: max-age=0. - Тримайте його достатньо довго, щоб користувачі, які повертаються, отримали його.
- Приберіть або замініть заголовок після завершення інциденту.
Якщо домен у preload, віддавати max-age=0 недостатньо для нових профілів браузера. Також потрібно запросити видалення зі списку preload і чекати, доки ця зміна дійде через оновлення браузерів.
Checklist для тестування перед випуском
Скористайтеся цим checklist перед збільшенням max-age або додаванням includeSubDomains:
- Канонічний HTTPS URL повертає дійсний сертифікат.
- HTTP перенаправляється на HTTPS.
- Є лише один заголовок HSTS.
- Заголовок з’являється на перенаправленнях і відповідях із помилками там, де це доречно.
- Усі публічні субдомени мають дійсний HTTPS.
- Поновлення сертифікатів моніториться.
- Жодна критична внутрішня система не залежить від HTTP під тим самим батьківським доменом.
- Preload було обговорено явно, а не додано за звичкою.
Lighthouse також може позначати відсутні або слабкі заголовки безпеки в деяких контекстах, але він не має бути єдиним методом перевірки. Якщо ви використовуєте його як частину ширшого огляду, сприймайте результати як сигнали, а не як вироки; той самий підхід працює, коли ви читаєте звіт Lighthouse без паніки.
<!-- tool-cta:start -->
💡 Спробуйте це: До та після кожної зміни HSTS перевіряйте відповідь Strict-Transport-Security за допомогою Get Headers, щоб підтвердити, що max-age, includeSubDomains і preload відповідають вашим очікуванням.
<!-- tool-cta:end -->
Аргумент HSTS на користь приватності
HSTS часто подають як заголовок безпеки, і це справді так. Він також має перевагу для приватності: зменшує ймовірність того, що перший запит користувача витече через звичайний HTTP у недовіреній мережі.
Це важливо у Wi-Fi в аеропортах, готельних мережах, гостьових корпоративних мережах і будь-де, де трафік користувача можуть спостерігати або змінювати. Звичайний HTTP-запит може розкрити hostname, шлях, cookies без прапорця Secure та інші деталі запиту. HTTPS не є магією, але послідовне примусове використання HTTPS прибирає цілий клас витоків, яких можна уникнути.
Найкращі впровадження HSTS нецікаві. Їх розгортають повільно, вони спираються на надійні сертифікати й достатньо нудні, щоб ніхто їх не помічав. Саме цього ви й хочете від заголовка, режим відмови якого може бути драматичним.