HTTPS on Stack Overflow: The End of a Long Road
Bài tóm tắt Stack Overflow 2017 3. Quy mô lớn Độ khó: Khó
Stack Overflow · 2017 · 3. Quy mô lớn · Độ khó: Khó — bài gốc
Nằm ngoài các bài đánh số của series, nhưng cho thấy tầng edge (CDN, DNS, TLS) phía trước kiến trúc trong Stack Overflow 2016.
Bối cảnh
- 22/5/2017: HTTPS thành mặc định trên Stack Overflow, site cuối cùng và lớn nhất của mạng; thao tác bật chỉ là một feature flag, nhưng chuẩn bị mất 4 năm (2013→2017).
- Theo tác giả, chậm vì hai lý do của mọi dự án IT: phụ thuộc và ưu tiên. Dữ liệu Stack Overflow phần lớn là công khai (DB được phát hành qua torrent mỗi quý), nên bảo mật một mình không đủ lý do để đầu tư.
- Các điểm khó đặc thù: hàng trăm domain nhiều cấp; nội dung do user nhúng (ảnh, YouTube); phục vụ từ một data center; mạng quảng cáo; hơn 500.000 websocket đồng thời; hay bị DDoS; nhiều API nội bộ gọi nhau qua HTTP.
Thay đổi chính
- Lý do thật là hiệu năng: HTTP/2 trên thực tế đòi HTTPS. Theo tác giả, động lực chính là hiệu năng chứ không phải bảo mật.
- Chứng chỉ: không dùng Let's Encrypt vì khi đó không có wildcard, mà mạng có hàng trăm domain. Dùng một chứng chỉ gộp mọi domain chính và wildcard (DigiCert), cài giống hệt ở cả load balancer và CDN để failover được. Domain dạng
meta.gaming.stackexchange.comkhông được wildcard phủ (RFC 6125), nên phải đổi sanggaming.meta.stackexchange.com, kéo theo việc xây hệ đăng nhập chung (Universal Login: cookie ở domain cấp hai, phát cho các domain khác qua<img>kèm nonce). - Cookie: khi cookie nằm ở domain gốc thì mọi subdomain đều nhận cookie. Mọi dịch vụ bên thứ ba dưới domain đó (link email SendGrid, blog marketing) phải dời ra domain khác để không lộ cookie; đó là lý do blog nằm ở
stackoverflow.blog. - HAProxy kết thúc TLS từ 2013 (HAProxy 1.5); bỏ lớp nginx đứng trước vì "đơn giản hơn thường tốt hơn". 4 process: 1 cho HTTP, 3 cho bắt tay TLS; frontend HTTPS nối vào backend HTTP qua abstract named socket.
- CDN/proxy để giảm độ trễ của một data center: cần một điểm kết thúc TLS gần user, chống DDoS và CDN.
- Đo trước khi chuyển: dựng pipeline client timings lấy dữ liệu
window.performancetừ 5% lượt xem trang, lưu vào SQL Server columnstore và gửi số tổng hợp sang Bosun; đến 2017 có hơn 5 tỷ điểm dữ liệu. - Thử bằng traffic thật: mua domain
teststackoverflow.com, nhúng<iframe>vào một phần lượt xem trang Stack Overflow để đo DNS và thời gian tải qua từng cấu hình, mỗi lần đo ít nhất 24 giờ. - Cloudflare: DNS nhanh hơn hẳn. Mỹ và Canada chậm hơn một chút vì thêm một hop, phần còn lại của thế giới bằng hoặc nhanh hơn. Phải thêm ISP riêng cho kết nối CDN (4 ISP mỗi data center, chạy BGP) và 2 load balancer riêng. Railgun (chỉ gửi phần diff của trang) không chạy ổn định sau hơn một năm thử, nên bỏ.
- Chuyển sang Fastly, theo tác giả vì cấu hình edge bằng VCL (Varnish) linh hoạt hơn, thay đổi lan nhanh hơn và tự động hoá được. Ví dụ: khi .NET 4.6.2 có bug đặt
max-agehơn 2000 năm, họ sửa header ngay ở edge cho mọi app.
- Đo trước khi chuyển: dựng pipeline client timings lấy dữ liệu
- DNS nhiều nhà cung cấp sau vụ Dyn 2016: viết DNSControl (cấu hình DNS bằng code JavaScript, đẩy toàn cầu dưới một phút) và httpUnit (test tích hợp cho endpoint: status, nội dung, chứng chỉ, firewall). Thay đổi load balancer được thử trên máy dự phòng qua dải VIP phụ (
keepctl), lỗi thì lật lại. - Mixed content: trước hết chặn nội dung
http://mới ("bịt lỗ rồi mới tát nước"), sau đó dọn phần cũ. Ảnh trong bài viết: đổi link imgur sang HTTPS hàng loạt; các ảnh còn lại thì thửhttps://, không được thì chuyển thành link thường. Không dựng proxy ảnh vì vướng bản quyền và chỉ còn vài nghìn ảnh trên hàng triệu. Hơn 1.000 link cứng trong code được đổi thànhSite.Url(), để tự chuyển sang HTTPS khi flag của site đó bật. - Rollout: meta.stackexchange → security → superuser (để đo tác động lên traffic từ Google), rồi toàn mạng trong 2 tháng. Redirect 302 trước, 301 sau; chỉ redirect GET/HEAD, không redirect request từ IP nội bộ. Theo tác giả, thay đổi thứ hạng tìm kiếm nằm trong mức dao động thường ngày.
- Websocket: chuyển
ws://sangwss://. Hơn 600.000 kết nối đồng thời, TLS session cache chiếm phần lớn bộ nhớ, HAProxy dùng 19 GB trên máy 64 GB (2017).
Sai lầm được kể lại
- URL tương đối giao thức (
//) vỡ trong email, API và app mobile, nên chuyển hết sanghttps://tuyệt đối với hai biến (gốc CDN, thư mục site). - API nội bộ đi vòng qua CDN: khi
stackoverflow.comtrỏ tới Fastly, một lệnh gọi nội bộ phải đi ra Internet, qua CDN rồi mới về. Họ thêm hậu tố.internal(ví dụstackoverflow.com.internal) phân giải về phía DMZ của load balancer; HAProxy bỏ hậu tố khỏi headerHost. Không dùng split-horizon DNS vì khó debug và khó xử lý khi có nhiều data center. - Fastly cache cả redirect 301 vì cache key mặc định không tính giao thức, dẫn tới vòng lặp redirect vô hạn. Sửa bằng cách thêm
Fastly-SSLvàoVary. - Backfill bài Help Center lấy nhầm post của site hiện tại thay vì site gốc, nên các trang trợ giúp hiện nội dung lạ trên toàn mạng.
- HSTS preload với
includeSubDomainschưa làm được: các domain meta cũ vẫn nhận khoảng 80.000 hit redirect mỗi ngày, và domain nội bộds.stackexchange.comcũng sẽ bị ép HTTPS.
Bài học cho SWE
- Một thay đổi "chỉ là cài chứng chỉ" chạm tới domain, cookie, đăng nhập, CDN, DNS, nội dung user và API nội bộ. Bật bằng feature flag theo từng site giúp rollout an toàn.
- Đo bằng traffic thật của user (RUM, iframe tới domain thử) trước khi đổi tầng edge.
- Khi đặt CDN trước site, phải nghĩ tới đường đi của traffic nội bộ.
- Kiến trúc một data center thuận lợi cho hiệu năng server nhưng bất lợi cho độ trễ tới user ở xa; CDN bù phần đó.
Liên quan
#HTTPS#HTTP/2#CDN#Cloudflare#Fastly#Varnish VCL#HAProxy TLS#Wildcard certificate#HSTS#Split-horizon DNS#Real user monitoring#DNSControl#httpUnit#Feature flag
Được nhắc tới trong
Công ty (1)