İçeriğe geç
Approvalens

Rehberler · 6 dk okuma

Fail2ban Kurulumu: Ubuntu'da SSH ve WordPress Koruması

Ubuntu'da fail2ban kur, jail.local kullan, sshd jail'ini kontrol et, nginx ya da Apache log'u için wp-login.php jail'i ekle, banı kaldır, sınırlarını bil.

Approvalens ekibi

Fail2ban log'larını okur, başarısız denemeleri IP adresine göre sayar ve bir adres sınırı aşınca onu engelleyen bir güvenlik duvarı kuralı ekler. Yaptığı iş bu kadar; baştan net olmakta fayda var. Projenin kendi README dosyası şöyle diyor: "Though Fail2Ban is able to reduce the rate of incorrect authentication attempts, it cannot eliminate the risk presented by weak authentication." Yani yanlış giriş denemelerinin hızını düşürür ama zayıf kimlik doğrulamanın riskini ortadan kaldıramaz.

Kısacası bu, girişler için hız sınırlama; ne güvenlik duvarının yerini tutar ne de zayıf bir şifreyi düzeltir. Yine de tipik bir blog VPS'inde on beş dakikaya değer: SSH'a ve wp-login.php'ye yönelik şifre tahminini damla damla akan bir seviyeye indirir, log'larını okunur tutar.

Ubuntu'da kurulum

sudo apt update
sudo apt install fail2ban
sudo systemctl status fail2ban

Ubuntu 24.04'te güncellenmiş paketi kullandığından emin ol. 24.04'ün ilk paketi Python 3.12 altında açılmıyordu (hata kaydı #2055114); 1.0.2-3ubuntu0.1 sürümünde düzeltildi. Hangi sürümün kurulu olduğunu apt policy fail2ban gösterir. systemctl status çıktısında active (running) görüyorsan sorun yok.

jail.conf değil, jail.local

/etc/fail2ban/jail.conf dosyasını asla düzenleme; paket güncellemeleri onu değiştirir. jail.conf kılavuzu okuma sırasını veriyor: önce jail.conf, sonra jail.d/*.conf, sonra jail.local, en son jail.d/*.local. Kılavuza göre sonra okunan dosyadaki ayar, öncekilerdeki aynı ayarın önüne geçer. .local dosyalarına da yalnızca değiştirmek istediğin ayarları yazarsın.

Ubuntu zaten bir geçersiz kılma dosyasıyla geliyor: /etc/fail2ban/jail.d/defaults-debian.conf. 24.04'teki içeriği şu (paket kaynağı):

[DEFAULT]
banaction = nftables
banaction_allports = nftables[type=allports]
backend = systemd

[sshd]
enabled = true

Bundan iki sonuç çıkıyor. SSH jail'i kurar kurmaz açık ve systemd journal'ını okuyor; yani /var/log/auth.log olmayan sunucularda da çalışıyor. Ve aksini söylemeyen her jail backend = systemd ayarını miras alıyor. Bu, aşağıdaki WordPress jail'i için önemli.

/etc/fail2ban/jail.local dosyasını kendi varsayılanlarınla oluştur:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 198.51.100.7

maxretry, banlanmak için son findtime süresi içinde kaç başarısız deneme olması gerektiğini, bantime da banın ne kadar süreceğini belirler. 198.51.100.7 yerine, varsa kendi sabit IP'ni yaz. ignoreip banlanmayacak IP'lerin listesi ve kendini dışarıda bırakmamanın en kolay yolu. Evdeki IP'n değişiyorsa bunu boş bırak ve aşağıdaki ban kaldırma komutlarına güven.

SSH jail'ini kontrol et

sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed:	3
|  |- Total failed:	214
|  `- Journal matches:	_SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned:	4
   |- Total banned:	19
   `- Banned IP list:	192.0.2.41 192.0.2.88 198.51.100.200 203.0.113.77

SSH'ta şifreyle girişi zaten kapattıysan (yeni VPS'te SSH ve UFW güvenliği rehberine bak), bu banlar çoğunlukla gürültüyü azaltır; tahminler zaten tutamazdı. Şifre hâlâ açıksa bu jail gerçek iş yapıyor ama asıl çözüm şifreyi kapatmak.

wp-login.php için jail

Fail2ban bir WordPress filtresiyle gelmiyor; küçük bir tane kendin yazacaksın. Fikir şu: web sunucusunun erişim log'unda wp-login.php'ye giden POST isteklerini saymak.

Önce kendi log'unda başarısız bir girişin neye benzediğine bak. Yanlış şifreyle giriş yapmayı dene, sonra:

sudo tail -n 3 /var/log/nginx/access.log
203.0.113.25 - - [07/Oct/2026:09:14:02 +0000] "POST /wp-login.php HTTP/2.0" 200 4521 "https://ornek.com/wp-login.php" "Mozilla/5.0 ..."

Standart bir WordPress'te başarısız giriş formu 200 ile yeniden gösterir, başarılı giriş ise 302 ile yönlendirir. Seninkinin de böyle davrandığını kontrol et (bir güvenlik eklentisi ya da özel bir giriş sayfası bunu değiştirebilir), çünkü filtre buna dayanıyor.

Üç parçalı bir WordPress giriş jail'i: 200 durum koduyla POST /wp-login.php isteğini yakalayan failregex içeren wordpress-login.conf filtre dosyası; jail.local içinde backend auto, port http,https, logpath /var/log/nginx/access.log, maxretry 5, findtime 10m, bantime 1h ayarlı jail bloğu; toplam 37 başarısız deneme ve bir banlı IP gösteren fail2ban-client status çıktısı
Filtre, jail, durum. backend = auto satırına dikkat: o olmadan Ubuntu 24.04'ün varsayılanı jail'in log dosyanı yok saymasına yol açar.

Filtre, /etc/fail2ban/filter.d/wordpress-login.conf:

[Definition]
failregex = ^(?:\S+:\d+ )?<HOST> \S+ \S+ \[[^\]]+\] "POST /wp-login\.php[^"]*" 200\b
ignoreregex =

<HOST>, fail2ban'in istemci adresi için kullandığı yer tutucu. Baştaki isteğe bağlı (?:\S+:\d+ )? kısmı, her satırın ornek.com:443 ile başladığı Apache other_vhosts_access.log dosyası için. Nginx'in ve Apache'nin varsayılan combined biçimi IP'yi en başa yazar; aynı filtre ikisinde de çalışır.

Jail, /etc/fail2ban/jail.local dosyasına eklenecek:

[wordpress-login]
enabled  = true
backend  = auto
port     = http,https
filter   = wordpress-login
logpath  = /var/log/nginx/access.log
maxretry = 5
findtime = 10m
bantime  = 1h

Herkesin atladığı satır backend = auto. Ubuntu 24.04 her jail için backend = systemd ayarlıyor; kılavuza göre de systemd backend'inde logpath geçerli değil, onun yerine journalmatch kullanılıyor. Nginx log'un journal'da olmadığı için jail açılır, hiçbir şey okumaz ve kimseyi banlamaz. Apache için logpath = /var/log/apache2/access.log kullan (siteler oraya yazıyorsa ayrı bir satıra /var/log/apache2/other_vhosts_access.log ekle). Her birinin kendi log'u olan birden fazla nginx sitesi için: logpath = /var/log/nginx/*access.log.

Filtreye güvenmeden önce gerçek log üzerinde test et (fail2ban-regex):

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress-login.conf

Sona doğru Lines: N lines, 0 ignored, X matched satırını basar. Başarısız girişler olduğunu bildiğin halde X sıfırsa log biçimi uymuyordur; bir satırı regex ile yan yana koyup karşılaştır. Sonra yükle:

sudo fail2ban-client reload
sudo fail2ban-client status wordpress-login

Peki xmlrpc.php? Başarılı ve başarısız çağrılara aynı şekilde 200 döner; filtre yalnızca istek sayabilir ve Jetpack bağlantısı ya da WordPress mobil uygulaması da sayılır. İkisini de kullanmıyorsan xmlrpc.php'yi web sunucusunda engellemek jail kurmaktan daha basit.

Cloudflare ya da başka bir proxy arkasındaysan

Site Cloudflare arkasındaysa sunucu tarafındaki ban iki yoldan biriyle ters gider. Gerçek IP'yi log'lamıyorsan erişim log'unda Cloudflare'in adresleri görünür; jail Cloudflare'i banlar ve o uçtan gelen gerçek ziyaretçileri keser. Gerçek IP'yi log'luyorsan jail doğru adresi banlar ama paketler yine Cloudflare'den gelir, yani güvenlik duvarı kuralı hiç eşleşmez. İkisi de işe yaramaz. Proxy arkasında giriş hız sınırını proxy'de kur; fail2ban'i yine de çalıştıracaksan WordPress jail'ini kapalı tut.

Banı kaldır, kendini bir daha banlama

sudo fail2ban-client banned
sudo fail2ban-client set wordpress-login unbanip 198.51.100.7
sudo fail2ban-client unban 198.51.100.7

İlki her jail'i banlı IP'leriyle listeler. İkincisi bir IP'yi tek bir jail'den çıkarır. Üçüncüsü, fail2ban-client kılavuzuna göre banı "in all jails and database", yani bütün jail'lerde ve veritabanında kaldırır. SSH'tan kilitlendiysen bunları sağlayıcının web konsolundan ya da başka bir ağdan (telefonun hotspot'u iş görür) çalıştır.

Tekrar olmaması için IP'ni jail.local içindeki ignoreip satırına ekle ve reload yap. ignoreself varsayılan olarak açık; ama o senin adresini değil, sunucunun kendi adreslerini korur.

Fail2ban neyi yapmaz?

  • Yalnızca log satırlarına tepki verir. Hata log'a düşmüyorsa ya da filtre eşleşmiyorsa hiçbir şey olmaz.
  • On bin adresin her birinden iki şifre deneyen bir botnet, makul her maxretry değerinin altında kalır.
  • Doğru şifreyi, çalınmış bir oturumu ya da bir eklentideki açığı durdurmaz. Bunları SSH'ta anahtar, WordPress'te güçlü şifre ve iki aşamalı giriş, bir de güncellemeler durdurur.
  • Güvenlik duvarı değildir; bir güvenlik duvarına kayıt ekleyip çıkarır. Yine de yalnızca gereken portları açan, varsayılanı "reddet" olan bir duvar istersin (SSH ve UFW rehberi bunu anlatıyor).

Site zaten ele geçirildiyse jail onu temizlemez; temizlik sırasını hacklenen site rehberi anlatıyor.

Çalışıp çalışmadığını gör

Approvalens sunucu ajanı, fail2ban'in çalışıp çalışmadığını ve kaç adresi banladığını gösterir; --auth-log ile kurarsan başarısız SSH girişlerini de sayar.

Sık sorulan sorular

jail.conf dosyasını düzenlemeli miyim?

Hayır. Değişikliklerini /etc/fail2ban/jail.local dosyasına ya da jail.d/ içinde .local ile biten bir dosyaya yaz. Güncellemeler jail.conf'u değiştirir; .local dosyaları ondan sonra okunduğu için onların değerleri geçerli olur.

WordPress jail'im neden kimseyi banlamıyor?

Genelde üç sebepten biri: backend systemd (Ubuntu 24.04 varsayılanı) olduğu için logpath yok sayılıyor; filtre log biçimine uymuyor (fail2ban-regex ile test et); ya da log'da ziyaretçinin değil bir proxy'nin IP'si var.

Fail2ban ufw ile birlikte çalışır mı?

Evet. Ubuntu 24.04'te banları nftables üzerinden uygular (Debian varsayılanlarında banaction = nftables), ufw de kendi kurallarını yönetmeye devam eder. Banları ufw status ile değil, fail2ban-client status <jail> ile kontrol et; ufw onları listelemez.

Ban ne kadar sürmeli?

Resmi bir öneri yok. Bir saat, bir tahmin dalgasını durdurur ama şifresini yanlış yazan birini uzun süre cezalandırmaz; ısrarcı adresler zaten geri gelir. Aynı adresler dönüp duruyorsa bantime değerini artır.

Eskimiş ya da yanlış bir şey mi gördün? Bize yaz, düzeltelim.

Bu rehberi İngilizce oku →

Ücretsiz tarama

Kendi siteni kontrol et

Ücretsiz tarama ilk 50 sayfayı okur; puanını ve bulduğu tüm sorunları gösterir.

İlk 50 sayfa ücretsiz · üyelik yok · kart gerekmez

Tüm rehberler