• Indonesian
  • English
  • Mendeteksi & Memblokir Brute Force WordPress: 5000+ Login

    Kecepatan:

    Difficulty: Intermediate–Advanced
    Last Updated: 20 Juli 2026
    Tested On: LiteSpeed Enterprise, Apache 2.4, cPanel/VestaCP, CentOS 7/8, CloudLinux

    Pendahuluan

    Jam 3:38 siang. Saya sedang duduk santai di ruang NOC, menyeruput kopi hangat, ketika monitoring Telegram bunyi: “Warning — Brute force detected, throttle active”. Saya cek log LiteSpeed — ada 2 IP yang kena throttle. Tapi itu belum seberapa. Ketika saya buka error log Apache, saya malah menemui sesuatu yang lebih parah: “Too many open files: could not open transfer log file”.

    Masalahnya tidak berhenti di situ. Saya lari ke server dan menjalankan command grep untuk mengecek aktivitas login WordPress di jam terakhir. Hasilnya? Lebih dari 5.000 percobaan login wp-login.php dalam satu jam — dari satu IP saja. Dan ini baru satu server.

    Itu bukan manusia. Itu bot. Ribuan request login otomatis yang mencoba brute force akun admin WordPress Anda. Dan jika Anda tidak punya proteksi tambahan, suatu hari bot akan berhasil — karena password yang “kuat” sekalipun bisa di-crack jika punya waktu cukup.

    Cerita ini adalah tentang bagaimana saya menghentikan serangan brute force yang masif ini, memperbaiki file descriptor exhaustion yang menyebabkan error log macet, dan membangun HTTP Basic Auth sebagai benteng pertahanan pertama sebelum WordPress login.

    Gejala — Apa yang Terjadi?

    Ada tiga gejala yang muncul bersamaan di server hari itu:

    Gejala 1: LiteSpeed Brute Force Throttle

    Log LiteSpeed menunjukkan beberapa IP yang sudah terdeteksi melakukan brute force dan di-throttle otomatis:

    [root@mr-x ruak3711]# tail -f /usr/local/apache/logs/error_log
    2026-07-20 15:32:38.263607 [WARN] [3402173] [T0] [10.0.0.1:40442#APVH_client-a.com:443] Brute force detected for IP [10.0.0.1], throttle.
    2026-07-20 15:32:38.869189 [WARN] [3402173] [T0] [10.0.0.2:62269#APVH_site-lama-client.com:443] Brute force detected for IP [10.0.0.2], throttle.

    LiteSpeed memang punya fitur brute force protection bawaan. Tapi masalahnya: throttle hanya memperlambat request, bukan memblokir. Bot tetap bisa mencoba — lebih lambat, tapi tetap mencoba. Dan ketika ada ribuan bot dari IP berbeda, throttle tidak cukup.

    Gejala 2: Apache “Too Many Open Files”

    Error log Apache menunjukkan masalah yang berbeda — file descriptor exhaustion:

    [Mon Jul 20 15:32:46.712781 2026] [log_config:error] [pid 3486344:tid 3486344] (24)Too many open files: AH00649: could not open transfer log file /etc/apache2/logs/domlogs/client-b.com.
    AH00015: Unable to open logs
    
    [Mon Jul 20 15:32:50.986574 2026] [log_config:error] [pid 3486614:tid 3486614] (24)Too many open files: AH00649: could not open transfer log file /etc/apache2/logs/domlogs/client-b.com.
    AH00015: Unable to open logs
    
    [Mon Jul 20 15:33:08.009242 2026] [log_config:error] [pid 3490205:tid 3490205] (24)Too many open files: AH00649: could not open transfer log file /etc/apache2/logs/domlogs/portal-news-client.com.
    AH00015: Unable to open logs
    
    [Mon Jul 20 15:36:00.576506 2026] [log_config:error] [pid 3521150:tid 3521150] (24)Too many open files: AH00649: could not open transfer log file /etc/apache2/logs/domlogs/portal-news-client.com.
    AH00015: Unable to open logs

    Error (24)Too many open files artinya Apache sudah mencapai batas maksimum file descriptor yang diizinkan sistem operasi. Ketika ini terjadi, Apache tidak bisa membuka file log baru — dan dalam kasus terburuk, tidak bisa melayani request sama sekali.

    Domain yang terdampak: client-b.com, portal-news-client.com. Artinya website-website ini tidak bisa diakses atau setidaknya logging-nya terganggu.

    Gejala 3: Massive wp-login.php Brute Force

    Ini yang paling menakutkan. Ketika saya grep aktivitas login WordPress dalam satu jam terakhir:

    [root@brantas ruak3711]# grep -r 'POST /wp-login.php' /usr/local/apache/logs/domlogs/ | grep -E "$(date +'%d/%b/%Y:%H:')|$(date -d '1 hour ago' +'%d/%b/%Y:%H:')" | awk '{print $1}' | cut -d: -f2 | sort | uniq -c | sort -nr | head -n 5
       5046 10.0.0.2
       4734 10.0.0.3
       4652 10.0.0.4
       4642 10.0.0.5
       4166 10.0.0.6

    Perhatikan angkanya: 5.046 percobaan login dalam satu jam dari satu IP. Itu artinya rata-rata 84 login attempts per menit, atau hampir 1.5 per detik. Dan itu baru 5 IP teratas — kemungkinan besar ada puluhan atau ratusan IP lain yang juga melakukan hal sama.

    Total percobaan login dari 5 IP ini saja: 23.240 attempts dalam satu jam. Jika ada 100 IP yang melakukan hal yang sama, itu 464.800 percobaan login per jam. Dengan rate seperti ini, brute force akan berhasil menemukan password yang lemah dalam hitungan jam.

    Root Cause — Apa yang Salah?

    1. Brute Force: Tidak Ada Proteksi di Depan WordPress Login

    WordPress login (wp-login.php) adalah pintu masuk utama ke dashboard WordPress. Tanpa proteksi tambahan, siapa pun bisa mengakses halaman ini dan mencoba login sebanyak mungkin. LiteSpeed memang punya throttle, tapi throttle hanya memperlambat — tidak memblokir. Dan ketika serangan datang dari banyak IP (distributed brute force), throttle menjadi tidak efektif.

    2. File Descriptor Exhaustion: Terlalu Banyak Request Simultan

    Ketika brute force menyerang server dengan ribuan request per menit, Apache harus membuka banyak koneksi sekaligus. Setiap koneksi membutuhkan file descriptor (untuk socket, log file, dll). Jika jumlah request melebihi batas ulimit -n yang dikonfigurasi untuk Apache, sistem operasi menolak membuka file baru — dan muncullah error Too many open files.

    Ini bukan hanya masalah logging. Jika Apache tidak bisa membuka file log, ia juga mungkin tidak bisa membuka file konfigurasi, certificate SSL, atau bahkan melayani request HTTP. Dalam kasus terburuk, seluruh website di server bisa down.

    3. Kombinasi Kedua Masalah

    Brute force yang masif → ribuan koneksi simultan → file descriptor habis → Apache tidak bisa buka file log → error beruntun → website down. Ini adalah chain reaction yang dimulai dari satu titik: ketiadaan proteksi di depan wp-login.php.

    Step-by-Step Solution — HTTP Basic Auth untuk wp-login.php

    PERINGATAN KEAMANAN: Sebelum Mengubah Config Apache

    Mengubah pre_virtualhost_global.conf adalah tindakan berisiko tinggi. Jika config salah, semua website di server bisa down. Sebelum melanjutkan:

    1. Backup config yang adacp pre_virtualhost_global.conf pre_virtualhost_global.conf.bak
    2. Test config sebelum restart — selalu jalankan apachectl configtest sebelum restart
    3. Pastikan Anda punya akses console/terminal — jika config salah, website down dan Anda tidak bisa akses via browser
    4. Gunakan HTTPS — HTTP Basic Auth mengirim username/password dalam base64 (bukan enkripsi). Tanpa HTTPS, credentials bisa di-intercept
    5. Catat password htpasswd Anda — jika lupa, Anda terkunci dari wp-login.php

    Langkah 1: Buat File htpasswd

    File htpasswd berisi username dan password untuk HTTP Basic Auth. Buat file ini di lokasi yang aman (di luar document root):

    # Buat file htpasswd dengan username admin
    htpasswd -cb /home/wp-admin-attack-htpasswd-file admin123
    # Masukkan password saat diminta

    Contoh isi file htpasswd (ter-encrypt):

    admin123:$apr1$xxxx$x.xxxxxxxxxxxxxxxxxxxx

    Penting: Jangan letakkan file htpasswd di document root (misal /home/user/public_html/). Jika file ini bisa diakses publik, attacker bisa membaca username-nya (meskipun password-nya ter-encrypt).

    Langkah 2: Edit pre_virtualhost_global.conf

    File ini berada di /usr/local/apache/conf/includes/pre_virtualhost_global.conf. Tambahkan blok berikut di akhir file:

    #BEGIN BLOCK-xmlrpc
    
    <Files "xmlrpc.php">
        Require all denied
        Require ip 122.248.245.244/32
        Require ip 54.217.201.243/32
        Require ip 54.232.116.4/32
        Require ip 192.0.80.0/20
        Require ip 192.0.96.0/20
        Require ip 192.0.112.0/20
        Require ip 195.234.108.0/22
        Require ip 192.0.64.0/18
    </Files>
    
    #END BLOCK-xmlrpc
    
    #BEGIN BLOCK-WP-ADMIN-ATTACK
    #
    <Files wp-login.php>
    AuthType basic
    AuthName "Untuk membuktikan bahwa Anda bukan robot, silakan memasukkan username dan katasandi sebagai berikut:"
    AuthBasicProvider file
    AuthUserFile /home/wp-admin-attack-htpasswd-file
    Require valid-user
    ErrorDocument 401 "Authentication required"
    </Files>
    
    #
    # END BLOCK-WP-ADMIN-ATTACK

    Penjelasan blok ini:

    • <Files wp-login.php> — aturan ini hanya berlaku untuk file wp-login.php, tidak untuk file lain di WordPress
    • AuthType basic — menggunakan HTTP Basic Authentication (browser akan menampilkan popup login)
    • AuthBasicProvider file — credential diambil dari file htpasswd
    • Require valid-user — hanya user yang terdaftar di htpasswd yang boleh mengakses
    • ErrorDocument 401 — pesan yang muncul jika autentikasi gagal
    • Blok xmlrpc — hanya mengizinkan IP tertentu untuk mengakses xmlrpc.php (WordPress.com, Jetpack, dll)

    Langkah 3: Test Config & Restart Apache

    Jangan langsung restart. Test dulu apakah config valid:

    # Test apakah config valid
    apachectl configtest
    # Output yang diharapkan: Syntax OK

    Jika output Syntax OK, restart Apache:

    # Restart Apache ( graceful agar tidak drop koneksi aktif)
    apachectl graceful
    # atau
    systemctl restart httpd
    PERINGATAN:

    Jika configtest mengembalikan error, JANGAN restart. Perbaiki error-nya terlebih dahulu. Jika Anda restart dengan config yang salah, semua website di server akan down sampai config diperbaiki.

    Langkah 4: Verifikasi Proteksi Aktif

    Buka browser dan akses https://domain-anda.com/wp-login.php. Anda seharusnya melihat popup login HTTP Basic Auth sebelum halaman WordPress login muncul:

    • Masukkan username dan password htpasswd yang sudah dibuat
    • Jika benar, halaman WordPress login akan muncul seperti biasa
    • Jika salah atau cancel, Anda akan melihat pesan “Authentication required”

    Sekarang coba akses wp-login.php tanpa credentials — Anda akan ditolak. Bot brute force juga akan ditolak, karena mereka tidak tahu username dan password HTTP Basic Auth Anda.

    Langkah 5: Fix File Descriptor Exhaustion

    Sementara proteksi wp-login.php menghentikan brute force, Anda juga perlu fix masalah Too many open files. Cek batas saat ini:

    # Cek batas file descriptor untuk Apache
    cat /proc/$(pgrep -f "apache2|httpd" | head -1)/limits | grep "Max open files"

    Jika Max open files terlalu rendah (misal 1024 atau 4096), tingkatkan:

    # Edit limits.conf
    nano /etc/security/limits.conf
    
    # Tambahkan di akhir file:
    apache hard nofile 65535
    apache soft nofile 32768
    * hard nofile 65535
    * soft nofile 32768

    Jika menggunakan systemd, edit juga service file Apache:

    # Edit systemd service
    systemctl edit httpd
    
    # Tambahkan:
    [Service]
    LimitNOFILE=65535

    Setelah itu, restart Apache:

    systemctl daemon-reexec
    systemctl restart httpd

    Pro Tips & Warnings

    • Gunakan HTTPS selalu — HTTP Basic Auth mengirim credentials dalam base64 (bukan enkripsi). Tanpa HTTPS, attacker bisa membaca username dan password Anda dari network traffic. Pastikan SSL aktif di server
    • Jangan gunakan password lemah di htpasswd — jika attacker tahu Anda menggunakan HTTP Basic Auth, mereka akan mencoba brute force htpasswd juga. Gunakan password minimal 16 karakter dengan kombinasi huruf, angka, dan simbol
    • Batasi IP untuk xmlrpc.php — blok xmlrpc di atas hanya mengizinkan IP WordPress.com dan Jetpack. Jika Anda tidak menggunakan Jetpack, bisa blok semua: Require all denied
    • Monitor error log secara berkala — jangan tunggu sampai error muncul sendiri. Jalankan tail -f error_log minimal sekali sehari untuk mengetahui masalah sejak dini
    • Gunakan Fail2Ban sebagai lapisan tambahan — HTTP Basic Auth melindungi wp-login.php, tapi Fail2Ban bisa memblokir IP secara permanen setelah beberapa percobaan gagal
    • Backup config sebelum edit — selalu backup pre_virtualhost_global.conf sebelum mengubah apapun

    FAQ

    Q: Apakah HTTP Basic Auth bisa di-crack?

    HTTP Basic Auth mengirim username dan password dalam encoding base64 (bukan enkripsi). Jika ada attacker yang bisa memonitor traffic (man-in-the-middle), mereka bisa membaca credentials tersebut. Itulah kenapa HTTPS wajib digunakan — HTTPS mengenkripsi seluruh traffic, termasuk credentials HTTP Basic Auth. Tanpa HTTPS, HTTP Basic Auth hanya melindungi dari bot yang tidak bisa decode base64 (kebanyakan bot memang tidak bisa, tapi attacker manusia bisa).

    Q: Bagaimana jika saya lupa password htpasswd?

    Jika Anda lupa password, Anda bisa membuat ulang file htpasswd dengan username yang sama:

    # Buat ulang file htpasswd (akan menghapus yang lama)
    htpasswd -cb /home/wp-admin-attack-htpasswd-file admin123
    # Masukkan password baru saat diminta

    Setelah itu, restart Apache (apachectl graceful) agar config ter-load ulang. Tidak perlu restart server — cukup restart service Apache.

    Q: Apakah HTTP Basic Auth mempengaruhi performa server?

    Tidak signifikan. HTTP Basic Auth hanya melakukan satu pengecekan tambahan: membaca file htpasswd dan membandingkan hash password. Proses ini membutuhkan waktu mikro-detik — jauh lebih cepat dari satu request database WordPress. Performa server tidak akan terpengaruh oleh HTTP Basic Auth.

    Q: Kenapa harus di pre_virtualhost_global.conf, bukan di .htaccess?

    Karena <Files> directive tidak bisa digunakan di .htaccess — hanya bisa di file konfigurasi Apache utama. Selain itu, pre_virtualhost_global.conf berlaku untuk semua virtual host di server, jadi semua website akan terlindungi secara seragam. Jika Anda hanya ingin melindungi satu website, gunakan .htaccess di document root website tersebut.

    Kesimpulan

    Serangan brute force WordPress adalah ancaman nyata yang terjadi setiap hari di ribuan server di seluruh dunia. Dari log yang saya analisis, satu IP bisa melakukan 5.000+ percobaan login dalam satu jam — dan itu baru satu dari puluhan IP yang menyerang secara bersamaan.

    Solusi HTTP Basic Auth yang saya implementasikan adalah benteng pertama yang sangat efektif. Bot brute force tidak bisa melewati HTTP Basic Auth, karena mereka tidak tahu username dan password yang Anda konfigurasi. Mereka hanya akan melihat pesan “Authentication required” dan berhenti mencoba.

    Tapi(HTTP Basic Auth bukan satu-satunya lapisan pertahanan yang Anda butuhkan. Anda juga perlu: Fail2Ban untuk memblokir IP secara permanen, limit login attempts di WordPress, dan yang paling penting — password yang kuat. Kombinasi dari semua lapisan pertahanan ini akan membuat server Anda jauh lebih aman dari serangan brute force.

    Author: NOC Engineer — ditulis berdasarkan pengalaman menangani brute force 5.000+ attempts per jam di server production.