HSTS and Preload List: Complete Implementation Guide
HTTP Strict Transport Security (HSTS) and Preload
HTTP Strict Transport Security is a security mechanism that forces browsers to communicate with your website exclusively over SSL/TLS проверку. Once a browser receives an HSTS header, it will refuse to connect via plain HTTP for the specified duration, eliminating an entire class of attacks. The HSTS preload list takes this further by hardcoding your domain into browsers, providing HTTPS enforcement from the very first visit.
Why HSTS Matters
Even if your server redirects HTTP to HTTPS, the initial request is still vulnerable. Without HSTS, attackers can exploit this window through several attack vectors:
- SSL stripping: A man-in-the-middle intercepts the initial HTTP request and serves the user an HTTP version of the site, proxying requests to the real HTTPS server. The user sees no browser warning.
- Cookie hijacking: Cookies set without the Secure flag can be intercepted over the initial HTTP connection, even if the user is quickly redirected to HTTPS.
- Mixed content downgrades: Without HSTS, resources loaded over HTTP on an HTTPS page can be intercepted and modified.
- WiFi captive portal attacks: On public WiFi, attackers can intercept the first HTTP request and redirect users to phishing pages.
HSTS closes these gaps by telling the browser: \"Never connect to this domain over HTTP. Always use HTTPS. If the certificate is invalid, do not allow the user to bypass the warning.\"
The HSTS Header
HSTS is implemented as a response header on HTTPS connections:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Header Directives
| Directive | Required | Description |
|---|---|---|
| max-age | Yes | Time in seconds the browser should remember the HSTS policy. 63072000 = 2 years. |
| includeSubDomains | For preload | Applies the policy to all subdomains of the current domain. |
| preload | For preload | Signals eligibility for inclusion in browser preload lists. |
Implementation Steps
Implementing HSTS requires a careful, phased approach. Rushing to a long max-age or enabling includeSubDomains without preparation can lock you out of your own services.
Phase 1: Audit and Prepare
Before enabling HSTS, ensure every part of your infrastructure supports HTTPS:
- Audit all subdomains: Every subdomain (www, API документацию, cdn, mail, staging, internal tools) must have valid HTTPS certificates if includeSubDomains will be used.
- Check mixed content: Ensure no pages load resources over HTTP. Use browser DevTools or automated scanners.
- Verify certificate automation: Confirm that certificate renewal is automated and monitored. An expired certificate with HSTS means total site inaccessibility.
- Review third-party integrations: Verify that payment processors, analytics, and other integrations work correctly over HTTPS.
Phase 2: Start with a Short max-age
Begin with a 5-minute max-age to test without risk:
# nginx
add_header Strict-Transport-Security "max-age=300" always;
# Apache
Header always set Strict-Transport-Security "max-age=300"
Monitor for issues for at least one week. Check error logs, user reports, and analytics for anomalies.
Phase 3: Increase max-age Gradually
Progressively extend the duration:
# Week 2: 1 hour
add_header Strict-Transport-Security "max-age=3600" always;
# Week 3: 1 day
add_header Strict-Transport-Security "max-age=86400" always;
# Week 4: 1 week
add_header Strict-Transport-Security "max-age=604800" always;
# Week 6: 1 month
add_header Strict-Transport-Security "max-age=2592000" always;
Phase 4: Add includeSubDomains
Only after confirming all subdomains work correctly over HTTPS:
add_header Strict-Transport-Security "max-age=2592000; includeSubDomains" always;
Phase 5: Set Final max-age and Add Preload
Set the max-age to 2 years (minimum for preload) and add the preload directive:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
The HSTS Preload List
The HSTS preload list is maintained by the Chromium project and used by all major browsers (Chrome, Firefox, Safari, Edge, Opera). Domains on this list have HSTS enforced before the browser ever makes a request to the domain — eliminating even the first-visit vulnerability.
Submission Requirements
To be eligible for the preload list, your domain must meet all of the following criteria:
- Serve a valid HTTPS certificate on the root domain.
- Redirect all HTTP traffic to HTTPS on the same host (if listening on port 80).
- Serve the HSTS header on the root domain over HTTPS with: max-age of at least 63072000 (2 years), includeSubDomains directive, and preload directive.
- All subdomains must support HTTPS, including the www subdomain if a DNS record for it exists.
Submit your domain at hstspreload.org after meeting all requirements.
Important Warnings About Preload
- Removal is slow: Getting removed from the preload list can take months. Browsers ship updates on different schedules, and cached browser versions may never receive the update.
- Includes ALL subdomains: If any subdomain cannot serve HTTPS, it will become inaccessible. This includes internal tools, development environments, and legacy services.
- No easy rollback: Unlike a header with a short max-age, preload cannot be undone quickly. Plan thoroughly before submitting.
Risks and Mitigation
| Risk | Impact | Mitigation |
|---|---|---|
| Certificate expiry | Total site inaccessibility | Automate renewal, monitor expiry, set alerts at 30/14/7 days |
| Subdomain without HTTPS | Subdomain inaccessible | Audit all subdomains before enabling includeSubDomains |
| Mixed content | Broken page resources | Scan all pages for HTTP resources before enabling HSTS |
| Incorrect configuration | Users locked into broken HTTPS | Start with short max-age, increase gradually |
| Preload regret | Cannot easily revert to HTTP | Only preload after months of successful HSTS operation |
Testing Your HSTS Configuration
Verify your HSTS header is correctly configured:
# Check HSTS header
curl -sI https://example.com | grep -i strict
# Test with SSL Labs
# Visit: https://www.ssllabs.com/ssltest/
# Check preload eligibility
# Visit: https://hstspreload.org/
# Verify in Chrome
# Navigate to: chrome://net-internals/#hsts
# Query your domain to see the current HSTS state
Common Mistakes
- Setting HSTS on HTTP: The header must only be sent over HTTPS. Browsers ignore HSTS headers received over HTTP.
- Missing the always directive in nginx: Without
always, nginx only adds the header on successful responses (2xx), not on redirects (3xx) or errors. - Forgetting www subdomain: If users access www.example.com, it needs HTTPS and HSTS too.
- Jumping to max max-age: Going from 0 to 63072000 seconds immediately creates a 2-year commitment without testing.
- Not monitoring certificate renewal: The most common HSTS disaster is an expired certificate with no way for users to bypass the warning.
Summary
HSTS is one of the most important security headers you can implement. It eliminates SSL stripping attacks, prevents cookie hijacking, and enforces HTTPS at the browser level. The preload list extends this protection to the first visit, but requires careful preparation and carries significant commitment. Follow the phased implementation approach: audit first, start with short max-age values, enable includeSubDomains only after subdomain verification, and only submit to the preload list after months of successful HSTS operation. The security benefits are substantial, but only if implemented correctly.
Check your website right now
Check now →