MikroTik WireGuard VPN Kurulumu: Sunucu + Mobil/Laptop İstemci Pratik Rehberi
MikroTik üzerinde WireGuard VPN sunucusu adım adım kurulumu; telefon ve laptop istemci yapılandırması, QR kod, troubleshooting ve saha vakaları.
Devamını Oku →
WireGuard’ın ortaya çıkışı VPN dünyasında bir dönüm noktası oldu. OpenVPN’in TLS karmaşıklığı, IPsec’in IKE müzakere ağırlığı ve özellikle yıllar içinde birikmiş yamalı protokol tasarımları yerini; 4000 satırın altında kernel modülü, modern kriptografi ve son derece sade bir konfigürasyon felsefesiyle yeni bir paradigmaya bıraktı. Bu yazıda WireGuard’ı bir uygulama tutorial’ı olarak değil, protokolün iç işleyişi perspektifinden inceleyeceğiz. Noise framework, ChaCha20-Poly1305, crypto-routing, Linux kernel modülünün tasarımı ve MikroTik RouterOS 7.x üzerindeki implementasyonu bu yazının ana eksenidir.
Bir Linux sistem mühendisi olarak yıllarca OpenVPN ve strongSwan ile boğuştuktan sonra WireGuard’a geçtiğimde duyduğum his, Python yazan birinin Go’ya geçtiğinde hissettiğine benziyor: daha az satır, daha az olasılık, daha öngörülebilir davranış. Bu yazıyı bitirdiğinizde WireGuard’ı sadece “kurmuş” değil içeriden tanımış olacaksınız.
WireGuard’ın yaratıcısı Jason A. Donenfeld’in açıkça benimsediği felsefe şudur: “Vendor seçimleri yapmak, kullanıcıya seçim yükü bindirmemek”. OpenVPN ve IPsec’in birden fazla cipher suite, çoklu key exchange, çoklu auth backend desteklemesinin aksine WireGuard tek bir cipher kombinasyonuyla gelir, tek bir handshake mantığıyla çalışır. Bu yaklaşımın faydaları:
Bu felsefeyi anladığınızda WireGuard’ın neden “tek bir [Interface] ve [Peer] bloğu” ile yetindiğini, neden TLS olmadığını, neden DH parametresi sunmadığını da anlarsınız. Sade görünmesi gerçekten basit olduğu için değil; doğru basitleştirilmiş olduğu içindir.
WireGuard handshake’i Trevor Perrin tarafından tasarlanan Noise Protocol Framework‘ün özel bir varyantı olan Noise_IKpsk2 patterninin üzerine inşa edilmiştir. Bu paterni açmak istersek:
Handshake iki mesajdan oluşur: Initiation ve Response. Bu kadar. Kullanılan ilkel kriptografi yapı taşları:
Tipik bir handshake şu sırayı izler. Burada I = Initiator, R = Responder, S = Statik, E = Ephemeral anahtardır:
# Mesaj 1: I -> R
ephemeral_I = curve25519_generate()
ck = HASH("Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s")
ck = HKDF(ck, ephemeral_I.public)
shared = DH(ephemeral_I, R.static_public)
ck, k = HKDF(ck, shared)
encrypted_static_I = AEAD(k, 0, I.static_public, hash)
shared2 = DH(I.static, R.static_public)
ck, k2 = HKDF(ck, shared2)
encrypted_timestamp = AEAD(k2, 0, tai64n_now(), hash)
# Mesaj 2: R -> I
ephemeral_R = curve25519_generate()
ck = HKDF(ck, ephemeral_R.public)
ck = HKDF(ck, DH(ephemeral_R, ephemeral_I.public))
ck = HKDF(ck, DH(ephemeral_R, I.static_public))
ck, t, k3 = HKDF(ck, PSK)
encrypted_empty = AEAD(k3, 0, "", hash)
Bu iki mesajın sonunda her iki taraf bir transport key pair türetmiş olur. Asıl veri akışı bu anahtarlarla AEAD altında şifrelenir. Önemli bir nokta: handshake’in tamamı 148 bayt + 92 bayt’tan ibarettir. Toplam 240 bayt. OpenVPN TLS handshake’i 5-10 paket ve birkaç kilobayt sürer.
Her transport oturum maksimum 120 saniye veya 2^60 mesaja kadar geçerlidir. Bu süre dolmadan WireGuard otomatik olarak handshake’i tekrarlar (rekey). Replay attack koruması ise sabit boyutta sliding window (varsayılan 2048) ile sağlanır. Bu, IPsec’in Anti-Replay Window mantığına çok benzer ancak daha sade implemente edilmiştir.
Handshake mesajlarının doğrulanması ucuz olmadığından, WireGuard’a yapılacak yoğun handshake floodu kaynak tüketebilir. Bu durumda responder, initiator’a cookie mesajı gönderir. Initiator, sonraki handshake’lerinde bu cookie’yi MAC2 alanına ekler ve bu sayede responder pahalı DH işlemine başlamadan önce gerçek bir client olduğunu doğrular. Bu mekanizma DTLS-SRTP’deki cookie değişimine benzer ancak daha kompakttır.
WireGuard’ı diğer VPN’lerden ayıran teknik fikirlerin en güzeli crypto-routing‘dir. Klasik VPN’lerde “policy” ve “key” iki ayrı kavramdır: hangi trafik tünelden gidecek (selector/SAD) ve hangi anahtarla şifrelenecek (SAD’deki anahtar). WireGuard bu iki kavramı birleştirir.
Mantık şudur: Her peer’in bir AllowedIPs listesi vardır. Bu liste, hem outbound hem inbound trafik için çift yönlü çalışır.
AllowedIPs‘ine düşüyorsa o peer’in anahtarıyla şifrelenir ve o peer’in endpoint’ine gönderilir. Bu bir routing table lookup‘tan farksızdır.AllowedIPs‘inde yoksa paket düşürülür. Bu otomatik bir reverse-path filter‘dır.Bu basit kuralın getirisi büyüktür:
AllowedIPs‘iyle sınırlı; deceptive source IP spoofing imkânsız.Pratik bir örnek: hub-and-spoke topolojide hub’ın peer config’i şu şekildedir:
[Interface]
PrivateKey =
Address = 10.99.0.1/16
ListenPort = 51820
[Peer] # branch-01
PublicKey =
AllowedIPs = 10.99.1.0/24, 10.10.1.0/24
[Peer] # branch-02
PublicKey =
AllowedIPs = 10.99.2.0/24, 10.10.2.0/24
Hub’a düşen “10.10.2.5” hedefli paket otomatik olarak branch-02’nin anahtarıyla şifrelenir; başka bir peer’in trafiğine karışmaz. Bu, açıkça yazılmış statik route’lar gibi davranır ama aslında dinamik bir lookup’tır.
WireGuard’ın Linux 5.6’da mainline’a girmesi (Mart 2020) önemli bir milestone’du. Linus Torvalds bile “WireGuard’a aşkım var” tarzı bir mesaj yayınlamıştı. Kernel modülünün yapısı şöyledir:
İlginç tasarım kararları:
Modülü yüklemek artık birkaç satır:
# Linux 5.6+ kernel'inde yerleşik
modprobe wireguard
# Eski kernel'lerde DKMS ile
apt install wireguard-dkms wireguard-tools
# Kullanıcı alanı aracı
wg genkey | tee privatekey | wg pubkey > publickey
ip link add dev wg0 type wireguard
ip address add 10.99.0.1/24 dev wg0
wg setconf wg0 wg0.conf
ip link set up dev wg0
wireguard-tools paketindeki wg-quick betiği bu komutları otomatize eder ve sysctl + PostUp/PostDown hook’ları ekler. Production deployment’larında ben genelde wg-quick yerine doğrudan systemd-networkd .netdev + .network dosyaları kullanmayı tercih ediyorum; daha öngörülebilir.
Modern x86 CPU’lar AES-NI ile AES-GCM’i hardware accelerated yapar. Bu durumda AES-GCM, ChaCha20-Poly1305’ten 2-3x daha hızlı olabilir. Peki WireGuard neden AES yerine ChaCha tercih etti?
Pratik rakamlar (10 Gbit fiziksel, Xeon E5-2680 v4):
RouterOS 7.x ile birlikte WireGuard MikroTik’in standart enstrümanlarından biri haline geldi. CLI’de:
/interface/wireguard
add name=wg-corp listen-port=51820
private-key="cMtP...=" mtu=1420
/interface/wireguard/peers
add interface=wg-corp
public-key="aZQv...="
allowed-address=10.99.0.10/32,10.10.0.0/24
endpoint-address=peer.example.com endpoint-port=51820
persistent-keepalive=25s
/ip/address
add address=10.99.0.1/24 interface=wg-corp
/ip/route
# AllowedIPs zaten route oluşturur, ekstra rotaya genelde gerek yok
Önemli noktalar:
# /etc/wireguard/wg0.conf (Linux client tarafında)
[Interface]
PrivateKey =
Address = 10.99.0.10/24
DNS = 10.99.0.1
[Peer]
PublicKey =
Endpoint = router.example.com:51820
AllowedIPs = 10.99.0.0/24, 10.10.0.0/24
PersistentKeepalive = 25
wg-quick up wg0 ve bitti. Test:
# Tünel durumu
wg show wg0
# Latency
ping -c 5 10.99.0.1
# Bandwidth
iperf3 -c 10.99.0.1 -t 30 -P 4
WireGuard endpoint adresleri dinamiktir. Bir peer’in endpoint’i değiştiğinde (örneğin mobil cihaz WiFi’den 4G’ye geçtiğinde), WireGuard otomatik olarak yeni adresi öğrenir. Bunun mekanizması şudur: handshake mesajı geldiğinde, paketin geldiği UDP src adresi peer için yeni endpoint olarak kaydedilir. Bu işlem “endpoint discovery” değil “endpoint update” olarak çalışır; sessiz bir roaming.
NAT arkasındaki peer’ler için PersistentKeepalive = 25 seçeneği kritiktir. Her 25 saniyede bir küçük bir keepalive paketi gönderilerek NAT eşleştirmesinin (binding) düşmesi engellenir. 25 saniye değeri ampiriktir: çoğu carrier-grade NAT’ın binding timeout’u 30-60 saniye civarındadır.
wg genpsk ile üretip her peer için ayrı ayrı paylaşın.wg show all dump çıktısı parse edilerek Prometheus’a node_exporter textfile collector ile beslenebilir. Handshake yaşı, RX/TX byte sayaçları izlenebilir.AllowedIPs = ::/0 ile IPv6 trafiği de tünelden geçirilebilir. Çift stack ortamlarda DNS sızıntısını engellemek için fwmark + policy routing kullanın.dynamic_debug ile geçici tanılama yapılabilir: echo module wireguard +p > /sys/kernel/debug/dynamic_debug/controlÜretim ortamında WireGuard’ı izlemek için kullandığım küçük bir exporter snippet’i:
#!/usr/bin/env bash
# /usr/local/bin/wg-exporter.sh
OUT=/var/lib/node_exporter/textfile/wireguard.prom
echo "# HELP wg_peer_handshake_seconds Last handshake epoch" > $OUT.tmp
echo "# TYPE wg_peer_handshake_seconds gauge" >> $OUT.tmp
wg show all dump | awk 'NR>1 && NF>=8 {
iface=$1; peer=$2; hs=$6; rx=$7; tx=$8;
printf "wg_peer_handshake_seconds{iface="%s",peer="%s"} %sn", iface, peer, hs;
printf "wg_peer_rx_bytes{iface="%s",peer="%s"} %sn", iface, peer, rx;
printf "wg_peer_tx_bytes{iface="%s",peer="%s"} %sn", iface, peer, tx;
}' >> $OUT.tmp
mv $OUT.tmp $OUT
Bu script cron ile her 30 saniyede bir çalıştırılır; Prometheus node_exporter textfile collector tarafından scrape edilir. Grafana’da “handshake 180 saniyeden eski” alert’i kurarak sessizce kopan peer’leri yakalayabilirsiniz.
WireGuard’ı diğer VPN protokollerinden ayıran bir diğer özellik, akademik olarak formally verified olmasıdır. Tamarin Prover ile yapılan analiz (Donenfeld + Milner, 2018) WireGuard handshake’inin şu güvenlik özelliklerini matematiksel olarak kanıtlamıştır:
OpenVPN için karşılaştırılabilir kapsamlı bir formal proof bulunmamaktadır. IPsec’in IKEv2’si için zayıf bir formal model vardır ancak protokol kompleksitesi tam kapsamı zorlaştırmaktadır. Bu, akademik dünyada WireGuard’ın saygı kazanmasının temel nedenidir.
WireGuard sadece UDP destekler. TCP-over-TCP problemi (segment retransmission’ın hem tünel hem inner stream’de yaşanması) WireGuard’ın deliberately kaçındığı bir tasarım kararıdır. UDP-blokeli ortamlar için udp2raw, wstunnel veya AmneziaWG gibi obfuscation çözümleri kullanılabilir.
Tipik bir SME ortamı için: konfigürasyon migration 1-2 gün, peer paralel deployment 1 hafta, klimatize edilmiş cut-over 1 ay. Aralarında protocol farkı olmadığından, kullanıcı deneyimi açısından geçiş şeffaftır. Sadece istemci yazılımı değişir.
Hayır. Curve25519 Shor algoritması altında kuantum bilgisayar tarafından çözülebilir. Bu nedenle PresharedKey alanı sunulmuştur. Symmetric PSK kuantum saldırılarına karşı doğrudan direnç sağlar. NIST PQC standartlarının kernel-level entegrasyonu beklenirken, PSK ekleme önerilen yaklaşımdır.
Evet, ancak her peer’in tüm diğer peer’lerin public key’ini bilmesi gerekir. Bu manuel olarak çekilmez hale geldiğinde Headscale, Tailscale, Netbird veya Innernet gibi koordinatör araçlar devreye girer. Bunlar bir control plane sunar; peer’ler arasındaki anahtar dağıtımını otomatize eder.
RB5009 üzerinde ~1 Gbit/s, CCR2004 üzerinde ~3-4 Gbit/s typical. Aynı yapıdaki bir Linux server’da 8-10 Gbit/s mümkündür. MikroTik için software-only implementation darboğazdır; ARM çekirdeği üzerinde ChaCha20-Poly1305 yine de iyi performans verir ancak bir Xeon-D + AES-NI’nin gerisindedir.
WireGuard kendi başına HA sunmaz; stateless tasarımı sayesinde keepalived/VRRP ile aktif-pasif yapı kurulabilir. Endpoint adresinin bir floating IP’ye işaret etmesi ve config’in iki node arasında sync olması yeterlidir. Active-active için ECMP + birden fazla peer endpoint kullanılır.
Tamamen. Her peer’in kendine ait anahtarı vardır; kimlik kriptografik olarak doğrulanır; her bağlantı segment edilebilir (AllowedIPs ile). Headscale/Tailscale gibi koordinatörler ACL tabanlı micro-segmentation ekler; bu BeyondCorp tarzı bir zero-trust arc oluşturmak için yeterlidir.
WireGuard’ı sadece “modern VPN” diye geçiştirmek haksızlık olur. Protokol; kriptografi tasarımı, kernel implementasyonu ve crypto-routing kavramıyla VPN dünyasının on yıllık sorunlarına temiz cevaplar getirdi. Linux çekirdeğinde mainline olarak yer alması, MikroTik dahil tüm ana router platformlarına yayılması ve formal verification ile akademik onay kazanması onu yeni standart haline getirdi. Bir sonraki yazımızda WireGuard’ı Headscale ile mesh topolojide nasıl orkestre edeceğinizi ve adaptive firewall ile zero-trust ACL’leri nasıl ekleyeceğinizi inceleyeceğiz.
Konuyu daha geniş ele almak için aşağıdaki yazılarımıza da göz atabilirsiniz:
Bu yazıdaki konuları derinleştirmek için aşağıdaki otoriter kaynaklara başvurabilirsiniz:
WireGuard, Noise Protocol Framework tabanlı 1-RTT el sıkışmayla oturum kurar; kimlik sadece anahtarlarla doğrulanır.
| Peer public key | allowed-address | Anlamı |
|---|---|---|
| Peer A | 10.10.0.2/32 | Yalnız bu IP bu peer'a yönlenir |
| Peer B (site) | 10.10.0.3/32, 192.168.20.0/24 | Uzak şube subnet'i bu peer'dan geçer |
allowed-address hem yönlendirme tablosu hem de erişim kontrolü görevi görür. Entegrasyon için WireGuard VPN Hizmetimize bakın.