fail2ban ile Brute Force Saldırılarını Engelleme
Sunucularını yöneten herkes er ya da geç loglarında şu manzarayla karşılaşır: binlerce başarısız SSH giriş denemesi, farklı IP adreslerinden gelen sistematik parola denemeleri, servisin yavaşlaması. Brute force saldırıları internet dünyasının kaçınılmaz gerçeklerinden biri. Bu noktada fail2ban devreye giriyor ve hayat kurtarıyor.
Fail2ban Nedir ve Nasıl Çalışır?
Fail2ban, log dosyalarını izleyen ve belirlediğin kurallara göre şüpheli IP adreslerini otomatik olarak engelleyen bir güvenlik aracıdır. Python ile yazılmış olan bu araç, temelde şu mantıkla çalışır: bir IP adresi belirli bir süre içinde belirlediğin eşik değerinin üzerinde başarısız giriş denemesi yaparsa, o IP adresi firewall kurallarıyla engellenir.
Fail2ban’ın çalışma döngüsü şöyle özetlenebilir:
- Log dosyasını sürekli izler (SSH, Apache, Nginx, FTP vb.)
- Başarısız girişimleri filtrelerle yakalar
- Belirli bir zaman penceresinde eşik aşıldığında aksiyon alır
- IP’yi iptables, nftables veya ufw üzerinden banlar
- Ban süresi dolunca IP’yi otomatik serbest bırakır
Bu kadar basit bir mantık, doğru yapılandırılınca son derece etkili bir savunma hattı oluşturuyor.
Kurulum
Fail2ban hemen hemen tüm Linux dağıtımlarının depolarında mevcut. Kurulum tek satır.
Debian/Ubuntu:
sudo apt update && sudo apt install fail2ban -y
CentOS/RHEL/Rocky Linux:
sudo dnf install epel-release -y
sudo dnf install fail2ban -y
Arch Linux:
sudo pacman -S fail2ban
Kurulum sonrası servisi başlatıp otomatik başlangıca ekliyoruz:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo systemctl status fail2ban
Temel Yapılandırma Mantığı
Fail2ban’ın yapılandırma sistemi biraz farklı çalışıyor. /etc/fail2ban/ dizininde iki tür dosya var: .conf uzantılı orijinal dosyalar ve .local uzantılı özelleştirilmiş dosyalar. Asla .conf dosyalarını doğrudan düzenleme. Fail2ban güncellendiğinde bu dosyalar sıfırlanır. Bunun yerine .local dosyaları oluşturuyoruz.
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
jail.local dosyasının [DEFAULT] bölümünde global ayarları yapılandırıyoruz:
[DEFAULT]
# Asla banlanmayacak IP'ler (kendi ofis IP'ni buraya ekle!)
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 78.186.XX.XX
# Başarısız deneme sayma penceresi (saniye cinsinden, 10 dakika)
findtime = 600
# Kaç başarısız denemede ban uygulanacak
maxretry = 5
# Ban süresi (saniye, -1 ise kalıcı ban)
bantime = 3600
# Ban süresi artırma özelliği (her tekrarda süre katlanır)
bantime.increment = true
bantime.factor = 1
bantime.maxtime = 604800
# Backend (systemd logları için systemd kullan)
backend = systemd
ignoreip burası kritik. Kendi IP adresini buraya eklemeyi unutma. Yoksa bir gün yanlışlıkla kendi sunucundan kilitlenebilirsin. Bunu bizzat yaşadım, sorma.
SSH Koruması
En yaygın kullanım senaryosu SSH koruması. jail.local dosyasına şunu ekliyoruz:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 300
bantime = 86400
Eğer SSH’ı varsayılan 22 dışında bir porta taşıdıysan:
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 300
bantime = 86400
Ubuntu/Debian sistemlerde log /var/log/auth.log‘da, CentOS/RHEL sistemlerde /var/log/secure‘da. Systemd tabanlı sistemlerde backend’i systemd yaparsak logpath’e gerek kalmaz.
Yapılandırmayı uygulamak için fail2ban’ı yeniden başlatıyoruz:
sudo systemctl restart fail2ban
Gerçek Dünya Senaryosu: Atak Altındaki Sunucu
Diyelim ki bir müşterinin web sunucusunu yönetiyorsun ve sabah mailboxında şu alarm var: “Sunucu yavaş, bir şeyler oluyor.” Auth log’a bakıyorsun:
sudo tail -f /var/log/auth.log | grep "Failed password"
Ekrana akan onlarca satır, farklı IP’lerden SSH denemeleri. Bot net saldırısı. Fail2ban kurulu ve aktif olsaydı bu IP’lerin büyük çoğunluğu çoktan banlanmış olurdu. Şimdi fail2ban’ı kurup aktif edelim ve mevcut durumu yönetelim.
Önce kim bizi dövüyor görelim:
sudo fail2ban-client status sshd
Çıktı şuna benzer:
Status for the jail: sshd
|- Filter
| |- Currently failed: 12
| |- Total failed: 847
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 23
|- Total banned: 156
`- Banned IP list: 185.234.XX.XX 45.33.XX.XX ...
847 başarısız deneme, 156 banlanan IP. Fail2ban olmadan bu sunucu saatlerdir bu yükü taşıyor olurdu.
Web Sunucusu Koruması
Nginx Brute Force Koruması
Web panel giriş sayfaları ve WordPress gibi CMS’lerin login sayfaları sık sık hedef alınır. Nginx için jail.local’a ekleyelim:
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 300
bantime = 7200
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 10
findtime = 600
bantime = 7200
WordPress için özel bir jail oluşturalım. Önce filter dosyasını yazıyoruz:
sudo nano /etc/fail2ban/filter.d/wordpress.conf
[Definition]
failregex = ^<HOST> .* "POST /wp-login.php
^<HOST> .* "POST /xmlrpc.php
ignoreregex =
Sonra jail.local’a ekliyoruz:
[wordpress]
enabled = true
filter = wordpress
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 86400
Apache Koruması
[apache-auth]
enabled = true
filter = apache-auth
port = http,https
logpath = /var/log/apache2/error.log
maxretry = 5
findtime = 300
bantime = 7200
[apache-badbots]
enabled = true
filter = apache-badbots
port = http,https
logpath = /var/log/apache2/access.log
maxretry = 2
findtime = 86400
bantime = 604800
Apache bad bot koruması burada dikkat çekici. Kötü niyetli botlar ve tarayıcılar iki denemede bir haftaya banlanıyor. Agresif ama etkili.
Özel Filter Yazma
Fail2ban’ın hazır filtreleri olmayan servisler için kendi filtremizi yazabiliriz. Örneğin özel bir uygulama log’u için:
sudo nano /etc/fail2ban/filter.d/myapp.conf
[INCLUDES]
before = common.conf
[Definition]
_daemon = myapp
# Log satirinda basarisiz giris icin regex
failregex = ^%(__prefix_line)s.*Authentication failed for user .* from <HOST>$
^%(__prefix_line)s.*Invalid login attempt from <HOST>$
^%(__prefix_line)sFailed login: .* from <HOST>$
ignoreregex =
# Tarih formatini belirt (opsiyonel)
datepattern = %%Y-%%m-%%d %%H:%%M:%%S
Regex’i test etmek için fail2ban-regex aracını kullanıyoruz:
sudo fail2ban-regex /var/log/myapp/auth.log /etc/fail2ban/filter.d/myapp.conf
Bu komut kaç satırın eşleştiğini ve eşleşmeyen satırları gösterir. Filtreyi geliştirmeden önce mutlaka test et.
Yönetim ve Monitoring
Fail2ban’ı kurup bırakmak yeterli değil. Düzenli takip etmek gerekiyor.
Genel durum:
sudo fail2ban-client status
Belirli bir jail’in durumu:
sudo fail2ban-client status sshd
sudo fail2ban-client status nginx-http-auth
Manuel IP banlama:
sudo fail2ban-client set sshd banip 185.234.XX.XX
IP ban kaldırma:
sudo fail2ban-client set sshd unbanip 185.234.XX.XX
Banlanan IP’leri iptables üzerinden kontrol etme:
sudo iptables -L f2b-sshd -n --line-numbers
Fail2ban logunu izleme:
sudo tail -f /var/log/fail2ban.log
Fail2ban log’unda şu mesajları görmen gerekiyor: Ban, Unban, Found. Eğer sadece Found görüp Ban görmüyorsan maxretry ayarın yüksek ya da findtime düşük olabilir.
Kalıcı Ban Listesi Oluşturma
Bazı IP aralıkları sürekli saldırıyor ve bunları kalıcı olarak engellemek mantıklı. Fail2ban ile kalıcı ban için bantime = -1 kullanabilirsin:
[sshd-permanent]
enabled = true
filter = sshd
port = ssh
logpath = /var/log/auth.log
maxretry = 1
findtime = 86400
bantime = -1
Bu jail’de bir günde bir kez başarısız deneyen IP kalıcı olarak banlanır. Dikkatli kullan, yanlış pozitif durumunda manuel müdahale gerekir.
Alternatif olarak bilinen kötü niyetli IP listelerini (blocklist) fail2ban ile entegre edebilirsin. /etc/fail2ban/action.d/ dizinine özel aksiyon yazarak bu işi otomatize edebilirsin.
E-posta Bildirimleri
Her ban işleminde mail almak isteyebilirsin. jail.local‘daki [DEFAULT] bölümüne:
[DEFAULT]
destemail = [email protected]
sender = [email protected]
mta = sendmail
action = %(action_mwl)s
action parametreleri:
- %(action_)s: Sadece ban, bildirim yok
- %(action_mw)s: Ban + whois bilgisiyle mail
- %(action_mwl)s: Ban + whois + log satırlarıyla mail
Log satırları içeren mailler bazen çok uzun oluyor, bunu aklında bulundur.
Recidive Jail: Tekrarlayan Saldırganlar için
Bu benim en sevdiğim fail2ban özelliği. Recidive jail, başka jail’lerde defalarca banlanan IP’leri uzun süreli olarak banlar. Yani “sen çok problem çıkardın, seni uzun süre görmek istemiyorum” diyor.
[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
action = iptables-allports[name=recidive]
bantime = 604800
findtime = 86400
maxretry = 5
Bu ayarla: bir gün içinde 5 farklı jail’de banlanan IP, bir hafta boyunca TÜM portlardan engellenir. Botlar bunu sevmez.
Performans Optimizasyonu
Çok trafikli sunucularda fail2ban’ın log okuma yükü artabilir. Birkaç optimizasyon önerisi:
Backend seçimi: Systemd kullanan modern sistemlerde backend = systemd seçeneği backend = auto‘dan daha hızlı çalışır.
Gereksiz jail’leri devre dışı bırak: Kullanmadığın servislerin jail’leri aktif olmasın. Her aktif jail, fail2ban’ın tarama yükünü artırır.
dbpurgeage ayarı: Fail2ban kendi veritabanında geçmiş ban kayıtlarını saklar. Çok uzun tutmak veritabanını şişirir:
[DEFAULT]
dbpurgeage = 86400
Findtime ve maxretry dengesi: Çok kısa findtime ile çok düşük maxretry kombinasyonu meşru kullanıcıları da banlar. İyi bir başlangıç noktası: findtime=600 (10dk), maxretry=5.
Sık Karşılaşılan Sorunlar ve Çözümleri
Fail2ban başlamıyor:
sudo journalctl -u fail2ban -n 50
sudo fail2ban-client -x start
Genellikle ya syntax hatası var ya da log dosyası bulunamıyor. fail2ban-client -x start komutu hata mesajını daha açık gösterir.
IP banlanmıyor:
Log’da Found görüyorsun ama Ban yok. Olası sebepler:
- ignoreip listesinde bu IP var
- maxretry eşiği aşılmamış
- findtime çok kısa, denemeler pencere dışında kalıyor
- Filter regex log formatıyla eşleşmiyor
Test için:
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf --print-all-matched
Kendi IP’ni banladın:
Panik yapma. Sunucuya başka bir yoldan (VPS console, IPMI, ikinci sunucu üzerinden) bağlan ve:
sudo fail2ban-client set sshd unbanip SENIN_IP_ADRESIN
Sonra ignoreip listene ekle ve bir daha bu dramayı yaşama.
Cloudflare Entegrasyonu
Sunucun önünde Cloudflare varsa gerçek IP’ler Cloudflare’in IP’si olarak görünür. Fail2ban yanlış IP’yi banlar. Bu durumda Nginx/Apache’yi gerçek IP’yi loglaması için yapılandırman gerekir.
Nginx için:
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
# ... diğer Cloudflare IP aralıkları
real_ip_header CF-Connecting-IP;
Bu yapılandırmayla log’a gerçek ziyaretçi IP’si yazılır ve fail2ban doğru IP’yi banlar.
Pratik Kontrol Checklist’i
Yeni bir sunucu kurduğunda fail2ban için şu adımları takip et:
- Kendi IP adresini
ignoreip‘e ekle (VPN IP’lerin dahil) jail.localoluştur, aslajail.confdüzenleme- SSH jail’i aktif et, port numarasını doğru ayarla
- Kullandığın web sunucusunun jail’ini aktif et
- Recidive jail’i aktif et
bantime.increment = trueayarla- Servisi başlat ve
fail2ban-client statusile kontrol et - Test için bir IP’yi manuel banla, banladığını iptables ile doğrula
- Bir hafta sonra log’u incele, kaç IP banlanmış gör
Logları Analiz Etme
Düzenli log analizi fail2ban’ın ne kadar iş yaptığını ve ayarlarını optimize etmen gerekip gerekmediğini gösterir:
# En cok saldiran IP'ler
sudo grep "Ban " /var/log/fail2ban.log | awk '{print $NF}' | sort | uniq -c | sort -rn | head 20
# Hangi jail en cok ban atiyor
sudo grep "Ban " /var/log/fail2ban.log | awk '{print $6}' | sort | uniq -c | sort -rn
# Son 24 saatin ban sayisi
sudo grep "Ban " /var/log/fail2ban.log | grep "$(date +%Y-%m-%d)" | wc -l
Bu komutları haftada bir çalıştırıp çıktıları not tutarsan, sunucuna yönelik saldırı trendlerini zamanla görmeye başlarsın.
Sonuç
Fail2ban kurulumu ve temel yapılandırması birkaç saatlik iş. Ama bu birkaç saat, sunucunun güvenliği açısından son derece değerli bir yatırım. Brute force saldırıları tamamen durdurulamaz ama hız kesilebilir, maliyeti artırılabilir ve sunucu üzerindeki etkisi minimize edilebilir.
Önemli noktalara tekrar değinelim: .local dosyalarını kullan, kendi IP’ni ignoreip‘e ekle, bantime.increment ile tekrarlayan saldırganlara karşı daha sert ol, recidive jail ile çok sorun çıkaran IP’leri uzun süre engelle, düzenli log analizi yap.
Fail2ban tek başına bir mucize değil elbette. SSH key authentication, iki faktörlü doğrulama, gerekmedikçe portları kapatma gibi diğer güvenlik önlemleriyle birlikte kullanıldığında gerçek bir savunma katmanı oluşturuyor. Güvenlik katmanları üst üste eklendiğinde, her ekstra katman saldırganın işini biraz daha zorlaştırıyor. Fail2ban bu katmanların en pratik ve en etkili olanlarından biri.
