Bu yazıda sentetik Nginx kayıtlarını Fail2Ban filtresiyle sınıyor, jail sayacını ve dummy eylemini kontrol ediyorum. Amaç hangi satırın eşleştiğini görmek. Nginx'in, Django girişlerinin veya proxy arkasındaki bütün trafiğin güvenliğini doğrulamıyorum.
Bir jail'in adında auth bulunması, sitedeki bütün giriş denemelerini gördüğü anlamına gelmiyor. Kayıt, filtre eşleşmesi ve gerçek ağ engellemesi ayrı kontroller gerektiriyor.
Test edilen ortam
7 Ekim 2026 UTC'de Docker Engine 29.8.0 üzerinde Linux/arm64 konteynerde denedim: Debian GNU/Linux 13 (trixie, imaj metadata değeri 13.7), Debian Fail2Ban paketi 1.1.0-8, Fail2Ban v1.1.0, sistem Python 3.13.5. Bu, sentetik kayıtlarla filtre ve jail deneyidir. Gerçek Nginx/Django isteği, systemd journal, firewall, Cloudflare/proxy ve üretim sunucusu test edilmedi.
Örnek paketi indirin, fail2ban-validation dizinine geçin:
docker compose --project-name example-fail2ban-validation build
docker compose --project-name example-fail2ban-validation run --rm lab
Test konteynerinde ağ bağlantısı, yayınlanan port veya host dosya bağlantısı yoktur. UID 65534, salt okunur root dosya sistemi ve kaldırılmış Linux capabilities ile çalışır. Loglar ve yapılandırma yalnız geçici /tmp alanına yazılır. Gerçek hesap, üretim logu veya sır gerekmez.
Nginx hatası ile Django girişi farklı
nginx-http-auth filtresinin normal modu, Nginx'in HTTP kimlik doğrulama hatalarındaki belirli mesajları seçer. Bu deneyde password mismatch ve was not found biçimlerini kullandım. Django giriş formunda yanlış parola, aynı Nginx hata mesajını üretmek zorunda değil. Bu yüzden filtreyi açıp yönetim panelinin bütün girişlerini koruduğumu söyleyemem. Mesaj biçimleri resmi 1.1.0 filtresinde bulunur.
nginx-botsearch de her 404 yanıtını saldırı saymaz. Seçilmiş adresler ve desteklenen log biçimleri üzerinden çalışır. Normal kırık bağlantıyı bot saldırısıyla karıştırmamak gerekir. Kapsamı botsearch filtresinde tanımlanır; bu deneyde botsearch çalıştırılmadı.
Filtreyi görmek ve sonucu yorumlamak
Lab dört satır üretir: iki Nginx auth hatası, sıradan bir eksik dosya hatası ve Django giriş POST isteği biçiminde bir access kaydı. Üretim günlüğünü okumadan şu komutu çalıştırır:
fail2ban-regex -c /tmp/fail2ban-validation/config /tmp/fail2ban-validation/nginx-fixture.log 'nginx-http-auth[mode=normal]'
İzole çalıştırmada alınan kısa çıktı:
Lines: 4 lines, 0 ignored, 2 matched, 2 missed
İki auth hata mesajı eşleşti. Örnekteki sıradan eksik dosya ve Django POST access satırı eşleşmedi. missed, o satırın bu filtreyle seçilmediğini söyler; satırın saldırı olup olmadığını tek başına söylemez. Sentetik POST kaydı bir Django parola hatası kanıtı da değildir. Aracın seçenekleri resmi regex kılavuzunda açıklanır.
Kendi ortamında dosya kaynağı gerçekten /var/log/nginx/error.log ise okunacak dosya ayrıca kontrol edilir. Access log, error log ve journal birbirinin yerine kullanılmaz. Yanlış dosya veya desteklenmeyen biçim, çalışan bir jail'in beklenen hataları görmemesine yol açabilir.
Çalışan jail, çalışan firewall demek değil
Lab, nginx-lab adında polling jail'i oluşturur: nginx-http-auth[mode=normal], beş hata için maxretry = 5, on dakikalık findtime ve bantime. Eylem yalnız resmi dummy dosya eylemidir. Host'un /etc/fail2ban ayarını değiştirmez.
Yapılandırma testi ve çalışan sunucu kontrolünde alınan sonuç:
OK: configuration test is successful
Server replied: pong
Jail önce sıfır sayaç gösterdi. Sentetik aynı IP'den beş auth hatası eklendiğinde status nginx-lab çıktısı:
Total failed: 5
Currently banned: 1
Total banned: 1
Banned IP list: 198.51.100.20
Lab, dummy dosyasındaki +198.51.100.20 kaydını ve unbanip sonrası sunucu durumunun temizlenmesini de doğruladı. Kontrol IP'si ban edilmedi. Bu sayaçlar ağ trafiğinin engellendiğini göstermiyor: dummy eylemi firewall kullanmaz. Gerçek hedefe bağlantı denemesi yapılmadı.
| Doğrulama | Bu deneydeki kapsam |
|---|---|
| Filtre eşleşmesi | Dört sentetik satırın ikisi seçildi |
| Servis ve jail durumu | Sunucu yanıtı ve beş hatadan sonraki sayaçlar doğrulandı |
| Eylem | Geçici dosyaya dummy ban/unban kaydı yazıldı |
| Gerçek erişim veya engelleme | Test edilmedi |
Proxy arkasında hangi IP engelleniyor?
Cloudflare gibi bir proxy varsa sunucuya gelen ağ bağlantısının kaynağı proxy olabilir. Logdaki adresin ziyaretçiye mi, proxy'ye mi ait olduğunu doğrulamadan ban açmam. Nginx gerçek IP modülünde güvenilen kaynaklar ve kullanılan başlık birlikte tanımlanır; bütün kaynaklara koşulsuz güvenmek doğru olmaz. Resmi real IP belgesi bu ayarları açıklar.
Loga ziyaretçi IP'si yazdırmak, sunucunun firewall katmanında o IP'yi engelleyebileceğini tek başına göstermez. Bağlantı hâlâ proxy üzerinden gelebilir. Filtre ve ban eylemi ayrı doğrulanmalı; proxy IP'sini engellemek normal ziyaretçilerin erişimini de kesebilir. Gerçek eylem denemesinde mevcut oturum ve ikinci erişim yolu korunmalı.
Bu nedenle bu yazıdaki dummy jail'i üretim için tamamlanmış engelleme ayarı olarak kullanmıyorum. Önce kayıt kaynağı, eşleşen mesaj ve trafik yolu anlaşılmalı. Beklenen satırlar eşleşmiyorsa dosya/biçim/mod; jail görünmüyorsa yapılandırma/etkinleştirme; ban sayacı artıp erişim sürüyorsa eylem ve proxy yolu ayrı incelenmeli.