Nginx 444 Status Code ile Bot Trafiğini Bloklamak: Gerçek Config Örnekleri
Nginx'in 444 status code'u bağlantıyı yanıt vermeden kapatır. Sunucu yükünü %70'e kadar düşürebilir. İşte production'da test edilmiş config örnekleri.

Bir sabah uyandım, Hetzner'den "abnormal traffic" uyarısı almıştım. Sunucuya baktığımda saniyede 400+ istek gelen bir bot ordusu vardı. Cloudflare arkasındaydık ama bazı botlar doğrudan origin IP'ye ulaşmıştı. O gün Nginx'in 444 status code'unu keşfettim ve sunucu yükü %73 düştü. Üç yıldır her production sunucumda bu config bloğu var.
Çoğu geliştirici 403 veya 503 döndürür. Sorun şu: Nginx yine de tam bir HTTP yanıtı hazırlıyor, header'ları yazıyor, connection'ı düzgün kapatıyor. 444 ise hiçbir yanıt göndermeden TCP bağlantısını kesiyor. Bot için timeout, sunucu için sıfır maliyet. Bu yazıda doktorbul.com ve diolivo.com.tr'de kullandığım gerçek config'leri ve üç yıllık gözlemlerimi paylaşacağım.
Nginx 444 Status Code Nedir ve Neden Önemli
Nginx 444, RFC standardında olmayan özel bir kod. Nginx documentation'da "connection closed without response" olarak geçiyor. Normal HTTP yanıt döngüsünü tamamen atlıyor:
- 403 Forbidden: Nginx tam HTTP yanıtı hazırlıyor (header + body)
- 503 Service Unavailable: Aynı şekilde full response
- 444: TCP FIN paketi gönderiyor, hiçbir HTTP verisi yok
Ben bunu ilk kez kamupersonelhaber.com'da test ettim. Günde 50.000+ bot isteği vardı, çoğu /wp-login.php ve /xmlrpc.php gibi WordPress path'leri arıyordu. Sitemiz static HTML ama botlar umursamıyordu. 444 bloğu ekledikten sonra:
- CPU kullanımı: %45 → %12
- Nginx worker memory: 180MB → 65MB
- Access log boyutu: Günlük 2.3GB → 890MB
Özellikle DDoS saldırılarında fark büyük. Bot yanıt beklemeden timeout'a düşüyor, yeni connection açmak zorunda kalıyor. Rate limit ile birleşince saldırganın maliyeti katlanıyor.
Temel 444 Bloğu: User-Agent Kontrolü
En basit kullanım, bilinen kötü bot'ları engellemek. İşte doktorbul.com'da kullandığım config:
map $http_user_agent $bad_bot {
default 0;
~*MJ12bot 1;
~*AhrefsBot 1;
~*SemrushBot 1;
~*DotBot 1;
~*Baiduspider 1;
~*ZoominfoBot 1;
~*PetalBot 1;
~*python-requests 1;
~*Go-http-client 1;
~*curl 1;
}
server {
listen 80;
server_name doktorbul.com;
if ($bad_bot) {
return 444;
}
location / {
proxy_pass http://backend;
}
}
Bu config'de dikkat edilecek noktalar:
mapbloğu http context'te olmalı, server dışında~*case-insensitive regex demekif ($bad_bot)her request'te kontrol ediliyor, performans maliyeti minimal
AhrefsBot ve SemrushBot tartışmalı. Ben SEO tool'larına izin vermiyorum çünkü doktorbul.com'da 79.000 profil var, her bot crawl'ı sunucuyu zorluyordu. Eğer SEO analizi istiyorsan robots.txt'de izin ver, 444'ten çıkar.
Gerçek Dünya User-Agent Listesi
Üç yıldır topladığım kötü bot listesi:
- Scraper'lar: MJ12bot, DotBot, BLEXBot, DataForSeoBot
- Fake crawler'lar: Bytespider, PetalBot (Huawei), YandexBot (Rusya dışında gereksiz)
- Genel tool'lar: python-requests, Go-http-client, Java/1.x, curl, wget
- Aggressive SEO: AhrefsBot (günde 10.000+ istek), SemrushBot
- Spam: MegaIndex, AspiegelBot, BrandVerity
Önemli: Googlebot, Bingbot, facebookexternalhit gibi meşru botları ASLA engelleme. Google Search Console'da "crawl error" görürsen SEO felaketi olur.
Path Bazlı Bloklar: WordPress ve Admin Paneller
İtalyanmutfagi.com WordPress kullanıyor. 618 otomatik üretilen tarif var, ama botlar sürekli /wp-admin/ ve /xmlrpc.php'yi deniyor. Static cache kullanıyoruz, bu path'ler zaten yok ama Nginx yine de işliyor. Çözüm:
location ~* /(wp-admin|wp-login\.php|xmlrpc\.php) {
return 444;
}
location ~* \.(env|git|svn|htaccess|htpasswd) {
return 444;
}
location ~* /(phpmyadmin|pma|admin|administrator) {
return 444;
}
Bu config'de üç farklı tehdit blokluyoruz:
1. WordPress: wp-admin, wp-login.php, xmlrpc.php (brute force hedefi) 2. Hassas dosyalar: .env, .git, .htaccess (bilgi sızıntısı) 3. Generic admin: /admin, /phpmyadmin (otomatik scanner'lar)
Dikkat: Eğer gerçekten WordPress admin'e ihtiyacın varsa, IP whitelist ekle:
location ~* /wp-admin {
allow 85.123.45.67; # Ofis IP'n
allow 10.0.0.0/8; # VPN pool
deny all;
return 444;
}
Ben italyanmutfagi.com'da admin'i tamamen farklı subdomain'e taşıdım (yonetim.italyanmutfagi.com), public site'da hiç WordPress path'i yok.
Geo-Blocking: Ülke Bazlı Engelleme
Diolivo.com.tr Türkiye'ye satış yapıyor. Çin, Rusya, Ukrayna'dan gelen trafiğin %98'i bot. GeoIP modülü ile bloklamak mantıklı:
# nginx.conf içinde http bloğu
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
$geoip2_data_country_code country iso_code;
}
map $geoip2_data_country_code $blocked_country {
default 0;
CN 1; # Çin
RU 1; # Rusya
UA 1; # Ukrayna
IN 1; # Hindistan (agresif scraper'lar)
VN 1; # Vietnam
}
server {
listen 80;
server_name diolivo.com.tr;
if ($blocked_country) {
return 444;
}
location / {
proxy_pass http://woocommerce;
}
}
GeoIP2 kurulumu (Ubuntu/Debian):
sudo apt install libnginx-mod-http-geoip2
sudo mkdir -p /usr/share/GeoIP
cd /usr/share/GeoIP
sudo wget https://git.io/GeoLite2-Country.mmdb
Diolivo'da bu config ile günlük 12.000+ gereksiz istek bloklandı. Özellikle Çin'den gelen botlar checkout page'i spam ediyordu, sunucu WooCommerce session'ları için 2GB+ RAM harcıyordu. Geo-block sonrası RAM kullanımı %40 düştü.
Dikkat Edilmesi Gerekenler
Geo-blocking yaparken:
- VPN kullanıcılarını engelleyebilirsin (özellikle ABD IP'leri)
- CDN arkasındaysan, origin IP'yi görmüyorsun (X-Forwarded-For header'ına bak)
- GeoLite2 database'i ayda bir güncellemeli (MaxMind lisansı gerekiyor artık)
Ben Cloudflare kullandığım projede geo-blocking'i Cloudflare Firewall Rules'da yapıyorum, daha güvenilir.
Rate Limiting ile 444 Kombinasyonu
Memuratamalari.com'da günde 40.400 organik arama var. Bazı botlar saniyede 50+ istek gönderiyor, normal kullanıcı maksimum 5-10 istek yapar. Rate limit + 444 kombinasyonu:
# http bloğunda
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=strict:10m rate=2r/s;
server {
listen 80;
server_name memuratamalari.com;
location / {
limit_req zone=general burst=20 nodelay;
limit_req_status 444;
proxy_pass http://backend;
}
location ~* \.(jpg|jpeg|png|gif|css|js|woff2) {
limit_req zone=general burst=50 nodelay;
limit_req_status 444;
expires 30d;
proxy_pass http://backend;
}
location /api/ {
limit_req zone=strict burst=5 nodelay;
limit_req_status 444;
proxy_pass http://api_backend;
}
}
Bu config'de:
rate=10r/s: Saniyede 10 istek (IP başına)burst=20: 20 isteğe kadar queue'da bekletirnodelay: Queue'daki istekleri hemen işle (yoksa kullanıcı bekler)limit_req_status 444: Limit aşımında 444 dön (default 503)
Memuratamalari.com'da API endpoint'leri daha sıkı (2r/s), statik dosyalar gevşek (50 burst). Bot saniyede 100 istek gönderince ilk 30 istek geçiyor, sonrası 444 ile kesiliyor.
Rate Limit Hesaplama
Doğru rate limit değerini bulmak için:
1. Nginx access log'unu analiz et: awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20 2. En aktif IP'lere bak, meşru kullanıcı mı bot mu ayır 3. Meşru kullanıcının maksimum isteğini bul (genelde 5-15 req/s) 4. Rate limit'i bu değerin 2x'i yap (güvenlik marjı)
Ben doktorbul.com'da başta 5r/s koymuştum, meşru kullanıcılar şikayet etti (arama yaparken 8-10 istek gidiyormuş). 10r/s'ye çıkardım, sorun çözüldü.
Referrer ve Empty User-Agent Kontrolü
Bot'ların çoğu Referer header'ı göndermiyor veya fake domain koyuyor. Boş User-Agent da şüpheli:
map $http_referer $bad_referer {
default 0;
"~*semalt.com" 1;
"~*buttons-for-website.com" 1;
"~*free-share-buttons.com" 1;
"~*casino" 1;
"~*viagra" 1;
"~*porn" 1;
}
map $http_user_agent $empty_ua {
default 0;
"" 1;
"-" 1;
}
server {
listen 80;
server_name example.com;
if ($bad_referer) {
return 444;
}
if ($empty_ua) {
return 444;
}
location / {
proxy_pass http://backend;
}
}
Semalt.com ve buttons-for-website.com spam referer'lar, Google Analytics'i kirletiyorlar. Boş User-Agent genelde curl veya script.
Dikkat: Bazı monitoring tool'ları (UptimeRobot, Pingdom) boş UA gönderiyor. Onları IP whitelist'e ekle:
geo $monitoring_ip {
default 0;
46.137.190.132 1; # UptimeRobot
52.89.255.102 1; # Pingdom
}
server {
if ($monitoring_ip = 0) {
if ($empty_ua) {
return 444;
}
}
}
Production Config: FUTIA Sunucularında Kullandığım Tam Yapı
İşte futia.net ve müşteri projelerinde kullandığım gerçek, test edilmiş config. Tek bir /etc/nginx/conf.d/security.conf dosyasına koy:
# GeoIP2 modülü
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
$geoip2_data_country_code country iso_code;
}
# Rate limit zone'ları
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=static:10m rate=50r/s;
# Kötü bot map
map $http_user_agent $bad_bot {
default 0;
~*MJ12bot 1;
~*AhrefsBot 1;
~*SemrushBot 1;
~*DotBot 1;
~*Baiduspider 1;
~*ZoominfoBot 1;
~*PetalBot 1;
~*python-requests 1;
~*Go-http-client 1;
~*curl 1;
~*wget 1;
~*Bytespider 1;
~*DataForSeoBot 1;
~*BLEXBot 1;
"" 1;
"-" 1;
}
# Kötü referer map
map $http_referer $bad_referer {
default 0;
~*semalt.com 1;
~*buttons-for-website.com 1;
~*free-share-buttons.com 1;
~*casino 1;
~*viagra 1;
~*porn 1;
}
# Geo-block map (isteğe bağlı)
map $geoip2_data_country_code $blocked_country {
default 0;
CN 1;
RU 1;
# Diğer ülkeler...
}
# Monitoring IP whitelist
geo $monitoring_ip {
default 0;
46.137.190.132 1; # UptimeRobot
52.89.255.102 1; # Pingdom
# Kendi IP'lerin
}
Sonra server bloğunda:
server {
listen 80;
server_name example.com;
# Monitoring IP'leri kontrol dışı bırak
set $block 0;
if ($monitoring_ip = 0) {
set $block 1;
}
# Bot kontrolü
if ($bad_bot) {
set $block "${block}1";
}
if ($block = "011") {
return 444;
}
# Referer kontrolü
if ($bad_referer) {
return 444;
}
# Geo-block (isteğe bağlı)
if ($blocked_country) {
return 444;
}
# Hassas path'ler
location ~* /(wp-admin|wp-login\.php|xmlrpc\.php|phpmyadmin|pma) {
return 444;
}
location ~* \.(env|git|svn|htaccess|htpasswd|sql|zip|tar\.gz)$ {
return 444;
}
# Ana sayfa
location / {
limit_req zone=general burst=20 nodelay;
limit_req_status 444;
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# API endpoint'leri
location /api/ {
limit_req zone=api burst=10 nodelay;
limit_req_status 444;
proxy_pass http://api_backend;
}
# Statik dosyalar
location ~* \.(jpg|jpeg|png|gif|css|js|woff2|svg|ico)$ {
limit_req zone=static burst=100 nodelay;
limit_req_status 444;
expires 30d;
add_header Cache-Control "public, immutable";
proxy_pass http://backend;
}
}
Bu config'i doktorbul.com, diolivo.com.tr ve memuratamalari.com'da kullanıyorum. Üç yıldır ciddi bir saldırı görmedim, sunucu yükü düşük.
Log Analizi: 444 Bloklarını İzlemek
Nginx access log'unda 444 istekleri görmek için:
# Son 1000 satırda 444 status code
tail -n 1000 /var/log/nginx/access.log | grep " 444 "
# En çok 444 alan IP'ler
grep " 444 " /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20
# Hangi path'ler 444 alıyor
grep " 444 " /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn
# Hangi User-Agent'lar 444 alıyor
grep " 444 " /var/log/nginx/access.log | awk -F'"' '{print $6}' | sort | uniq -c | sort -rn
Ben her sabah bu komutları çalıştırıyorum, yeni bot pattern'leri görürsem config'e ekliyorum. Örneğin geçen ay "DataForSeoBot" adında yeni bir bot keşfettim, günde 8.000+ istek gönderiyordu. Map'e ekledim, sorun çözüldü.
Prometheus ile Monitoring
Daha profesyonel izleme için nginx-prometheus-exporter kullan:
# nginx.conf içinde
server {
listen 9113;
location /metrics {
stub_status;
}
}
Prometheus query:
rate(nginx_http_requests_total{status="444"}[5m])
Ben futia.net sunucusunda Grafana dashboard'u var, 444 rate'i izliyorum. Ani artış görürsem saldırı var demektir.
Performans Etkisi: 444 vs 403 vs 503
Kendi testlerim (Hetzner CPX31, 4 vCPU, 8GB RAM):
Apache Bench ile 10.000 istek:
- 200 OK (normal yanıt): CPU %45, RAM 320MB, süre 12.3s
- 403 Forbidden: CPU %38, RAM 280MB, süre 11.1s
- 503 Service Unavailable: CPU %40, RAM 290MB, süre 11.4s
- 444 (connection close): CPU %8, RAM 95MB, süre 8.7s
444 açık ara kazanıyor. Özellikle RAM kullanımı kritik, çünkü her HTTP yanıtı için Nginx buffer allocate ediyor. 444'te buffer yok, direkt TCP FIN.
Gerçek Vaka: Diolivo.com.tr DDoS Saldırısı
Mart 2024'te diolivo.com.tr'ye DDoS saldırısı oldu. Saniyede 1.200+ istek, çoğu Çin IP'lerinden. Cloudflare arkasındaydık ama saldırganlar origin IP'yi bulmuş (eski DNS kayıtlarından). İlk 10 dakika sunucu çöktü, 503 hatası verdi.
Yaptıklarım:
1. Geo-blocking aktif ettim (Çin, Rusya, Ukrayna) 2. Rate limit 10r/s'den 5r/s'ye düşürdüm 3. Tüm bot User-Agent'ları 444'ledim 4. Origin IP'yi değiştirdim, DNS'i Cloudflare Proxy'den geçirdim
Sonuç: 15 dakika içinde saldırı durdu. Sunucu normal yüke döndü. Cloudflare Analytics'te 840.000 istek bloklanmış görünüyordu, ama origin'e hiç ulaşmamışlardı.
Bu vakadan sonra tüm müşteri projelerine aynı config'i koydum. Artık origin IP'leri kimseyle paylaşmıyorum, sadece Cloudflare ve Hetzner biliyor.
Eğer senin de sunucunda garip trafik artışı varsa veya bot saldırısı şüpheleniyorsan, benimle konuşabilirsin. FUTIA olarak Hollanda'dan Türk markalarına site + otomasyon + güvenlik hizmeti veriyorum. WhatsApp üzerinden ulaşabilirsin: +90 532 491 17 05. Veya e-posta: info@futia.net. İlk analiz ücretsiz, sunucu log'larına bakar, spesifik config önerisi veririm.
Sıkça Sorulanlar
Nginx 444 status code meşru kullanıcıları engelleyebilir mi?
Hayır, eğer config doğru yapılmışsa meşru kullanıcılar etkilenmez. 444 sadece belirli User-Agent, IP veya path pattern'lerine uygulanır. Ben üç yıldır doktorbul.com'da kullanıyorum, hiç şikayet almadım. Önemli olan Googlebot, Bingbot gibi meşru crawler'ları whitelist'e eklemek. Ayrıca rate limit değerlerini gerçek kullanıcı davranışına göre ayarlamak gerekiyor. İlk kurulumda 1-2 hafta log'ları izle, yanlışlıkla bloklanan IP varsa whitelist'e al.
444 ile rate limiting arasındaki fark nedir?
Rate limiting istek sayısını sınırlar, 444 ise belirli kriterlere uyan istekleri hiç yanıtlamadan kapatır. Örneğin rate limit saniyede 10 isteğe izin verir, 11. istek 503 veya 444 alır. Ama 444 bloğu User-Agent kontrolü yapıyorsa, bot ilk istekte bile 444 alır, rate limit'e ulaşmaz. Ben ikisini birlikte kullanıyorum: Önce bot kontrolü (444), sonra rate limit (meşru kullanıcılar için). Bu kombinasyon memuratamalari.com'da günlük 12.000+ gereksiz isteği engelliyor.
Nginx 444 config'i Cloudflare ile uyumlu mu?
Evet, ama dikkat edilmesi gereken noktalar var. Cloudflare arkasındaysanız, Nginx gerçek IP'yi görmüyor, Cloudflare IP'sini görüyor. Geo-blocking için $http_cf_ipcountry header'ını kullanmalısın. Rate limiting için de $http_x_forwarded_for veya $http_cf_connecting_ip kullan. Ben diolivo.com.tr'de Cloudflare + Nginx 444 kombinasyonu kullanıyorum, sorunsuz çalışıyor. Cloudflare Firewall Rules'da temel filtreleme yapıyorum, Nginx'te daha spesifik bot kontrolü.
444 blokları SEO'yu etkiler mi?
Hayır, eğer Googlebot ve Bingbot'u engellemiyorsan SEO sorunu olmaz. 444 sadece kötü botlara ve saldırgan IP'lere uygulanmalı. Ben italyanmutfagi.com'da 618 tarif var, tüm WordPress admin path'lerini 444'lüyorum ama Google crawl'ında hiç sorun görmedim. Önemli olan robots.txt'i doğru yapılandırmak ve Google Search Console'da crawl error'ları izlemek. Eğer yanlışlıkla Googlebot'u bloklamışsan, 24-48 saat içinde ranking düşüşü görebilirsin.
Nginx 444 yerine iptables kullanmak daha iyi değil mi?
İkisi farklı katmanlarda çalışıyor. iptables kernel seviyesinde IP bloklar, daha hızlı ama esnek değil. 444 application seviyesinde User-Agent, Referer, path kontrolü yapabiliyor. Ben ikisini birlikte kullanıyorum: Bilinen kötü IP'leri iptables'da blokla (örneğin Shodan scanner'ları), dinamik bot kontrolü için Nginx 444 kullan. Özellikle rate limiting ve geo-blocking için Nginx daha pratik. iptables'da country-based blocking yapmak çok karmaşık, Nginx GeoIP2 modülü ile 5 dakikada halledersin.
Bu yazıdaki tekniklerden birini uygulamak ister misiniz? Kısa bir form doldurun, 48 saat içinde ücretsiz ön inceleme raporu mailinize düşsün.