WireGuard ile Çoklu WAN Bağlantısında Yük Dengeleme ve Yedeklilik Yapılandırması
Birden fazla internet bağlantısı olan bir yapıda WireGuard çalıştırmak, kulağa karmaşık gelebilir ama doğru yapılandırıldığında hem yük dengeleme hem de kesintisiz çalışma için oldukça güçlü bir çözüm ortaya çıkıyor. Bu yazıda gerçek dünya senaryolarına dayanan bir çoklu WAN yapılandırmasını adım adım inceleyeceğiz.
Senaryo ve Altyapı Tanımı
Elimizde şu yapı olduğunu varsayalım: Bir merkez ofis (hub) ve buna bağlı şube ofisler. Merkez ofiste iki ayrı ISP bağlantısı var. Birincisi fiber 500 Mbps, ikincisi ADSL yedek hat olarak kullanılıyor. Şube ofislerden gelen VPN trafiğini her iki hat üzerinden dengelemek ve birisi çöktüğünde otomatik olarak diğerine geçmek istiyoruz.
Sunucu yapısı şu şekilde:
- WAN1:
203.0.113.1– Fiber hat (eth0) - WAN2:
198.51.100.1– ADSL hat (eth1) - WireGuard Arayüzü:
wg0–10.10.0.1/24 - İşletim Sistemi: Ubuntu 22.04 LTS
WireGuard Kurulumu ve Temel Yapılandırma
Önce WireGuard’ı kuralım ve anahtar çiftimizi oluşturalım.
apt update && apt install -y wireguard wireguard-tools
cd /etc/wireguard
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key
cat server_private.key
cat server_public.key
Şimdi çift WAN için temel WireGuard yapılandırmasını oluşturalım. Bu noktada kritik bir karar vermemiz gerekiyor: WireGuard her iki IP’de de dinleyecek mi, yoksa her hat için ayrı interface mi kullanacağız? Ben ayrı interface kullanmayı tercih ediyorum çünkü yönetimi çok daha temiz oluyor.
# wg0 - Fiber hat için (WAN1)
cat > /etc/wireguard/wg0.conf << 'EOF'
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
# Fiber hat üzerinden çıkış için policy routing tablosu
Table = off
PostUp = ip rule add from 10.10.0.0/24 table 100 priority 100
PostUp = ip route add default via 203.0.113.254 table 100
PostDown = ip rule del from 10.10.0.0/24 table 100
[Peer]
# Şube 1
PublicKey = <SUBE1_PUBLIC_KEY>
AllowedIPs = 10.10.0.2/32, 192.168.10.0/24
PersistentKeepalive = 25
[Peer]
# Şube 2
PublicKey = <SUBE2_PUBLIC_KEY>
AllowedIPs = 10.10.0.3/32, 192.168.20.0/24
PersistentKeepalive = 25
EOF
# wg1 - ADSL hat için (WAN2)
cat > /etc/wireguard/wg1.conf << 'EOF'
[Interface]
Address = 10.10.1.1/24
ListenPort = 51821
PrivateKey = <SERVER_PRIVATE_KEY>
Table = off
PostUp = ip rule add from 10.10.1.0/24 table 101 priority 101
PostUp = ip route add default via 198.51.100.254 table 101
PostDown = ip rule del from 10.10.1.0/24 table 101
[Peer]
# Şube 1 - yedek bağlantı
PublicKey = <SUBE1_PUBLIC_KEY>
AllowedIPs = 10.10.1.2/32, 192.168.10.0/24
PersistentKeepalive = 25
[Peer]
# Şube 2 - yedek bağlantı
PublicKey = <SUBE2_PUBLIC_KEY>
AllowedIPs = 10.10.1.3/32, 192.168.20.0/24
PersistentKeepalive = 25
EOF
Policy Routing ile Çoklu WAN Yapılandırması
Linux’ta çoklu WAN yönetiminin kalbi policy routing’dir. iproute2 ile her hat için ayrı routing tablosu oluşturacağız.
# /etc/iproute2/rt_tables dosyasına tablolarımızı ekleyelim
echo "100 wan1" >> /etc/iproute2/rt_tables
echo "101 wan2" >> /etc/iproute2/rt_tables
# WAN1 (Fiber) için routing tablosunu yapılandır
ip route add default via 203.0.113.254 dev eth0 table wan1
ip route add 203.0.113.0/24 dev eth0 src 203.0.113.1 table wan1
ip rule add from 203.0.113.1 table wan1 priority 100
# WAN2 (ADSL) için routing tablosunu yapılandır
ip route add default via 198.51.100.254 dev eth1 table wan2
ip route add 198.51.100.0/24 dev eth1 src 198.51.100.1 table wan2
ip rule add from 198.51.100.1 table wan2 priority 101
# Bu ayarları kalıcı yapmak için netplan veya /etc/network/interfaces kullanabilirsiniz
# Ubuntu 22.04 için netplan örneği:
cat > /etc/netplan/01-multiwan.yaml << 'EOF'
network:
version: 2
ethernets:
eth0:
addresses:
- 203.0.113.1/24
routes:
- to: default
via: 203.0.113.254
metric: 100
table: 100
routing-policy:
- from: 203.0.113.1
table: 100
priority: 100
eth1:
addresses:
- 198.51.100.1/24
routes:
- to: default
via: 198.51.100.254
metric: 200
table: 101
routing-policy:
- from: 198.51.100.1
table: 101
priority: 101
EOF
netplan apply
Yük Dengeleme için ECMP Yapılandırması
ECMP (Equal-Cost Multi-Path) routing ile gelen trafiği iki hat arasında dağıtabiliriz. Ancak WireGuard ile kullanırken dikkatli olmak gerekiyor, çünkü UDP bağlantılarının simetrik akması kritik.
# ECMP ile çift default route
ip route add default
nexthop via 203.0.113.254 dev eth0 weight 5
nexthop via 198.51.100.254 dev eth1 weight 1
# Bunu /etc/rc.local veya systemd service ile kalıcı hale getirin
cat > /etc/systemd/system/multiwan-routes.service << 'EOF'
[Unit]
Description=Multi-WAN Route Configuration
After=network.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/setup-multiwan.sh
ExecStop=/bin/true
[Install]
WantedBy=multi-user.target
EOF
cat > /usr/local/bin/setup-multiwan.sh << 'EOF'
#!/bin/bash
# Önce eski ECMP route'u temizle
ip route del default 2>/dev/null
# Fiber hat 5 birim ağırlık, ADSL 1 birim
ip route add default
nexthop via 203.0.113.254 dev eth0 weight 5
nexthop via 198.51.100.254 dev eth1 weight 1
# Policy routing tablolarını kur
ip route add default via 203.0.113.254 dev eth0 table wan1 2>/dev/null
ip route add default via 198.51.100.254 dev eth1 table wan2 2>/dev/null
ip rule add from 203.0.113.1 table wan1 priority 100 2>/dev/null
ip rule add from 198.51.100.1 table wan2 priority 101 2>/dev/null
EOF
chmod +x /usr/local/bin/setup-multiwan.sh
systemctl enable multiwan-routes
systemctl start multiwan-routes
Hat İzleme ve Otomatik Failover
İşte asıl iş bu noktada başlıyor. Hat düşüşlerini tespit edip otomatik geçiş yapacak bir script yazacağız. Bu scripti cron veya systemd timer ile her dakika çalıştırabiliriz.
cat > /usr/local/bin/wan-monitor.sh << 'EOF'
#!/bin/bash
# Yapılandırma
WAN1_GW="203.0.113.254"
WAN2_GW="198.51.100.254"
WAN1_DEV="eth0"
WAN2_DEV="eth1"
CHECK_HOST1="8.8.8.8"
CHECK_HOST2="1.1.1.1"
LOG_FILE="/var/log/wan-monitor.log"
STATE_FILE="/var/run/wan-state"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}
check_wan() {
local dev=$1
local gw=$2
# 3 kez dene, 2 saniye timeout
ping -I $dev -c 3 -W 2 -q $CHECK_HOST1 > /dev/null 2>&1 ||
ping -I $dev -c 3 -W 2 -q $CHECK_HOST2 > /dev/null 2>&1
return $?
}
get_state() {
cat $STATE_FILE 2>/dev/null || echo "both_up"
}
set_state() {
echo $1 > $STATE_FILE
}
current_state=$(get_state)
check_wan $WAN1_DEV $WAN1_GW
WAN1_UP=$?
check_wan $WAN2_DEV $WAN2_GW
WAN2_UP=$?
if [ $WAN1_UP -eq 0 ] && [ $WAN2_UP -eq 0 ]; then
if [ "$current_state" != "both_up" ]; then
log "Her iki hat da aktif - ECMP routing devreye aliniyor"
ip route del default 2>/dev/null
ip route add default
nexthop via $WAN1_GW dev $WAN1_DEV weight 5
nexthop via $WAN2_GW dev $WAN2_DEV weight 1
# wg0 ve wg1 her ikisi de aktif
wg-quick up wg0 2>/dev/null
wg-quick up wg1 2>/dev/null
set_state "both_up"
fi
elif [ $WAN1_UP -ne 0 ] && [ $WAN2_UP -eq 0 ]; then
if [ "$current_state" != "wan2_only" ]; then
log "UYARI: WAN1 (Fiber) DOWN - WAN2 (ADSL) uzerinden devam ediliyor"
ip route del default 2>/dev/null
ip route add default via $WAN2_GW dev $WAN2_DEV
# wg0'ı durdur, wg1 aktif kalsın
wg-quick down wg0 2>/dev/null
wg-quick up wg1 2>/dev/null
# Şubelere bildirim gönder (opsiyonel)
logger -t wan-monitor "WAN1 DOWN - Failover WAN2"
set_state "wan2_only"
fi
elif [ $WAN1_UP -eq 0 ] && [ $WAN2_UP -ne 0 ]; then
if [ "$current_state" != "wan1_only" ]; then
log "UYARI: WAN2 (ADSL) DOWN - WAN1 (Fiber) uzerinden devam ediliyor"
ip route del default 2>/dev/null
ip route add default via $WAN1_GW dev $WAN1_DEV
wg-quick up wg0 2>/dev/null
wg-quick down wg1 2>/dev/null
set_state "wan1_only"
fi
else
log "KRITIK: Her iki hat da DOWN!"
set_state "both_down"
fi
EOF
chmod +x /usr/local/bin/wan-monitor.sh
# Systemd timer ile her 30 saniyede bir çalıştır
cat > /etc/systemd/system/wan-monitor.service << 'EOF'
[Unit]
Description=WAN Monitor Check
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/wan-monitor.sh
EOF
cat > /etc/systemd/system/wan-monitor.timer << 'EOF'
[Unit]
Description=WAN Monitor Timer
After=network.target
[Timer]
OnBootSec=60
OnUnitActiveSec=30s
[Install]
WantedBy=timers.target
EOF
systemctl enable wan-monitor.timer
systemctl start wan-monitor.timer
Şube Tarafı Yapılandırması
Şube ofislerde WireGuard istemcisinin her iki WAN IP’sini bilmesi gerekiyor. Bu noktada wg-quick ile birden fazla endpoint tanımlamak doğrudan mümkün değil, ama bir endpoint değişim scripti yazabiliriz.
# Şube 1 - Birincil bağlantı (WAN1 üzerinden)
cat > /etc/wireguard/wg0.conf << 'EOF'
[Interface]
Address = 10.10.0.2/24
PrivateKey = <SUBE1_PRIVATE_KEY>
DNS = 10.10.0.1
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = 203.0.113.1:51820
AllowedIPs = 10.10.0.0/24, 192.168.0.0/16
PersistentKeepalive = 25
EOF
# Şube tarafında endpoint kontrolü ve değiştirme scripti
cat > /usr/local/bin/wg-endpoint-check.sh << 'EOF'
#!/bin/bash
PRIMARY_ENDPOINT="203.0.113.1:51820"
SECONDARY_ENDPOINT="198.51.100.1:51821"
PEER_PUBKEY="<SERVER_PUBLIC_KEY>"
WG_IFACE="wg0"
LOG="/var/log/wg-endpoint.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG
}
# Mevcut handshake zamanını kontrol et
LAST_HANDSHAKE=$(wg show $WG_IFACE latest-handshakes | awk '{print $2}')
NOW=$(date +%s)
ELAPSED=$((NOW - LAST_HANDSHAKE))
# 3 dakikadan uzun süredir handshake yoksa endpoint değiştir
if [ $ELAPSED -gt 180 ]; then
CURRENT=$(wg show $WG_IFACE endpoints | grep $PEER_PUBKEY | awk '{print $2}')
if [ "$CURRENT" = "$PRIMARY_ENDPOINT" ]; then
log "Primary endpoint yanıt vermiyor, secondary'e geçiliyor: $SECONDARY_ENDPOINT"
wg set $WG_IFACE peer $PEER_PUBKEY endpoint $SECONDARY_ENDPOINT
else
log "Secondary endpoint deneniyor, primary'e geçiliyor: $PRIMARY_ENDPOINT"
wg set $WG_IFACE peer $PEER_PUBKEY endpoint $PRIMARY_ENDPOINT
fi
fi
EOF
chmod +x /usr/local/bin/wg-endpoint-check.sh
Firewall ve NAT Yapılandırması
Çoklu WAN yapısında iptables kuralları doğru yazılmazsa asimetrik routing sorunları yaşanır.
cat > /usr/local/bin/setup-firewall.sh << 'EOF'
#!/bin/bash
# Temel ileri yönlendirme
echo 1 > /proc/sys/net/ipv4/ip_forward
# Kalıcı hale getir
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/99-wireguard.conf
sysctl -p /etc/sysctl.d/99-wireguard.conf
# iptables kurallarını temizle
iptables -F
iptables -t nat -F
iptables -t mangle -F
# WireGuard portlarını aç
iptables -A INPUT -p udp --dport 51820 -j ACCEPT
iptables -A INPUT -p udp --dport 51821 -j ACCEPT
# WireGuard arayüzleri arasında forward izni
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -i wg1 -j ACCEPT
iptables -A FORWARD -o wg0 -j ACCEPT
iptables -A FORWARD -o wg1 -j ACCEPT
# WAN1 için NAT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# WAN2 için NAT
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
# Asimetrik routing sorununu önlemek için connection tracking ile source routing
iptables -t mangle -A PREROUTING -i eth0 -j CONNMARK --set-mark 1
iptables -t mangle -A PREROUTING -i eth1 -j CONNMARK --set-mark 2
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m connmark --mark 1 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -m connmark --mark 2 -j MARK --set-mark 2
# Mark'a göre routing tablosu seç
ip rule add fwmark 1 table wan1 priority 90 2>/dev/null
ip rule add fwmark 2 table wan2 priority 91 2>/dev/null
# Kuralları kaydet
iptables-save > /etc/iptables/rules.v4
EOF
chmod +x /usr/local/bin/setup-firewall.sh
bash /usr/local/bin/setup-firewall.sh
İzleme ve Durum Takibi
Yapılandırmanızın sağlıklı çalışıp çalışmadığını düzenli olarak kontrol etmeniz gerekiyor. Bunun için birkaç kullanışlı komut ve bir durum özeti scripti yazalım.
# Anlık durum özeti scripti
cat > /usr/local/bin/wan-status.sh << 'EOF'
#!/bin/bash
echo "========== WAN DURUM RAPORU =========="
echo "Tarih: $(date)"
echo ""
echo "--- Aktif Routing Tablosu ---"
ip route show
echo ""
echo "--- WAN1 (Fiber) WireGuard Durumu ---"
wg show wg0 2>/dev/null || echo "wg0 aktif degil"
echo ""
echo "--- WAN2 (ADSL) WireGuard Durumu ---"
wg show wg1 2>/dev/null || echo "wg1 aktif degil"
echo ""
echo "--- Peer Handshake Zamanlari ---"
for iface in wg0 wg1; do
echo "[$iface]"
wg show $iface latest-handshakes 2>/dev/null | while read peer ts; do
elapsed=$(( $(date +%s) - ts ))
echo " Peer: ${peer:0:12}... - Son handshake: ${elapsed}s once"
done
done
echo ""
echo "--- Baglanti Testi ---"
echo -n "WAN1 (8.8.8.8 via eth0): "
ping -I eth0 -c 2 -W 2 -q 8.8.8.8 > /dev/null 2>&1 && echo "OK" || echo "FAIL"
echo -n "WAN2 (8.8.8.8 via eth1): "
ping -I eth1 -c 2 -W 2 -q 8.8.8.8 > /dev/null 2>&1 && echo "OK" || echo "FAIL"
echo ""
echo "--- Son 10 WAN Monitor Logu ---"
tail -10 /var/log/wan-monitor.log 2>/dev/null
echo "======================================"
EOF
chmod +x /usr/local/bin/wan-status.sh
Durum raporunu çalıştırmak için:
bash /usr/local/bin/wan-status.sh
Sık Karşılaşılan Sorunlar ve Çözümleri
Gerçek ortamlarda bu yapıyı kurarken şu sorunlarla karşılaşabilirsiniz:
Asimetrik routing: Paket eth0’dan gelip eth1’den çıkıyor ve yanıt dönmüyor. Bunun çözümü yukarıdaki iptables connmark kurallarıdır. Ekledikten sonra conntrack -L ile bağlantıları inceleyebilirsiniz.
WireGuard handshake başarısız: wg show komutunda latest-handshakes sütununda çok eski bir zaman görüyorsanız, önce tcpdump -i eth0 udp port 51820 ile paketin interface’e ulaşıp ulaşmadığını kontrol edin.
ECMP ile UDP bağlantısı kopuyor: Linux kernel varsayılan olarak UDP akışlarını 5-tuple’a göre hash’ler, ama bazı sürümlerde sorun çıkabilir. net.ipv4.fib_multipath_hash_policy=1 sysctl parametresini aktif edin.
- net.ipv4.fib_multipath_hash_policy=1: Kaynak ve hedef port dahil 5-tuple hash kullanır
- net.ipv4.fib_multipath_use_neigh=1: Erişilemeyen next-hop’ları ECMP’den otomatik çıkarır
- PersistentKeepalive = 25: NAT arkasındaki peer’lar için bağlantıyı canlı tutar
# Bu parametreleri kalıcı hale getirelim
cat >> /etc/sysctl.d/99-wireguard.conf << 'EOF'
net.ipv4.fib_multipath_hash_policy = 1
net.ipv4.fib_multipath_use_neigh = 1
net.core.rps_sock_flow_entries = 32768
EOF
sysctl -p /etc/sysctl.d/99-wireguard.conf
Gerçek Dünya Notları
Bir müşteri ortamında bu yapıyı devreye alırken şunu öğrendim: ISP’lerin modem/router’ları bazen default gateway olarak değil, NAT arkasında çalışıyor. Bu durumda WireGuard’ın gerçek public IP’yi görmesi için Endpoint adresini elle doğru girilmesi gerekiyor. curl -s --interface eth0 ifconfig.me komutu ile hangi public IP’den göründüğünüzü test edin.
Yük dengeleme ağırlıklarını belirlerken bant genişliği oranını değil, gecikme ve paket kaybı oranını dikkate alın. 500 Mbps fiber’in 5 birim, 10 Mbps ADSL’in 1 birim alması mantıklı görünüyor ama ADSL’in latency’si yüksekse yük dengeleme yerine sadece yedek olarak tutmak daha iyi bir fikir olabilir. mtr --report --interface eth1 8.8.8.8 ile her hat için gerçekçi ölçüm yapın.
wg-quick yerine systemd-networkd ve wg komutlarını doğrudan kullanmayı da değerlendirin, özellikle çok sayıda peer ve interface yönetiminde daha esnek bir yapı sunuyor.
Sonuç
WireGuard ile çoklu WAN yapılandırması, görünürde birçok farklı katmanı bir arada yönetmeyi gerektiriyor: policy routing, iptables, WireGuard konfigürasyonu ve izleme scriptleri. Ama her katmanı ayrı ayrı anladıktan sonra bunları bir araya getirmek oldukça sistematik bir hal alıyor.
Temel prensip şu: Linux’un kendi routing altyapısını eksiksiz kullan, WireGuard’ı sadece şifreleme katmanı olarak düşün. ECMP ve policy routing WireGuard’dan bağımsız çalışıyor, bu yüzden önce bu katmanı sağlamlaştırın, sonra WireGuard interface’lerini üstüne oturtun.
Failover süresini minimize etmek istiyorsanız izleme aralığını 30 saniyenin altına indirmekten kaçının, çünkü agresif ping kontrolleri bazen kendisi bir sorun kaynağına dönüşebilir. 30-60 saniyelik bir failover süresi çoğu kurumsal kullanım için kabul edilebilir bir değer.
