nftables ile Linux Güvenlik Duvarı Kuralları Oluşturma ve Yönetme

Yıllarca iptables ile boğuşmuş biri olarak şunu net söyleyeyim: nftables geçişi düşündüğünüzden çok daha az acı verici. Hatta birkaç kavramı kavradıktan sonra “neden bu kadar beklemiştim?” diye kendinize kızabilirsiniz. Linux çekirdeğine 2014’te giren ve Debian 10, RHEL 8 ile birlikte varsayılan güvenlik duvarı çerçevesi haline gelen nftables, eski araçların dağınıklığını temizleyip tutarlı bir sözdizimi sunuyor. Bu yazıda sıfırdan başlayarak üretim ortamında kullanabileceğiniz kural setleri oluşturacağız.

nftables Neden Farklı?

iptables, ip6tables, arptables, ebtables… Bunların hepsini ayrı ayrı yönetmek zorunda kaldıysanız ne demek istediğimi anlarsınız. nftables tüm bu araçları tek bir çatı altında birleştiriyor. IPv4, IPv6, ARP ve köprü kurallarını aynı sözdizimi ile yazıyorsunuz.

Başka bir fark: iptables’da bir kural eklemek için çekirdek kodu çalışırdı, bu da yüzlerce kural varsa ciddi performans sorunlarına yol açardı. nftables ise kuralları bir sanal makine bytecode’una derleyerek çok daha verimli çalışıyor. Büyük ölçekli ortamlarda bu fark gerçekten hissediliyor.

Kurulum ve İlk Adımlar

Çoğu modern dağıtımda nftables zaten kurulu gelir. Kontrol edelim:

# Servis durumunu kontrol et
systemctl status nftables

# Mevcut kural setini görüntüle
nft list ruleset

# Versiyon kontrolü
nft --version

Eğer kurulu değilse:

# Debian/Ubuntu
apt install nftables

# RHEL/CentOS/Rocky Linux
dnf install nftables

# Servisi başlat ve otomatik başlatmaya al
systemctl enable --now nftables

nftables’ın yapısını anlamak için önce terminolojiye bakmak gerekiyor. Her şey bir table içinde başlar. Tablolar chain (zincir) içerir, zincirler ise rule (kural) barındırır. iptables’daki sabit tablo/zincir yapısının aksine, nftables’da bunları siz tanımlıyorsunuz. Bu esneklik başta kafa karıştırabilir ama zamanla çok değerli olduğunu anlıyorsunuz.

Temel Tablo ve Zincir Yapısı

Hemen pratik bir örneğe geçelim. Basit bir sunucu için temel güvenlik duvarı kurallarını komut satırından yazalım:

# Yeni bir tablo oluştur (inet = IPv4 + IPv6 birlikte)
nft add table inet filter

# Input zinciri oluştur - varsayılan politika drop
nft add chain inet filter input '{ type filter hook input priority 0; policy drop; }'

# Forward zinciri
nft add chain inet filter forward '{ type filter hook forward priority 0; policy drop; }'

# Output zinciri - varsayılan politika accept
nft add chain inet filter output '{ type filter hook output priority 0; policy accept; }'

Şimdi bu iskelet üzerine kuralları ekleyelim:

# Loopback arayüzüne izin ver
nft add rule inet filter input iif lo accept

# Kurulu bağlantılara ve bağlantılı trafiğe izin ver
nft add rule inet filter input ct state established,related accept

# ICMP'ye izin ver (ping)
nft add rule inet filter input ip protocol icmp accept
nft add rule inet filter input ip6 nexthdr icmpv6 accept

# SSH erişimine izin ver
nft add rule inet filter input tcp dport 22 accept

# HTTP ve HTTPS
nft add rule inet filter input tcp dport { 80, 443 } accept

# Geçersiz paketleri düşür
nft add rule inet filter input ct state invalid drop

Kuralları görüntülemek için:

nft list chain inet filter input

Kalıcı Yapılandırma: nft Dosyaları

Komut satırından eklediğiniz kurallar reboot sonrası kaybolur. Üretim ortamında /etc/nftables.conf dosyasını kullanmanız gerekiyor. Buraya geçmeden önce şunu belirteyim: dosya tabanlı yapılandırma aynı zamanda versiyon kontrolü (git) ve kod incelemesi için de çok daha uygun.

İşte tipik bir web sunucusu için tam yapılandırma dosyası:

#!/usr/sbin/nft -f

# Mevcut kuralları temizle
flush ruleset

table inet filter {
    # Güvenilir IP adresleri için set tanımla
    set trusted_hosts {
        type ipv4_addr
        elements = { 10.0.0.1, 192.168.1.0/24 }
    }

    # SSH brute-force için rate limiting seti
    set ssh_ratelimit {
        type ipv4_addr
        flags dynamic, timeout
        timeout 5m
    }

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

        # Loopback
        iif "lo" accept

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

        # Kurulu bağlantılar
        ct state { established, related } accept

        # ICMP - flood koruması ile
        ip protocol icmp icmp type { echo-request } limit rate 5/second accept
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # SSH - sadece güvenilir hostlardan veya rate limit ile
        ip saddr @trusted_hosts tcp dport 22 accept
        tcp dport 22 ct state new 
            add @ssh_ratelimit { ip saddr limit rate 3/minute } 
            accept

        # Web trafiği
        tcp dport { 80, 443 } accept

        # Log: reddedilen paketler
        limit rate 5/minute log prefix "[nftables DROP] " flags all
    }

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

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

Bu dosyayı uygulamak için:

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

# Uygula
nft -f /etc/nftables.conf

# Veya servisi yeniden başlat
systemctl restart nftables

Set Kullanımı: Güçlü Bir Özellik

nftables’ın en kullanışlı özelliklerinden biri set yapısı. IP adresleri, portlar veya başka veri tipleri için dinamik veya statik listeler oluşturabilirsiniz. Bir CDN arkasındaki sunucuda sadece CDN IP’lerinden gelen trafiği kabul etmek istediğinizi düşünün:

# Named set oluştur
nft add set inet filter cloudflare_ips '{ type ipv4_addr; flags interval; }'

# IP aralıkları ekle
nft add element inet filter cloudflare_ips '{ 
    103.21.244.0/22,
    103.22.200.0/22,
    103.31.4.0/22,
    104.16.0.0/13,
    173.245.48.0/20
}'

# Sadece bu setden gelen HTTP/S trafiğini kabul et
nft add rule inet filter input 
    ip saddr @cloudflare_ips tcp dport { 80, 443 } accept

Dinamik set kullanımı ise özellikle güvenlik senaryolarında çok işe yarıyor. Örneğin port tarama yapan IP’leri otomatik olarak geçici olarak engellemek:

# Konfigürasyon dosyasında port scanner bloklama
set port_scanners {
    type ipv4_addr
    flags dynamic, timeout
    timeout 1h
}

chain input {
    # Kapalı portlara bağlantı gelirse işaretle ve düşür
    tcp dport { 23, 3389, 4444, 5900 } 
        add @port_scanners { ip saddr } 
        drop
    
    # Daha önce işaretlenenlerden gelen her şeyi düşür
    ip saddr @port_scanners drop
}

NAT ve Port Yönlendirme

nftables ile NAT kuralları da son derece temiz yazılıyor. Bir gateway/router sunucusunda masquerade ve DNAT örneği:

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

        # 80 portuna gelen trafiği iç sunucuya yönlendir
        iif "eth0" tcp dport 80 dnat to 192.168.1.10:8080

        # 443'ü farklı bir sunucuya
        iif "eth0" tcp dport 443 dnat to 192.168.1.20:443
    }

    chain postrouting {
        type nat hook postrouting priority 100; policy accept;

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

        # Belirli bir IP ile source NAT
        # ip saddr 192.168.1.0/24 oif "eth0" snat to 1.2.3.4
    }
}

IP forwarding’i de etkinleştirmeyi unutmayın:

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

Gerçek Dünya Senaryosu: VPS Güvenlik Sertleştirmesi

Piyasada bir VPS aldınız, üzerine bir uygulama kuracaksınız. Standart sertleştirme akışım şu şekilde:

#!/usr/sbin/nft -f

flush ruleset

# Değişkenler
define WAN_IFACE = eth0
define ADMIN_IP = 203.0.113.10  # Sizin IP'niz

table inet filter {

    set blocked_ips {
        type ipv4_addr
        flags interval
        # Bilinen kötü amaçlı aralıklar buraya eklenebilir
    }

    set admin_access {
        type ipv4_addr
        elements = { $ADMIN_IP }
    }

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

        # Temel kurallar
        iif "lo" accept comment "loopback"
        ct state invalid counter drop comment "gecersiz paketler"
        ct state { established, related } counter accept comment "kurulu baglanti"

        # Kara liste
        ip saddr @blocked_ips counter drop comment "engellenen IPler"

        # ICMP flood koruması
        ip protocol icmp icmp type echo-request 
            limit rate over 10/second burst 20 packets drop
        ip protocol icmp accept
        ip6 nexthdr icmpv6 icmpv6 type {
            nd-neighbor-solicit, nd-neighbor-advert,
            nd-router-solicit, nd-router-advert
        } accept
        ip6 nexthdr icmpv6 accept

        # SSH sadece admin IP'den
        ip saddr @admin_access tcp dport 22 counter accept comment "admin ssh"
        tcp dport 22 counter drop comment "diger ssh engelleme"

        # Uygulama portları
        tcp dport { 80, 443 } counter accept comment "web"

        # Her şeyi logla ve düşür
        counter log prefix "[BLOCKED] " drop
    }

    chain output {
        type filter hook output priority filter; policy accept;
        
        # Sunucudan dışarı çıkışları kısıtlamak isterseniz
        # ct state { established, related, new } accept
    }

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

Bu yapılandırmada comment kullanımına dikkat edin. Altı ay sonra döndüğünüzde ne yaptığınızı anlayabilmek için kural yorumları çok değerli.

Kural Yönetimi İpuçları

Bir kuralı silmek için önce handle numarasını bulmanız gerekiyor:

# Handle numaraları ile listele
nft -a list chain inet filter input

# Belirli bir kuralı sil (handle 7 örneği)
nft delete rule inet filter input handle 7

Kural ekleme sırası önemli. Belirli bir konuma kural eklemek için:

# En başa ekle
nft insert rule inet filter input position 0 ip saddr 10.0.0.0/8 accept

# Belirli bir handle'dan sonra ekle
nft add rule inet filter input handle 5 tcp dport 8080 accept

Mevcut kuralları yedeklemek ve geri yüklemek:

# Tüm kural setini yedekle
nft list ruleset > /root/nftables_backup_$(date +%Y%m%d).conf

# Geri yükle
nft -f /root/nftables_backup_20240115.conf

# Canlı ortamda test ederken dikkatli olmak için:
# Önce mevcut durumu kaydet
nft list ruleset > /tmp/current_rules.conf
# Değişiklik yap, eğer bağlantı kesilirse:
# at now + 5 minutes <<EOF
# nft -f /tmp/current_rules.conf
# EOF

Son satırdaki at komutu tricks aslında. Uzak sunucuda çalışırken yanlış bir kural kendi bağlantınızı kesebilir. 5 dakika içinde geri dönmezseniz otomatik eski kurallar yükleniyor.

İzleme ve Debug

Sorun gidermede en çok kullandığım yöntem counter ve log kombinasyonu:

# Tüm zincirlerdeki sayaçları görüntüle
nft list ruleset | grep counter

# Belirli bir zinciri izle
watch -n2 'nft list chain inet filter input'

# Kernel loglarından nftables kayıtlarını takip et
journalctl -f | grep nftables
# veya
tail -f /var/log/kern.log | grep BLOCKED

Bir paketin neden düşürüldüğünü anlamak için geçici izleme ekleyebilirsiniz:

# Geçici debug kuralı ekle
nft insert rule inet filter input 
    tcp dport 8080 
    log prefix "[DEBUG-8080] " 
    accept

# İşiniz bittikten sonra sil
nft -a list chain inet filter input
# Handle numarasını bulup sil
nft delete rule inet filter input handle XX

iptables ile Birlikte Çalışma

Bazı araçlar hâlâ iptables kuralları yazıyor (Docker, libvirt gibi). Bu durumu yönetmek için iptables-nft wrapper’ı kullanılabilir. Ancak bu geçiş dönemine özgü bir çözüm. Uzun vadede:

# iptables komutlarını nftables'a çevir
iptables-translate -A INPUT -p tcp --dport 80 -j ACCEPT
# Çıktı: nft add rule ip filter INPUT tcp dport 80 counter accept

# Tüm iptables kurallarını dönüştür
iptables-restore-translate -f /tmp/iptables.rules > /etc/nftables.conf

Docker kullananlar için: Docker’ın kendi zincirlerini oluşturduğunu, bunları silmemeniz gerektiğini hatırlatayım. Docker ile nftables birlikteliği ayrı bir yazı konusu ama temel kural: Docker’ın oluşturduğu tablolara müdahale etmeyin, kendi tablolarınızda çalışın.

Sonuç

nftables’a geçiş bir öğrenme eğrisi gerektiriyor, bunu inkar etmeyeyim. Ama bu eğri iptables’ı ilk öğrenmekten daha kısa ve sonunda çok daha temiz bir araçla çıkıyorsunuz karşınıza. Tek bir sözdizimi ile IPv4/IPv6 yönetimi, güçlü set yapısı, okunabilir yapılandırma dosyaları ve daha iyi performans; bunlar küçük avantajlar değil.

Üretim geçişi için önerim: önce yeni bir test VM’de bu yapılandırmaları deneyin, nft -c ile sözdizimi kontrolü yapmayı alışkanlık edinin ve en önemlisi her önemli değişiklikten önce mevcut kural setini yedekleyin. at komutu ile otomatik geri alma mekanizması kurmayı da ihmal etmeyin, uzak sunucularda bu basit önlem sizi büyük bir baş ağrısından kurtarır.

nftables dökümantasyonu için wiki.nftables.org adresini şiddetle tavsiye ederim; açıklamaları ve örnek reposu oldukça kapsamlı. nft describe komutu da bir anahtar kelime hakkında hızlıca bilgi almanızı sağlıyor, sık kullanın.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir