4 điểm bởi GN⁺ 2025-11-17 | 1 bình luận | Chia sẻ qua WhatsApp
  • Bài viết bàn về vấn đề các bot scraper gửi yêu cầu quá mức lên website công khai đến mức hoạt động như DDoS, đồng thời đưa ra một cách tiếp cận mang tính thử nghiệm để lợi dụng ngược lại và khiến chúng lãng phí thời gian
  • Tác giả tạo một trình sinh văn bản dựa trên chuỗi Markov để tạo dữ liệu giả trông giống các tệp .php, nhằm dụ bot độc hại tải chúng xuống
  • Sau đó xây dựng máy chủ nội dung tĩnh để trả về ngẫu nhiên các đoạn trong tiểu thuyết Frankenstein, được thiết kế với cấu trúc liên kết khiến crawler lan rộng theo cấp số nhân
  • Thêm thuộc tính noindex, nofollow và bộ đếm số lần yêu cầu vào mọi trang để loại trừ công cụ tìm kiếm bình thường và chỉ bắt các bot vi phạm quy tắc
  • Kết quả thử nghiệm khá thú vị, nhưng do rủi ro nhận diện nhầm Googlebot, tác giả không áp dụng vào dịch vụ thực tế mà chỉ giữ như một dự án học tập và thử nghiệm

Vấn đề bot scraper và ý tưởng đối phó

  • Scraper vô tình gây ra mức tải cỡ DDoS lên các website nhỏ
  • Một số quản trị viên đã hỏi cách tự bảo vệ, nhưng bài viết này tập trung vào “phản công thay vì phòng thủ”
  • Sau khi thấy một lập trình viên khác dùng chuỗi Markov để tạo vô hạn dữ liệu giả nhằm đánh lừa bot, tác giả bắt đầu tự thử nghiệm

Trình sinh PHP giả dựa trên chuỗi Markov

  • Tác giả triển khai bộ học chuỗi Markov bằng Rust để tạo nội dung trông chân thực từ dữ liệu văn bản tùy ý
  • Nhắm vào các bot độc hại tìm những đường dẫn dễ tổn thương như .env, .aws, .php, tác giả cung cấp mã PHP giả nhìn như thật nhưng vô nghĩa
  • Tăng kích thước tệp từ 2KB lên 10MB để buộc bot lãng phí tài nguyên
  • Kết quả đầu ra mẫu có dạng mã PHP giả trông khá thuyết phục, trộn lẫn tên hàm WordPress và chú thích
  • Mục tiêu là làm bot lãng phí thời gian, tài nguyên, đồng thời khiến kẻ tấn công tốn công tìm kiếm các lỗ hổng không có thật

Thử nghiệm hiệu quả và cung cấp dữ liệu tĩnh

  • Khi phục vụ tệp lớn hơn 1MB trên VPS, tác giả gặp độ trễ phản hồi và tải máy chủ tăng lên
  • Để giải quyết, tác giả xây dựng một “garbage server” dạng website tĩnh
    • Tải toàn bộ tiểu thuyết Frankenstein vào bộ nhớ và trả về ngẫu nhiên 4 đoạn văn cho mỗi yêu cầu
    • Thêm 5 liên kết ở cuối mỗi trang để kích thích crawler lan rộng bùng nổ (tăng theo bội số 5)
  • Có thể xem kết quả tại https://herm.app/babbler/

Chi tiết thiết kế và cách vận hành

  • Cuốn tiểu thuyết được chọn thuộc phạm vi công cộng, và được dùng vì tác giả làm dự án vào mùa Halloween cũng như thấy sự tương đồng giữa AI và Frankenstein
  • Mọi trang đều được gắn noindex,nofollow để chỉ bắt các bot vi phạm quy tắc
  • Ở cuối mỗi trang có hiển thị bộ đếm số lần yêu cầu, và bộ đếm này sẽ được đặt lại khi triển khai vì lưu trong bộ nhớ
  • Tác giả cũng dựng máy chủ riêng cho các yêu cầu .php, để trả ngẫu nhiên các tệp PHP thật từ bộ nhớ
  • Dự án được tóm gọn bằng câu: “Garbage for the garbage king!”

Rủi ro và giới hạn

  • Hệ thống này có rủi ro nhận diện nhầm công cụ tìm kiếm nếu áp dụng vào dịch vụ thực tế
    • Nếu Googlebot quét nhầm endpoint, website có thể bị phân loại là trang spam
    • Điều này có thể dẫn tới giảm hiển thị trên tìm kiếm hoặc hiện cảnh báo trên Chrome
  • Vì vậy, tác giả không khuyến nghị cho các website phụ thuộc vào tìm kiếm, mà chỉ vận hành như dự án thử nghiệm
  • Trình babbler cho .php không phải HTML nên không ảnh hưởng tới Googlebot, chỉ nhắm vào bot độc hại

Kết lại và quan điểm cá nhân

  • Để nhử scraper độc hại, tác giả thêm các liên kết ẩn (rel="nofollow") vào blog
  • Nếu VPS vượt giới hạn băng thông, tác giả cân nhắc dùng Cloudflare cache
  • Thông qua dự án này, tác giả học thêm về chuỗi Markov và nguyên lý hoạt động của bot, trong một thử nghiệm vừa vui vừa bực bội
  • Kết luận là không phải mọi thử nghiệm đều cần thực dụng, đôi khi chỉ để vui thôi cũng đủ

1 bình luận

 
GN⁺ 2025-11-17
Ý kiến trên Hacker News
  • Dù thế giới có thay đổi thì cuối cùng vẫn gặp những vấn đề tương tự
    10~15 năm trước tôi từng phải đối phó với các dịch vụ giám sát mạng xã hội. Các thương hiệu lớn trả tiền cho họ để theo dõi cảm xúc trên diễn đàn, và họ tự ý cào dữ liệu từ cộng đồng miễn phí mà tôi vận hành, gây tải cho máy chủ.
    Dù tôi chặn bot của họ thì chúng vẫn quay lại với IP và UA khác, nên tôi đã tạo một bộ lọc chèn ngẫu nhiên tên thương hiệu vào bài viết để phá hỏng chất lượng dữ liệu của họ. Sau khi bật biện pháp này, việc scrape đã dừng hẳn chỉ trong hai ngày

    • Tôi cũng có trải nghiệm tương tự. Từng có bot dùng biểu mẫu quyên góp trên site của tôi để test thẻ tín dụng, chúng liên tục thử bằng cách đổi IP. Vì vậy thay vì chặn, tôi trả về ngẫu nhiên thông báo thành công/thất bại, khiến dữ liệu của chúng bị nhiễm bẩn và chúng bỏ cuộc sau vài ngày
    • Câu chuyện phân tích header thực sự rất hữu ích. Trên máy chủ Fediverse của tôi, tôi cũng phát hiện các bot dùng UA Chrome cũ không gửi header Accept-Language chút nào. Sau khi cấu hình nginx trả về 403, lưu lượng bắt đầu giảm
    • Giống như trong phim The Imitation Game, nếu phản ứng ngay lập tức với mọi request thì đối phương sẽ nhận ra. Nếu chỉ xử lý một phần request hoặc trả về mã lỗi ngẫu nhiên thì sẽ khó bị phát hiện hơn nhiều, đồng thời khiến việc debug của chúng khó hơn đáng kể
    • Phần lớn bot vẫn không thể mô phỏng đúng bộ header HTTP. Đến năm 2025 tôi vẫn lọc theo cách này, và bot vẫn tiếp tục tiến hóa theo cùng một kiểu mẫu
    • Tôi thắc mắc vì sao việc chèn tên công ty lại khiến bot biến mất. Tôi muốn hỏi liệu có phải trong quá trình chúng tìm các lần nhắc đến thương hiệu, tín hiệu dữ liệu đã bị nhiễm bẩn nên mới như vậy không
  • Những bot này không thực sự parse file PHP, mà dùng sự tồn tại của chúng để tạo dấu vân tay (fingerprinting) phục vụ dò lỗ hổng. Chúng chỉ nhìn mã phản hồi rồi bỏ qua ngay

    • Đúng vậy, trong trường hợp này các công cụ như fail2ban hoặc crowdsec sẽ hiệu quả hơn. Sau khi dùng crowdsec, tôi mới nhận ra ngay cả máy chủ ít traffic cũng có vô số nỗ lực dò lỗ hổng
    • Nếu vậy thì có lẽ cũng có thể cố ý lộ ra lỗ hổng giả để nhử bot. Ví dụ, kéo bot tự động vào honeypot (honeybot) để quan sát hoạt động bên trong của chúng. Tham khảo: The Cuckoo’s Egg
    • Nếu các scraper LLM dùng những phản hồi này làm dữ liệu huấn luyện, rủi ro nhiễm độc dữ liệu (poisoning) có thể còn lớn hơn. Một số bài báo gần đây cũng nói rằng chỉ vài điểm dữ liệu thôi cũng có thể làm hỏng mô hình
  • Gần đây tôi có nghe về tarpit cho AI và scraper. Cách này là không ngắt kết nối mà gửi vô hạn dữ liệu với tốc độ cực chậm. Công cụ Nepenthes khá thú vị, tôi muốn thử nghiệm

  • Trước đây trên HN, nếu chặn scraper thì sẽ bị chỉ trích. Lập luận là “tôi truy cập theo cách nào cũng là việc của tôi”

    • Nhưng bây giờ thì khác. Một con người truy cập riêng lẻ và công ty AI gửi lượng lớn request ở mức gần như DDoS là hai chuyện hoàn toàn khác nhau. Trường hợp sau rõ ràng là hành vi đẩy chi phí sang cho người khác
    • Tôi cũng nghĩ scraping hợp lý thì chấp nhận được. Chỉ cần khai báo UA và tuân thủ robots.txt. Nhưng kiểu gửi hàng chục request mỗi giây như bây giờ rồi ngụy trang thành Chrome bản cũ thì không thể chấp nhận
    • Tôi scrape các trang tuyển dụng mỗi ngày một lần cho một dự án học thuật. Đó là cách dùng hợp lý. Còn cào nội dung theo từng phút hoặc đi dò lỗ hổng thì là vấn đề hoàn toàn khác
    • Điều buồn nhất là sự trỗi dậy của AI đang làm suy yếu chính ý thức đạo đức. Những người từng coi trọng tự do giờ lại đòi tăng cường bản quyền hoặc xóa bỏ tính ẩn danh. Công nghệ đang khiến con người trở nên tệ hơn
  • Nếu bạn tự quản lý máy chủ Apache, có thể dùng RewriteEngine để chặn ngay các request PHP

    RewriteEngine On
    RewriteCond %{REQUEST_URI} (\.php|%2ephp|%2e%70%68%70) [NC,OR]
    RewriteCond %{QUERY_STRING} \.php [NC,OR]
    RewriteCond %{THE_REQUEST} \.php [NC]
    RewriteRule .* - [F,L]
    

    Máy chủ của tôi không có PHP, nên mọi request kiểu này đều là độc hại

    • Trên nginx tôi cũng cấu hình tương tự. Với request PHP hoặc ASPX, tôi trả về mã HTTP 418 “I’m a teapot”
      location ~* \.(?:php|aspx?|jsp|dll|sql|bak)$ { return 418; }
      error_page 418 /418.html;
      
      Làm vậy sẽ dễ lọc log hơn. Ví dụ: FreeSolitaire.win/wp-login.php
  • Phần lớn scraper mang tính tấn công đều nhắm vào lỗ hổng WordPress. Thứ chúng muốn không phải bản thân file PHP mà là kết quả đầu ra của nó. Kiểu cấu hình này gần giống một honeypot, nhưng nếu bot không thấy thứ nó mong đợi theo kịch bản thì sẽ rời đi

    • Có lẽ chúng sẽ dùng regex để tìm mẫu đăng nhập quản trị trong output. Nếu không có thì bỏ qua ngay. Tức là so với việc tạo ra một file PHP giả 4KB, chỉ một dòng regex đã hiệu quả hơn nhiều
  • Trước đây tôi từng đăng chiến lược zipbomb lên HN và traffic tăng vọt lên 100 nghìn lượt mỗi ngày. Một VPS giá $6 không thể chịu nổi. Bây giờ tôi chỉ đáp trả bằng zipbomb với những bot hung hãn nhất, còn lại thì trả 403. Chiến lược mới đang phát huy tác dụng, nhưng tôi vẫn phân vân có nên công khai lại không. Tham khảo: bài viết trước

  • Trước đây tôi chỉ dùng fail2ban, nhưng tôi muốn tạo một biện pháp phòng thủ thú vị hơn
    Trong .htaccess, tôi redirect các đường dẫn đáng ngờ (/.git, /wp-login) sang decoy.php, rồi ép tải xuống decoy.zip dung lượng 10GB.
    decoy.php trông giống như file nhạy cảm được yêu cầu, nhưng thực ra nó stream vô hạn log giả và dữ liệu SQL giả để giữ bot mắc kẹt

  • Những bot này không cào file PHP, mà đang tìm lỗ hổng framework. Chỉ cần trả về phản hồi ngoài dự đoán là chúng sẽ bỏ cuộc ngay và chuyển sang mục tiêu khác

  • Đôi khi tôi nghĩ thế này — liệu có thể khiến chúng dùng tài nguyên bị lãng phí đó để đào tiền mã hóa hay không?

    • Nếu muốn thử thì phải dụ được chúng thực thi JavaScript, nhưng hầu hết bot có lẽ đã có biện pháp đối phó để chặn kiểu thử nghiệm đó