Debian’da Güvenlik Duvarı: nftables ile Kapsamlı Yapılandırma Rehberi

Güvenlik duvarı yönetimi söz konusu olduğunda, Debian dünyasında uzun yıllar boyunca iptables hakimiyeti sürdü. Ancak kernel 3.13 ile birlikte hayatımıza giren nftables, artık modern Debian kurulumlarında varsayılan güvenlik duvarı çözümü haline geldi. Debian 10 Buster’dan itibaren nftables ön plana çıktı, Debian 11 ve 12’de ise neredeyse tamamen standart hale geldi. Bu yazıda, nftables’ı sıfırdan yapılandırmayı, gerçek bir üretim sunucusu senaryosunda kural setleri oluşturmayı ve iptables’tan geçiş sürecini ele alacağız.

nftables Neden iptables’ın Yerini Aldı?

iptables yıllarca gayet iyi iş gördü, bunu inkâr etmek mümkün değil. Ancak zamanla ciddi sorunlar birikiyor. iptables, ip6tables, arptables ve ebtables gibi ayrı araçlar kullanmak zorunda kalıyordunuz. Her biri kendi kural setini tutuyordu, senkronizasyon kabusu yaratıyordu.

nftables bu sorunu şu şekilde çözüyor:

  • Tek çerçeve: IPv4, IPv6, ARP ve bridge trafiği tek bir araçla yönetiliyor
  • Atomik kural güncellemeleri: Kural setini tek seferde yükleyip uygulayabiliyorsunuz, yarım kalmış güncellemeler yok
  • Daha iyi performans: Kural setleri derleniyor, kernel içinde bytecode olarak çalışıyor
  • Set ve map desteği: IP adreslerini ve portları kümeler halinde yönetebiliyorsunuz
  • Okunabilir sözdizimi: iptables komutlarına kıyasla çok daha anlaşılır

Kurulum ve Temel Kontroller

Debian 11/12 üzerinde nftables genellikle zaten kurulu geliyor. Kontrol edelim:

dpkg -l nftables
systemctl status nftables

Kurulu değilse:

apt update && apt install nftables -y
systemctl enable nftables
systemctl start nftables

Mevcut kural setini görmek için:

nft list ruleset

Temiz bir kurulumda bu komut boş çıktı verir ya da minimal bir şey gösterir. Eğer iptables kuralları varsa ve nftables’a geçiş yapıyorsanız, önce mevcut durumu kaydedin:

iptables-save > /root/iptables-backup-$(date +%Y%m%d).txt

nftables Temel Kavramları

Kural yazmaya geçmeden önce terminolojiyi netleştirmek gerekiyor.

Tables (Tablolar): Kural setinin en üst düzey kapsayıcısı. Her tablo bir adres ailesine sahip: ip (IPv4), ip6 (IPv6), inet (her ikisi), arp, bridge.

Chains (Zincirler): Tablolar içinde kural grupları. Base chain’ler doğrudan kernel hook’larına bağlıdır. Hook türleri:

  • prerouting: Paket sisteme girişte
  • input: Yerel process’e giden paketler
  • forward: Başka hedefe yönlendirilen paketler
  • output: Yerel process’ten çıkan paketler
  • postrouting: Paket sistemden çıkışta

Rules (Kurallar): Zincirler içindeki eşleştirme ve aksiyon ifadeleri.

Sets: IP adresleri, portlar gibi değerlerin gruplandırılması.

İlk Kural Seti: Temel Sunucu Koruması

Şimdi gerçek bir senaryoya geçelim. Elimizde bir web sunucusu var, SSH, HTTP ve HTTPS trafiğine izin vermemiz, geri kalanı engellemememiz gerekiyor.

Konfigürasyon dosyasını doğrudan düzenleyeceğiz. nftables konfigürasyonu /etc/nftables.conf dosyasında tutuluyor:

nano /etc/nftables.conf

Aşağıdaki temel yapıyı oluşturalım:

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        # Loopback arayüzüne izin ver
        iifname "lo" accept

        # Kurulu bağlantılara ve ilişkili paketlere izin ver
        ct state established,related accept

        # Geçersiz paketleri düşür
        ct state invalid drop

        # ICMP (ping) trafiğine izin ver
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # SSH erişimine izin ver
        tcp dport 22 accept

        # HTTP ve HTTPS trafiğine izin ver
        tcp dport { 80, 443 } accept

        # Loglama: engellenen paketleri kaydet
        log prefix "[nftables-drop] " flags all counter drop
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Bu kural setini uygulamak için:

nft -f /etc/nftables.conf

Hata yoksa kurallar aktif. Kontrol edelim:

nft list ruleset

SSH Brute Force Koruması

Basit bir web sunucusu için yukarıdaki kural seti yeterli, ancak SSH brute force saldırıları gerçek bir tehdit. Rate limiting ekleyelim. Bu senaryo, internet’e açık her sunucu için zorunlu:

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        iifname "lo" accept
        ct state established,related accept
        ct state invalid drop

        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # SSH brute force koruması
        # 60 saniyede 5'ten fazla yeni bağlantıyı engelle
        tcp dport 22 ct state new 
            limit rate over 5/minute 
            log prefix "[SSH-BRUTE] " 
            drop

        tcp dport 22 accept

        tcp dport { 80, 443 } accept

        log prefix "[INPUT-DROP] " flags all counter drop
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Bu yöntem belirli bir IP’yi kalıcı olarak engellemez, sadece hız limitini aşan paketleri düşürür. Daha kalıcı bir çözüm için set kullanabiliriz.

Set Kullanımı: Dinamik IP Kara Listesi

nftables’ın en güçlü özelliklerinden biri set desteği. Aşağıdaki örnekte brute force deneyen IP’leri otomatik olarak engelleyen bir yapı kuruyoruz:

table inet filter {

    # Engellenen IP'ler için dinamik set
    set blacklist {
        type ipv4_addr
        flags dynamic, timeout
        timeout 1h
    }

    chain input {
        type filter hook input priority 0; policy drop;

        iifname "lo" accept
        ct state established,related accept
        ct state invalid drop

        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # SSH: dakikada 5'ten fazla deneme yapan IP'yi kara listeye al
        tcp dport 22 ct state new 
            add @blacklist { ip saddr limit rate over 5/minute } 
            log prefix "[BLACKLISTED] " drop

        # Kara listedeki IP'lerden gelen tüm trafiği engelle
        ip saddr @blacklist drop

        tcp dport 22 accept
        tcp dport { 80, 443 } accept

        log prefix "[INPUT-DROP] " counter drop
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Kara listedeki IP’leri görmek için:

nft list set inet filter blacklist

Manuel olarak IP eklemek ya da çıkarmak için:

# IP ekle (1 saat sonra otomatik kaldırılır)
nft add element inet filter blacklist { 192.168.1.100 }

# IP çıkar
nft delete element inet filter blacklist { 192.168.1.100 }

NAT ve Port Yönlendirme

Senaryo: Sunucunuz aynı zamanda bir VPS router görevi görüyor. 8080 portuna gelen trafiği iç ağdaki bir servise yönlendirmeniz gerekiyor.

table ip nat {
    chain prerouting {
        type nat hook prerouting priority -100;

        # Dışarıdan 8080'e gelen TCP trafiğini iç sunucuya yönlendir
        iifname "eth0" tcp dport 8080 
            dnat to 10.0.0.50:80
    }

    chain postrouting {
        type nat hook postrouting priority 100;

        # İç ağdan çıkan trafiği masquerade et
        oifname "eth0" masquerade
    }
}

table inet filter {
    chain forward {
        type filter hook forward priority 0; policy drop;

        # Yönlendirilen trafiğe izin ver
        ct state established,related accept

        # 10.0.0.50'ye giden yönlendirilmiş trafiğe izin ver
        ip daddr 10.0.0.50 tcp dport 80 accept
    }
}

Forwarding’in kernel seviyesinde de etkin olması gerekiyor:

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p

Kural Yönetimi: Komut Satırından Anlık Değişiklikler

Bazen yapılandırma dosyasını düzenlemeden hızlıca bir kural eklemek gerekiyor. nftables’ta bu oldukça kolay.

Mevcut zincire kural eklemek:

# Belirli bir IP'ye SSH erişimi engelle
nft add rule inet filter input ip saddr 203.0.113.10 tcp dport 22 drop

# 3306 portunu (MySQL) sadece iç ağa aç
nft add rule inet filter input ip saddr 10.0.0.0/8 tcp dport 3306 accept
nft add rule inet filter input tcp dport 3306 drop

Kural numarasıyla silme işlemi için önce handle numarasını bulun:

nft list ruleset -a

Çıktıda her kuralın yanında # handle X yazısı görünür. O handle ile silme:

nft delete rule inet filter input handle 7

Mevcut durumu kaydetmek:

nft list ruleset > /etc/nftables.conf

Dikkat: Bu komut mevcut konfigürasyonun üzerine yazar. Öncesinde yedek almayı unutmayın.

Debian’a Özel Yapılandırma: Kalıcılık ve Servis Yönetimi

Sunucu yeniden başladığında kuralların kaybolmaması için nftables servisinin düzgün yapılandırılması şart. Debian’da bu işleyişi anlayalım.

nftables servisi başlarken /etc/nftables.conf dosyasını okur. Dosyanın başında #!/usr/sbin/nft -f satırı bulunmalı ve flush ruleset komutu ile eski kurallar temizlenmeli.

Servisi yeniden başlatmak yerine konfigürasyonu test edip uygulamak için:

# Sözdizimi kontrolü
nft -c -f /etc/nftables.conf

# Uygula
nft -f /etc/nftables.conf

# Servisi de yeniden başlat (systemd state'ini güncel tut)
systemctl reload nftables

Yanlış bir kural yazıp sunucuya erişiminizi kaybetmenin önüne geçmek için bir güvenlik ağı oluşturun. Cron ile 5 dakika sonra kuralları sıfırlayan geçici bir görev ekleyin, kurallar çalışıyorsa bu görevi silin:

# Kural testinden önce çalıştır
echo "nft flush ruleset && nft -f /etc/nftables.conf.backup" | at now + 5 minutes

# Kurallar çalışıyor, görevi iptal et
atq
atrm [job_number]

Loglama ve İzleme

Güvenlik duvarı kurallarını yazdınız, ama ne kadar etkili olduğunu nasıl anlayacaksınız? Loglama kritik önem taşıyor.

nftables logları /var/log/syslog veya journald üzerinden okunabilir:

# Gerçek zamanlı nftables loglarını izle
journalctl -f | grep nftables

# Son 100 engellenen paketi göster
journalctl | grep "[INPUT-DROP]" | tail -100

# Brute force denemeleri
journalctl | grep "[SSH-BRUTE]" | awk '{print $NF}' | sort | uniq -c | sort -rn

Sayaçları doğrudan nft ile de izleyebilirsiniz:

# Tüm zincirdeki sayaçları listele
nft list chain inet filter input

# Belirli aralıklarla izle (watch ile)
watch -n 2 "nft list ruleset | grep -A2 counter"

iptables’tan Geçiş

Eski bir Debian sunucunuzda iptables kuralları var ve nftables’a geçmek istiyorsunuz. iptables-translate ve ip6tables-translate araçları bu süreci kolaylaştırıyor:

# Tek bir kuralı çevir
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT

# Tüm mevcut kuralları toplu çevir
iptables-save | iptables-restore-translate -f > /etc/nftables.conf

Çıktıyı düzenleyip test etmeden uygulamayın. Özellikle karmaşık NAT kuralları veya modul bağımlılıkları olan kurallar elle gözden geçirilmeli.

Geçiş sırasında iptables’ın hâlâ aktif olmadığından emin olun:

# iptables-legacy'yi devre dışı bırak
update-alternatives --set iptables /usr/sbin/iptables-nft
update-alternatives --set ip6tables /usr/sbin/ip6tables-nft

# Kontrol et
iptables --version
# "iptables v1.8.x (nf_tables)" yazmalı

Gerçek Dünya Senaryosu: Veritabanı Sunucusu Güvenliği

Şimdi hepsini bir araya getirelim. Bu senaryo, internete kapalı ama uygulama sunucularına açık bir PostgreSQL sunucusu için kural seti:

#!/usr/sbin/nft -f

flush ruleset

define APP_SERVERS = { 10.0.1.10, 10.0.1.11, 10.0.1.12 }
define ADMIN_IPS = { 10.0.0.5, 10.0.0.6 }
define DB_PORT = 5432

table inet filter {

    set brute_force {
        type ipv4_addr
        flags dynamic, timeout
        timeout 24h
    }

    chain input {
        type filter hook input priority 0; policy drop;

        # Temel izinler
        iifname "lo" accept
        ct state established,related accept
        ct state invalid drop

        # ICMP sadece iç ağdan
        ip saddr 10.0.0.0/8 ip protocol icmp accept

        # SSH sadece yönetici IP'lerinden, brute force korumasıyla
        ip saddr @brute_force drop
        tcp dport 22 ip saddr $ADMIN_IPS ct state new 
            add @brute_force { ip saddr limit rate over 3/minute } drop
        tcp dport 22 ip saddr $ADMIN_IPS accept
        tcp dport 22 drop

        # PostgreSQL sadece uygulama sunucularından
        tcp dport $DB_PORT ip saddr $APP_SERVERS accept
        tcp dport $DB_PORT log prefix "[DB-UNAUTH] " drop

        # Diğer her şeyi düşür
        log prefix "[INPUT-DROP] " counter drop
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Bu kural setinde dikkat edilmesi gereken noktalar:

  • define ifadeleriyle değişken tanımladık, kural setini daha okunabilir ve bakımı kolay hale getirdik
  • Veritabanı portuna yetkisiz erişim girişimleri loglanıyor
  • SSH brute force koruma ağı, admin IP’leriyle sınırlı tutuluyor
  • ICMP sadece iç ağdan kabul ediliyor

Sonuç

nftables, ilk başta iptables’a kıyasla farklı bir sözdizimi sunduğu için alışmak biraz zaman alıyor. Ancak bir kez kavramları özümsediğinizde, IPv4 ve IPv6’yı tek yerde yönetmek, dinamik setler kullanmak ve atomik güncellemeler yapmak büyük kolaylık sağlıyor.

Özellikle vurgulamamız gereken birkaç pratik nokta var. Her zaman değişiklik yapmadan önce mevcut kural setini yedekleyin. Yeni kural setini nft -c -f ile sözdizimi kontrolünden geçirin. Uzak bir sunucuda çalışıyorsanız at komutuyla güvenlik ağı kurun. Loglamayı ihmal etmeyin, engellenen trafik size saldırı vektörleri hakkında değerli bilgi veriyor. Son olarak, servis yönetimini systemd üzerinden yapın ki yeniden başlatmalarda sorun yaşamayın.

nftables dokümantasyonu oldukça iyi durumda. man nft ve resmi nftables wiki, referans olarak el altında bulundurmanız gereken kaynaklar. Üretim ortamına geçmeden önce bir test ortamında denemek, özellikle karmaşık NAT veya multi-homed sunucu senaryolarında sizi büyük baş ağrısından kurtaracak.

Yorum yapın