Bir web sunucusunu internete açtığınız anda, saldırı denemeleri neredeyse anında başlar. Bot taramaları, kaba kuvvet saldırıları, port taramaları… Bunların hepsine karşı ilk savunma hattınız iyi yapılandırılmış bir güvenlik duvarıdır. Linux sistemlerde bu işin en güvenilir aracı ise iptables‘tır. Yıllardır prodüksiyon ortamlarında kullandığım, bir kez doğru kurduğunuzda sizi çok kötü durumlardan kurtaran bu araç, başlangıçta karmaşık görünse de mantığını kavradıktan sonra oldukça güçlü bir silaha dönüşüyor.
Bu yazıda sıfırdan başlayarak, gerçek bir web sunucusuna uygun kapsamlı bir iptables güvenlik duvarı kuracağız. Sadece teorik bilgi değil, prodüksiyonda kullandığım gerçek kural setlerini paylaşacağım.
iptables Nasıl Çalışır?
iptables, Linux çekirdeğinin netfilter modülü üzerine inşa edilmiştir. Ağ trafiğini zincirler (chains) aracılığıyla filtreler. Üç temel zinciri bilmek zorundasınız:
- INPUT: Sunucuya gelen trafiği kontrol eder
- OUTPUT: Sunucudan çıkan trafiği kontrol eder
- FORWARD: Sunucu üzerinden geçen trafiği kontrol eder (router senaryolarında kullanılır)
Her zincirin bir default policy (varsayılan politikası) vardır. Biz güvenli bir yapı için bu politikayı DROP olarak ayarlayacağız. Yani kurallara uymayan her şey engellenecek. Bu yaklaşıma whitelist (beyaz liste) modeli deniyor ve en güvenli yaklaşım bu.
Ayrıca üç temel tablo var:
- filter: Paketleri kabul edip etmeyeceğimize karar verdiğimiz tablo (en çok kullanılan)
- nat: Ağ adresi çevirimi için kullanılır
- mangle: Paket başlıklarını düzenlemek için kullanılır
Biz bu yazıda ağırlıklı olarak filter tablosunu kullanacağız.
Kuruluma Başlamadan Önce
Önce sisteminizde iptables‘ın kurulu olup olmadığını kontrol edin:
iptables --version
# Çıktı: iptables v1.8.7 (nf_tables)
# Ubuntu/Debian'da kurulum
apt-get install iptables iptables-persistent -y
# CentOS/RHEL'de kurulum
yum install iptables-services -y
Kritik uyarı: Uzak sunucuda çalışıyorsanız, yanlış bir kural SSH bağlantınızı kesebilir. Bu yüzden ilk olarak bir “güvenlik ağı” komutu çalıştırın. Bu komut 5 dakika sonra tüm kuralları sıfırlayacak:
# 5 dakika sonra kuralları sıfırlayan güvenlik komutu
# SSH bağlantısı kesilirse bu komut sizi kurtarır
echo "iptables -F && iptables -P INPUT ACCEPT && iptables -P OUTPUT ACCEPT" | at now + 5 minutes
# at komutu yoksa şunu kullanın:
(sleep 300 && iptables -F && iptables -P INPUT ACCEPT) &
Kurulum tamamlandıktan sonra bu zamanlanmış görevi iptal etmeyi unutmayın.
Mevcut Kuralları Görüntüleme ve Temizleme
Başlamadan önce mevcut durumu kontrol edelim:
# Mevcut kuralları listele
iptables -L -v -n --line-numbers
# NAT tablosunu listele
iptables -t nat -L -v -n
# Tüm kuralları ve sayaçları göster
iptables -L -v -n -x
Şimdi temiz bir başlangıç için her şeyi temizleyelim:
# Tüm kuralları sil (flush)
iptables -F
# Tüm zincir politikalarını ACCEPT'e al (geçici olarak)
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# Özel zincirleri sil
iptables -X
# Sayaçları sıfırla
iptables -Z
Temel Web Sunucusu Güvenlik Duvarı Yapılandırması
Şimdi adım adım kuralları oluşturalım. Ben bu kuralları genellikle bir shell script içinde yazarım. Hem yönetimi kolaylaşır hem de yedekleme ve versiyon kontrolü için çok daha pratik olur.
#!/bin/bash
# web_firewall.sh - Web sunucusu güvenlik duvarı kurulum scripti
# Hazırlayan: Sysadmin Blog
echo "[*] Mevcut kurallar temizleniyor..."
iptables -F
iptables -X
iptables -Z
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
echo "[*] Varsayılan politikalar ayarlanıyor..."
# Varsayılan politikayı DROP yap - her şeyi engelle
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
echo "[*] Loopback arayüzüne izin veriliyor..."
# Loopback (127.0.0.1) trafiğine her zaman izin ver
# Bu olmazsa pek çok servis çalışmaz
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
echo "[*] Mevcut bağlantılara izin veriliyor..."
# Kurulmuş ve ilgili bağlantılara izin ver
# Bu kural olmadan sunucudan gönderdiğiniz paketlerin dönüşü engellenir
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
echo "[*] SSH erişimi yapılandırılıyor..."
# SSH - dikkatli olun, yanlış port yazarsanız kilitlenirsiniz!
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
echo "[*] Web trafiğine izin veriliyor..."
# HTTP ve HTTPS
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
echo "[*] ICMP (ping) trafiği yapılandırılıyor..."
# Ping'e izin ver ama flood koruması ekle
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 5 -j ACCEPT
echo "[*] Güvenlik duvarı aktif!"
iptables -L -v -n
Gelişmiş Güvenlik Kuralları
Temel kurallar yeterli değil. Gerçek prodüksiyon ortamında karşılaştığınız saldırı türlerine karşı ek korumalar ekleyelim.
Kötü Niyetli Paketleri Engelleme
# Invalid (geçersiz) paketleri engelle
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# NULL paketleri engelle (port tarama tespiti)
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# SYN flood koruması
iptables -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
# XMAS paketleri engelle (Noel ağacı taraması)
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
# Fragmented paketleri engelle
iptables -A INPUT -f -j DROP
# Spoofed paketler için anti-spoofing kuralları
# Loopback adresinden gelen ama lo arayüzünde olmayan paketleri engelle
iptables -A INPUT ! -i lo -s 127.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
SSH Kaba Kuvvet Koruması
SSH’a karşı kaba kuvvet saldırıları çok yaygın. recent modülü ile belirli bir sürede çok fazla bağlantı kurmaya çalışanları engelleyebiliriz:
# SSH brute force koruması
# Son 60 saniye içinde 4'ten fazla bağlantı denemesi yapanı engelle
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set --name SSH_BRUTE
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 --name SSH_BRUTE -j DROP
# Bu kuralı kullanmak için önce SSH için ACCEPT kuralını kaldırın
# ve şu sıralamayı kullanın:
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
HTTP Flood Koruması
Web sunucusuna yönelik bağlantı bazlı saldırılara karşı:
# HTTP için bağlantı hızı sınırlaması
# Tek bir IP'den saniyede 25'ten fazla yeni HTTP bağlantısını engelle
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --dport 443 -m connlimit --connlimit-above 50 -j REJECT --reject-with tcp-reset
# SYN flood koruması için SYN paketlerine hız sınırı
iptables -A INPUT -p tcp --syn -m limit --limit 25/s --limit-burst 50 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
# Yeni HTTP bağlantılarını rate limiting ile kontrol et
iptables -N HTTP_RATELIMIT
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -j HTTP_RATELIMIT
iptables -A HTTP_RATELIMIT -m recent --set --name HTTP
iptables -A HTTP_RATELIMIT -m recent --update --seconds 10 --hitcount 20 --name HTTP -j DROP
iptables -A HTTP_RATELIMIT -j ACCEPT
Özel Zincirler ile Modüler Yapı
Büyük kural setlerini yönetmek için özel zincirler oluşturmak çok işe yarıyor. Bu yaklaşım hem okunabilirliği artırıyor hem de belirli kuralları kolayca açıp kapatmanıza olanak tanıyor:
#!/bin/bash
# Modüler firewall yapısı
# Özel zincirler oluştur
iptables -N BLACKLIST
iptables -N WHITELIST
iptables -N WEB_TRAFFIC
iptables -N SSH_PROTECT
iptables -N ANTI_SCAN
# Ana INPUT zincirine özel zincirlere yönlendirme ekle
iptables -A INPUT -j BLACKLIST
iptables -A INPUT -j WHITELIST
iptables -A INPUT -j ANTI_SCAN
iptables -A INPUT -j SSH_PROTECT
iptables -A INPUT -j WEB_TRAFFIC
# BLACKLIST zinciri - engellenen IP'ler
iptables -A BLACKLIST -s 192.168.100.50 -j DROP
iptables -A BLACKLIST -s 10.0.0.100 -j DROP
# Ülke bazlı engelleme için ipset ile birlikte kullanabilirsiniz
# WHITELIST zinciri - her zaman izin verilen IP'ler
# Örneğin ofis IP adresiniz
iptables -A WHITELIST -s 85.123.45.67 -j ACCEPT
# SSH_PROTECT zinciri
iptables -A SSH_PROTECT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set --name SSH_TRACK
iptables -A SSH_PROTECT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 300 --hitcount 10 --name SSH_TRACK -j DROP
iptables -A SSH_PROTECT -p tcp --dport 22 -j ACCEPT
# WEB_TRAFFIC zinciri
iptables -A WEB_TRAFFIC -p tcp --dport 80 -j ACCEPT
iptables -A WEB_TRAFFIC -p tcp --dport 443 -j ACCEPT
# ANTI_SCAN zinciri - port tarama engelleme
iptables -A ANTI_SCAN -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT
iptables -A ANTI_SCAN -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j DROP
Veritabanı ve Uygulama Sunucusu Erişimlerini Kısıtlama
Gerçek dünyada web sunucunuzun arkasında bir veritabanı sunucusu olabilir. Bu portlara erişimi sadece belirli IP’lerden kabul etmek şart:
# MySQL/MariaDB - sadece uygulama sunucusundan erişime izin ver
iptables -A INPUT -p tcp --dport 3306 -s 10.0.0.10 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP
# PostgreSQL - sadece belirli bir IP bloğundan
iptables -A INPUT -p tcp --dport 5432 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 5432 -j DROP
# Redis - sadece localhost ve uygulama sunucusu
iptables -A INPUT -p tcp --dport 6379 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -s 10.0.0.10 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP
# Elasticsearch - dışarıdan erişimi tamamen kapat
iptables -A INPUT -p tcp --dport 9200 -j DROP
iptables -A INPUT -p tcp --dport 9300 -j DROP
Kuralları Kalıcı Hale Getirme
iptables kuralları sistem yeniden başlatıldığında kaybolur. Kalıcı hale getirmek için:
# Ubuntu/Debian - iptables-persistent paketi ile
netfilter-persistent save
netfilter-persistent reload
# Manuel kaydetme yöntemi
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
# Kuralları geri yükleme
iptables-restore < /etc/iptables/rules.v4
# CentOS/RHEL 7+ - iptables-services ile
service iptables save
systemctl enable iptables
systemctl start iptables
# Systemd service dosyası oluşturarak her boot'ta yükleme
cat > /etc/systemd/system/iptables-restore.service << 'EOF'
[Unit]
Description=Restore iptables rules
Before=network.target
[Service]
Type=oneshot
ExecStart=/sbin/iptables-restore /etc/iptables/rules.v4
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable iptables-restore
Loglama ve İzleme
İyi bir güvenlik duvarı sessiz kalmamalı. Engellenen bağlantıları loglamak hem güvenlik analizi hem de sorun giderme için kritik:
# Engellenen paketleri logla
# LOG hedefi paketi loglar ama engellemez, DROP sonrasına değil öncesine koyulur
# Özel loglama zinciri oluştur
iptables -N LOGGING
iptables -A INPUT -j LOGGING
iptables -A LOGGING -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "[IPTABLES DROP] " --log-level 4
iptables -A LOGGING -j DROP
# SSH brute force girişimlerini ayrıca logla
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 --name SSH -j LOG --log-prefix "[SSH BRUTEFORCE] " --log-level 4
# Logları görüntüle
tail -f /var/log/syslog | grep IPTABLES
# veya
journalctl -f | grep IPTABLES
# Log rotasyonu için /etc/logrotate.d/iptables dosyası oluşturun
cat > /etc/logrotate.d/iptables << 'EOF'
/var/log/iptables.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
}
EOF
Kurallara Sorun Giderme
Bir şeyler ters gittiğinde paniklemeden önce şu adımları takip edin:
# Mevcut kuralları numaralarıyla listele
iptables -L INPUT -v -n --line-numbers
# Belirli bir kuralı numarasıyla sil (örnek: INPUT zincirinin 3. kuralı)
iptables -D INPUT 3
# Paket sayaçlarını sıfırla
iptables -Z
# Bağlantı takibini izle
conntrack -L
conntrack -E # canlı izleme
# Belirli bir porta gelen trafiği izle
iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix "[HTTP DEBUG] "
# Test ettikten sonra kuralı kaldırmayı unutmayın
# tüm kuralları geçici olarak devre dışı bırak (acil durum)
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F
Gerçek Dünya Senaryosu: Nginx + PHP-FPM Sunucusu
Tipik bir LAMP/LEMP stack için tam firewall konfigürasyonu:
#!/bin/bash
# production_webserver_firewall.sh
# LEMP Stack (Nginx + PHP-FPM + MySQL) için tam firewall
set -e
WEB_ADMIN_IP="85.123.45.67" # Yönetici IP adresi
APP_SERVER_IP="10.0.0.10" # Uygulama sunucusu
MONITORING_IP="10.0.0.20" # Monitoring sunucusu
echo "[1/8] Temizleniyor..."
iptables -F && iptables -X && iptables -Z
echo "[2/8] Varsayılan politikalar DROP..."
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
echo "[3/8] Temel kurallar..."
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
echo "[4/8] Yönetici erişimi..."
iptables -A INPUT -s $WEB_ADMIN_IP -p tcp --dport 22 -j ACCEPT
echo "[5/8] Web trafiği..."
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m limit --limit 100/s --limit-burst 200 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -m limit --limit 100/s --limit-burst 200 -j ACCEPT
echo "[6/8] Veritabanı erişimi..."
iptables -A INPUT -s $APP_SERVER_IP -p tcp --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP
echo "[7/8] Monitoring..."
iptables -A INPUT -s $MONITORING_IP -p tcp --dport 9100 -j ACCEPT # Node Exporter
iptables -A INPUT -s $MONITORING_IP -p icmp -j ACCEPT
echo "[8/8] Loglama ve kaydetme..."
iptables -A INPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[FW DROP] " --log-level 6
iptables -A INPUT -j DROP
iptables-save > /etc/iptables/rules.v4
echo "[TAMAMLANDI] Firewall aktif ve kaydedildi."
iptables -L -v -n
Sonuç
iptables ile web sunucusu güvenlik duvarı kurmak, bir kez doğru yaptığınızda size çok büyük güven veriyor. Özetlemek gerekirse kritik noktalar şunlar:
- Her zaman DEFAULT DROP politikasıyla başlayın. Yani her şey engellensin, sadece izin verdikleriniz geçsin.
- SSH için önce izin verin, sonra diğer kuralları ekleyin. Yoksa kendinizi kilitlersiniz.
- Kuralları script olarak yazın. Hem versiyon kontrolü yapabilirsiniz hem de sunucu yeniden başladığında kolayca uygulayabilirsiniz.
- Loglama ekleyin. Neyin engellendiğini bilmeden güvenlik duvarınızı iyileştiremezsiniz.
- Düzenli olarak test edin.
nmapile kendi sunucunuzu tarayarak açık portları ve güvenlik açıklarını kontrol edin. - Kuralları aşırı karmaşık yapmayın. Basit ama doğru kurallar, karmaşık ama yanlış kurallardan her zaman daha iyidir.
iptables günümüzde nftables ile birlikte kullanılıyor ve bazı distrolarda nftables artık varsayılan olarak geliyor. Ancak iptables hala yaygın olarak kullanılıyor ve bu mantığı öğrenmek sizi nftables‘a geçişe de hazırlıyor çünkü temel kavramlar neredeyse aynı. Bir sonraki adım olarak ipset ile dinamik kara listeler ve fail2ban entegrasyonuna bakmanızı öneririm.