Privacy & Security

Cách thiết lập HSTS mà không tự khóa mình bên ngoài

Một kế hoạch triển khai theo giai đoạn, có thể đảo ngược cho Strict-Transport-Security, giúp cải thiện quyền riêng tư mà không biến một chứng chỉ lỗi thành sự cố ngừng hoạt động.

The Wux Webtools Team The Wux Webtools Team 16 phút đọc Hỗ trợ AI, được con người xem xét
Illustration of a secure browser connection with redirect arrows and subdomain warning markers.
Mục lục
  1. HSTS đơn giản cho đến khi không còn đơn giản
  2. Header HSTS thực sự làm gì
  3. Các kịch bản khóa ngoài cần tránh
  4. 1. Một subdomain bị lãng quên chưa sẵn sàng cho HTTPS
  5. 2. Chứng chỉ hết hạn
  6. 3. Staging hoặc công cụ nội bộ nằm dưới domain production
  7. 4. Preload được xem như một checkbox thường lệ
  8. Một kế hoạch triển khai an toàn
  9. Step 1: Kiểm tra mọi hostname bạn kiểm soát
  10. Step 2: Sửa HTTPS trước khi thêm HSTS
  11. Step 3: Bắt đầu với max-age rất ngắn
  12. Step 4: Tăng dần
  13. Step 5: Chỉ thêm includeSubDomains sau khi audit là thực chất
  14. Step 6: Xem preload như một dự án riêng
  15. Ví dụ cấu hình
  16. Nginx
  17. Apache
  18. CDN hoặc edge platform
  19. Cách hoàn tác HSTS an toàn
  20. Checklist kiểm thử trước khi phát hành
  21. Lý do quyền riêng tư cho HSTS

HSTS đơn giản cho đến khi không còn đơn giản

HTTP Strict Transport Security, thường được viết tắt là HSTS, nói với trình duyệt: “với trang này, luôn dùng HTTPS.” Khi trình duyệt nhận được header qua một kết nối HTTPS hợp lệ, nó sẽ ghi nhớ quy tắc đó trong khoảng thời gian bạn chỉ định.

Điều đó hữu ích. Nó ngăn các cuộc tấn công hạ cấp giao thức, giảm các yêu cầu không an toàn do vô tình, và tránh khoảnh khắc khó xử khi người dùng gõ example.com rồi chạm vào HTTP thuần trong chốc lát trước khi được chuyển hướng.

Nó cũng rất “dính”. Nếu bạn công bố sai chính sách HSTS, trình duyệt có thể tiếp tục thực thi chính sách đó rất lâu sau khi bạn đã gỡ header khỏi máy chủ. Đó là cách các nhóm tự khóa mình bên ngoài: không hẳn là khỏi bảng quản trị của chính họ, mà khỏi trình duyệt của người dùng, subdomain, hệ thống staging, endpoint cũ, và các dịch vụ bị lãng quên chưa sẵn sàng cho HTTPS bắt buộc.

Mục tiêu không phải là tránh HSTS. Mục tiêu là triển khai nó như một cuộc di trú, không phải như một công tắc bật/tắt.

Header HSTS thực sự làm gì

Một header HSTS điển hình trông như sau:

Strict-Transport-Security: max-age=31536000; includeSubDomains

Nó có ba phần quan trọng:

  • max-age: trong bao lâu, tính bằng giây, trình duyệt nên bắt buộc dùng HTTPS cho host này.
  • includeSubDomains: quy tắc có áp dụng cho mọi subdomain hay không.
  • preload: tín hiệu cho biết bạn muốn domain được đưa vào danh sách preload của trình duyệt.

Trình duyệt chỉ tin header này khi nhận được nó qua HTTPS hợp lệ. Nếu chứng chỉ không hợp lệ, hết hạn, hoặc không khớp, trình duyệt không nên chấp nhận chính sách HSTS mới từ phản hồi đó.

Khi chính sách đã được lưu, các lần truy cập sau tới http://example.com sẽ được trình duyệt nâng cấp thành https://example.com trước khi yêu cầu được gửi đi. Đó là lợi ích về quyền riêng tư: yêu cầu không an toàn không bao giờ rời khỏi thiết bị.

Các kịch bản khóa ngoài cần tránh

Hầu hết lỗi HSTS không bắt nguồn từ website chính. Chúng xảy ra ở vùng rìa.

1. Một subdomain bị lãng quên chưa sẵn sàng cho HTTPS

includeSubDomains nghe có vẻ gọn gàng, nhưng nó tuyệt đối. Nếu bạn đặt nó trên example.com, nó áp dụng cho:

  • www.example.com
  • api.example.com
  • old-crm.example.com
  • printer-setup.example.com
  • staging.example.com
  • bất kỳ thứ gì khác bên dưới domain đó

Nếu bất kỳ host nào trong số đó không thể phục vụ HTTPS hợp lệ, người dùng đã cache chính sách HSTS sẽ không thể truy cập chúng qua HTTP.

2. Chứng chỉ hết hạn

Khi không có HSTS, đôi khi người dùng bấm bỏ qua cảnh báo chứng chỉ. Đó không phải là thực hành bảo mật tốt, nhưng vẫn xảy ra.

Với HSTS, các trình duyệt hiện đại không cho phép dễ dàng bỏ qua lỗi chứng chỉ đối với host đó. Đây chính là mục đích. Điều đó cũng có nghĩa là việc gia hạn chứng chỉ cần phải nhàm chán, được giám sát, và được kiểm thử.

3. Staging hoặc công cụ nội bộ nằm dưới domain production

Đặt công cụ nội bộ dưới *.example.com có thể trở nên phiền toái khi domain cha dùng includeSubDomains. Nếu các công cụ đó dùng chứng chỉ tự ký, certificate authority riêng, cấu hình TLS cũ, hoặc hoàn toàn không có HTTPS, HSTS sẽ phơi bày lối tắt này.

Đây là một lý do khiến nhiều nhóm giữ hệ thống nội bộ và thử nghiệm dưới một domain riêng có chính sách bảo mật riêng.

4. Preload được xem như một checkbox thường lệ

HSTS preload không chỉ là một directive khác. Nó có nghĩa là domain của bạn có thể được đóng gói sẵn trong trình duyệt dưới dạng chỉ-HTTPS trước khi bất kỳ người dùng nào từng truy cập trang của bạn.

Điều đó đóng khoảng trống “lần truy cập đầu tiên”, nhưng khó đảo ngược hơn nhiều. Việc gỡ khỏi danh sách preload có thể mất vài tuần hoặc vài tháng mới đến được người dùng, tùy theo chu kỳ phát hành của trình duyệt. Preload phù hợp với các domain ổn định, trưởng thành. Nó không phù hợp với một site vẫn đang khám phá danh mục subdomain của mình.

Một kế hoạch triển khai an toàn

Step 1: Kiểm tra mọi hostname bạn kiểm soát

Trước khi đặt includeSubDomains, hãy liệt kê mọi hostname bên dưới domain. Bản ghi DNS là điểm khởi đầu, nhưng không phải toàn bộ câu chuyện. Hãy kiểm tra cấu hình CDN, dashboard hosting, hostname liên quan đến email, công cụ marketing cũ, storage bucket, và tài liệu nội bộ.

Với mỗi hostname, hãy trả lời:

  • Nó phục vụ HTTP, HTTPS, hay cả hai?
  • Chứng chỉ HTTPS có hợp lệ và được gia hạn tự động không?
  • Nó có chuyển hướng HTTP sang HTTPS sạch sẽ không?
  • Nó có được dự định công khai không?
  • Nó còn cần thiết không?

Nếu nhóm của bạn đã có thói quen debug header production, việc này sẽ nằm tự nhiên bên cạnh các bước kiểm tra redirect và header. Chúng tôi đã đề cập quy trình đó trong một bộ công cụ nhỏ để debug redirect và HTTP header trong production.

Step 2: Sửa HTTPS trước khi thêm HSTS

HSTS không làm cho một thiết lập HTTPS hỏng trở nên an toàn. Nó chỉ làm cho HTTPS trở thành bắt buộc.

Trước khi bật nó, hãy xác minh:

  • Chứng chỉ TLS bao phủ đúng hostname.
  • Chứng chỉ được gia hạn tự động.
  • HTTP chuyển hướng sang HTTPS bằng một bước nhảy sạch duy nhất khi có thể.
  • Chuyển hướng host canonical nhất quán, ví dụ từ non-www sang www, hoặc ngược lại.
  • Asset của ứng dụng không phụ thuộc vào URL http:// không an toàn.

Mixed content ít phổ biến hơn trước đây, nhưng vẫn xuất hiện trong theme CMS cũ, snippet analytics, media nhúng, và đường dẫn ảnh được hard-code.

Step 3: Bắt đầu với max-age rất ngắn

Đừng bắt đầu bằng một năm. Hãy bắt đầu bằng năm phút:

Strict-Transport-Security: max-age=300

Chỉ triển khai điều đó trên hostname bạn đang kiểm thử, thường là website production canonical. Tạm thời bỏ qua includeSubDomains.

Sau đó kiểm thử trong trình duyệt thật và bằng yêu cầu dòng lệnh:

curl -I https://example.com

Bạn nên thấy đúng một header Strict-Transport-Security. Header HSTS bị lặp từ app server và CDN là nguồn gây nhầm lẫn phổ biến. Trình duyệt thường áp dụng chính sách hiệu lực, nhưng con người đang debug sự cố không cần thêm sự mơ hồ.

Step 4: Tăng dần

Nếu không có gì hỏng, hãy tăng thời lượng theo từng giai đoạn:

Strict-Transport-Security: max-age=86400

Sau đó:

Strict-Transport-Security: max-age=604800

Rồi có thể là:

Strict-Transport-Security: max-age=2592000

Một lịch trình thực tế là:

  • 5 phút
  • 1 ngày
  • 1 tuần
  • 1 tháng
  • 6 tháng hoặc 1 năm

Không có phần thưởng nào cho việc vội vàng. Toàn bộ ý nghĩa của triển khai theo giai đoạn là cho monitoring, hộp thư hỗ trợ, và các trường hợp biên có thời gian để nói cho bạn biết checklist của bạn đã bỏ sót gì.

Step 5: Chỉ thêm includeSubDomains sau khi audit là thực chất

Khi mọi subdomain công khai đã sẵn sàng cho HTTPS, bạn có thể cân nhắc:

Strict-Transport-Security: max-age=31536000; includeSubDomains

Đây là thời điểm cần thận trọng. Nếu một dịch vụ legacy vẫn cần HTTP, đừng thêm includeSubDomains vào domain cha. Hoặc di trú dịch vụ đó, chuyển nó sang domain khác, hoặc chấp nhận rằng chính sách HSTS của bạn hiện tại phải hẹp hơn.

Security header nên phản ánh thực tế. Chúng không nên được dùng như những tấm poster truyền động lực cho hạ tầng mà bạn hy vọng sẽ có sau này.

Step 6: Xem preload như một dự án riêng

Chỉ cân nhắc preload khi tất cả điều sau là đúng:

  • Domain và tất cả subdomain hỗ trợ HTTPS hợp lệ.
  • HTTP chuyển hướng sang HTTPS.
  • Header HSTS dùng max-age ít nhất 31536000 giây.
  • Header bao gồm includeSubDomains.
  • Header bao gồm preload.
  • Bạn tự tin rằng sẽ không cần HTTP thuần ở bất kỳ đâu bên dưới domain.

Một header sẵn sàng cho preload trông như sau:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Gửi vào danh sách preload là một cam kết dài hạn. Nếu site là microsite chiến dịch, domain sản phẩm tạm thời, hoặc domain có ranh giới sở hữu chưa rõ, hãy bỏ qua.

Ví dụ cấu hình

Nginx

Dùng always để header cũng được gửi trên các phản hồi lỗi:

add_header Strict-Transport-Security "max-age=300" always;

Sau khi triển khai ổn định:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Apache

Khi đã bật mod_headers:

Header always set Strict-Transport-Security "max-age=300"

Về sau:

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

CDN hoặc edge platform

Nếu CDN của bạn đặt response header, hãy ưu tiên quản lý HSTS ở một nơi. Đừng đặt một chính sách ở origin và một chính sách khác ở edge trừ khi bạn có lý do rất rõ ràng.

Cũng hãy kiểm tra liệu CDN có áp dụng header cho redirect, lỗi được cache, và trang lỗi tùy chỉnh hay không. Một site production không chỉ là phản hồi 200 OK của nó.

Cách hoàn tác HSTS an toàn

Nếu bạn cần tắt HSTS, hãy gửi:

Strict-Transport-Security: max-age=0

Nhưng có một điểm vướng: trình duyệt phải truy cập thành công site qua HTTPS hợp lệ để nhận header đó. Nếu bản thân HTTPS bị hỏng, người dùng có chính sách HSTS đã cache không thể lấy chỉ dẫn sẽ xóa nó.

Vì vậy thứ tự khôi phục thông thường là:

  1. Khôi phục HTTPS hợp lệ.
  2. Phục vụ Strict-Transport-Security: max-age=0.
  3. Giữ nó đủ lâu để người dùng quay lại nhận được.
  4. Gỡ hoặc thay thế header sau khi sự cố được giải quyết.

Nếu domain được preload, việc phục vụ max-age=0 là chưa đủ đối với hồ sơ trình duyệt mới. Bạn cũng cần yêu cầu gỡ khỏi danh sách preload và chờ thay đổi đó được phát hành qua các bản cập nhật trình duyệt.

Checklist kiểm thử trước khi phát hành

Hãy dùng checklist này trước khi tăng max-age hoặc thêm includeSubDomains:

  • URL HTTPS canonical trả về chứng chỉ hợp lệ.
  • HTTP chuyển hướng sang HTTPS.
  • Chỉ có một header HSTS.
  • Header xuất hiện trên redirect và phản hồi lỗi khi phù hợp.
  • Tất cả subdomain công khai có HTTPS hợp lệ.
  • Việc gia hạn chứng chỉ được giám sát.
  • Không có hệ thống nội bộ trọng yếu nào phụ thuộc vào HTTP dưới cùng domain cha.
  • Preload đã được thảo luận rõ ràng, không được thêm theo thói quen.

Lighthouse cũng có thể gắn cờ security header bị thiếu hoặc yếu trong một số ngữ cảnh, nhưng đó không nên là phương pháp xác minh duy nhất của bạn. Nếu bạn dùng nó như một phần của đánh giá rộng hơn, hãy đọc các phát hiện như tín hiệu thay vì phán quyết; cùng tư duy đó cũng áp dụng khi bạn đọc báo cáo Lighthouse mà không hoảng loạn.

<!-- tool-cta:start -->

💡 Hãy thử cách này: Trước và sau mỗi thay đổi HSTS, hãy kiểm tra phản hồi Strict-Transport-Security bằng Get Headers để xác nhận rằng max-age, includeSubDomains và preload đúng như bạn mong đợi.

<!-- tool-cta:end -->

Lý do quyền riêng tư cho HSTS

HSTS thường được mô tả như một security header, và đúng là vậy. Nó cũng có lợi ích về quyền riêng tư: nó giảm khả năng yêu cầu đầu tiên của người dùng bị rò rỉ qua HTTP thuần trên một mạng không đáng tin cậy.

Điều đó quan trọng trên Wi-Fi sân bay, mạng khách sạn, mạng khách doanh nghiệp, và bất kỳ nơi nào lưu lượng của người dùng có thể bị quan sát hoặc sửa đổi. Một yêu cầu HTTP thuần có thể lộ hostname, path, cookie không có cờ Secure, và các chi tiết yêu cầu khác. HTTPS không phải phép màu, nhưng việc bắt buộc nó một cách nhất quán sẽ loại bỏ cả một lớp rò rỉ có thể tránh được.

Những triển khai HSTS tốt nhất là những triển khai không có gì đáng chú ý. Chúng được triển khai chậm rãi, được chống lưng bởi chứng chỉ đáng tin cậy, và nhàm chán đến mức không ai để ý. Đó chính xác là điều bạn muốn từ một header mà chế độ lỗi của nó có thể rất kịch tính.

Câu hỏi thường gặp

Header HSTS đầu tiên an toàn là gì?
Hãy bắt đầu với `Strict-Transport-Security: max-age=300`. Điều đó cung cấp cho trình duyệt một chính sách năm phút, đủ dài để kiểm thử hành vi nhưng đủ ngắn để nhanh chóng khôi phục sau hầu hết sai sót.
Mọi site có nên dùng includeSubDomains không?
Không. Chỉ dùng `includeSubDomains` khi mọi subdomain dưới domain cha hỗ trợ HTTPS hợp lệ và sẽ tiếp tục như vậy. Một host legacy bị lãng quên có thể trở nên không thể truy cập đối với người dùng đã cache chính sách.
HSTS preload có cần thiết không?
Không cần với hầu hết site nhỏ hoặc vừa. Preload bảo vệ lần truy cập đầu tiên, nhưng khó đảo ngược và yêu cầu toàn bộ namespace của domain sẵn sàng cho HTTPS. Chỉ cân nhắc sau khi triển khai HSTS ổn định.
Tôi có thể gỡ HSTS bằng cách xóa header không?
Xóa header sẽ ngừng đặt chính sách mới, nhưng không xóa các chính sách đã được trình duyệt cache. Để xóa HSTS, hãy phục vụ `Strict-Transport-Security: max-age=0` qua HTTPS hợp lệ.
HSTS có sửa mixed content không?
Không. HSTS bắt buộc kết nối site cấp cao nhất dùng HTTPS. Bạn vẫn cần sửa riêng các URL asset không an toàn, nội dung nhúng, và các tham chiếu `http://` cũ được hard-code.

Nguồn & tài liệu tham khảo thêm

  1. MDN Web Docs: Strict-Transport-Security
  2. OWASP HTTP Strict Transport Security Cheat Sheet
  3. HSTS Preload Submission Requirements
  4. RFC 6797: HTTP Strict Transport Security
Về tác giả
The Wux Webtools Team

Cập nhật lần cuối:

Tiếp tục đọc