Ringkasan

WireGuard adalah protokol VPN modern yang dirancang dengan prinsip minimalis: hanya ~4.000 baris kode vs OpenVPN ~600.000 baris. Keamanannya berasal dari kriptografi modern (Noise_IK, Curve25519, BLAKE2, ChaCha20Poly1305) dan attack surface yang diminimalkan. Catatan ini membahas protocol internals, handshake flow, kernel vs userspace implementation, routing & allowed-ips, multi-hop, serta perbandingan performa dengan OpenVPN/IPsec.

Domain Terkait: networking-fundamentals-tcpip-bgp (fondasi network) → linux-hardening-cis (hardening) → homelab-security-architecture-synthesis (infrastruktur) → dns-fundamentals-bind9 (DNS) → podman-networking-ufw (firewall) → tls-ssl-deepdive (perbandingan crypto)


Daftar Isi


1. Filosofi Desain WireGuard

WireGuard (Jason A. Donenfeld, 2015-2020) hadir karena frustrasi dengan VPN existing:

AspekOpenVPNIPsecWireGuard
Kode~600.000 baris~400.000 baris~4.000 baris
CryptoOpenSSL (ribuan opsi)Complex IKENoise_IK (fixed)
HandshakeTLS + authIKEv1/v2 (6-9 msg)1-RTT (3 msg)
Key rotationManualComplexAutomatic (perfect forward secrecy)
Roaming✅ Native
Kernel integrationVia tunVia tun/ipsec✅ In-kernel (wg)

Prinsip: Setiap opsi adalah attack surface. Tidak ada pilihan cipher, algoritma, atau mode — semuanya fixed.


2. Cryptographic Primitives — Noise_IK

WireGuard menggunakan protokol Noise_IK (Noise Protocol Framework — initiator/pre-known static key). Satu pattern: Noise_IK_25519_ChaChaPoly_BLAKE2s.

PrimitiveFungsiAlasan
Curve25519Key exchange (ECDH)Side-channel resistant, konstanta-time
ChaCha20Poly1305AEAD encryptionCepat di CPU tanpa AES-NI
BLAKE2sHashingHash cepat, built-in keying
HKDF (BLAKE2s)Key derivationExtract-expand dari DH result

Mengapa ChaCha20 bukan AES? ChaCha20 adalah ARX cipher (add-rotate-xor) yang tidak butuh hardware AES-NI. Performa konsisten di semua CPU, termasuk ARM dan embedded.

Pre-shared Keys (PSK) Opsional

[Interface]
PrivateKey = base64
ListenPort = 51820
 
[Peer]
PublicKey = base64
PresharedKey = base64  # Opsional — anti-quantum layer
AllowedIPs = 10.0.0.0/24

PSK menambahkan lapisan symmetric encryption di luar Curve25519. Berguna sebagai defense terhadap quantum computer (Grover’s algorithm).


3. Handshake Flow

WireGuard menggunakan 1-RTT handshake (3 messages):

Initiator (Client)            Responder (Server)
      │                              │
      │  Msg 1: Initiation           │
      │  - Static public key (encrypted) │
      │  - Ephemeral public key       │
      │  - Timestamp (anti-replay)    │
      ├─────────────────────────────▶│
      │                              │
      │  Msg 2: Response             │
      │  - Static public key (encrypted) │
      │  - Ephemeral public key       │
      │  - Encrypted empty transport  │
      │◄─────────────────────────────┤
      │                              │
      │  Msg 3: Cookie (if needed)   │
      │  - Anti-DoS cookie           │
      ├─────────────────────────────▶│
      │                              │
      │  ←─── Session established ──→│
      │  Transport key derived       │
      │  (Perfect Forward Secrecy)   │

Key Derivation (KDF Chain)

static_static = DH(init_static, resp_static)      # Long-term auth
ephemeral_remote = DH(init_ephemeral, resp_static) # ECDH
static_remote = DH(init_static, resp_ephemeral)    # ECDH
ephemeral_ephemeral = DH(init_ephemeral, resp_ephemeral) # PFS

# Mix via HKDF chain → session key

Re-keying

Setiap 120 detik atau setelah 2^64 paket, WireGuard melakukan re-handshake otomatis. Ini memberikan Perfect Forward Secrecy: jika kunci jangka panjang bocor, session key tidak bisa di-decrypt.


4. Data Plane Encryption

Setelah handshake, data di-enkripsi dengan ChaCha20Poly1305:

┌─────────────────────────────────────────────┐
│                 WireGuard Packet             │
├────────────┬──────────┬──────────┬───────────┤
│ Type (4B)  │ Reserved │ Session │ Counter   │
│            │ (4B)     │  ID (8B) │ (8B)      │
├────────────┴──────────┴──────────┴───────────┤
│ Encrypted Payload (ChaCha20Poly1305 AEAD)     │
│  - Inner IP packet                           │
│  - Padding (opsional)                        │
├──────────────────────────────────────────────┤
│ Poly1305 MAC tag (16B)                       │
└──────────────────────────────────────────────┘

Counter-based: Setiap packet punya counter monotonic → mencegah replay attack. Counter di-reset saat re-key.


5. Kernel vs Userspace Implementation

Kernel Module (wg)

Packet flow: Network → wg module → ChaCha20 (kernel crypto) → tun → userspace
                      ↓
                  Zero-copy di kernel
                      ↓
              Performa ~ linier dengan CPU

Keunggulan:

  • Latensi lebih rendah (skip context switch)
  • Throughput lebih tinggi (zero-copy)
  • Integrasi dengan network stack kernel

Instalasi:

# Kernel module sudah built-in di Linux 5.6+
modprobe wireguard
# Cek
lsmod | grep wireguard

Userspace (boringtun — Cloudflare)

Packet flow: Network → tun → userspace (boringtun) → ChaCha20 → userspace lagi

Keunggulan:

  • Cross-platform (Windows, macOS, BSD)
  • Update tanpa reboot
  • Sandboxing lebih mudah
  • Debug lebih mudah

Perbandingan performa:

ImplementasiThroughput (1Gbps)Latensi (ms)CPU Usage
Kernel (wg)~940 Mbps0.1-0.35-10%
boringtun~850 Mbps0.3-0.815-25%
OpenVPN (TLS)~400 Mbps1-330-50%

6. Routing & Allowed-IPs

WireGuard tidak menggunakan routing table tradisional — ia menggunakan AllowedIPs sebagai routing + ACL sekaligus.

[Peer]
PublicKey = peer1_publickey
AllowedIPs = 10.0.0.2/32, 192.168.1.0/24

Bagaimana AllowedIPs Bekerja

  1. Terima: Packet dengan src IP dalam AllowedIPs diterima
  2. Kirim: Packet dengan dst IP dalam AllowedIPs dikirim ke peer ini
  3. Route otomatis: WireGuard menambahkan route ke table kernel
# Cek route yang dibuat WireGuard
ip route show dev wg0
# Output: 10.0.0.0/24 dev wg0 proto kernel scope link src 10.0.0.1

Full Tunnel vs Split Tunnel

# Full tunnel — semua traffic via VPN
AllowedIPs = 0.0.0.0/0, ::/0
 
# Split tunnel — hanya subnet tertentu
AllowedIPs = 10.0.0.0/8, 172.16.0.0/12

7. Multi-Hop & Site-to-Site

Multi-Hop (Bounce)

Client ⇄ Relay (VPS) ⇄ Office

Konfigurasi relay:

[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = relay_private
 
[Peer]
# Client
PublicKey = client_public
AllowedIPs = 10.0.0.2/32
 
[Peer]
# Office
PublicKey = office_public
AllowedIPs = 10.0.0.3/32, 192.168.1.0/24

Relay harus enable IP forwarding:

sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

Site-to-Site

Site A (10.0.0.0/24) ⇄ VPS ⇄ Site B (10.0.1.0/24)
# Site A
[Peer]
PublicKey = site_b_public
AllowedIPs = 10.0.1.0/24, 10.0.0.0/24
Endpoint = site-b.example.com:51820

8. NAT Traversal & Roaming

Native Roaming

WireGuard mendeteksi perubahan source IP/port setiap kali packet diterima. Jika client pindah jaringan (WiFi → 4G), WireGuard tetap connect tanpa handshake ulang.

Client @ IP A ────▶ Server
     │
     │ (pindah WiFi)
     ▼
Client @ IP B ────▶ Server
     │               │
     │ Packet tiba   │ Server update endpoint
     │ dari IP baru  │ di memory
     ◀───────────────┤

Persistent Keepalive

Untuk NAT/firewall yang timeout:

[Peer]
PersistentKeepalive = 25  # detik

Nilai umum: 25 detik. Jangan terlalu kecil (< 10) — bisa dianggap DoS.


9. Performance Benchmark

VPN1-Core Throughput4-Core ThroughputLatency AddCPU/Connection
WireGuard940 Mbps3.8 Gbps+0.1 ms1% / 1K conn
IPsec (AES-NI)800 Mbps3.2 Gbps+0.3 ms3% / 1K conn
OpenVPN (AES-256)300 Mbps800 Mbps+1.5 ms8% / 1K conn
OpenVPN (ChaCha20)250 Mbps700 Mbps+2.0 ms10% / 1K conn

WireGuard 3-10× lebih cepat dari OpenVPN untuk throughput tinggi.


10. MTU/MSS Considerations

WireGuard menambahkan 60-byte overhead per packet. Jika interface MTU = 1500:

Payload max = 1500 - 60 = 1440 bytes

Konfigurasi:

[Interface]
Address = 10.0.0.1/24
MTU = 1420  # Untuk ethernet tunnel

MTU calculator:

Recomendasi tabel:

Link TypeMTU
Ethernet (1500)1420
PPPoE (1492)1412
4G/LTE (1500)1420
IPv6 tunnel1400
GRE tunnel1360

11. Deploy Guide

Server

# Install
dnf install wireguard-tools  # Fedora
# atau
apt install wireguard         # Ubuntu
 
# Generate keys
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
chmod 600 /etc/wireguard/private.key
 
# Config /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server-private>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
 
[Peer]
PublicKey = <client-public>
AllowedIPs = 10.0.0.2/32
# Start
systemctl enable --now wg-quick@wg0

Client

[Interface]
PrivateKey = <client-private>
Address = 10.0.0.2/24
DNS = 1.1.1.1
 
[Peer]
PublicKey = <server-public>
Endpoint = server.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0  # Full tunnel
PersistentKeepalive = 25

12. Keamanan & Auditing

Audit Checklist

  • PrivateKey file mode 600
  • ListenPort tidak exposed ke publik (pakai firewall)
  • AllowedIPs serumit mungkin — tidak 0.0.0.0/0 kecuali perlu
  • Rotate keys periodik (setiap 6 bulan)
  • PresharedKey enabled untuk sensitive link
  • Firewall: hanya port 51820/UDP dari peer yang dikenal

Firewall Config

# UFW
ufw allow in on eth0 to any port 51820 proto udp
 
# nftables
nft add rule inet filter input udp dport 51820 accept
nft add rule inet filter input iifname "wg0" accept
nft add rule inet filter forward iifname "wg0" oifname "eth0" accept

13. Referensi

Cross-link vault: