Birden fazla internet bağlantısı yönetmek, özellikle küçük ve orta ölçekli işletmelerde hem bant genişliği optimizasyonu hem de yüksek erişilebilirlik açısından kritik bir ihtiyaç haline geldi. iptables bu işi yapmak için her ne kadar tek başına yeterli olmasa da, iproute2 araçlarıyla birlikte çalıştığında gerçekten güçlü bir çoklu WAN çözümü ortaya çıkıyor. Bu yazıda sıfırdan bir çoklu WAN yapısı kuracak, yük dengelemeyi devreye alacak ve en sık karşılaşılan sorunları nasıl çözeceğini göreceğiz.
Temel Kavramlar ve Senaryo
Önce ne yapmak istediğimizi netleştirelim. Elimizde şu ortam var:
- eth0: LAN arayüzü, 192.168.1.1/24
- eth1: ISP-1 (Türk Telekom fiber), 203.0.113.2/30, gateway 203.0.113.1
- eth2: ISP-2 (kablo internet), 198.51.100.2/30, gateway 198.51.100.1
Hedefimiz:
- Gelen trafiği her iki bağlantı üzerinden dengelemek
- Bir bağlantı düştüğünde otomatik olarak diğerine geçmek
- Belirli servisleri (örneğin VoIP) hep aynı bağlantı üzerinden göndermek
- NAT ve firewall kurallarını doğru şekilde uygulamak
Linux çekirdeğinin yük dengeleme mekanizması iptables’tan değil, ip route komutunun nexthop özelliğinden gelir. iptables ise bu yapının üstüne NAT, MARK ve politika tabanlı yönlendirme kurallarını ekler. İkisi birlikte çalışınca gerçek bir kurumsal çözüm elde ediyoruz.
Sistem Hazırlığı
Önce gerekli modüllerin yüklü olduğunu kontrol edelim:
# Gerekli kernel modüllerini yükle
modprobe ip_tables
modprobe iptable_nat
modprobe ip_conntrack
modprobe xt_mark
modprobe xt_multiport
# Modüllerin yüklü olduğunu doğrula
lsmod | grep -E "ip_tables|xt_mark|ip_conntrack"
# IP forwarding'i etkinleştir
echo 1 > /proc/sys/net/ipv4/ip_forward
# Kalıcı hale getir
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.rp_filter = 0" >> /etc/sysctl.conf
echo "net.ipv4.conf.eth1.rp_filter = 0" >> /etc/sysctl.conf
echo "net.ipv4.conf.eth2.rp_filter = 0" >> /etc/sysctl.conf
sysctl -p
rp_filter’ı neden kapatıyoruz? Reverse path filtering, bir paketi aldığı arayüzden yanıt verilmesini bekler. Çoklu WAN’da paket eth1’den gelip eth2’den çıkabilir, bu durum rp_filter açıkken paketlerin düşürülmesine yol açar.
iproute2 ile Politika Tabanlı Yönlendirme
Bu adım iptables ile birlikte çalışacak olan yönlendirme tablolarını kurar. Linux’ta 255 ayrı yönlendirme tablosu tanımlayabilirsiniz.
# /etc/iproute2/rt_tables dosyasına özel tablolar ekle
echo "100 isp1" >> /etc/iproute2/rt_tables
echo "200 isp2" >> /etc/iproute2/rt_tables
# ISP-1 tablosunu yapılandır
ip route add 203.0.113.0/30 dev eth1 src 203.0.113.2 table isp1
ip route add default via 203.0.113.1 table isp1
# ISP-2 tablosunu yapılandır
ip route add 198.51.100.0/30 dev eth2 src 198.51.100.2 table isp2
ip route add default via 198.51.100.1 table isp2
# Ana yönlendirme tablosuna her iki ISP rotasını ekle
ip route add 203.0.113.0/30 dev eth1 src 203.0.113.2
ip route add 198.51.100.0/30 dev eth2 src 198.51.100.2
# Yük dengeleme için multipath default route
# weight değerleri bant genişliğine göre ayarlanabilir
ip route add default
nexthop via 203.0.113.1 dev eth1 weight 1
nexthop via 198.51.100.1 dev eth2 weight 1
Buradaki weight parametresi önemli. 100 Mbps fiber ve 50 Mbps kablo bağlantın varsa weight değerlerini sırasıyla 2 ve 1 yaparak bant genişliğiyle orantılı dağıtım sağlayabilirsin.
Politika Kuralları (ip rule)
Kaynak IP’ye göre hangi tablonun kullanılacağını belirleyen kurallar:
# ISP-1 IP'sinden gelen yanıtlar ISP-1 üzerinden gitsin
ip rule add from 203.0.113.2 table isp1 priority 100
ip rule add from 198.51.100.2 table isp2 priority 200
# Firewall mark'larına göre yönlendirme (sonraki adımda iptables ile entegre)
ip rule add fwmark 0x1 table isp1 priority 300
ip rule add fwmark 0x2 table isp2 priority 400
# Kuralları listele
ip rule show
iptables NAT Kuralları
Şimdi asıl kritik kısma geliyoruz. Her iki arayüz için ayrı NAT kuralları tanımlamalıyız:
#!/bin/bash
# /etc/firewall/multiwan.sh
# Değişkenler
LAN_IF="eth0"
ISP1_IF="eth1"
ISP2_IF="eth2"
LAN_NET="192.168.1.0/24"
ISP1_IP="203.0.113.2"
ISP2_IP="198.51.100.2"
ISP1_GW="203.0.113.1"
ISP2_GW="198.51.100.1"
# Mevcut kuralları temizle
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X
iptables -t nat -X
iptables -t mangle -X
# Default politikalar
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Loopback trafiğine izin ver
iptables -A INPUT -i lo -j ACCEPT
# Established/related bağlantılara izin ver
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# LAN'dan WAN'a yönlendirme
iptables -A FORWARD -i $LAN_IF -o $ISP1_IF -j ACCEPT
iptables -A FORWARD -i $LAN_IF -o $ISP2_IF -j ACCEPT
# ISP-1 üzerinden NAT (MASQUERADE yerine SNAT daha verimli çalışır)
iptables -t nat -A POSTROUTING -o $ISP1_IF -j SNAT --to-source $ISP1_IP
iptables -t nat -A POSTROUTING -o $ISP2_IF -j SNAT --to-source $ISP2_IP
echo "NAT kuralları uygulandı"
MASQUERADE ile SNAT arasındaki fark: MASQUERADE her paket için arayüzün IP’sini dinamik olarak sorgular. SNAT sabit IP belirttiği için çok daha hızlı çalışır. Statik IP adresleriniz varsa her zaman SNAT tercih edin.
Mangle Tablosu ile Trafik İşaretleme
Bu bölüm gerçek sihrin yaşandığı yer. mangle tablosu paketleri işaretleyerek iproute2’nin onları doğru tabloya yönlendirmesini sağlar:
# mangle tablosu kuralları - aynı script içine ekle
# Bağlantı takibi ile mevcut oturumları koru
# Bir bağlantı hangi ISP üzerinden başladıysa orada kalsın
iptables -t mangle -A PREROUTING -m conntrack --ctstate ESTABLISHED,RELATED
-j CONNMARK --restore-mark
# Yeni bağlantıları yük dengeleme için işaretle
# Statistic modülü ile round-robin dağıtım
iptables -t mangle -A PREROUTING -i $LAN_IF
-m conntrack --ctstate NEW
-m statistic --mode nth --every 2 --packet 0
-j MARK --set-mark 0x1
iptables -t mangle -A PREROUTING -i $LAN_IF
-m conntrack --ctstate NEW
-m mark --mark 0x0
-j MARK --set-mark 0x2
# Mark'ları bağlantıya kaydet (sonraki paketlere de uygulanması için)
iptables -t mangle -A PREROUTING -i $LAN_IF
-m conntrack --ctstate NEW
-j CONNMARK --save-mark
echo "Mangle kuralları uygulandı"
Servis Bazlı Yönlendirme
Gerçek dünya senaryolarında bazı servislerin hep aynı bağlantıdan gitmesi gerekir. Örneğin VoIP için düşük gecikmeli bağlantıyı, büyük dosya transferleri için yüksek bantlı bağlantıyı kullanmak:
# VoIP trafiğini (SIP ve RTP) her zaman ISP-1'den gönder
# ISP-1 daha düşük gecikme süresi sunuyor
VOIP_SUBNET="192.168.1.50/32" # VoIP sunucusu
SIP_PORT="5060"
RTP_LOW="10000"
RTP_HIGH="20000"
# SIP trafiğini işaretle
iptables -t mangle -A PREROUTING -i $LAN_IF
-s $VOIP_SUBNET
-p udp --dport $SIP_PORT
-j MARK --set-mark 0x1
# RTP trafiğini işaretle
iptables -t mangle -A PREROUTING -i $LAN_IF
-s $VOIP_SUBNET
-p udp --dport $RTP_LOW:$RTP_HIGH
-j MARK --set-mark 0x1
# CONNMARK ile oturumu kaydet
iptables -t mangle -A PREROUTING -i $LAN_IF
-s $VOIP_SUBNET
-j CONNMARK --save-mark
# Yönetim trafiğini (SSH, RDP) ISP-2'den gönder
MGMT_SUBNET="192.168.1.100/28"
iptables -t mangle -A PREROUTING -i $LAN_IF
-s $MGMT_SUBNET
-p tcp -m multiport --dports 22,3389
-j MARK --set-mark 0x2
iptables -t mangle -A PREROUTING -i $LAN_IF
-s $MGMT_SUBNET
-p tcp -m multiport --dports 22,3389
-j CONNMARK --save-mark
echo "Servis bazlı yönlendirme kuralları uygulandı"
Failover: Otomatik Bağlantı Değişimi
Yük dengeleme güzel ama bir bağlantı düştüğünde sistem ne yapacak? Basit bir monitoring scripti ile bunu otomatikleştirebiliriz:
#!/bin/bash
# /usr/local/bin/wan-monitor.sh
ISP1_GW="203.0.113.1"
ISP2_GW="198.51.100.1"
ISP1_IF="eth1"
ISP2_IF="eth2"
ISP1_IP="203.0.113.2"
ISP2_IP="198.51.100.2"
LOG_FILE="/var/log/wan-monitor.log"
PING_COUNT=3
PING_TIMEOUT=2
# Bağlantı durumu dosyaları
ISP1_STATUS="/tmp/isp1_status"
ISP2_STATUS="/tmp/isp2_status"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}
check_connection() {
local gw=$1
local iface=$2
ping -c $PING_COUNT -W $PING_TIMEOUT -I $iface $gw > /dev/null 2>&1
return $?
}
update_routes() {
local isp1_up=$1
local isp2_up=$2
# Mevcut default route'u kaldır
ip route del default 2>/dev/null
if [ "$isp1_up" = "1" ] && [ "$isp2_up" = "1" ]; then
log "Her iki ISP aktif - yük dengeleme modu"
ip route add default
nexthop via $ISP1_GW dev $ISP1_IF weight 1
nexthop via $ISP2_GW dev $ISP2_IF weight 1
elif [ "$isp1_up" = "1" ]; then
log "Sadece ISP-1 aktif"
ip route add default via $ISP1_GW dev $ISP1_IF
elif [ "$isp2_up" = "1" ]; then
log "Sadece ISP-2 aktif"
ip route add default via $ISP2_GW dev $ISP2_IF
else
log "KRITIK: Her iki ISP de erişilemez durumda!"
fi
}
# Ana döngü
ISP1_PREV=""
ISP2_PREV=""
while true; do
if check_connection $ISP1_GW $ISP1_IF; then
ISP1_CURRENT="1"
else
ISP1_CURRENT="0"
fi
if check_connection $ISP2_GW $ISP2_IF; then
ISP2_CURRENT="1"
else
ISP2_CURRENT="0"
fi
# Durum değişikliği var mı?
if [ "$ISP1_CURRENT" != "$ISP1_PREV" ] || [ "$ISP2_CURRENT" != "$ISP2_PREV" ]; then
log "Durum değişikliği tespit edildi: ISP1=$ISP1_CURRENT, ISP2=$ISP2_CURRENT"
update_routes $ISP1_CURRENT $ISP2_CURRENT
ISP1_PREV=$ISP1_CURRENT
ISP2_PREV=$ISP2_CURRENT
fi
sleep 10
done
Bu scripti systemd servisi olarak çalıştıralım:
# /etc/systemd/system/wan-monitor.service
cat > /etc/systemd/system/wan-monitor.service << 'EOF'
[Unit]
Description=WAN Baglanti Izleme ve Failover
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/wan-monitor.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
chmod +x /usr/local/bin/wan-monitor.sh
systemctl daemon-reload
systemctl enable wan-monitor
systemctl start wan-monitor
Güvenlik Duvarı Kurallarını Tamamlama
Çoklu WAN yapısında güvenlik kuralları biraz farklı düşünülmeli. Her iki arayüz için de gelen bağlantıları filtrelemek gerekiyor:
# Her iki WAN arayüzünden gelen istenmeyen trafiği engelle
for IF in $ISP1_IF $ISP2_IF; do
# Spoofed LAN adreslerini engelle
iptables -A INPUT -i $IF -s 192.168.0.0/16 -j DROP
iptables -A INPUT -i $IF -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i $IF -s 172.16.0.0/12 -j DROP
# ICMP flood koruması
iptables -A INPUT -i $IF -p icmp
-m limit --limit 5/second --limit-burst 10 -j ACCEPT
iptables -A INPUT -i $IF -p icmp -j DROP
# SYN flood koruması
iptables -A INPUT -i $IF -p tcp --syn
-m limit --limit 20/second --limit-burst 30 -j ACCEPT
iptables -A INPUT -i $IF -p tcp --syn -j DROP
# Port scan tespiti
iptables -A INPUT -i $IF -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -i $IF -p tcp --tcp-flags ALL ALL -j DROP
done
# SSH sadece ISP-1'den kabul et (yönetim erişimi)
iptables -A INPUT -i $ISP1_IF -p tcp --dport 22
-m conntrack --ctstate NEW
-m recent --set --name SSH_BRUTE
iptables -A INPUT -i $ISP1_IF -p tcp --dport 22
-m conntrack --ctstate NEW
-m recent --update --seconds 60 --hitcount 4 --name SSH_BRUTE
-j DROP
iptables -A INPUT -i $ISP1_IF -p tcp --dport 22 -j ACCEPT
Yapılandırmayı Kalıcı Hale Getirme
iptables kuralları reboot sonrası kaybolur. Kalıcı hale getirmenin en temiz yolu iptables-save ve systemd kombinasyonu:
# Mevcut kuralları kaydet
iptables-save > /etc/iptables/rules.v4
ip route save > /etc/iproute2/rt_rules.backup
# Systemd ile yükleme servisi
cat > /etc/systemd/system/iptables-restore.service << 'EOF'
[Unit]
Description=iptables Kural Yukleme
Before=network.target
[Service]
Type=oneshot
ExecStart=/sbin/iptables-restore /etc/iptables/rules.v4
ExecStart=/usr/local/bin/multiwan-routes.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
# iproute2 kuralları için ayrı script
cat > /usr/local/bin/multiwan-routes.sh << 'EOF'
#!/bin/bash
# Politika tabloları ve kuralları yükle
ip route add 203.0.113.0/30 dev eth1 src 203.0.113.2 table isp1
ip route add default via 203.0.113.1 table isp1
ip route add 198.51.100.0/30 dev eth2 src 198.51.100.2 table isp2
ip route add default via 198.51.100.1 table isp2
ip rule add from 203.0.113.2 table isp1 priority 100
ip rule add from 198.51.100.2 table isp2 priority 200
ip rule add fwmark 0x1 table isp1 priority 300
ip rule add fwmark 0x2 table isp2 priority 400
ip route add default
nexthop via 203.0.113.1 dev eth1 weight 1
nexthop via 198.51.100.1 dev eth2 weight 1
EOF
chmod +x /usr/local/bin/multiwan-routes.sh
systemctl enable iptables-restore
Sorun Giderme ve İzleme
Bir şeyler ters gittiğinde nereye bakacağını bilmek çok önemli:
# Aktif bağlantı sayısını ISP'ye göre gör
iptables -t mangle -L PREROUTING -n -v | grep -E "mark|MARK"
# Yönlendirme tablolarını kontrol et
ip route show table isp1
ip route show table isp2
ip route show table main
# Politika kurallarını listele
ip rule show
# Belirli bir kaynaktan paketin hangi yolu izleyeceğini test et
ip route get 8.8.8.8 from 192.168.1.10 iif eth0
# Bağlantı takibini izle
conntrack -L | grep -E "ESTABLISHED" | wc -l
# Her arayüzden geçen trafik miktarı
watch -n 2 "ip -s link show eth1; ip -s link show eth2"
# NAT tablosunu kontrol et
iptables -t nat -L POSTROUTING -n -v
# Mangle tablısundaki işaretli paketler
iptables -t mangle -L -n -v --line-numbers
Sık Karşılaşılan Sorunlar
Asimetrik yönlendirme problemi: Paket eth1’den gelip eth2’den yanıt vermeye çalışıyorsa bağlantı kesilir. Çözüm: Her ISP için ayrı politika tablosu ve ip rule ile kaynak IP’ye göre tablo seçimi, yukarda tam olarak bunun için yapıldı.
CONNMARK kaybı: Sistem yeniden başladığında mevcut bağlantılar yeni mark almak zorunda kalır. Bu geçici bir kargaşa yaratır ama yeni bağlantılar oluştukça düzelir.
NAT bağlantılarının ISP değiştirmesi: Bir bağlantı ISP-1 üzerinden başladıktan sonra ISP-2’ye geçerse NAT tablosundaki kayıt geçersiz kalır. CONNMARK –restore-mark kullanımı bu sorunu büyük ölçüde giderir.
weight ile adil dağıtım yapılmaması: Linux çekirdeği multipath route kararını flow hash’e göre verir, paket bazında değil. Bu aslında iyi bir şey çünkü aynı bağlantının paketleri aynı yoldan gider. Ama bazı durumlarda dağıtım eşitsiz görünebilir.
Sonuç
iptables ve iproute2 kombinasyonu, ticari çözümlerle boy ölçüşebilecek bir çoklu WAN altyapısı kurmanı sağlar. Burada anlattığımız yapı; yük dengeleme, otomatik failover, servis bazlı yönlendirme ve güvenlik duvarı özelliklerini tek bir Linux kutusunda birleştiriyor.
Kurulumun en kritik noktaları şunlar: rp_filter’ı doğru kapatmak, her ISP için ayrı yönlendirme tablosu kullanmak, CONNMARK ile oturum bütünlüğünü korumak ve wan-monitor scriptiyle failover’ı otomatikleştirmek. Bu dört noktayı doğru kurarsanız gerisi neredeyse kendi kendine çalışır.
Üretim ortamına almadan önce her adımı test ortamında dene. Özellikle failover senaryolarını elle simüle et; bir arayüzü ip link set eth1 down ile kapat ve sistemin nasıl davrandığını gözlemle. Sistemin beklenen şekilde tepki verdiğini gördükten sonra canlı ortama geçebilirsin.