FUTIA
GÜVENLIK10 dk okuma

Nginx 444 Status Code ile Bot Saldırılarını Kesmek: Config Örnekleri

Nginx'in 444 status code'u bağlantıyı anında keser, sunucu yükünü %80'e kadar düşürür. Gerçek config örnekleri ve ölçümlerle anlatıyorum.

Nginx 444 Status Code ile Bot Saldırılarını Kesmek: Config Örnekleri
Miraç Eroğlu
24 Nisan 2026

Geçen ay doktorbul.com'da 24 saat boyunca saniyede 180 istek alan bir endpoint vardı. Access log'a baktığımda hepsi aynı user agent, hepsi aynı IP bloğundan. Cloudflare'de rate limit açtım, biraz yavaşladı ama trafiğin %60'ı hâlâ sunucuya ulaşıyordu. Sonra Nginx level'de 444 status code ile kesmeye başladım. Sunucu CPU kullanımı %73'ten %22'ye düştü. Bağlantı bile kurmadan kestim çünkü. Nginx'in 444 kodu standart HTTP değil, kendi özel bir davranış. Response body yok, header yok, sadece TCP bağlantısını anında kapatıyor. Saldırgan tarafa hiçbir bilgi dönmüyor, log'a bile yazmıyorsun istersen. Bu yazıda gerçek config örnekleriyle, hangi senaryoda nasıl kullanacağını, ölçüm yöntemlerini ve FUTIA projelerindeki deneyimlerimi paylaşıyorum.

Nginx 444 Status Code Nedir ve Nasıl Çalışır

Nginx'in 444 kodu RFC 7231'de tanımlı değil. Nginx'e özel bir direktif. Normal HTTP response'lar (200, 404, 500) header ve body döner, saldırgan tarafa bilgi gider. 444 kullandığında Nginx bağlantıyı sessizce kapatır, hiçbir veri göndermez. TCP handshake tamamlandıktan sonra istemci HTTP request gönderir, Nginx okur ama cevap vermeden bağlantıyı koparır. İstemci tarafında "connection reset" veya timeout hatası oluşur.

Bu davranış özellikle brute force, scraping botları ve DDoS saldırılarına karşı etkili. Çünkü saldırgan tarafa hiçbir feedback vermiyor. Normal 403 veya 429 döndüğünde saldırgan "tamam, engellendim, IP değiştireyim" diye hemen reaksiyon verir. 444'te ne olduğunu anlayamaz, bir süre denemeye devam eder, sonra bırakır.

Bir de log yükü var. Access log'a yazmamayı seçersen (access_log off;) disk I/O'su azalır. Saniyede 500 bot isteği varsa ve hepsini logluyorsan günlük log dosyası gigabyte'lara ulaşır. 444 ile kestikten sonra loglamayı kapatırsan hem disk hem CPU kazancı elde edersin.

444 vs 403 vs 429: Hangisi Ne Zaman

403 Forbidden: "Bu kaynağa erişim yetkin yok" der, header ve body döner. Saldırgan bilgi alır.

429 Too Many Requests: "Rate limit aştın, yavaşla" der, Retry-After header'ı ile ne zaman tekrar denemesi gerektiğini söyler. Saldırgan bu bilgiyi kullanır.

444: Hiçbir şey demez, bağlantıyı kapatır. Saldırgan karanlıkta kalır.

Legitim kullanıcılara 444 döndürme. Çünkü tarayıcıda "bağlantı hatası" gibi belirsiz bir mesaj görürler, ne olduğunu anlamazlar. 444'ü sadece bot, scraper veya açıkça kötü niyetli trafiğe uygula.

Temel Config: User Agent ve Referrer Bazlı Bloklar

İlk adım basit: bilinen bot user agent'larını engellemek. Örnek config:

map $http_user_agent $block_ua {
    default 0;
    ~*curl 1;
    ~*wget 1;
    ~*python-requests 1;
    ~*Go-http-client 1;
    ~*scrapy 1;
    ~*bot 1;
    ~*spider 1;
    "" 1;  # Boş user agent
}

server {
    listen 80;
    server_name ornek.com;

    if ($block_ua) {
        return 444;
    }

    location / {
        proxy_pass http://backend;
    }
}

Bu config curl, wget, python-requests gibi araçları engeller. Ama dikkat: Google bot, Bing bot gibi meşru botları da engelleyebilirsin. Onları whitelist'e alman gerekir:

map $http_user_agent $block_ua {
    default 0;
    ~*Googlebot 0;
    ~*Bingbot 0;
    ~*baiduspider 0;
    ~*YandexBot 0;
    ~*curl 1;
    ~*wget 1;
    ~*python 1;
    "" 1;
}

Referrer bazlı blok da işe yarar. Spam sitelerden gelen trafiği kesebilirsin:

map $http_referer $block_ref {
    default 0;
    ~*spam-site\.com 1;
    ~*casino 1;
    ~*viagra 1;
}

server {
    if ($block_ref) {
        return 444;
    }
}

FUTIA'da kamupersonelhaber.com için benzer bir config kullandık. Spam referrer'lardan gelen trafiği 444 ile kestik, aylık 120 GB bandwidth tasarrufu sağladık. Access log boyutu %40 küçüldü.

IP Bazlı Bloklar ve Geo-Blocking

Belirli IP'leri veya IP bloklarını engellemek için deny direktifini kullanırsın, ama 444 döndürmek için biraz farklı yaklaşım gerekir:

geo $block_ip {
    default 0;
    192.168.1.50 1;
    10.0.0.0/8 1;
    203.0.113.0/24 1;
}

server {
    if ($block_ip) {
        return 444;
    }
}

Geo-blocking için GeoIP modülünü kullanırsın. Nginx'e GeoIP2 veya GeoLite2 veritabanını yüklemen gerekir. Örnek:

geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_country_code country iso_code;
}

map $geoip2_country_code $block_country {
    default 0;
    CN 1;  # Çin
    RU 1;  # Rusya
    KP 1;  # Kuzey Kore
}

server {
    if ($block_country) {
        return 444;
    }
}

Bu config Çin, Rusya ve Kuzey Kore'den gelen tüm trafiği keser. Ama dikkat: VPN kullanıcılarını da engellersin. Eğer global bir servisin yoksa ve sadece Türkiye'ye hizmet veriyorsan mantıklı olabilir.

FUTIA'da diolivo.com.tr için Türkiye dışı trafiği sınırladık. E-ticaret sitesi, sadece Türkiye'ye satış yapıyor. Türkiye dışından gelen bot trafiği %90 azaldı, sunucu maliyeti ayda 80 EUR düştü.

Rate Limiting ile Kombinasyon: limit_req ve 444

Nginx'in limit_req modülü saniyede veya dakikada kaç istek kabul edileceğini belirler. Limiti aşan isteklere 503 döner normalde, ama 444 döndürmesini sağlayabilirsin:

limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_status 444;

server {
    location / {
        limit_req zone=general burst=20 nodelay;
        proxy_pass http://backend;
    }
}

Burada $binary_remote_addr her IP için ayrı sayaç tutar. rate=10r/s saniyede 10 istek, burst=20 anlık 20 isteklik buffer demek. Limiti aşan istek geldiğinde limit_req_status 444 sayesinde 503 yerine 444 döner.

Ama dikkat: limit_req_status global bir direktif, tüm location'lara uygulanır. Sadece belirli endpoint'lere 444 döndürmek istersen farklı zone'lar kullanman gerekir:

limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=static:10m rate=50r/s;

server {
    location /api/ {
        limit_req zone=api burst=10;
        limit_req_status 444;
        proxy_pass http://api_backend;
    }

    location /static/ {
        limit_req zone=static burst=100;
        # Burada 503 dönecek
    }
}

FUTIA'da memuratamalari.com için /api/ilanlar endpoint'ine saniyede 3 istek limiti koyduk. Bir scraper bot dakikalarca denedi, hep 444 aldı, sonunda vazgeçti. Log'da 40.000 satır 444 kaydı vardı, hepsi aynı IP'den. O IP'yi manuel olarak geo bloğa ekledik.

Access Log Filtreleme: 444'leri Loglamamak

Binlerce 444 isteği loglanırsa disk dolar, log analizi zorlaşır. Sadece 444 dışındaki istekleri loglamak için map kullanırsın:

map $status $loggable {
    444 0;
    default 1;
}

server {
    access_log /var/log/nginx/access.log combined if=$loggable;

    if ($block_ua) {
        return 444;
    }
}

Bu config 444 dönen istekleri access.log'a yazmaz. Sadece 200, 404, 500 gibi normal response'lar loglanır. Disk I/O azalır, log dosyası küçük kalır.

Alternatif olarak 444'leri ayrı bir log dosyasına yazabilirsin:

map $status $blocked_log {
    444 /var/log/nginx/blocked.log;
    default /dev/null;
}

server {
    access_log /var/log/nginx/access.log combined;
    access_log $blocked_log combined;
}

Burada 444 dönen istekler blocked.log'a, diğerleri access.log'a yazılır. Böylece hangi IP'lerin ne kadar engellendiğini takip edebilirsin.

FUTIA'da italyanmutfagi.com için bu yöntemi kullandık. 618 otomatik üretilen tarif sayfası var, botlar sürekli tarayıp duruyor. 444'leri ayrı logladık, günlük 2-3 GB log yerine 200 MB'a düştü. Aylık log depolama maliyeti %85 azaldı.

Gerçek Vaka: doktorbul.com'da 79.000 Profil ve Bot Trafiği

doktorbul.com 79.000 doktor profili olan bir platform. Programatik SEO ile oluşturuldu, her profil ayrı bir URL. Botlar bu sayfalara sürekli istek atıyor, bazıları meşru (Google, Bing), bazıları scraper. Bir dönem saniyede 200 istek geliyordu, sunucu CPU %90'lara çıkıyordu.

Çözüm: Nginx level'de üç katmanlı blok sistemi kurdum.

1. User agent bazlı blok: curl, wget, python-requests gibi araçları 444 ile kestim. Meşru botları whitelist'e aldım. 2. Rate limiting: Her IP için saniyede 10 istek limiti, aşanlar 444. 3. Geo-blocking: Türkiye dışından gelen ve meşru bot olmayan trafiği 444 ile kestim.

Sonuç: Sunucu CPU kullanımı %90'dan %35'e düştü. Aylık bandwidth 1.2 TB'den 400 GB'a indi. Access log boyutu %70 küçüldü. Cloudflare'de rate limit kuralları da var ama Nginx level'deki 444 blokları en büyük etkiyi yaptı. Çünkü Cloudflare'den geçen trafiği bile sunucuya ulaşmadan kesiyorsun.

Bir detay daha: 444 döndürürken access_log off; kullanmadım. Çünkü hangi IP'lerin ne kadar engellendiğini görmek istedim. İlk hafta günlük log dosyası 5 GB oldu, sonra en çok istek atan 20 IP'yi manuel olarak deny listesine ekledim. İkinci hafta log boyutu 800 MB'a düştü.

İleri Seviye: Lua ile Dinamik 444 Blokları

Nginx'in Lua modülü (OpenResty) ile daha karmaşık bloklar oluşturabilirsin. Örneğin Redis'te tutulan bir IP listesini kontrol edip dinamik olarak 444 döndürebilirsin:

location / {
    access_by_lua_block {
        local redis = require "resty.redis"
        local red = redis:new()
        red:set_timeout(1000)

        local ok, err = red:connect("127.0.0.1", 6379)
        if not ok then
            ngx.log(ngx.ERR, "Redis bağlantı hatası: ", err)
            return
        end

        local ip = ngx.var.remote_addr
        local blocked, err = red:get("blocked:" .. ip)

        if blocked == "1" then
            ngx.exit(444)
        end
    }

    proxy_pass http://backend;
}

Bu config her istek geldiğinde Redis'e sorar: "Bu IP engellenmiş mi?" Eğer engellenmişse 444 döner. Redis'e IP eklemek için ayrı bir script kullanabilirsin:

redis-cli SET blocked:192.168.1.50 1 EX 3600

Bu komut 192.168.1.50 IP'sini 1 saat (3600 saniye) boyunca engeller. Süre dolunca Redis otomatik siler, IP tekrar erişebilir.

Lua ile request body'yi de kontrol edebilirsin. Örneğin SQL injection denemelerini tespit edip 444 döndürebilirsin:

access_by_lua_block {
    local args = ngx.req.get_uri_args()
    for key, val in pairs(args) do
        if type(val) == "string" then
            if string.match(val, "SELECT.*FROM") or string.match(val, "UNION.*SELECT") then
                ngx.log(ngx.WARN, "SQL injection denemesi: ", ngx.var.remote_addr)
                ngx.exit(444)
            end
        end
    end
}

Bu kod URL parametrelerinde "SELECT FROM" veya "UNION SELECT" gibi SQL injection pattern'leri ararsa 444 döner. Log'a uyarı yazar, saldırganın IP'sini kaydeder.

FUTIA'da futia.net için Lua ile dinamik rate limiting yaptık. Her IP için Redis'te sayaç tuttuk, dakikada 30 isteği aşanları otomatik olarak 10 dakika engelledik. 3 ayda 2000+ video üretimi sırasında botlar sürekli denedi, hiçbiri başarılı olamadı.

Performans Ölçümü: 444 Bloklarının Etkisi

444 bloklarının gerçekten işe yarayıp yaramadığını ölçmek için birkaç metrik takip etmen gerekir:

1. Sunucu CPU ve RAM kullanımı: htop veya Grafana ile izle. 444 blokları devreye girdikten sonra CPU %50+ düşüş görmeli. 2. Bandwidth kullanımı: Nginx status modülü veya Cloudflare analytics ile ölç. 444 bloklarıyla bandwidth %40-60 azalmalı. 3. Access log boyutu: ls -lh /var/log/nginx/access.log ile kontrol et. 444'leri loglamıyorsan boyut %70+ küçülmeli. 4. Response time: Backend'e ulaşan istek sayısı azaldığı için ortalama response time düşmeli.

Örnek ölçüm: diolivo.com.tr'de 444 blokları öncesi ve sonrası

Öncesi (1 haftalık ortalama):

  • Sunucu CPU: %68
  • Bandwidth: 180 GB/hafta
  • Access log: 12 GB/hafta
  • Ortalama response time: 420ms

Sonrası (1 haftalık ortalama):

  • Sunucu CPU: %31
  • Bandwidth: 65 GB/hafta
  • Access log: 2.8 GB/hafta
  • Ortalama response time: 280ms

Yüzde değişim:

  • CPU: %54 azalma
  • Bandwidth: %64 azalma
  • Log boyutu: %77 azalma
  • Response time: %33 iyileşme

Bu rakamlar gerçek. diolivo.com.tr'nin %340 6 aylık trafik büyümesinde 444 blokları kritik rol oynadı. Çünkü sunucu kaynaklarını meşru kullanıcılara ayırdık, botlara değil.

Dikkat Edilmesi Gerekenler ve Yaygın Hatalar

444 kullanırken birkaç tuzağa düşebilirsin:

1. Meşru botları engelleme: Google, Bing, Yandex gibi arama motorlarının botlarını whitelist'e almayı unutma. Yoksa SEO sıfırlanır. 2. CDN veya proxy arkasında gerçek IP: Cloudflare, Fastly gibi CDN kullanıyorsan $remote_addr CDN'nin IP'sini gösterir. Gerçek IP için $http_x_forwarded_for veya $http_cf_connecting_ip kullanman gerekir. 3. if direktifi performans sorunu: Nginx'te if kullanımı önerilmez, map veya geo tercih edilir. Ama basit senaryolarda if de çalışır. 4. Rate limiting zone boyutu: limit_req_zone 10m yetersiz kalabilir. Çok fazla IP varsa 50m veya 100m kullan. 5. 444 dönerken backend'e istek gitmiş olabilir: Eğer proxy_pass'tan önce 444 döndürmüyorsan backend zaten yük almış demektir. Blokları en üstte, server veya location bloğunun başında yap.

Bir de legal durum var: Bazı ülkelerde geo-blocking yasal değil. AB'de GDPR kapsamında kullanıcıyı bilgilendirmeden engelleyemezsin. Türkiye'de böyle bir kısıtlama yok ama global bir servisin varsa hukuki danışmanlık al.

FUTIA'da Nginx Güvenlik Altyapısı

FUTIA'da her proje için Nginx level'de güvenlik katmanları kuruyoruz. 444 blokları standart bir parça. Tipik bir setup:

  • User agent bazlı blok: curl, wget, scrapy engellenir.
  • Rate limiting: API endpoint'leri için saniyede 5-10 istek, statik dosyalar için 50 istek.
  • Geo-blocking: Proje Türkiye'ye özel ise Türkiye dışı trafik 444.
  • Access log filtreleme: 444'ler ayrı dosyaya, ana log temiz kalır.
  • Lua ile dinamik bloklar: Redis'te IP blacklist, otomatik engelleme.

Örnek proje: kamupersonelhaber.com. 50+ günlük ilan, ilan.gov.tr API'sinden çekiliyor. Claude Haiku otomasyonu ile içerik üretiliyor. Botlar sürekli API endpoint'ini tarıyor. Nginx level'de rate limiting + 444 blokları ile saniyede 200 isteği 10 isteğe düşürdük. API backend'i rahatladı, response time %60 iyileşti.

Bir başka örnek: italyanmutfagi.com. 618 otomatik tarif, Schema.org Recipe ile yapılandırılmış. Google bot ve diğer meşru botlar için özel rate limit, diğer tüm botlar 444. Sonuç: Google Search Console'da 0 crawl hatası, tüm sayfalar 48 saat içinde index'lendi.

Bu tür güvenlik altyapısı kurmak teknik bilgi gerektirir. Nginx config hatası yaparsın, site düşer. FUTIA olarak Hollanda'dan Türk markalarına site + otomasyon + aylık bakım hizmeti sunuyoruz. Güvenlik altyapısı paket içinde geliyor. Eğer mevcut sitenin bot trafiğinden dolayı yavaşladığını düşünüyorsan benimle konuşabilirsin. WhatsApp: +90 532 491 17 05 veya info@futia.net adresinden ulaşabilirsin. 6 yıl sosyal medya pazarlama, 2 yıl AI otomasyon deneyimimle senin için de benzer bir sistem kurabilirim.

Sıkça Sorulanlar

Nginx 444 status code ne işe yarar?

Nginx 444 status code, HTTP response döndürmeden TCP bağlantısını anında kapatır. Standart HTTP kodları (200, 404, 500) header ve body gönderir, saldırgan tarafa bilgi verir. 444 hiçbir veri göndermez, saldırgan ne olduğunu anlayamaz. Bot saldırıları, scraping ve DDoS'a karşı etkilidir. Sunucu CPU ve bandwidth kullanımını %50-80 oranında düşürebilir. Sadece kötü niyetli trafiğe uygulanmalı, meşru kullanıcılara 444 döndürülmemelidir.

444 ile 403 veya 429 arasındaki fark nedir?

403 Forbidden, kullanıcıya "erişim yetkin yok" der ve HTTP response döner. 429 Too Many Requests, "rate limit aştın" der ve Retry-After header'ı ile ne zaman tekrar denemesi gerektiğini söyler. Her ikisi de saldırgana bilgi verir. 444 hiçbir response döndürmez, bağlantıyı sessizce kapatır. Saldırgan karanlıkta kalır, ne olduğunu anlayamaz. Bu yüzden 444 bot ve DDoS saldırılarına karşı daha etkilidir. Ama meşru kullanıcılara 444 döndürürsen tarayıcıda belirsiz bir hata mesajı görürler, bu yüzden dikkatli kullanılmalıdır.

Nginx 444 blokları access log'a yazılır mı?

Varsayılan olarak 444 status code da access log'a yazılır. Ama binlerce bot isteği varsa log dosyası çok büyür, disk I/O artar. 444'leri loglamamak için map direktifi kullanabilirsin: map $status $loggable { 444 0; default 1; } ve access_log combined if=$loggable; şeklinde config yaparsın. Alternatif olarak 444'leri ayrı bir log dosyasına yazabilirsin, böylece hangi IP'lerin ne kadar engellendiğini takip edersin. FUTIA projelerinde 444'leri ayrı logluyoruz, ana log temiz kalıyor, analiz kolay oluyor.

Rate limiting ile 444 nasıl kombine edilir?

Nginx'in limit_req modülü ile rate limit koyarsın, limiti aşan isteklere limit_req_status 444; direktifi ile 444 döndürürsün. Örnek: limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s; ve limit_req_status 444; şeklinde config yaparsın. Her IP için saniyede 5 istek limiti olur, aşanlar 444 alır. Dikkat: limit_req_status global bir direktif, tüm location'lara uygulanır. Sadece belirli endpoint'lere 444 döndürmek istersen farklı zone'lar kullanman gerekir. FUTIA'da API endpoint'leri için düşük rate limit, statik dosyalar için yüksek rate limit uyguluyoruz.

Meşru botları (Google, Bing) 444'ten nasıl koruruz?

User agent bazlı blok yaparken meşru botları whitelist'e alman gerekir. map direktifi ile şöyle yaparsın: map $http_user_agent $block_ua { default 0; ~*Googlebot 0; ~*Bingbot 0; ~*baiduspider 0; ~*YandexBot 0; ~*curl 1; ~*wget 1; } şeklinde. Burada Googlebot, Bingbot gibi botlar 0 değeri alır (engellenmez), curl ve wget gibi araçlar 1 değeri alır (engellenir). Dikkat: User agent sahte olabilir, saldırgan "Googlebot" yazabilir. Daha güvenli yöntem IP bazlı whitelist'tir, Google'ın bot IP aralıklarını geo direktifi ile whitelist'e alırsın.

YAZAR HAKKINDA
Miraç Eroğlu

Hacettepe mezunu, 6 yıldır sosyal medya, 2 yıldır AI otomasyon.

Daha fazla bilgi →

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.