- Merangkum cara memblokir sebagian besar bot yang implementasi atau konfigurasinya buruk dengan menggabungkan protokol HTTP/rentang IP/sinyal klien/karakteristik TCP/sidik jari TLS/kompresi konten tanpa CDN
- Semua metode harus disesuaikan secara selektif, dan tanpa menganalisis log akses 1~3 tahun terlebih dahulu, pengguna VPN/mesin pencari/CDN/sekolah/perpustakaan/pengguna bahasa tertentu bisa ikut terblokir
- Memblokir klien HTTP/1.1 dan rentang AS/CIDR pusat data dapat menghilangkan banyak bot, tetapi mesin pencari termasuk GoogleBot dan pengguna pusat data yang sah juga bisa ikut dikecualikan
- Pemeriksaan header Nginx dan filter ukuran jendela TCP/MSS/TTL di nftables mengurangi crawler dan pemindai sederhana, tetapi false positive bisa terjadi pada lingkungan normal seperti LTE/VPN/Windows
- Dalam jangka panjang, deteksi sidik jari TLS JA4 dan respons khusus Brotli diajukan sebagai alternatif, tetapi tidak menjamin pemblokiran sempurna, dan diperingatkan agar tidak digunakan pada layanan yang menghasilkan pendapatan
Cakupan pemblokiran dan asumsi penerapan
- Tujuan pemblokiran harus ditentukan lebih dulu: sebagian bot/sebagian besar bot/semua bot
- Pendekatan yang dibahas di sini tidak berfokus pada seluruh alat otomasi canggih, melainkan pada pemblokiran sebagian besar bot dengan implementasi atau konfigurasi buruk secara relatif sederhana
- Untuk tiap metode, risiko memblokir pengguna normal dan mesin pencari juga ditandai
- Setelah dibagikan di Hacker News pada 26 Juli 2026, sebagian besar fungsi pemblokiran akan dipindahkan dari blog ke situs demo terpisah dan diubah menjadi bentuk teka-teki agar pembaca membaca metodenya lalu mencoba mengakses sendiri
- Semua konfigurasi dapat dimodifikasi atau dihilangkan secara selektif, dan sebelum diterapkan sungguhan diperlukan penyelidikan dan pengujian yang memadai
- Karena pengguna normal/sistem internal organisasi/layanan eksternal yang diandalkan bisa terblokir, tanggung jawab penerapan sepenuhnya ada pada operator
- Jangan gunakan di lingkungan operasional yang menghasilkan pendapatan
Metode 1: Membedakan lewat protokol HTTP
- Risiko memblokir pengguna normal rendah, dan risiko memblokir sebagian mesin pencari berada di tingkat sedang
- Memanfaatkan perbedaan bahwa browser umum memakai HTTP/2.0 sedangkan banyak bot memakai HTTP/1.1
- GoogleBot dianggap memakai HTTP/1.1 dan akan terblokir dengan cara ini
- Crawler Bing dan Facebook memakai HTTP/2.0
- Layanan yang mengambil judul tautan atau pratinjau singkat lewat HTTP/1.1 juga bisa terblokir
- Opera Mini juga dikecualikan dari target
- Di Nginx, jika
$server_protocol bukan HTTP/2.0, konfigurasikan agar diarahkan ke halaman lain atau mengembalikan 200, 403, 444
if ($server_protocol != HTTP/2.0) {
return 403 'Upgrade your client';
}
- Jika mengembalikan
444, koneksi bisa diputus tanpa respons terpisah
- Tiap organisasi harus menilai sendiri apakah manfaatnya lebih besar daripada kerugian akibat memblokir trafik dari pencarian Google
Metode 2: Memblokir rentang IP pusat data
- Risiko memblokir pengguna rumahan/LTE normal rendah, tetapi pengguna VPN berada di tingkat sedang, dan mesin pencari yang berjalan di pusat data berisiko tinggi terblokir
- Cari permintaan mencurigakan dari log akses 1~2 tahun terakhir dengan menggabungkan sinyal berikut
- Protokol HTTP
- User-Agent
Accept-Language
Sec-Fetch-Mode
Accept
- Cek IP yang mencurigakan di BGP Tools atau Hurricane Electric BGP Toolkit untuk melihat AS asal dan Prefix yang sedang diumumkan
- Daftar blackhole jaringan yang disediakan dapat mencakup rentang CDN dan mesin pencari, jadi harus diterapkan secara selektif
- Sebelum daftar terpisah, digunakan konfigurasi yang sudah mem-blackhole rentang
3/8, 10/8, 11/8, 25/8, 26/8, 38/8, 41/8, 60/8, 61/8, 200/8, 224/3
- Setelah menyalin halaman Prefix milik AS, gunakan fungsi shell untuk mengekstrak hanya CIDR lalu urutkan/hapus duplikasi/gabungkan
- Menggunakan sum_cidr.pl dan memerlukan modul Perl
Net::CIDR::Lite
- Hasil yang dibuat ditinjau lalu dipindahkan ke file
/usr/local/etc/*.netset
- Saat server mulai, tiap CIDR ditambahkan sebagai rute blackhole
for CflIP in $(grep -E ^[1-9] /usr/local/etc/_cloudflare.netset); do
/sbin/ip route add blackhole "${CflIP}" 2>/dev/null
done
- Dalam contoh, seluruh rentang Cloudflare diblokir agar tidak menerima permintaan melalui Workers dan sejenisnya
- Metode routing dipilih karena routing blackhole Linux memakai CPU lebih sedikit dibanding aturan ipset di firewall
- Rentang milik penyedia hosting tempat server saat ini berada juga bisa diblokir
- DNS/konfigurasi/layanan internal tidak boleh memakai ruang alamat yang sama
- Rute gateway yang terhubung langsung akan diprioritaskan dibanding rute blackhole
Metode 3: Memblokir negara/proksi/Tor/IP berbahaya
- Unduh daftar dari repositori FireHOL Blocklists lalu tambahkan rentang yang diperlukan sebagai rute blackhole
- Karena file daftar berisi komentar, hapus dulu dengan
grep -Ev '^#' sebelum diproses
- Daftar berikut sangat direkomendasikan
firehol_abusers_30d.netset
firehol_level2.netset
- Daftar besar dapat membuat waktu eksekusi skrip startup menjadi lama
- File konfigurasi yang dipakai pada server dan susunan firewall sebenarnya juga disediakan
Metode 4: Memeriksa sinyal klien HTTP
- Berdasarkan asumsi bahwa meski User-Agent atau header bisa dipalsukan, bot sederhana yang mengutamakan kecepatan sering kali tidak memalsukannya dengan benar
- Untuk permintaan
Curl, Wget dikembalikan teks biasa, dan untuk permintaan yang mengandung Bot, GPT, LLM, Spider dikembalikan 410 Gone
if ($http_user_agent ~* Curl) { return 200 '\nGNU Terry Pratchett\n\n'; }
if ($http_user_agent ~* Wget) { return 200 '\nGNU Terry Pratchett\n\n'; }
if ($http_user_agent ~* Bot) { return 410 '1000101'; }
if ($http_user_agent ~* GPT) { return 410 '1000101'; }
if ($http_user_agent ~* LLM) { return 410 '1000101'; }
if ($http_user_agent ~* Spider) { return 410 '1000101'; }
- Sebagian string User-Agent yang teramati diperiksa dengan satu regex panjang untuk memblokir crawler/pemindai/alat pengumpul
- Mencakup substring seperti
Go-http, Java, libwww, okhttp, urllib, python, nmap, zgrab, semrush, shodan, rss, scrap, crawler, headless, github, facebook, google, bing
- Sebelum diterapkan, User-Agent 2~3 tahun harus diagregasi untuk memastikan klien normal yang sebenarnya tidak cocok dengan regex
sort access-user-agents.txt | uniq -c | sort
- Jika permintaan yang cocok memakai HTTP/1.1, anggap kemungkinan besar itu bot, tetapi GoogleBot dipertimbangkan sebagai pengecualian
- Jika permintaan HTTP/2.0, cek lagi kepemilikan IP di alat BGP
Sec-Fetch-Mode
- Tambahkan
Sec-Fetch-Mode ke log akses, dan blokir jika nilainya bukan cors, no-cors, navigate
if ($http_sec_fetch_mode !~ (cors|no-cors|navigate)) {
return 410 '1000101';
}
Pemeriksaan Referer
- Untuk memblokir permintaan yang menyematkan konten atau memindai dari situs lain, blokir jika
Referer berisi string tertentu
- Memeriksa string terkait halaman admin/mesin pencari/jejaring sosial/kripto/konten dewasa/pemindai/WordPress, dll.
- Tipe bot tertentu yang mengaku memakai
https://www.google.com/ sebagai Referer juga diblokir terpisah
- Pola ini diamati pada permintaan yang menyamar sebagai Android lama
Membatasi metode HTTP
- Hanya izinkan
GET dan POST yang diperlukan untuk permintaan browser normal, dan blokir metode lain
if ($request_method !~ (^GET$|^POST)) {
return 410 '1000101';
}
- Pada aplikasi nyata, jalur yang memerlukan
POST bisa dibatasi lebih rinci, atau dihapus sepenuhnya jika tidak digunakan
Memeriksa proksi dan bentuk browser
- Jika ada header
X-Forwarded-For, anggap sebagai permintaan melalui proksi lalu blokir
- Lingkungan proksi bersama yang sah seperti sekolah atau perpustakaan juga bisa ikut terblokir
- Jika User-Agent tidak mengandung salah satu dari
Linux, BSD, Macintosh, Windows, Mozilla, WhatsApp, anggap permintaannya tidak terlihat seperti browser
- Juga digunakan aturan yang memblokir jika
Accept-Language tidak mengandung en atau es
- Kemungkinan besar akan memblokir sebagian browser dan pengguna sah yang tidak memakai bahasa Inggris/Spanyol
- Aturan opsional untuk memblokir setelan bahasa yang mengandung
br atau sy juga ditunjukkan
Memblokir pemindaian jalur sensitif
- Jika meminta file atau jalur berikut, dianggap sebagai pemindaian otomatis dan diblokir
Metode 5: Memblokir pemindai TCP dengan nftables
- Memeriksa karakteristik paket TCP SYN di chain
PREROUTING pada tabel raw nftables
- Alamat server contoh
172.238.221.88 ditentukan sebagai tujuan untuk mengurangi false positive yang dapat muncul saat terjadi kehilangan paket
- Dari paket SYN yang masuk ke port 80/443, blokir kondisi berikut
- Ukuran jendela TCP kurang dari 12.288 byte
- MSS di luar rentang 1.220~1.460
- Patokannya adalah klien nyata memakai ukuran jendela yang lebih besar, dan MSS di luar rentang tersebut kecil kemungkinannya merupakan klien normal
- Jika MSS dibatasi tepat ke
1460, aturan menjadi lebih ketat tetapi dapat memblokir sebagian besar pengguna LTE dan VPN
Pembatasan opsional berbasis TTL
- Jika TTL TCP SYN lebih besar dari
128, sebagian besar perangkat LTE bisa diblokir
- Jika TTL lebih besar dari
64, sebagian besar sistem Windows juga akan terblokir
- Kriteria TTL dasar dijelaskan sebagai berikut
- Linux/Mac/BSD:
64
- Windows:
128
- LTE: nilai lebih besar dari itu
Mengecualikan pelacakan koneksi
- Menetapkan port 80/443 sebagai
notrack agar trafik web tidak dimasukkan ke tabel conntrack
- Dalam kasus ini, di tabel filter juga harus dibuat langsung aturan tanpa penyimpanan status untuk arah kirim/terima
- Dalam contoh, trafik antara port sumber klien
1000-65535 dan port server 80/443 diizinkan
Metode 6: Konten dewasa dan header robot
- Untuk pembatasan akses konten dewasa digunakan header RTA: Restricted To Adults
- Cara verifikasi usia selain RTA dianggap ditujukan untuk pelacakan pengguna dan monetisasi
- Header berikut selalu ditambahkan pada respons Nginx
add_header Rating 'RTA-5042-1996-1400-1577-RTA' always;
add_header adult 'porn, sex, politics, religion, philosophy' always;
add_header X-Robots-Tag "none,noindex,nofollow,nosnippet,noai" always;
- Bot umum dapat mengabaikan header tersebut, tetapi bisa berdampak pada mesin pencari atau bot yang dirancang untuk menghindari konten dewasa
Metode 7: Deteksi sidik jari TLS
- Metode 1~6 sebelumnya semuanya adalah heuristik kasar, dan dalam jangka panjang analisis sidik jari TLS mungkin menjadi pilihan yang lebih baik
- JA4 dapat dimanfaatkan dengan syarat bot tidak mengubah sidik jari TLS-nya agar sama dengan browser normal
- Dianjurkan untuk lebih dulu melihat metode deployment Deploying JA4 lalu menerapkan FoxIO JA4
Metode 8: Hanya menyajikan konten terkompresi Brotli
- Kompres dulu konten situs dengan Brotli, lalu konfigurasikan web server agar hanya mengembalikan file yang sudah dikompresi
- Memanfaatkan fakta bahwa banyak bot tidak bisa menafsirkan HTML terkompresi Brotli
- Setelah diterapkan, dipastikan beberapa bot tidak lagi mengikuti tautan halaman, yang menunjukkan bahwa mereka tidak benar-benar bisa mem-parsing HTML
- Di Nginx, atur agar file Brotli statis selalu disajikan
brotli_static always;
- File HTML dikompresi terlebih dahulu seperti berikut
cat ./i.html | brotli --best -fncv > ./i.html.br
Metode 9: Mendorong pemindai mengidentifikasi dirinya sendiri
- Metode terpisah untuk mengurangi penyerang pemula dan pemindai yang berulang kali menelusuri jalur kerentanan dibahas di Help Attackers Self Report
1 komentar
Komentar Hacker News
Sebagai orang yang mengelola beberapa situs web publik dan memanfaatkan alat dengan mengambil data dari situs lain, saya penasaran kenapa orang begitu memusingkan bot
WordPress dengan cache pun bisa menangani sekitar 1.000 request per detik di VPS termurah, dan situs statis yang dibuat dengan benar sepertinya bisa 10 kali lipat dari itu. Saya jadi bertanya-tanya apakah blognya disajikan dengan sesuatu seperti Lambda, atau ini soal dorongan kompulsif, pertahanan terhadap kerentanan, atau kebiasaan dari masa ketika crawling benar-benar memengaruhi layanan nyata
Repositorinya memang sengaja dibuka karena open source. Saat ini saya bertahan dengan pemeriksaan cookie sederhana dan hanya sedikit bot yang lolos, tetapi ini kompromi yang mengorbankan visibilitas di mesin pencari
Tujuannya menunjukkan cara yang bisa diterapkan pada forum, imageboard, server chat, dan sebagainya, dan semua opsi bisa disetel atau dimatikan. Sebelum dipakai sungguhan, harus divalidasi di server uji, dan kalau mau ditertawakan lalu diabaikan juga tidak masalah
Tidak bisa dibilang masalah besar kalau perlu menunggu beberapa detik lebih lama untuk mengecek server IMAP lokal karena DMZ sedang tersumbat, tapi bukan berarti saya harus menyukainya atau terus membiarkannya
Akhir pekan ini saya mematikan antarmuka web viewvc (CVS·Subversion) dan hgweb (Mercurial) yang sudah berjalan selama 10~20 tahun. Alasannya, ada 2,7 juta request per hari dari IP proxy residensial, rata-rata 30 request per detik, yang membebani program lama seperti uWSGI/CGI dan situs lain di server yang sama, dan trafiknya juga mendekati batas VPS sebesar 1TB per bulan
Kombinasi URL VCS dinamis bisa berjumlah jutaan sehingga efek cache juga tidak pasti, dan tidak layak lagi menghabiskan waktu untuk terus menyetel server, jadi pada akhirnya saya memilih langkah yang membuat internet semakin tersentralisasi
Jika memblokir semua selain user agent yang “disetujui”, itu akan membantu monopoli browser yang sudah ada dan mempercepat distopia. Ini juga jenis masalah yang sudah diperingatkan RMS sejak puluhan tahun lalu
Kalau memang bermasalah, seharusnya diblokir berdasarkan volume trafik dan frekuensi request. Saya sendiri juga tidak bisa mengakses situs itu, tetapi saya tidak berniat menyesuaikan diri, dan seperti DRM, pihak yang benar-benar gigih pada akhirnya akan tetap lolos
Namun terlepas dari klaim bahwa browser apa pun boleh dipakai, browser yang kodenya dibuat dadakan atau belum cukup diverifikasi untuk menghadapi situs berbahaya memang harus sangat diwaspadai. Aplikasi pembaca juga bisa rentan terhadap server berbahaya jika tidak melalui peninjauan kode pihak ketiga yang luas oleh ahli uji penetrasi
Saya suka ide menambahkan subdomain cpanel palsu yang mengarah ke
169.254.169.254, sehingga penyerang pemula bisa dibuat memindai port penyedia hosting mereka sendiri lalu terdeteksi atau diblokirIP asalnya tersebar di seluruh dunia, tetapi kebisingan pemindaian yang sebenarnya ternyata berasal dari satu orang saja
Pemblokiran berbasis IP perlu dilakukan dengan hati-hati. Rentang IP kadang dialokasikan ulang, jadi bisa memblokir orang yang tidak bersalah, dan saya juga sudah beberapa kali melihat rentang yang dulu diblokir karena dianggap wilayah atau datacenter ternyata berpindah ke ISP rumahan
Memblokir HTTP/1.1 juga berisiko memblokir pengguna nyata yang memakai browser lama. Selain itu, ada browser yang tidak mengirim URL lengkap pada permintaan lintas asal, jadi jika trafik datang dari penelusuran Google, referrer bisa saja hanya menunjuk ke halaman root Google; jika ini langsung dianggap sebagai kebohongan bot lalu diblokir, trafik dari Google Search juga bisa hilang
Di sisi lain, saya rasa pemblokiran HTTP/1.1 itu masuk akal. Sudah lebih dari 10 tahun hampir semua browser mendukung protokol yang lebih baru dari itu, dan browser setua itu kemungkinan sudah rusak di sebagian besar web arus utama, jadi ada satu situs pribadi lagi yang tidak bisa dibuka bukan pengecualian melainkan hal biasa
Meski harus melewatkan browser lama dan alat API, saya tetap akan mempertahankan pemblokiran HTTP/1.1. Jika ini kode monopoli untuk sistem keuangan lama saya bisa mengerti, tetapi internet publik harus memperbarui dirinya sendiri demi kelangsungannya
Karena saya sudah lama memblokir Google, semua permintaan yang mengaku datang dari Google adalah bohong. Saya memutar blog di beberapa domain acak untuk memutus keterkaitan dan snapshot, serta ingin mengendalikan jalur orang menemukan tulisan saya
Berkat itu saya juga mendapat uji penetrasi gratis, dan menyimpulkan bahwa pertahanan serta pipeline penanganan saya cukup kokoh. Karena tekanan untuk bertahan, 90% trafik bot berpindah ke VPN sehingga endpoint VPN menyala seperti pohon Natal
Saya bisa saja menyediakan feed IP akses sekali pakai, tetapi pengguna harus diverifikasi dengan benar dan tujuan penggunaannya juga harus disetujui. Proses itu sendiri menyenangkan
Jika tidak bisa dibaca, bisa lihat salinannya di https://archive.ph/d3236
Saya bukan bot, tetapi tetap tidak ingin mematikan iCloud Private Relay hanya untuk membaca sesuatu. Menurut jawaban lain dari penulisnya, ini implementasi yang bagus untuk situs uji, tetapi saya harap pengelola web lain tidak menyalin semua caranya begitu saja jika memungkinkan
Dari fakta bahwa isi respons hanya menampilkan 410 dan string
Sec-Fetch-Mode:, sepertinya saya dinilai sebagai bot. Tidak ada yang bisa dibaca atau dilihat, jadi saya langsung pergi; web modern memang mengerikanStatus dukungannya bisa dilihat di https://caniuse.com/?search=sec-fetch-mode, dan beberapa header bisa dicek di https://nochan.net/.env
PR_END_OF_FILE_ERRORyang berarti bahkan TLS handshake pun gagal dilewatiKarena diperkirakan lebih dari 99% trafik web adalah bot atau agen, saya sedang mempertimbangkan menghapus tampilan jumlah pengunjung. Angkanya tidak bermakna dan membuat situs tampak jauh lebih ramai daripada kenyataannya, tetapi saya ragu bertindak karena khawatir orang sungguhan jadi tidak bisa membaca tulisan atau mengunduh buku
Jika memang perlu memblokir, secara umum allowlist lebih efektif daripada blocklist, dan jika allowlist tidak bisa diterapkan, cara ini mungkin juga bukan solusi yang baik
Alat seperti Cloudflare dan Anubis bisa menimbulkan masalah aksesibilitas yang serius, jadi saya lebih memilih pembatasan frekuensi permintaan. Ini lebih rapi tanpa merusak aksesibilitas, dan untuk masalah sementara, pemblokiran IP singkat juga bekerja dengan baik
Secara pribadi saya menganalisis log HTTP dengan fail2ban lalu memblokir selama N jam IP yang meminta URL yang dilarang di
robots.txt, jalur sepertiwp-login.php, atau yang terlalu sering melampaui batas frekuensi permintaan. Saat ini saya sedang menguji Anubis di web UI GitDengan fail2ban saja sebenarnya sudah bisa memblokir cukup baik, tetapi beberapa bulan pertama perlu penyesuaian yang rinci agar cocok dengan lingkungan
Awalnya saya mendeteksi dengan filter
failregex = ^ - \\S+ \\[\\] ".*?" 40[034], lalu menambahkannya ke daftar yang lebih spesifik; sekarang dengan sekitar 80 regex semua trafik sudah terblokir sehingga sudah lama tidak ada permintaan yang sampai ke filter umum40[034]Namun di belakang load balancer atau proxy, baik fail2ban maupun metode di tulisan asli jadi merepotkan karena perlu cara untuk mendapatkan IP asli
Dari komentar-komentar ini dan percobaan akses saya, tampaknya bukan hanya bot tetapi semua trafik normal juga ikut diblokir
Pada hari Minggu biasanya paling banyak terlihat browser dan aplikasi aneh yang dipakai orang untuk menjelajah web, sedangkan pada hari kerja lebih banyak browser arus utama yang biasa, jadi itu menjadi uji yang bagus