İçeriğe geç
Süreçlerinize uygun yazılımı birlikte planlayalım. Demo ve teklif için arayın: +90 546 737 48 29

TR EN DE

Nginx güvenlik ayarları: oran sınırlama, başlıklar, erişim kısıtları

Nginx, sitenize gelen her isteğin ilk karşılandığı yerdir. Bu yüzden birçok koruma, uygulamanın koduna dokunmadan burada kurulabilir: aşırı istek gönderen adresleri yavaşlatmak, açıkta kalmaması gereken dosyaları kapatmak, yönetim sayfasını yalnızca belirli adreslere açmak, çok büyük ya da çok yavaş istekleri kesmek.

Bu ayarlar uygulamadaki açıkları kapatmaz; hatanın etkisini küçülten ve otomatik taramaların büyük bölümünü uygulamaya ulaşmadan durduran bir ön katmandır. Rehber, her ayarın ne işe yaradığını ve Nginx yapılandırmasında nasıl yazıldığını anlatır. HTTPS kurulumu ayrı bir rehberdedir: Nginx'te HTTPS.

Kısaca

  • Bilinmeyen alan adıyla gelen istekler varsayılan sunucu bloğunda reddedilir.
  • limit_req ve limit_conn, tek adresten gelen istek ve bağlantı sayısını sınırlar.
  • Alt blokta add_header varsa üstteki başlıklar devralınmaz; ortak başlıklar yinelenmelidir.
  • Gizli dosyalar, yönetim yolu ve yükleme klasörü ayrı location bloklarıyla korunur.

Dikkat

Ayarları tek tek ekleyin, her değişiklikten sonra "nginx -t" ile sınayın. Yanlış bir IP kısıtı ya da çok sıkı bir oran sınırı sizi ve gerçek ziyaretçileri de dışarıda bırakabilir; değerleri kendi trafiğinize göre belirleyin.

Bu sayfada

Yedi adımda sıkılaştırma

  1. Bilinmeyen alan adlarını reddedin, sürümü gizleyin

    Nginx, gelen isteğin Host başlığını server_name satırlarıyla eşleştirir. Hiçbiri uymazsa isteği o bağlantı noktasının varsayılan sunucusuna verir; ayrıca belirtilmediyse bu, yapılandırmada ilk tanımlanan server bloğudur. Sonuç: sunucuya IP adresiyle ya da size ait olmayan bir alan adıyla gelen otomatik taramalar gerçek sitenize ulaşır.

    Bunu önlemek için hiçbir siteye ait olmayan bir varsayılan (catch-all) blok tanımlayın. return 444; Nginx'e özgü bir koddur: yanıt göndermeden bağlantıyı kapatır.

    Nginx
    # Hata sayfalarında ve Server başlığında sürüm numarasını gösterme
    server_tokens off;
    
    # Varsayılan blok: hiçbir siteyle eşleşmeyen Host istekleri
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        server_name _;
    
        # Bilinmeyen adla gelen TLS el sıkışmasını reddet
        ssl_reject_handshake on;
    
        # Yanıt göndermeden bağlantıyı kapat
        return 444;
    }

    ssl_reject_handshake on; bilinmeyen adla gelen HTTPS bağlantılarını sertifika sunmadan reddeder ve güncel Nginx sürümlerinde bulunur; eski sürümlerde bu blok için kendinden imzalı bir sertifika tanımlamak gerekir. server_tokens off; ise hata sayfalarından ve Server başlığından sürüm numarasını kaldırır. Bu tek başına koruma sağlamaz; yalnızca sürüme göre hedef seçen taramalara daha az bilgi verir. Asıl önlem Nginx'i güncel tutmaktır.

    Şema: Host başlığı tanımlı alan adıyla eşleşen istek site bloğuna gider; IP adresiyle ya da bilinmeyen adla gelen istek varsayılan blokta 444 ile kapatılır : Büyüt
  2. Oran sınırlama: limit_req ve limit_conn

    Oran sınırlama (rate limiting), tek bir adresin belirli sürede gönderebileceği istek sayısını sınırlar. İki ayrı araç vardır:

    • limit_req_zone + limit_req: istek hızını sınırlar (ör. saniyede 10 istek).
    • limit_conn_zone + limit_conn: aynı anda açık bağlantı sayısını sınırlar.

    …_zone yönergeleri http bloğunda bir kez tanımlanır: anahtarı (genellikle istemci adresi, $binary_remote_addr), paylaşılan bellek alanının adını ve boyutunu, limit_req_zone için ayrıca hızı belirtir. Sınır, server ya da location içinde uygulanır.

    Nginx
    # http bloğunda: alanlar bir kez tanımlanır
    limit_req_zone  $binary_remote_addr zone=genel:10m rate=10r/s;
    limit_req_zone  $binary_remote_addr zone=giris:10m rate=5r/m;
    limit_conn_zone $binary_remote_addr zone=baglanti:10m;
    
    # Reddedilenlere 503 yerine 429 dön
    limit_req_status  429;
    limit_conn_status 429;
    
    server {
        listen 443 ssl;
        server_name ornek.com;
    
        ssl_certificate     /etc/letsencrypt/live/ornek.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/ornek.com/privkey.pem;
    
        # Tüm site: saniyede 10 istek, 20 isteklik sıra
        limit_req  zone=genel burst=20 nodelay;
        # Aynı adresten en çok 20 eş zamanlı bağlantı
        limit_conn baglanti 20;
    
        location / {
            proxy_pass http://127.0.0.1:8080;
        }
    
        # Giriş formu: dakikada 5 istek
        location = /giris {
            limit_req zone=giris burst=5 nodelay;
            proxy_pass http://127.0.0.1:8080;
        }
    }

    İki parametre davranışı belirler:

    • burst: hızın üzerindeki isteklerden kaçının hemen reddedilmeyip sıraya alınacağını belirtir. Yazılmazsa hızı aşan her istek reddedilir; bir sayfa açılışında art arda gelen görsel ve betik istekleri için bu çok serttir.
    • nodelay: sıraya alınan istekler bekletilmeden hemen işlenir; sıradaki yerler ise belirlenen hızla boşalır. Yazılmazsa sıradaki istekler hıza uyacak şekilde geciktirilir.

    Reddedilen isteklere varsayılan olarak 503 döner. limit_req_status 429; ve limit_conn_status 429; ile bunu "çok fazla istek" anlamına gelen 429 yapın; böylece günlüklerde gerçek sunucu hatalarından ayırt edilir. Giriş formu gibi hassas adreslere ayrı ve daha düşük bir sınır verin. Bir location içinde limit_req tanımlanırsa üst düzeydeki limit_req o blokta geçerli olmaz.

    Dikkat: Nginx bir CDN'in ya da başka bir vekil sunucunun arkasındaysa $binary_remote_addr ziyaretçinin değil, öndeki sunucunun adresidir; sınır tüm ziyaretçilere birlikte uygulanır. Bu durumda önce gerçek istemci adresini set_real_ip_from ve real_ip_header yönergeleriyle (yalnızca güvendiğiniz vekil adresleri için) tanımlayın. Oran sınırlama büyük hacimli saldırıları tek başına durdurmaz; katmanlar için DDoS ve bot saldırıları rehberine, giriş denemeleri için Giriş ve oturum güvenliği rehberine bakın.

    Şema: oran sınırlamada üç durum; yalnız rate ile fazlası reddedilir, burst ile fazlası sıraya alınıp geciktirilir, burst ve nodelay ile sıradakiler hemen işlenir, sırayı aşan 429 alır : Büyüt
  3. Güvenlik başlıkları ve add_header kalıtım tuzağı

    Güvenlik başlıkları tarayıcının yerleşik korumalarını açar. Nginx'te add_header ile eklenir; sondaki always, başlığın 404 ve 500 gibi hata yanıtlarında da gönderilmesini sağlar. Başlıkların anlamı için Güvenlik başlıkları ve HTTPS rehberine bakın.

    Nginx'e özgü önemli bir tuzak vardır: add_header yönergeleri üst düzeyden yalnızca geçerli blokta hiç add_header yoksa devralınır. Bir location içine tek bir add_header (ör. önbellek başlığı) yazdığınız anda, server düzeyindeki tüm güvenlik başlıkları o blokta kaybolur.

    Nginx
    # server düzeyi: tüm yanıtlara
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
    
    location /assets/ {
        # Bu blokta add_header var: yukarıdaki dört başlık burada DEVRALINMAZ
        add_header Cache-Control "public, max-age=2592000";
    
        # Çözüm: ortak başlıkları bu blokta da tanımla
        # (dosyanın içeriği yukarıdaki dört add_header satırıdır)
        include /etc/nginx/snippets/guvenlik-basliklari.conf;
    }

    Güvenilir çözüm, ortak başlıkları ayrı bir dosyada tutup add_header kullanan her bloğa include ile eklemektir. Değişiklikten sonra yalnızca ana sayfayı değil, statik dosyaları ve hata sayfalarını da curl -sI ile kontrol edin.

    Karşılaştırma: location içinde tek add_header yazılınca server düzeyindeki güvenlik başlıkları devralınmaz; doğrusu ortak başlıkları include ile o blokta da tanımlamaktır : Büyüt
  4. Gizli dosyalara erişimi kapatın

    Adı nokta ile başlayan dosya ve klasörler (.env, .git, .htpasswd) parola, anahtar ve kaynak kod içerebilir; otomatik taramaların ilk baktığı yerlerdir. Tek istisna .well-known klasörüdür: sertifika doğrulaması gibi standart işler için açık kalmalıdır.

    Nginx
    # İstisna: .well-known açık kalır (sertifika doğrulaması vb.)
    location ^~ /.well-known/ {
        allow all;
    }
    
    # Adı nokta ile başlayan her dosya ve klasör: .env, .git, .htpasswd ...
    location ~ /\. {
        deny all;
    }
    
    # Web kökünde unutulan yedek ve döküm dosyaları
    location ~* \.(?:sql|bak|old|orig|log|ini)$ {
        deny all;
    }

    ^~ işareti, bu ön ek eşleştiğinde düzenli ifadeli location bloklarına bakılmamasını sağlar; böylece .well-known altındaki istekler genel yasağa takılmaz. Üçüncü blok, web kökünde unutulan yedek ve döküm dosyalarını kapatır. Yine de en doğrusu bu dosyaları web kökünde hiç bulundurmamaktır: Sunucu ve barındırma güvenliği.

  5. Yönetim yolunu ve yükleme klasörünü koruyun

    Yönetim paneli yalnızca belirli yerlerden kullanılıyorsa IP kısıtı, parola tahmini denemelerini giriş formuna ulaşmadan keser. allow ve deny kuralları yazıldıkları sırayla denenir; ilk uyan kural geçerlidir, bu yüzden deny all; en sonda durur.

    Nginx
    # ^~ : bu ön ek eşleşince dıştaki düzenli ifadeli bloklara bakılmaz
    location ^~ /yonetim/ {
        allow 203.0.113.10;        # ofis
        allow 198.51.100.0/24;     # VPN
        deny  all;
    
        # Kısıt, bloğun içindeki PHP işleyicisi için de geçerlidir
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_pass unix:/run/php/php-fpm.sock;   # yol dağıtıma göre değişir
        }
    }

    Burada sık yapılan bir hata vardır. PHP sitelerinde genellikle location ~ \.php$ biçiminde düzenli ifadeli bir blok bulunur. Kısıtı sıradan bir location /yonetim/ bloğuna yazarsanız /yonetim/index.php isteği düzenli ifadeli bloğa düşer ve kısıt uygulanmaz. Örnekteki gibi ^~ kullanıp PHP işleyicisini bloğun içine yerleştirmek bunu önler. PHP-FPM soket yolu dağıtıma göre değişir.

    Aynı mantık yükleme klasörü için tersine çalışır: ziyaretçilerin dosya yükleyebildiği klasörde hiçbir betik çalıştırılmamalıdır. Aşağıdaki blok, klasördeki dosyaları yalnızca durağan dosya olarak sunar ve betik uzantılı isteklere 403 döndürür.

    Nginx
    # Yükleme klasörü: yalnız durağan dosya sunulur
    location ^~ /upload/ {
        # Betik uzantılı istekler çalıştırılmaz, sunulmaz
        location ~* \.(?:php|phtml|phar|pl|py|cgi|sh)$ {
            return 403;
        }
    }

    Bu, yüklenen bir dosyanın sunucuda çalıştırılmasını engelleyen ikinci katmandır; ilk katman yükleme sırasındaki denetimdir: Dosya yükleme güvenliği.

    Şema: /yonetim/index.php isteği sıradan ön ek bloğunda değil düzenli ifadeli PHP bloğunda işlenir ve IP kısıtı atlanır; ^~ ile ön ek bloğu seçilir ve kısıt uygulanır : Büyüt
  6. Büyük ve yavaş isteklere sınır koyun

    Çok büyük gövdeli istekler disk ve bellek tüketir; bilerek çok yavaş gönderilen istekler ise bağlantıları uzun süre meşgul eder. Üç yönerge bu ikisini sınırlar:

    YönergeNe sınırlar?VarsayılanAşılınca
    client_max_body_sizeİstek gövdesinin (ör. yüklenen dosyanın) en büyük boyutu1m413
    client_body_timeoutGövde okunurken art arda iki okuma arasındaki süre60s408
    client_header_timeoutİstek başlıklarının tamamının okunma süresi60s408
    Nginx
    # Genel sınırlar
    client_max_body_size  2m;
    client_body_timeout   15s;
    client_header_timeout 15s;
    
    # Yalnız dosya yüklenen adres için daha yüksek gövde sınırı
    location /dosya-yukle {
        client_max_body_size 20m;
        proxy_pass http://127.0.0.1:8080;
    }

    Genel sınırı düşük tutun, dosya yüklenen adrese ayrı ve daha yüksek bir değer verin. PHP kullanıyorsanız upload_max_filesize ve post_max_size ayarları da bu değerle uyumlu olmalıdır. Zaman aşımlarını (timeout) çok kısaltmak, yavaş mobil bağlantıdaki gerçek kullanıcıları da keser; değerleri kademeli düşürün ve günlüklerdeki 408 yanıtlarını izleyin.

  7. Sınayın, yükleyin ve dışarıdan doğrulayın

    Her değişiklikten sonra sözdizimini sınayın ve Nginx'i yeniden yükleyin. Ardından ayarların gerçekten çalıştığını kendi sitenize dışarıdan istek göndererek doğrulayın: gizli dosya adresleri 403 ya da 404 dönmeli, başlıklar statik dosyalarda da görünmeli, sunucunun IP adresine yapılan istek yanıtsız kapanmalıdır.

    Bash
    # Sözdizimini sına, sonra yeniden yükle
    sudo nginx -t
    sudo systemctl reload nginx
    
    # Başlıklar: ana sayfa ve bir statik dosya
    curl -sI https://ornek.com/
    curl -sI https://ornek.com/assets/site.css
    
    # Gizli dosyalar kapalı mı? (403 ya da 404 beklenir)
    curl -s -o /dev/null -w "%{http_code}\n" https://ornek.com/.env
    curl -s -o /dev/null -w "%{http_code}\n" https://ornek.com/.git/config
    
    # Sunucunun IP adresine istek: yanıtsız kapanmalı
    curl -sI http://203.0.113.20/

    IP kısıtını denerken ikinci bir oturumu açık tutun; yanlış bir kural sizi panelin dışında bırakırsa yapılandırmayı o oturumdan geri alabilirsiniz.

    Katman şeması: varsayılan sunucu, oran sınırlama, istek sınırları, erişim kısıtları, güvenlik başlıkları ve en içte uygulama : Büyüt

Bu ayarlar neyi çözmez?

  • Uygulama açıkları: SQL enjeksiyonu, XSS ya da yetki kontrolü hataları kodda düzeltilir; Nginx ayarı bunların yerini tutmaz.
  • Büyük hacimli saldırılar: sunucunun bant genişliğini dolduran trafik, sunucuya ulaşmadan önce (barındırma firması ya da CDN düzeyinde) karşılanmalıdır.
  • Dağıtık yavaş denemeler: çok sayıda farklı adresten gelen az sayıda istek, adres başına sınıra takılmaz; giriş güvenliği uygulamada da kurulmalıdır.
  • Ele geçirilmiş hesaplar: IP kısıtı ve oran sınırı, geçerli parolayla izinli adresten gelen birini durdurmaz; iki adımlı doğrulama gerekir.

Değerleri nasıl seçmeli?

Örneklerdeki sayılar başlangıç noktasıdır, öneri değildir. Doğru değer sitenizin trafiğine bağlıdır:

  • Bir sayfanın açılışında tarayıcının kaç istek gönderdiğine bakın; burst bu sayıyı karşılamalıdır.
  • Aynı kurum ağından çıkan çok sayıda kullanıcı tek IP adresiyle görünebilir; sınırı buna göre gevşetin ya da bilinen adresleri ayrı tutun.
  • Sınırı açtıktan sonra hata günlüğünde reddedilen istek kayıtlarını ve erişim günlüğündeki 429 yanıtlarını izleyin; gerçek kullanıcılar takılıyorsa değeri yükseltin.
  • HTTP/2 ve HTTP/3'te eş zamanlı her istek limit_conn için ayrı bir bağlantı sayılır; değeri çok düşük seçmeyin.
  • Arama motoru botlarını ve kendi izleme araçlarınızı sınırın dışında bırakmanız gerekip gerekmediğini değerlendirin.

Kontrol listesi

  • 80 ve 443 için varsayılan blok tanımlı; bilinmeyen Host ile gelen istek siteye ulaşmıyor.
  • server_tokens off; tanımlı ve Nginx güncel.
  • Genel ve giriş adresine özel oran sınırı var; reddedilenlere 429 dönüyor.
  • Vekil arkasında gerçek istemci adresi doğru tanımlı.
  • Güvenlik başlıkları always ile tanımlı; add_header kullanan alt bloklarda yinelenmiş.
  • Nokta ile başlayan dosyalar ve yedek uzantıları kapalı; .well-known açık.
  • Yönetim yolu IP ile kısıtlı ve kısıt .php isteklerinde de geçerli.
  • Yükleme klasöründe betik çalışmıyor.
  • Gövde boyutu ve zaman aşımı sınırları tanımlı; yükleme adresi için ayrı değer var.
  • Her değişiklik nginx -t ile sınandı ve dışarıdan doğrulandı.

Sık sorulan sorular

Oran sınırlama arama motoru botlarını etkiler mi?

Çok düşük bir sınır botları da yavaşlatır ve 429 yanıtı taramayı geciktirir. Sınırı gerçek trafiğinize göre belirleyin ve günlüklerde hangi isteklerin reddedildiğini izleyin.

server_tokens off yazınca Server başlığı tümüyle kalkar mı?

Hayır. Yalnızca sürüm numarası kalkar; başlıkta "nginx" yazmaya devam eder. Bu ayar bilgi sızıntısını azaltır, güncellemenin yerini tutmaz.

444 yerine 403 ya da 404 dönsem olur mu?

Olur. 444 yanıt göndermeden bağlantıyı kapattığı için otomatik taramalara en az bilgiyi verir. Bir izleme aracı ya da yük dengeleyici o adresten yanıt bekliyorsa standart bir kod kullanın.

Başlıklarım ana sayfada var ama görsellerde yok; neden?

Büyük olasılıkla statik dosyalara ait location bloğunda ayrı bir add_header var. Nginx bu durumda üst düzeydeki başlıkları o bloğa devralmaz; ortak başlıkları o blokta da tanımlayın.

Paylaşımlı barındırmada bu ayarları yapabilir miyim?

Genellikle hayır; Nginx yapılandırması sunucu yöneticisinin elindedir. Barındırma firmanızdan destek isteyebilir ya da benzer korumaları panelden ve CDN üzerinden açabilirsiniz.

BYK Yazılım Destek Ekibi
Bu rehber BYK Yazılım destek ekibi tarafından hazırlanır ve düzenli olarak gözden geçirilir. Son güncelleme: 04.10.2026.

İlgili rehberler

Web sitenizin altyapısını birlikte konuşalım

BYK Yazılım kurumsal web siteleri geliştirir. Sitenizle ilgili sorularınız için bize yazabilirsiniz.

Bize ulaşın Kurumsal web sitesi hizmetimiz