Bali, Indonesia
Insights

Kenapa Fail2ban Sering Gagal Menahan Brute Force SSH Modern

October 16, 2026
0:00
Kamu baru saja mengonfigurasi server Linux baru, mengaktifkan Fail2ban untuk memantau port SSH, dan merasa server sudah aman di balik proteksi otomatis. Namun beberapa hari kemudian, saat memeriksa log sistem, kamu mendapati ribuan baris kegagalan login (failed password) dari berbagai alamat IP asing yang terus mengalir tanpa henti. Di sisi lain, status Fail2ban menunjukkan hanya ada segelintir IP yang terkena ban (pemblokiran sementara). Kondisi ini sering memicu kebingungan bagi administrator maupun staf support hosting. Fail2ban tidak rusak, layanannya berjalan normal, dan aturan firewall terbentuk dengan benar. Masalahnya terletak pada cara kerja serangan brute force (percobaan menebak kredensial secara berulang) modern yang sudah bergeser jauh dari asumsi dasar alat pemblokir berbasis frekuensi IP.
Ketika kamu menyadari percobaan login masih sangat ramai, langkah pertama adalah melihat langsung apa yang sedang dicatat oleh daemon SSH (sshd). Di sistem berbasis Debian atau Ubuntu, catatan autentikasi berada di /var/log/auth.log, sedangkan pada distribusi keluarga RHEL seperti CentOS, AlmaLinux, atau Rocky Linux, log ini berada di /var/log/secure. Kamu bisa memfilter baris yang mencatat kegagalan login untuk melihat pola alamat IP yang datang:
BASH
grep 'Failed password' /var/log/auth.log | tail -n 20
Jika servermu menggunakan distribusi RHEL atau turunannya, ganti target berkas ke /var/log/secure. Perhatikan dua hal dari keluaran perintah di atas: nama pengguna (username) yang dicoba dan alamat IP sumbernya. Pada serangan konvensional zaman dulu, satu IP biasanya mencoba puluhan kata sandi dalam hitungan detik. Pola tersebut sangat mudah ditangkap oleh Fail2ban. Namun, pada log modern, kamu kemungkinan besar akan melihat fenomena berbeda: setiap IP hanya muncul satu atau dua kali untuk mencoba username acak seperti admin, root, ubuntu, atau test, lalu IP tersebut menghilang dan percobaan berikutnya datang dari rentang subnet atau negara yang sama sekali berbeda. Langkah kedua adalah memeriksa status jail SSH pada Fail2ban menggunakan utilitas klien resminya:
BASH
fail2ban-client status sshd
Perintah tersebut menampilkan jumlah kegagalan yang sedang dihitung (Currently failed), total kegagalan yang tercatat (Total failed), serta daftar IP yang sedang diblokir (Currently banned). Sering kali kamu akan melihat angka Total failed mencapai ribuan, tetapi Currently banned hanya menunjukkan hitungan jari. Hasil ini mengonfirmasi bahwa serangan memang masuk, tetapi tidak pernah memicu ambang batas (threshold) yang ditentukan.
Secara default, Fail2ban bekerja dengan prinsip rate-based blocking (pemblokiran berbasis laju kejadian). Konsepnya sederhana: jika satu alamat IP menghasilkan kegagalan autentikasi sebanyak maxretry (misalnya 5 kali) di dalam rentang waktu jendela pencarian findtime (misalnya 10 menit), maka IP tersebut akan dimasukkan ke dalam daftar blokir firewall (seperti iptables atau nftables) selama durasi bantime. Logika ini memiliki satu asumsi fundamental: penyerang menggunakan sumber daya yang terbatas dan menyerang secara terpusat dari satu mesin. Kenyataannya, lanskap ancaman saat ini didominasi oleh botnet terdistribusi. Pelaku menyebarkan skrip tebak kata sandi ke ribuan perangkat yang sudah mereka kuasai sebelumnya, mulai dari perangkat IoT, router rumahan yang rentan, hingga VPS murah yang disusupi. Dalam studi pengukuran berskala besar terhadap serangan brute force SSH yang dipublikasikan pada USENIX NSDI 2024 (Where The Wild Things Are: Brute-Force SSH Attacks In The Wild And How To Stop Them oleh Singh dkk.), terungkap bahwa pendekatan rate-based blocking standar hanya mampu menangkap sekitar 66,1% dari keseluruhan serangan di dunia nyata. Sisanya lolos karena penyerang membagi beban serangan secara terdistribusi dan menggunakan teknik low-and-slow. Pada teknik low-and-slow, sebuah bot sengaja diatur agar hanya mengirimkan satu percobaan login setiap 15 atau 30 menit per IP. Karena frekuensinya berada jauh di bawah ambang maxretry dalam periode findtime, Fail2ban menganggap percobaan tersebut sebagai anomali biasa dan menghapus riwayat kegagalan dari memori setelah rentang waktu berakhir. Ketika 2.000 IP berbeda melakukan satu percobaan per jam, servermu menerima 48.000 percobaan login per hari tanpa ada satu pun IP yang memenuhi syarat untuk diblokir.
Selain tidak efektif memblokir serangan terdistribusi, mengandalkan Fail2ban sebagai garda utama di server dengan spesifikasi kecil (seperti VPS 1 vCPU dengan RAM 1 GB) menimbulkan masalah efisiensi. Fail2ban memantau berkas teks secara pasif. Setiap kali sshd menerima koneksi, melakukan handshake kriptografi SSH, memverifikasi kredensial ke sistem PAM (Pluggable Authentication Modules), dan menulis baris kegagalan ke disk, Fail2ban baru membaca baris tersebut menggunakan ekspresi reguler (regex). Rangkaian proses ini mengonsumsi siklus CPU dan I/O disk. Saat server dihujani puluhan ribu percobaan koneksi per jam, beban CPU sshd dan Fail2ban bisa meningkat signifikan. Server memang belum tentu jebol—terutama jika kata sandi pengguna cukup kuat—tetapi kapasitas komputasi yang seharusnya digunakan untuk melayani aplikasi web atau basis data justru terbuang hanya untuk menolak handshake dan memproses teks log.
Mengetatkan aturan Fail2ban—misalnya dengan menurunkan maxretry menjadi 2 dan menaikkan findtime menjadi beberapa hari—bukan solusi yang ideal. Langkah ini berisiko tinggi mengunci pengguna sah yang tidak sengaja salah mengetik kata sandi (false positive), sementara botnet dengan puluhan ribu IP baru tetap akan bisa mencoba setidaknya satu kata sandi per IP. Solusi yang tepat adalah mengubah paradigma pertahanan: jangan biarkan mekanisme kata sandi aktif di pintu depan. Serangan brute force hanya ada karena server mengizinkan autentikasi berbasis teks tebakan. Jika pintu kata sandi ditutup total dan digantikan oleh autentikasi berbasis kunci publik (public key authentication), seluruh upaya tebak kredensial otomatis kehilangan targetnya. Langkah-langkah pengerasan (hardening) ini sebaiknya diterapkan secara bertahap agar kamu tidak terkunci dari servermu sendiri:
  1. Siapkan SSH Key Pair: Buat pasangan kunci (misalnya menggunakan algoritma modern seperti Ed25519) di komputer lokalmu, lalu salin kunci publik ke berkas ~/.ssh/authorized_keys milik akun pengguna di server.
  2. Uji Coba Login Kunci: Buka sesi terminal baru tanpa menutup sesi yang sedang aktif. Pastikan kamu bisa masuk ke server menggunakan kunci tersebut tanpa diminta memasukkan kata sandi akun Linux.
  3. Nonaktifkan Autentikasi Password di sshd: Buka berkas konfigurasi SSH server (biasanya di /etc/ssh/sshd_config atau di dalam direktori /etc/ssh/sshd_config.d/), lalu pastikan parameter berikut disetel:
    • PasswordAuthentication no
    • ChallengeResponseAuthentication no (atau KbdInteractiveAuthentication no pada versi OpenSSH yang lebih baru)
  4. Nonaktifkan Login Langsung Akun Root: Atur parameter PermitRootLogin prohibit-password (atau no jika kamu sepenuhnya menggunakan akun sudoer non-root). Ini mencegah bot menebak akun root secara langsung.
  5. Muat Ulang Layanan SSH: Periksa validitas sintaks konfigurasi menggunakan sshd -t sebelum menjalankan perintah reload (seperti systemctl reload sshd).
Ketika PasswordAuthentication disetel ke no, daemon sshd akan langsung menolak negosiasi autentikasi sejak awal koneksi bagi klien yang tidak membawa kunci privat yang cocok. Upaya koneksi dari botnet akan terputus seketika tanpa perlu membebani subsistem autentikasi PAM dan tanpa menghasilkan ribuan baris Failed password yang harus di-parse oleh Fail2ban. Opsi tambahan lain yang sangat efektif menurunkan kebisingan log adalah memindahkan port SSH dari port default 22 ke port acak di atas 1024. Mengganti port memang bukan perlindungan keamanan absolut (security through obscurity), tetapi secara praktis langkah ini langsung mengeliminasi sebagian besar pemindai botnet otomatis yang hanya menyisir port 22 di seluruh rentang IPv4 publik. Fail2ban tetap memiliki tempatnya sebagai lapisan pelindung sekunder, terutama untuk membatasi pemindaian kasar pada port lain atau aplikasi web. Namun untuk SSH modern, pertahanan utama tidak boleh digantungkan pada daftar blokir IP yang dinamis, melainkan pada penolakan autentikasi kata sandi di tingkat protokol.