4 điểm bởi GN⁺ 2025-06-02 | 1 bình luận | Chia sẻ qua WhatsApp
  • 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.comkrei.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 pullgit push trê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à lnavgoaccess
  • lnav hiể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 $badagent là đúng thì chặn truy cập nội dung bằng return 403;
  • 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-forbidden tạ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

 
GN⁺ 2025-06-02
Ý 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-Agent là thật
    Cá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 theo
    Việ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

    • Câu cuối khá đúng
      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
    • Tôi tò mò liệu bạn có thể giải thích thêm về cách dùng robots.txt nà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 đến robots.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ông
      Tô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
    • Tôi vận hành một trong những wiki lớn nhất trong lĩnh vực của mình, và đã không thể thuyết phục những người khác trong đội phát triển dùng bom gzip làm biện pháp phòng thủ
      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.txt nữ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 đi

    • Nếu nói vậy thì bạn cũng phải bảo những người dùng chatbot, công cụ tìm kiếm, công cụ so sánh giá biến đi nốt. Vì chính họ là bên tạo động cơ tài chính cho scraper
    • Với những bot chịu khó lục lọi robots.txt thay vì chỉ phớt lờ, đặt honeypot là hữu ích
  • Vấ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.html
    Giờ 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

    • Semrush đã cư xử quá tệ ở nhiều mức độ bất tài trong thời gian dài, đến mức ít nhất từ 8 năm trước tôi đã để một ghi chú riêng trong file 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
    • Vì các yêu cầu của bot tiêu tốn đáng kể băng thông, bộ nhớ, CPU và dung lượng đĩa. Như phần mở đầu nói, đó đơn giản là lưu lượng truy cập thô lỗ, và không có lý do gì phải cung cấp traffic cho những kẻ thu thập như vậy
      Google cũng vận hành scraper AI, nên thứ bạn thấy ở đó có thể là cái đó
    • Chẳng phải trong 10 năm qua chúng ta đáng ra đã bắt đầu dạy mọi người rằng không nên dùng Google nữa sao?
      Đặ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
    • Cũng có tác nhân độc hại giả làm scraper của Google. Google từng có tiếng là cào dữ liệu lịch sự, nhưng nếu bạn vẫn nhận được lượng traffic cần thiết dù có Googlebot hay không, thì chẳng có lý do gì phải bận tâm
  • 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

    • “API chỉ có thể truy cập bằng cách click trên site” thì tôi tò mò không biết còn truy cập bằng cách nào khác nữa?
    • Tôi tò mò liệu bạn có thể chia sẻ thông tin về các crawler truy cập những API chỉ có thể dùng bằng cách click trên website không
      Để 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-Agent là đ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ậy
    99% 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

    • Chúng cũng tôn trọng robots.txt
      Tuy 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-Agent của trình duyệt từ IP dân dụng
      Như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)

    • Từ góc nhìn người dùng, họ phải chấp nhận false positive của bức tường chặn dựa trên “IP datacenter”. Nói cách khác, hầu hết môi trường không duyệt web một cách ngây thơ từ địa chỉ rò rỉ thông tin của đường truyền chặng cuối đều có thể bị vướng
      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
    • Tôi tò mò không biết các bạn xử lý thế nào khi ISP đang chuyển sang CGNAT. Trên thực tế, một IP có thể đại diện cho hàng trăm người dùng
    • Chúng tôi cũng đang phát triển tính năng chặn bot dựa trên dải IP công khai thông qua cùng dashboard đó. Rất hoan nghênh các đề xuất
  • 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

    • Tôi từng thấy cách ngược lại. Đặt ở footer của site một liên kết mà người dùng ít có khả năng click hoặc prefetch, và ngay khi robot GET liê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áp
    • Tôi không rõ với cách đó người dùng được cấp quyền sẽ truy cập như thế nào. Cần tính đến việc bạn muốn người dùng bình thường tìm thấy dự án từ trang kết quả tìm kiếm và có thể xem ngay mà không cần tạo tài khoản hay xác thực
    • Dù thiết kế thế nào thì cũng sẽ không thân thiện với người dùng. Nếu tôi lưu bookmark hoặc gửi link cho bạn bè, người đó sẽ thấy 404
  • Vì 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 fail2ban
    sudo 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 -t
    sshd-ddos: 0
    postfix: 583
    dovecot: 9690
    postfix-sasl: 4227
    nginx-botsearch: 1421
    nginx-http-auth: 0
    postfix-botnet: 5425
    sshd: 202157
    Trời, 220.000 IP bị chặn cơ đấy

    • Có một bot tự nhận là DotBot/1.2, và tính đến hôm nay nó đã gửi hơn 220.000 request trong 2 tuần qua
      Nó 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