Huy động mọi công cụ nhỏ để chặn bot
(lambdacreate.com)- Gitea và blog trên máy chủ cá nhân bị lưu lượng scraping đè nặng, liên tục phát cảnh báo đĩa, CPU và bộ nhớ; người vận hành đã kết hợp phân tích log, Nginx và Fail2Ban để phòng thủ
- Theo Zabbix, lưu lượng tăng mạnh so với bình thường; trung bình một tháng của Nginx là 8 request/giây, còn giai đoạn tệ nhất lên tới hơn 20 request/giây
- Nguyên nhân không phải một đợt truy cập đột biến từ một nguồn duy nhất như Reddit hay Hacker News, mà giống scraping phân tán hơn, khi nhiều dải IP quét các URL của
www.lambdacreate.comvàkrei.lambdacreate.com - Nginx trả về 403 cho các user agent độc hại đã biết và áp dụng giới hạn request theo IP; các client tạo quá nhiều 403 bị Fail2Ban chặn trong 24 giờ
- Tại thời điểm viết, danh sách chặn đã tăng lên tổng cộng 735 lượt ban; đặc biệt, các request cố tạo tarball cho mọi commit trong các kho công khai của Gitea làm tăng tải cho máy chủ
Lưu lượng scraping gây áp lực lên máy chủ cá nhân
- Lưu lượng bot không mong muốn bất ngờ đổ vào không gian Internet cá nhân, ảnh hưởng cả các dịch vụ mà độc giả thật sự cần truy cập
- Các dịch vụ lập chỉ mục nhằm bảo tồn website như Archive.org được xem là đối tượng được phép, nhưng Amazon, Facebook, OpenAI và nhiều bot ngẫu nhiên khác được phân loại là những bên tiêu thụ nội dung cho mục đích riêng của họ
- Cho rằng việc các tập đoàn lớn thu thập dữ liệu Internet trên diện rộng và nhu cầu dữ liệu để huấn luyện mô hình AI đã làm áp lực scraping gia tăng hơn nữa
- Lưu lượng này không phải người tiêu dùng thực sự của Lambdacreate, mà được xem là yếu tố gây cản trở khả năng truy cập của độc giả con người
Zabbix phát hiện dấu hiệu bất thường đầu tiên
- Công cụ đầu tiên báo vấn đề là Zabbix, với cảnh báo rằng ổ đĩa dành cho container đã đầy
- Trong môi trường dựa trên LXD, người vận hành đã mở rộng ZFS sparse file, tạm đưa site xuống rồi bật lại, nhưng nguyên nhân gốc vẫn còn
- Sau đó, instance Gitea tiêu thụ hết dung lượng đĩa mỗi ngày, tạo ra 20–30GB dữ liệu mỗi ngày
- Ban đầu, vấn đề được cho là do Gitea không bật mặc định việc dọn dẹp archive của repository, nên tác giả đã cấu hình tác vụ dọn dẹp mạnh tay
- Không lâu sau, cảnh báo CPU và bộ nhớ cũng xuất hiện; việc
git pullvàgit pushtrên Gitea trở nên khó khăn, còn client weechat cũng không giữ được kết nối
Số request tăng lên mức gấp 10 lần bình thường
- Nhờ có giám sát out-of-band để so sánh chỉ số quá khứ với trạng thái hiện tại, mẫu bất thường đã được xác nhận
- Trên dashboard Zabbix, các chỉ số cốt lõi là số request Nginx và biểu đồ thông lượng mạng
- Tính theo một tháng, lượng request Nginx trung bình ở mức 8 request/giây
- Vào thời điểm tệ nhất, máy chủ nhận hơn 20 request/giây; tuy nhỏ theo chuẩn các dịch vụ lớn, nhưng với máy chủ cá nhân thì đó là mức gấp 10 lần bình thường nên tác động rất lớn
- Không chỉ số request đơn thuần, mức sử dụng đĩa và CPU liên quan đến Gitea cũng tăng cùng lúc, khiến gánh nặng vận hành máy chủ lớn hơn
Truy vết log bằng lnav và goaccess
- Để giữ máy chủ sống đủ lâu cho việc xem log, người vận hành tạm tắt container và Nginx rồi bắt đầu phân tích
- Các công cụ được dùng là lnav và goaccess
lnavhiển thị file log trong TUI có tô màu, đồng thời cung cấp một lớp trừu tượng trên các định dạng log phổ biến để có thể truy vấn log bằng SQL- Trong
access.log, việc kiểm tra tập trung vào các câu hỏi sau- Có bao nhiêu IP truy cập tổng cộng
- Có mẫu hình nào trong địa chỉ IP hay không
- Lưu lượng có đến từ một referrer cụ thể không
- Những user agent nào được sử dụng
- IP nào gắn với user agent nào
- Kết quả phân tích cho thấy đây không phải “hug of death” đến từ một referrer duy nhất, mà là nhiều dải IP đang quét URL trên toàn bộ site
Trả 403 dựa trên user agent và giới hạn request
- Biện pháp đầu tiên là liệt kê các user agent gây vấn đề trong Nginx và trả về 403
- Cấu hình ví dụ dùng
map $http_user_agent $badagentđể đánh dấu các agent nhưAdsBot-Google,Amazonbot,Amazonbot/0.1 - Trong cấu hình Nginx mặc định, các quy tắc user agent được include, đồng thời thiết lập cả rate limit theo IP
- Cấu hình virtual host bao gồm các hành vi sau
- Áp dụng giới hạn request bằng
limit_req zone=krei burst=20 nodelay; - Nếu
$badagentlà đúng thì chặn truy cập nội dung bằngreturn 403;
- Áp dụng giới hạn request bằng
- Cách này giúp giảm xử lý ở backend, nhưng vì máy chủ vẫn phải nhận request HTTP và xử lý 403, nên khi có lượng lớn request đồng thời thì vẫn còn gánh nặng
Tự động hóa chặn bằng tường lửa với Fail2Ban
- Sau khi log 403 tích lũy, có thể dùng
lnavđể kiểm tra các IP duy nhất đã nhận 403 goaccessđược dùng để phân tích log cũ và hiện tại cùng nhau, nhằm xác định số request vào máy chủ và các endpoint bị nhắm tới nhiều nhất- Để bảo vệ máy chủ thực tế, Fail2Ban được bổ sung
- Quy tắc Fail2Ban là một dạng đơn giản, bắt các IP tạo quá nhiều phản hồi 403 trong access log của Nginx
- Thời gian chặn được đặt là 86400 giây, tức 24 giờ
- Kết quả
fail2ban-client status nginx-forbiddentại thời điểm viết như sau- Lỗi hiện tại: 13
- Tổng số lỗi: 57135
- Đang bị chặn: 38
- Tổng số lần chặn: 735
Mục tiêu thực sự không phải blog mà là tạo tarball trên Gitea
- Cuối cùng, độc giả đã có thể truy cập lại blog và các dịch vụ khác của Lambdacreate
- Trong tình huống phải chặn lưu lượng robot, ngay cả việc viết bài blog cũng trở nên khó khăn
- Lưu lượng gây vấn đề không phải scraping blog, mà nhắm vào việc tạo tarball cho mọi commit trong từng kho công khai của instance Gitea
- Về dài hạn, tác giả dự định cân nhắc mở rộng danh sách chặn hoặc đặt ngoại lệ cho các dịch vụ hợp pháp như Archive.org
- Lập trường là không muốn nội dung biến mất khỏi công cụ tìm kiếm, nhưng cũng không muốn để nó trở thành nhiên liệu cho sự xuống cấp của Internet do AI
1 bình luận
Ý kiến trên Hacker News
Có vẻ khá nhiều crawler kém lương thiện đang giả mạo các crawler lớn. Cảm giác như nhiều người mặc định rằng
User-Agentlà thậtCách tôi thích nhất là đặt thông tin mồi nhử trong
robots.txt, để URL đó tải xuống một bom gzip, rồi tự động chặn các yêu cầu tiếp theoViệc cấu hình trong Caddy khá dễ, và nó bắt được những crawler tệ nhất rất tốt
Tôi không bênh vực hành vi của bot, nhưng nếu vài bot có thể làm sập site chỉ bằng các yêu cầu mù quáng, thì một kẻ tấn công ác ý còn có thể phá hoại hăng hơn nhiều
Không biết có phải vì tôi khác thế hệ với những người viết các bài blog kiểu này không, nhưng tôi khó hiểu được sự ám ảnh với mức sử dụng tài nguyên thấp như vậy
Nó giống cảm giác thấy ông bà nổi giận vì không tắt đèn LED, hoặc lái xe 15 dặm chỉ để tiết kiệm 5 cent mỗi gallon
20 yêu cầu mỗi giây thật sự chẳng là gì
Ngay cả khi mọi thứ đều được tạo động, tôi cũng không hiểu vì sao lại làm thế từ đầu, và lẽ ra dành thời gian sửa caching thì tốt hơn nhiều
Tôi hiểu là trong bầu không khí hiện nay, các bài kiểu “bot biến đi” đang được ưa chuộng, nhưng chuyện này cũng chẳng mới mẻ gì
Có nhiều cách xử lý hiệu quả hơn mà lãng phí ít thời gian hơn nhiều
robots.txtnày không. Theo tôi biết thì hầu hết AI hoàn toàn phớt lờ nội dung liên quan đếnrobots.txt, nên thực tế có phải nó chỉ đánh trúng các bot cố gắng tuân thủ hay khôngTôi không phản đối như một số người khác ở đây, chỉ tò mò cách triển khai mà không làm hại các tác nhân hành xử đúng đắn
Họ tin rằng nó có thể trở thành trách nhiệm pháp lý nguy hiểm và không đáng thử. Tôi thật sự tò mò liệu có website công khai thực tế nào dùng cách này không
Thật bực mình khi các bot giờ hoàn toàn không còn tôn trọng file
robots.txtnữa. Những người tạo ra mấy thứ này đúng là kẻ xấu hoàn toàn. Nếu bạn là một trong số đó thì tự biết mà biến đirobots.txtthay vì chỉ phớt lờ, đặt honeypot là hữu íchVấn đề dung lượng đĩa theo tôi là lỗi của Gitea. Khi ai đó tải zip, lẽ ra nó phải stream tới client, nhưng thực tế lại tạo zip trong vùng tạm, phục vụ cho client rồi không xóa
Tôi đã xử lý bằng cách đánh dấu thư mục đó là chỉ đọc. Dĩ nhiên tải zip sẽ không hoạt động. Nếu thật sự cần thì cứ checkout repository rồi tự tạo
Nếu tôi thật sự quan tâm, tôi đã sửa lỗi, hoặc tìm cách tắt tính năng cho đúng, hoặc chỉ bật cho người dùng đã đăng nhập
Ngoài ra tôi chuyển hướng một số
User-Agentở phía server tới https://git.immibis.com/gptblock.htmlGiờ không phải vì lãng phí tài nguyên, mà đơn giản là vì tôi không thích. Việc họ làm dù sao cũng vô giá trị, và tôi làm vì tôi có thể
Nếu thật sự cần dữ liệu của Git repository, thì đừng cào một cách ngu ngốc, hãy clone Git repository. Việc đó vốn đã được cho phép
8 yêu cầu mỗi giây không nhiều lắm trừ khi mỗi yêu cầu gây ra xử lý nặng, và thực tế ngoài lỗi dung lượng đĩa thì nó cũng không tạo tải đáng kể lên VPS nhỏ
Tôi chặn không phải vì đó là DoS, mà vì nó ngu ngốc
Tôi hiểu việc tác giả “không còn quan tâm nữa”, nhưng tôi thấy trong các IP bị chặn có Google, ripe.net, semrush
Nếu muốn người khác thấy và nói về nội dung, thì trong số này chắc chắn tôi sẽ không chặn Google, và phần còn lại có lẽ cũng không
Ngay cả khi nội dung bị bot AI của ai đó cào, tôi không hiểu vì sao lại vận hành một site công khai mà không kỳ vọng site được sử dụng
Tắt đèn biển hiệu nhà nghỉ trong khi mong khách ghé vào không phải là cách mời gọi tốt
robots.txt, và cuối cùng khiến người bên pháp lý chú ýViệc cho phép một công ty ‘SEO’ giẫm nát site một cách thô bạo và đẩy người dùng thật ra ngoài chẳng đem lại giá trị gì cho tôi hay người dùng tiềm năng
Một số đối thủ của Semrush cũng tệ y hệt
Mớ hỗn loạn AI hiện tại cũng rất kém. Ít nhất trong một trường hợp nổi tiếng, phải gửi không chỉ các biện pháp kỹ thuật mà cả ghi chú pháp lý tới bộ phận quan hệ nhà đầu tư và PR thì trật tự mới được khôi phục phần nào
Google cũng vận hành scraper AI, nên thứ bạn thấy ở đó có thể là cái đó
Đặc biệt là khi chuyện như thế này xảy ra
Google đang dùng AI để kiểm duyệt các website độc lập như của tôi
https://news.ycombinator.com/item?id=44124820
Nghe như giờ đã đến điểm Google trở thành một gánh nặng lớn hơn
Vì các bot này mà log phình ra quá nhanh, nên tôi đã tắt logging trên server. Chúng thật sự dai dẳng, điền mọi form và gọi cả những API chỉ có thể truy cập bằng cách click trên site
Anthropic, OpenAI, Facebook hiện vẫn đang tiếp tục cào
Để xác nhận, ý bạn là vì nó là một phần của UI nên chỉ con người mới nên bấm, và không có cách nào khác để truy cập API đó đúng không?
Giờ các AI agent đã tồn tại, nên nếu chúng bắt chước mẫu hành vi của con người thì về thực tế gần như không còn cách nào phân biệt người dùng thật với bot
Việc các bot crawler AI điền trung thực header
User-Agentlà điều tốt. Nhưng thật ngạc nhiên khi đó lại là nguyên nhân của lượng traffic lớn như vậy99% toàn bộ website không thay đổi thường xuyên đến mức cần lượng traffic như thế, và blog của lập trình viên thì càng không
robots.txtTuy nhiên tôi cũng từng thấy báo cáo rằng sau khi bị chặn bằng cách nào đó, chúng bắt đầu crawl bằng
User-Agentcủa trình duyệt từ IP dân dụngNhưng cũng có khả năng ngay từ đầu đã có ai đó giả mạo crawler của mình thành OpenAI/Amazon/Facebook, v.v.
Tôi là người tạo ra tirreno [1]
Nền tảng của chúng tôi chủ yếu được thiết kế cho người dùng đăng nhập theo thời gian thực, nhưng cũng hoạt động tốt cho phát hiện và chặn bot
Nó ẩn danh hóa địa chỉ IP bằng cách thay octet cuối bằng dấu sao, và trên thực tế gom cùng một subnet vào dưới một tài khoản
Sau đó, bằng rule engine tích hợp sẵn, có thể tự động tạo danh sách chặn theo các điều kiện như quá nhiều lỗi 500/404, thử đăng nhập brute-force, traffic từ IP datacenter
Cuối cùng, có thể tích hợp API danh sách chặn của tirreno vào logic ứng dụng để redirect traffic không mong muốn sang trang lỗi
Thêm nữa, chúng tôi cũng cung cấp dashboard [2] để theo dõi hoạt động và tinh chỉnh danh sách nhằm tránh chặn nhầm người dùng hợp lệ
[1] https://github.com/tirrenotechnologies/tirreno
[2] https://play.tirreno.com/login (admin/tirreno)
Dù có tìm được thứ gì đó chưa bị chặn trước, hoặc vượt qua bằng cách bấm 87 ô đèn giao thông, họ vẫn bị gom chung với những hàng xóm địa chỉ hoàn toàn không liên quan
Cách này trông giống như một cách tự trấn an lương tâm rằng mình không xử lý thông tin cá nhân mà không có sự đồng ý để tạo hệ thống giám sát người dùng
Tôi thật sự mong các bạn có quy trình phản hồi đủ tốt để khách hàng thấy rằng họ đang mất những khách hàng thật sự có chi tiền
Các site của tôi nhận khoảng 10.000–20.000 request mỗi ngày. Phần lớn là AI scraper
Một điểm đáng chú ý là nhiều bot tìm các trang PHP cụ thể. Nếu không dùng PHP, bạn có thể tự động chặn các IP request trang PHP. Nếu có dùng PHP, chỉ cần chặn các IP request những trang thực tế không tồn tại
Một số người trong chúng tôi sẵn lòng cho phép huấn luyện AI, nhưng muốn ngăn quá tải. Ví dụ, tôi rất vui nếu các trang về Phúc âm và thần học Kinh Thánh được scrape
Với nội dung lớn mà bạn không muốn bị scrape, việc đặt chúng trong một thư mục cụ thể có thể hữu ích. Sau đó nếu phát hiện bot, chỉ cần chặn IP đó truy cập thư mục ấy
Trường hợp của tôi cũng có chiến lược cơ bản để xử lý nhiều request: chỉ văn bản, trình bày bằng HTML/CSS, các thành phần khác được host bên ngoài, và dùng Perma-Cache của BunnyCDN ($10/tháng + 1 cent mỗi GB)
Request từ BunnyCDN đi tới VM $5/tháng trên Digital Ocean. Lúc đầu tôi thậm chí không nhận ra các AI scraper, vì chúng không ảnh hưởng đến hiệu năng, và trong một tháng số dư chỉ đổi từ $30 xuống $29,99
Tôi từng tự hỏi liệu có thứ gì giống “page knocking” không. Kiểu như mở nhiều trang theo một thứ tự nhất định thì sẽ có quyền truy cập
Ví dụ, nếu không bắt đầu bằng một URL không công khai cụ thể thì mọi thứ đều trả 404
GETliên kết đó thì biến phần còn lại của site thành những điều vô nghĩa nhưng hợp lệ về mặt cú phápVì server nhỏ của tôi cứ âm thầm chạy ổn, gần đây tôi không kiểm tra trạng thái
fail2bansudo fail2ban-client status | sed -n '/Jail list:/{s/^.*://; s/,//g; p}' | xargs -n1 sudo fail2ban-client status | awk '/jail:/{i=$5}; /Total failed:/{jail[i]=$5}; END{for(i in jail) printf("%s: %s\n", i, jail[i])}' | column -tsshd-ddos: 0postfix: 583dovecot: 9690postfix-sasl: 4227nginx-botsearch: 1421nginx-http-auth: 0postfix-botnet: 5425sshd: 202157Trời, 220.000 IP bị chặn cơ đấy
DotBot/1.2, và tính đến hôm nay nó đã gửi hơn 220.000 request trong 2 tuần quaNó request ngẫu nhiên tên file và thư mục trên web server
Tôi đang không chặn mà quan sát, vì tò mò không biết nó đào sâu đến mức nào và có giới hạn không