Một đợt tấn công bằng scraper trên gói Free của Cloudflare: điều gì đã chặn đứng nó, và chúng tôi đã để những gì ở trạng thái tắt
Vận hành
Một buổi sáng, trang danh sách sản phẩm của chúng tôi không mở được nữa. Cloudflare hiển thị mã lỗi 524 cho người truy cập, máy chủ nguồn mất từ hai đến sáu phút cho mỗi trang, và không có gì báo cho chúng tôi trong khoảng mười giờ. Nguyên nhân là một scraper sử dụng các proxy dân cư với tốc độ khoảng 225 yêu cầu mỗi giây.
Hình dạng của đợt tấn công
- Hàng nghìn địa chỉ, mỗi địa chỉ một đến ba yêu cầu. Các kết nối băng thông rộng gia đình tại Mỹ, Tây Ban Nha, Pháp, Brazil, Anh và các nơi khác, loại lưu lượng mà một mạng lưới proxy dân cư cho thuê.
- Chrome user agent trên Mac, với các số phiên bản từ 103 đến 151.
- Hầu như không có cookie hoặc Referer. Trong 2.697 yêu cầu chúng tôi lấy mẫu tại máy chủ, chỉ 4 yêu cầu có cookie và 4 yêu cầu có Referer.
- Hai loại client. Khoảng một nửa không gửi các header
Sec-Fetch-*và không có client hints: một script với chuỗi user agent sao chép. Nửa còn lại gửi đầy đủ các header trình duyệt: một trình duyệt headless.
Mỗi trang đều được render cho mỗi yêu cầu, nên mỗi worker xếp hàng hàng trăm lần render và chạm ngưỡng giới hạn CPU.
Tại sao giới hạn theo từng địa chỉ không giúp ích được
Giới hạn tốc độ đếm số yêu cầu theo từng địa chỉ. Với một đến ba yêu cầu từ mỗi địa chỉ trong số hàng nghìn địa chỉ, không có địa chỉ đơn lẻ nào tiến gần đến giới hạn. Chặn các quốc gia sẽ chặn luôn cả khách truy cập của chúng tôi. Điều mà scraper không thể giả mạo với chi phí thấp là hành xử như một trình duyệt đã từng truy cập trang web trước đó.
Tại edge của Cloudflare: ba quy tắc miễn phí
Gói Free cho phép năm quy tắc WAF tùy chỉnh mỗi zone. Chúng tôi dùng ba quy tắc, tất cả đều dùng managed challenge thay vì block, để một người bị chặn nhầm có thể click qua:
- Trình duyệt giả: một GET mà user agent chứa
Chrome/và không có headerSec-Fetch-Mode. Mọi phiên bản Chrome từ năm 2019 đều gửi header này. - Các đám mây scraper: một yêu cầu trang từ các mạng của Alibaba, Tencent và Huawei Cloud, nơi phần lớn các yêu cầu chúng tôi cần challenge xuất phát.
- Khẩn cấp, mặc định tắt: một GET hoàn toàn không có cookie và không có Referer. Một người đã từng truy cập trang web, hoặc truy cập qua một liên kết, sẽ đi qua mà không bị ảnh hưởng; một scraper không lưu cookie sẽ gặp challenge ở mỗi yêu cầu. Chúng tôi chỉ bật nó khi có đợt tấn công, vì nó cũng challenge cả người gõ địa chỉ vào một trình duyệt mới tinh.
Cả ba đều cho phép bot đã xác minh của Cloudflare, các user agent tự nhận là robot, địa chỉ của chúng tôi, các đường dẫn API và webhook, cùng các tệp không phải trang. Hai ngày sau, đợt tấn công vẫn tiếp diễn: trong một giờ, quy tắc giả lập trình duyệt đã yêu cầu xác thực hơn 10.000 lượt truy cập. 10.000 sự kiện mà Cloudflare trả về mỗi lần truy vấn đến từ 9.627 địa chỉ, không địa chỉ nào vượt quá 4.
Tại máy chủ gốc: một cổng kiểm soát trong ứng dụng
Phần chạy nền (headless) có đầy đủ tiêu đề trình duyệt, nên các quy tắc ở biên (edge) không chặn được khi quy tắc khẩn cấp đang tắt. Trong chính ứng dụng, chúng tôi đặt một middleware nhỏ phía trước bộ kết xuất trang:
- một user agent Chrome thiếu cả
Sec-Fetch-Modelẫn client hints sẽ nhận mã lỗi 403 trước khi bất kỳ xử lý nào diễn ra; - một người lạ, không có cookie của chúng tôi và không có Referer, chỉ được phục vụ khi worker còn dư năng lực, với tốc độ vài trang mỗi giây. Vượt quá ngưỡng đó, một trang 503 dài 400 byte sẽ đặt cookie và tải lại sau hai giây. Người dùng thật sẽ thấy trang ở lần thử thứ hai; một scraper không lưu cookie thì không bao giờ thấy.
Trong phút đầu tiên, cổng kiểm soát đã từ chối khoảng 6.700 trình duyệt giả và chặn khoảng 6.700 người lạ, trong khi phục vụ người lạ khoảng 9 trang mỗi giây. Các yêu cầu chậm giảm về không, CPU của worker giảm từ mức giới hạn xuống 12 đến 15 phần trăm, và bộ nhớ từ 4 đến 5 GB mỗi worker xuống còn 0,65 GB.
Những gì chúng tôi để tắt
- Bot Fight Mode. Nó yêu cầu xác thực lưu lượng tự động và không thể bỏ qua bằng quy tắc tùy chỉnh trên gói Free, đồng thời nó đã chặn webhook của nhà cung cấp thanh toán của chúng tôi.
- Chế độ Under Attack cho toàn bộ zone. Nó đưa mọi khách truy cập, client API và webhook qua trang trung gian. Quy tắc khẩn cấp làm công việc tương tự nhưng chỉ dành cho yêu cầu trang của người lạ.
- Quy tắc giới hạn tần suất của gói Free. Nó đếm theo địa chỉ, điều mà đợt tấn công này không bao giờ kích hoạt.
- Chặn crawler AI. Chúng tôi muốn được các trợ lý tìm kiếm AI tìm thấy, và những crawler đó không phải là vấn đề.
Bài học rút ra
Một đợt tấn công qua proxy dân cư dễ nhận biết nhờ những gì nó thiếu: tiêu đề fetch của trình duyệt, cookie và Referer. Hãy yêu cầu xác thực ở biên, giữ số lượng người lạ trong phạm vi worker của bạn có thể kết xuất, và đảm bảo có thứ gì đó bên ngoài máy chủ phát hiện khi trang ngừng mở. Night Watch đóng gói cả ba: bộ giám sát, các quy tắc kèm công tắc tự động cho quy tắc khẩn cấp, và cổng kiểm soát cho các ứng dụng web Python.