fail2ban Jail Sistemi: Servis Bazlı Engelleme

Sunucunu yöneten herkes bir gün SSH loglarına bakıp binlerce başarısız giriş denemesi gördüğünde o tanıdık soğukluk hissini yaşar. Brute force saldırıları, bot taramaları ve otomatik exploit denemeleri artık internet üzerindeki her açık portun kaçınılmaz gerçeği. fail2ban bu noktada devreye girerek log dosyalarını izler, belirlediğin kurallara göre şüpheli IP adreslerini otomatik olarak engeller. Ama fail2ban’ın gerçek gücü, tek bir kural setiyle her şeyi yönetmek değil, jail sistemi sayesinde her servisi ayrı ayrı, kendi kurallarıyla koruyabilmek.

Jail Sistemi Nedir ve Neden Önemlidir?

fail2ban’ın mimarisini anlamak için üç temel kavramı kafana oturtman gerekiyor: filter, action ve jail.

Filter, bir log dosyasında hangi satırların “başarısız deneme” sayılacağını tanımlayan regex kalıplarından oluşur. Örneğin SSH için “Failed password for” içeren satırlar, Apache için 401 yanıt kodları.

Action, bir IP engellendiğinde ne yapılacağını tanımlar. iptables kuralı eklemek, firewalld’a kural yazmak, bir email göndermek gibi işlemler bu katmanda gerçekleşir.

Jail ise bu ikisini bir araya getiren yapıdır. Hangi log dosyasına bakılacağını, hangi filtrenin kullanılacağını, kaç başarısız denemeden sonra engelleme yapılacağını ve engellemenin ne kadar süreceğini jail tanımlar. Her servis için ayrı bir jail oluşturabilirsin ve bu jail’ler birbirinden tamamen bağımsız çalışır.

Bu mimari sayesinde SSH için 3 başarısız denemede 24 saat engelleme yaparken, web uygulaması login sayfan için 10 denemede 1 saatlik engelleme uygulayabilirsin. Gerçek dünya senaryolarında bu esneklik son derece kritik.

Temel Yapılandırma Dosyaları

fail2ban’ın yapılandırması /etc/fail2ban/ dizininde yaşar. Bu dizinde birkaç önemli dosya var:

  • /etc/fail2ban/fail2ban.conf: Genel daemon ayarları
  • /etc/fail2ban/jail.conf: Varsayılan jail tanımları
  • /etc/fail2ban/jail.d/: Özel jail yapılandırmaları için dizin
  • /etc/fail2ban/filter.d/: Filter tanımları
  • /etc/fail2ban/action.d/: Action tanımları

Altın kural: jail.conf dosyasını doğrudan düzenleme. Paket güncellemelerinde bu dosya üzerine yazılır ve tüm özelleştirmelerin gider. Bunun yerine /etc/fail2ban/jail.local dosyası oluştur ya da /etc/fail2ban/jail.d/ dizinine .conf uzantılı dosyalar ekle.

# Mevcut jail.conf'u temel alarak jail.local oluştur
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Ya da sıfırdan başla
touch /etc/fail2ban/jail.d/custom-jails.conf

jail.local ile Genel Ayarları Yapılandırma

jail.local dosyasındaki [DEFAULT] bölümü tüm jail’ler için geçerli olan varsayılan değerleri belirler. Kendi ihtiyaçlarına göre şu şekilde yapılandırabilirsin:

[DEFAULT]
# Kendi IP adresin ve güvendiğin ağlar - bunlar asla engellenmez
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 10.0.0.0/8

# Kaç saniye boyunca deneme sayılacak (burada 10 dakika)
findtime = 600

# Bu süre içinde kaç başarısız deneme engellemeyi tetikler
maxretry = 5

# Engellenme süresi (saniye cinsinden, -1 kalıcı)
bantime = 3600

# Engelleme yöntemi
banaction = iptables-multiport

# Log seviyesi (1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
loglevel = INFO

# fail2ban'ın kendi log dosyası
logtarget = /var/log/fail2ban.log

# Backend: systemd journal için systemd, dosya için auto
backend = auto

bantime için negatif değer kullanırsan kalıcı engelleme yapılır. Bazı senaryolarda bu mantıklı olabilir ama dikkatli ol, yanlış bir IP’yi kalıcı engellersen erişimi kaybedebilirsin.

SSH Jail Yapılandırması

SSH, fail2ban’ın en yaygın kullanıldığı servis. Basit ama etkili bir SSH jail tanımı şöyle görünür:

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 300
bantime = 86400

Eğer SSH’ı varsayılan 22 numaralı porttan farklı bir porta taşıdıysan:

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 300
bantime = 86400

Systemd kullanan modern dağıtımlarda (Ubuntu 20.04+, Debian 10+, CentOS 8+) log yolu farklı olabilir:

[sshd]
enabled = true
port = ssh
filter = sshd
# systemd journal kullanıyorsa
backend = systemd
maxretry = 3
findtime = 300
bantime = 86400

Apache ve Nginx için Jail Tanımları

Web sunucuları için birden fazla jail tanımlamak iyi bir pratik. Farklı saldırı vektörleri için ayrı kurallar işleri çok daha yönetilebilir kılar.

# Apache brute force login girişimleri
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 5
findtime = 300
bantime = 3600

# Apache zararlı bot taramaları
[apache-badbots]
enabled = true
port = http,https
filter = apache-badbots
logpath = /var/log/apache2/access.log
maxretry = 2
findtime = 86400
bantime = 86400

# Apache noscript saldırıları
[apache-noscript]
enabled = true
port = http,https
filter = apache-noscript
logpath = /var/log/apache2/error.log
maxretry = 6
findtime = 60
bantime = 86400

# Nginx için
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 300
bantime = 3600

[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
findtime = 86400
bantime = 172800

Özel Filter Oluşturma

Hazır filtrelerin senin uygulamanın log formatıyla eşleşmediği durumlar olacak. Bu durumda kendi filtrenizi yazman gerekiyor. Örneğin WordPress’e yapılan brute force saldırılarını yakalamak için:

# /etc/fail2ban/filter.d/wordpress-auth.conf
[Definition]
failregex = ^<HOST> .* "POST /wp-login.php
            ^<HOST> .* "POST /xmlrpc.php

ignoreregex =

Regex’in çalışıp çalışmadığını test etmek için fail2ban-regex aracını kullan:

# Filter'ı gerçek log dosyasına karşı test et
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress-auth.conf

# Çıktı sana kaç eşleşme bulunduğunu gösterir
# Örnek çıktı:
# Lines: 5000 lines, 0 ignored, 127 matched, 4873 missed

Bu aracı özellikle özel uygulama logları için filter yazarken çok kullanacaksın. Regex’i doğrudan log satırına karşı test edebilirsin:

# Tek bir log satırını test et
fail2ban-regex "203.0.113.42 - - [01/Jan/2024:12:00:00 +0000] "POST /wp-login.php HTTP/1.1" 200 1234" "^<HOST> .* "POST /wp-login.php"

Şimdi bu filtreyi kullanan jail’i tanımlayalım:

[wordpress]
enabled = true
port = http,https
filter = wordpress-auth
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 7200

Mail Servisleri için Jail Yapılandırması

Postfix, Dovecot gibi mail servisleri de sık sık brute force hedefi olur. Özellikle SMTP auth ve IMAP/POP3 giriş denemeleri çok yaygın:

[postfix-sasl]
enabled = true
port = smtp,465,587
filter = postfix-sasl
logpath = /var/log/mail.log
maxretry = 3
findtime = 300
bantime = 86400

[dovecot]
enabled = true
port = pop3,pop3s,imap,imaps,submission,465,sieve
filter = dovecot
logpath = /var/log/mail.log
maxretry = 5
findtime = 300
bantime = 43200

Bantime Artırma: Tekrarlayan Saldırganlar İçin

fail2ban 0.10 ve sonrasında gelen bantime.increment özelliği çok işe yarar. Aynı IP sürekli saldırıyorsa engelleme süresi her seferinde artıyor:

[DEFAULT]
# Artan engelleme süresini etkinleştir
bantime.increment = true

# Her ban'da çarpan
bantime.factor = 1

# Maksimum engelleme süresi (saniye, burada 1 hafta)
bantime.maxtime = 604800

# Kalıcı engelleme için -1
# bantime.maxtime = -1

# Artan ban formülü
# default: ban1=bantime, ban2=bantime*2, ban3=bantime*4...
bantime.multiplier = 2

Bu ayarla ilk ban 1 saat, ikincisi 2 saat, üçüncüsü 4 saat şeklinde katlanarak artar. Maksimumu 1 hafta olarak ayarladığında gerçek saldırganları pratikte kalıcı olarak engellemiş olursun.

fail2ban-client ile Jail Yönetimi

Yapılandırmayı yaptıktan sonra servisi yönetmek için fail2ban-client aracını kullanırsın:

# Servisi başlat
systemctl start fail2ban
systemctl enable fail2ban

# Tüm jail'lerin durumunu gör
fail2ban-client status

# Belirli bir jail'in detaylarını gör
fail2ban-client status sshd

# Bir IP adresini manuel olarak engelle
fail2ban-client set sshd banip 203.0.113.42

# Bir IP adresinin engelini kaldır
fail2ban-client set sshd unbanip 203.0.113.42

# Jail'i yeniden yükle (yapılandırma değişikliği sonrası)
fail2ban-client reload sshd

# Tüm fail2ban'ı yeniden yükle
fail2ban-client reload

# Engelli IP'leri listele
fail2ban-client status sshd | grep "Banned IP"

Mevcut engelli IP’leri görmek ve yönetmek için kullanışlı bir one-liner:

# Tüm jail'lerdeki engelli IP'leri listele
for jail in $(fail2ban-client status | grep "Jail list" | sed "s/.*://;s/,//g"); do
    echo "=== $jail ===";
    fail2ban-client status $jail | grep "Banned IP";
done

Gerçek Dünya Senaryosu: Çok Katmanlı Web Sunucusu Koruması

Diyelim ki bir VPS üzerinde Nginx + PHP-FPM + WordPress çalıştırıyorsun ve aynı zamanda SSH erişimi var. Gerçekçi bir yapılandırma şu şekilde görünür:

# /etc/fail2ban/jail.d/production-server.conf dosyası oluştur
cat > /etc/fail2ban/jail.d/production-server.conf << 'EOF'
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1
bantime = 3600
findtime = 600
maxretry = 5
banaction = iptables-multiport

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 300
bantime = 86400

[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 300
bantime = 3600

[wordpress]
enabled = true
port = http,https
filter = wordpress-auth
logpath = /var/log/nginx/access.log
maxretry = 8
findtime = 300
bantime = 7200

[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
findtime = 86400
bantime = 172800
EOF

Bu yapılandırmayı uygulamadan önce her zaman test et:

# Yapılandırma sözdizimini kontrol et
fail2ban-client -t

# Çıktı:
# OK: configuration test is successful

Engelleme İstatistiklerini İzleme

Zamanla hangi jail’lerin ne kadar iş yaptığını görmek önemli. Basit bir izleme scripti:

#!/bin/bash
# /usr/local/bin/fail2ban-stats.sh

echo "=== fail2ban Engelleme İstatistikleri ==="
echo "Tarih: $(date)"
echo ""

for jail in $(fail2ban-client status | grep "Jail list" | sed "s/.*://;s/ //g" | tr ',' 'n'); do
    total=$(fail2ban-client status $jail | grep "Total banned" | awk '{print $NF}')
    current=$(fail2ban-client status $jail | grep "Currently banned" | awk '{print $NF}')
    echo "[$jail] Toplam: $total | Aktif: $current"
done

echo ""
echo "=== Son 24 saat içinde en çok engellenen IP'ler ==="
grep "Ban " /var/log/fail2ban.log | grep "$(date +%Y-%m-%d)" | awk '{print $NF}' | sort | uniq -c | sort -rn | head -10

Bu scripti cron’a ekleyerek günlük rapor alabilirsin:

chmod +x /usr/local/bin/fail2ban-stats.sh

# Her sabah 09:00'da rapor gönder
echo "0 9 * * * root /usr/local/bin/fail2ban-stats.sh | mail -s 'fail2ban Raporu' [email protected]" >> /etc/cron.d/fail2ban-report

Sık Yapılan Hatalar ve Çözümleri

Kendi IP’ni engellemek: Bu en klasik hata. ignoreip satırına mutlaka kendi IP adresini veya ağını ekle. VPN kullanıyorsan VPN IP bloğunu da ekle.

Log dosyası yolu yanlış: fail2ban bir jail’i etkinleştirdiğinde log dosyasının var olup olmadığını kontrol etmez, hata sadece runtime’da ortaya çıkar. Log yolunu doğrulamak için:

# Log dosyasının var olduğunu kontrol et
ls -la /var/log/nginx/error.log

# fail2ban logunda hata olup olmadığına bak
tail -f /var/log/fail2ban.log

Backend uyumsuzluğu: Systemd kullanan sistemlerde journald üzerinden log okumak için backend’i systemd olarak ayarlamalısın, aksi takdirde fail2ban logları göremez ve hiçbir engelleme yapmaz.

maxretry çok düşük: Meşru kullanıcılar da yanlış şifre girebilir. Özellikle web uygulamaları için maxretry değerini çok düşük tutmak kullanıcıları engeller. Servis tipine göre uygun değeri seç.

firewalld ile Kullanım

CentOS/RHEL/Rocky Linux gibi dağıtımlarda iptables yerine firewalld kullanılır. fail2ban’ı firewalld ile uyumlu hale getirmek için action’ı değiştirmen gerekir:

[DEFAULT]
banaction = firewallcmd-ipset
banaction_allports = firewallcmd-allports

firewalld ile çalışırken engellenen IP’leri şu şekilde görebilirsin:

# fail2ban tarafından oluşturulan firewalld kurallarını gör
firewall-cmd --direct --get-all-rules

# fail2ban zone'larını listele
firewall-cmd --get-zones | tr ' ' 'n' | grep f2b

Sonuç

fail2ban’ın jail sistemi, sunucu güvenliğini servis bazında granüler düzeyde yönetmenin en pratik yollarından biri. Her servisin kendine özgü saldırı profili olduğu için SSH’ı farklı, web sunucusunu farklı, mail servisini farklı kurallarla korumak çok daha etkili bir savunma sağlıyor.

Yapılandırırken dikkat etmen gereken birkaç temel nokta var: Kendi IP adreslerini ignoreip listesine ekle, bantime ve maxretry değerlerini servisin tolerans düzeyine göre ayarla, özel uygulama logları için kendi filter’larını yaz ve fail2ban-regex aracıyla test et. bantime.increment özelliğini etkinleştirirsen tekrarlayan saldırganları otomatik olarak daha uzun süre engellemiş olursun.

fail2ban mükemmel bir araç ama tek başına yeterli değil. IP tabanlı engelleme atlatılabilir, özellikle botnet saldırılarında sürekli değişen IP havuzlarıyla karşılaşırsın. fail2ban’ı firewall kuralları, rate limiting ve güçlü parola politikalarıyla birlikte kullanmak bütünsel bir güvenlik yaklaşımı oluşturur. Temel korumanı sağladıktan sonra log istatistiklerini düzenli izleyerek hangi jail’lerin en çok iş yaptığını ve saldırı örüntülerinin nasıl değiştiğini takip etmeyi alışkanlık haline getir.

Yorum yapın