Lessons

WireGuard VPN

Level: Expert Module: Security & Authentication 8 min read Lesson 53 of 66

Overview

  • What you will learn: The WireGuard VPN architecture and its cryptokey routing model, how WireGuard differs from OpenVPN and IPsec, generating key pairs with wg genkey, configuring the WireGuard interface (wg0.conf) on both server and client, adding peers, using wg-quick to manage tunnels, configuring firewall rules and IP forwarding for site-to-site and remote access VPN, and monitoring connections with the wg command.
  • Prerequisites: Lesson 52 (OpenVPN Setup), understanding of IP routing, public/private key cryptography
  • Estimated reading time: 25 minutes

Introduction

WireGuard is a modern VPN protocol designed for simplicity, speed, and strong security. Unlike OpenVPN, which runs in user space and relies on TLS with configurable cipher suites, WireGuard is implemented directly in the Linux kernel (since version 5.6) and uses a fixed set of state-of-the-art cryptographic primitives: Curve25519 for key exchange, ChaCha20 for symmetric encryption, Poly1305 for authentication, and BLAKE2s for hashing.

The WireGuard codebase is approximately 4,000 lines of code — compared to over 100,000 lines for OpenVPN — making it far easier to audit for security vulnerabilities. Its design philosophy is that a VPN should be as simple to configure as SSH: generate a key pair, share the public key, and connect.

In this lesson you will deploy a WireGuard VPN between a server and multiple clients, understand the cryptokey routing model that eliminates the need for complex routing tables, and learn operational best practices for production deployments.

Cryptokey Routing

WireGuard introduces a concept called cryptokey routing. Each peer has a public key and a list of allowed IP addresses. When WireGuard needs to send a packet, it looks at the destination IP, finds the peer whose AllowedIPs include that address, and encrypts the packet using that peer’s public key. When a packet arrives, WireGuard decrypts it and checks that the source IP is within the sender’s AllowedIPs.

This model combines routing and access control into a single, elegant mechanism. There is no need for separate firewall rules or complex routing configuration — the allowed IPs define both the routing table and the access policy.

# Conceptual cryptokey routing table:
# Public Key                AllowedIPs          Endpoint
# abc123...                 10.0.0.2/32         203.0.113.10:51820
# def456...                 10.0.0.3/32         198.51.100.20:51820
# ghi789...                 10.0.0.0/24         (server — no endpoint needed)

# When sending to 10.0.0.2:
#   1. Look up 10.0.0.2 in AllowedIPs -> peer abc123
#   2. Encrypt with abc123's public key
#   3. Send to endpoint 203.0.113.10:51820

Installing WireGuard

# WireGuard is included in Ubuntu 20.04+ kernels
$ sudo apt install wireguard wireguard-tools

# Verify the kernel module is available
$ sudo modprobe wireguard
$ lsmod | grep wireguard
wireguard             81920  0

Generating Key Pairs

Each WireGuard peer (server and client) needs its own private/public key pair. Keys are simple base64-encoded 32-byte values.

# Generate a private key
$ wg genkey | sudo tee /etc/wireguard/private.key
$ sudo chmod 600 /etc/wireguard/private.key

# Derive the public key from the private key
$ sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

# Generate a pre-shared key for additional security (optional)
$ wg genpsk | sudo tee /etc/wireguard/preshared.key
$ sudo chmod 600 /etc/wireguard/preshared.key

# One-liner to generate both keys
$ wg genkey | tee privatekey | wg pubkey > publickey

Server Configuration

# /etc/wireguard/wg0.conf — Server
[Interface]
# Server's private key
PrivateKey = SERVER_PRIVATE_KEY_HERE

# VPN IP address for the server
Address = 10.0.0.1/24

# Listening port
ListenPort = 51820

# Save configuration changes made with wg set
SaveConfig = false

# Post-up: enable NAT and forwarding
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: Client 1
[Peer]
PublicKey = CLIENT1_PUBLIC_KEY_HERE
# Optional pre-shared key for post-quantum resistance
PresharedKey = PRESHARED_KEY_HERE
# Which IPs this peer is allowed to send from
AllowedIPs = 10.0.0.2/32

# Peer: Client 2
[Peer]
PublicKey = CLIENT2_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.3/32
# Enable IP forwarding
$ echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-wireguard.conf
$ sudo sysctl -p /etc/sysctl.d/99-wireguard.conf

# Allow WireGuard port through the firewall
$ sudo ufw allow 51820/udp

Client Configuration

# /etc/wireguard/wg0.conf — Client 1
[Interface]
# Client's private key
PrivateKey = CLIENT1_PRIVATE_KEY_HERE

# VPN IP address for this client
Address = 10.0.0.2/24

# Optional: use the VPN's DNS server
DNS = 10.0.0.1, 1.1.1.1

[Peer]
# Server's public key
PublicKey = SERVER_PUBLIC_KEY_HERE

# Optional pre-shared key (must match server)
PresharedKey = PRESHARED_KEY_HERE

# Route only VPN traffic (split tunnel)
AllowedIPs = 10.0.0.0/24

# Route ALL traffic through the VPN (full tunnel)
# AllowedIPs = 0.0.0.0/0, ::/0

# Server's public IP and port
Endpoint = vpn.example.com:51820

# Send keepalive every 25 seconds (needed behind NAT)
PersistentKeepalive = 25

Managing Tunnels with wg-quick

# Bring up the WireGuard interface
$ sudo wg-quick up wg0

# Bring down the interface
$ sudo wg-quick down wg0

# Enable at boot with systemd
$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0

# Check interface status
$ sudo wg show
interface: wg0
  public key: SERVER_PUBLIC_KEY
  private key: (hidden)
  listening port: 51820

peer: CLIENT1_PUBLIC_KEY
  endpoint: 203.0.113.10:54321
  allowed ips: 10.0.0.2/32
  latest handshake: 42 seconds ago
  transfer: 1.24 MiB received, 3.47 MiB sent

# Show concise status
$ sudo wg show wg0 dump

# Add a peer dynamically (without editing config)
$ sudo wg set wg0 peer CLIENT3_PUBLIC_KEY allowed-ips 10.0.0.4/32

Site-to-Site VPN

WireGuard can connect entire networks, not just individual clients. Set the AllowedIPs to include the remote site’s subnet.

# Site A server (10.0.1.0/24 local network)
# /etc/wireguard/wg0.conf
[Interface]
PrivateKey = SITE_A_PRIVATE_KEY
Address = 10.0.0.1/24
ListenPort = 51820

[Peer]
PublicKey = SITE_B_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32, 10.0.2.0/24
Endpoint = site-b.example.com:51820

# Site B server (10.0.2.0/24 local network)
# /etc/wireguard/wg0.conf
[Interface]
PrivateKey = SITE_B_PRIVATE_KEY
Address = 10.0.0.2/24
ListenPort = 51820

[Peer]
PublicKey = SITE_A_PUBLIC_KEY
AllowedIPs = 10.0.0.1/32, 10.0.1.0/24
Endpoint = site-a.example.com:51820

# Both sites need IP forwarding enabled
# and AllowedIPs must include the remote subnet

Monitoring and Troubleshooting

# Check if the tunnel is active
$ sudo wg show wg0

# Verify latest handshake (should be recent if traffic is flowing)
$ sudo wg show wg0 latest-handshakes

# Check routing
$ ip route show
10.0.0.0/24 dev wg0 proto kernel scope link src 10.0.0.1

# Test connectivity
$ ping -c 3 10.0.0.2

# Debug: check kernel messages
$ sudo dmesg | grep wireguard

# Verify listening port
$ sudo ss -ulnp | grep 51820

# If handshake is not completing:
# 1. Verify public keys match on both ends
# 2. Check that the endpoint is reachable (firewall, port forwarding)
# 3. Ensure system clocks are roughly synchronized
# 4. Check that AllowedIPs do not overlap across peers

Key Takeaways

  • WireGuard is a kernel-level VPN that uses fixed, modern cryptography (Curve25519, ChaCha20, Poly1305, BLAKE2s) — there are no cipher suites to configure or misconfigure.
  • Cryptokey routing combines routing and access control: each peer’s public key maps to a set of AllowedIPs that define both what it can send and what it can receive.
  • Configuration is minimal — generate a key pair with wg genkey and wg pubkey, create a wg0.conf file, and manage the tunnel with wg-quick up/down.
  • Pre-shared keys add a symmetric encryption layer on top of the asymmetric Curve25519 exchange, providing defense against potential future quantum computing attacks.
  • WireGuard supports both remote access (individual clients) and site-to-site topologies by adjusting AllowedIPs to include remote subnets.

What’s Next

You have completed the Security & Authentication module. You now have the knowledge to secure Linux servers with mandatory access controls, configure enterprise authentication with Kerberos and LDAP, integrate with Active Directory, and build encrypted VPN tunnels with both OpenVPN and WireGuard. Continue to the next module to expand your Linux administration skills.

繁體中文

概述

  • 學習目標:WireGuard VPN 架構及其密碼金鑰路由模型、WireGuard 與 OpenVPN 和 IPsec 的區別、使用 wg genkey 產生金鑰對、在伺服器和客戶端設定 WireGuard 介面(wg0.conf)、添加對等方、使用 wg-quick 管理通道、設定防火牆規則和 IP 轉發,以及使用 wg 命令監控連線。
  • 先決條件:第 52 課(OpenVPN 設定),了解 IP 路由和公鑰/私鑰密碼學
  • 預計閱讀時間:25 分鐘

簡介

WireGuard 是一種現代 VPN 協定,設計目標是簡單、快速和高安全性。與在使用者空間運行的 OpenVPN 不同,WireGuard 直接在 Linux 核心中實現(自版本 5.6 起),使用固定的先進密碼學原語:用於金鑰交換的 Curve25519、用於對稱加密的 ChaCha20、用於認證的 Poly1305 和用於雜湊的 BLAKE2s。

WireGuard 的程式碼庫約 4,000 行——相比 OpenVPN 的超過 100,000 行——使其更容易進行安全漏洞稽核。其設計理念是 VPN 應該像 SSH 一樣簡單配置:產生金鑰對、分享公鑰、連線。

密碼金鑰路由

WireGuard 引入了密碼金鑰路由概念。每個對等方有一個公鑰和一個允許的 IP 位址列表。當 WireGuard 需要發送封包時,它查看目的地 IP,找到其 AllowedIPs 包含該位址的對等方,並使用該對等方的公鑰加密封包。這個模型將路由和存取控制合併為一個優雅的機制。

安裝 WireGuard

# WireGuard 包含在 Ubuntu 20.04+ 核心中
$ sudo apt install wireguard wireguard-tools

# 驗證核心模組
$ sudo modprobe wireguard

產生金鑰對

# 產生私鑰
$ wg genkey | sudo tee /etc/wireguard/private.key
$ sudo chmod 600 /etc/wireguard/private.key

# 從私鑰推導公鑰
$ sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

# 產生預共享金鑰(選用,用於後量子安全)
$ wg genpsk | sudo tee /etc/wireguard/preshared.key

伺服器設定

# /etc/wireguard/wg0.conf — 伺服器
[Interface]
PrivateKey = SERVER_PRIVATE_KEY_HERE
Address = 10.0.0.1/24
ListenPort = 51820
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 = CLIENT1_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.2/32

客戶端設定

# /etc/wireguard/wg0.conf — 客戶端
[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY_HERE
Address = 10.0.0.2/24
DNS = 10.0.0.1, 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.0/24
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25

使用 wg-quick 管理通道

# 啟動 WireGuard 介面
$ sudo wg-quick up wg0

# 關閉介面
$ sudo wg-quick down wg0

# 開機時啟用
$ sudo systemctl enable wg-quick@wg0

# 檢查介面狀態
$ sudo wg show

站對站 VPN

WireGuard 可以連接整個網路。將 AllowedIPs 設定為包含遠端站點的子網路。

# 站點 A 的 [Peer] 區段
AllowedIPs = 10.0.0.2/32, 10.0.2.0/24

# 站點 B 的 [Peer] 區段
AllowedIPs = 10.0.0.1/32, 10.0.1.0/24

重點摘要

  • WireGuard 是核心層級的 VPN,使用固定的現代密碼學——沒有密碼套件需要設定或可能設定錯誤。
  • 密碼金鑰路由結合了路由和存取控制:每個對等方的公鑰映射到一組 AllowedIPs,定義其可以發送和接收的內容。
  • 設定極簡——使用 wg genkeywg pubkey 產生金鑰對,建立 wg0.conf 檔案,使用 wg-quick up/down 管理通道。
  • 預共享金鑰在非對稱 Curve25519 交換之上添加對稱加密層,提供對未來量子計算攻擊的防禦。
  • WireGuard 通過調整 AllowedIPs 同時支援遠端存取(個別客戶端)和站對站拓撲。

下一步

您已完成安全與認證模組。您現在具備了使用強制存取控制保護 Linux 伺服器、使用 Kerberos 和 LDAP 設定企業認證、與 Active Directory 整合,以及使用 OpenVPN 和 WireGuard 建立加密 VPN 通道的知識。繼續下一個模組以擴展您的 Linux 管理技能。

日本語

概要

  • 学習内容:WireGuard VPN アーキテクチャと暗号鍵ルーティングモデル、WireGuard と OpenVPN・IPsec の違い、wg genkey による鍵ペアの生成、サーバーとクライアントでの WireGuard インターフェース(wg0.conf)の設定、ピアの追加、wg-quick によるトンネル管理、ファイアウォールルールと IP フォワーディングの設定、wg コマンドによる接続の監視。
  • 前提条件:レッスン52(OpenVPN セットアップ)、IP ルーティングと公開鍵/秘密鍵暗号の理解
  • 推定読了時間:25分

はじめに

WireGuard はシンプルさ、速度、強力なセキュリティを目指して設計されたモダンな VPN プロトコルです。ユーザースペースで動作する OpenVPN とは異なり、WireGuard は Linux カーネルに直接実装されており(バージョン 5.6 以降)、固定された最先端の暗号プリミティブを使用します:鍵交換に Curve25519、対称暗号化に ChaCha20、認証に Poly1305、ハッシュに BLAKE2s。

WireGuard のコードベースは約 4,000 行で、OpenVPN の 100,000 行以上と比較して、セキュリティ脆弱性の監査がはるかに容易です。設計思想は、VPN は SSH と同じくらい簡単に設定できるべきというものです。

暗号鍵ルーティング

WireGuard は暗号鍵ルーティングという概念を導入します。各ピアは公開鍵と許可された IP アドレスのリストを持ちます。WireGuard がパケットを送信する必要がある場合、宛先 IP を見て、その AllowedIPs にそのアドレスを含むピアを見つけ、そのピアの公開鍵でパケットを暗号化します。このモデルはルーティングとアクセス制御を単一のエレガントなメカニズムに統合します。

WireGuard のインストール

# WireGuard は Ubuntu 20.04+ カーネルに含まれている
$ sudo apt install wireguard wireguard-tools

# カーネルモジュールの確認
$ sudo modprobe wireguard

鍵ペアの生成

# 秘密鍵の生成
$ wg genkey | sudo tee /etc/wireguard/private.key
$ sudo chmod 600 /etc/wireguard/private.key

# 秘密鍵から公開鍵を導出
$ sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

# 事前共有鍵の生成(オプション、ポスト量子セキュリティ)
$ wg genpsk | sudo tee /etc/wireguard/preshared.key

サーバー設定

# /etc/wireguard/wg0.conf — サーバー
[Interface]
PrivateKey = SERVER_PRIVATE_KEY_HERE
Address = 10.0.0.1/24
ListenPort = 51820
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 = CLIENT1_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.2/32

クライアント設定

# /etc/wireguard/wg0.conf — クライアント
[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY_HERE
Address = 10.0.0.2/24
DNS = 10.0.0.1, 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.0/24
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25

wg-quick によるトンネル管理

# WireGuard インターフェースの起動
$ sudo wg-quick up wg0

# インターフェースの停止
$ sudo wg-quick down wg0

# ブート時に有効化
$ sudo systemctl enable wg-quick@wg0

# インターフェースステータスの確認
$ sudo wg show

サイト間 VPN

WireGuard は個々のクライアントだけでなく、ネットワーク全体を接続できます。AllowedIPs にリモートサイトのサブネットを含めます。

# サイト A の [Peer] セクション
AllowedIPs = 10.0.0.2/32, 10.0.2.0/24

# サイト B の [Peer] セクション
AllowedIPs = 10.0.0.1/32, 10.0.1.0/24

重要ポイント

  • WireGuard はカーネルレベルの VPN で、固定されたモダンな暗号を使用する。設定や誤設定の余地がある暗号スイートは存在しない。
  • 暗号鍵ルーティングはルーティングとアクセス制御を統合する。各ピアの公開鍵が AllowedIPs のセットにマッピングされ、送受信可能な内容を定義する。
  • 設定は最小限。wg genkeywg pubkey で鍵ペアを生成し、wg0.conf ファイルを作成し、wg-quick up/down でトンネルを管理する。
  • 事前共有鍵は非対称 Curve25519 交換の上に対称暗号化レイヤーを追加し、将来の量子コンピューティング攻撃に対する防御を提供する。
  • WireGuard は AllowedIPs を調整することで、リモートアクセス(個別クライアント)とサイト間トポロジーの両方をサポートする。

次のステップ

セキュリティと認証モジュールを完了しました。これで、強制アクセス制御による Linux サーバーの保護、Kerberos と LDAP によるエンタープライズ認証の設定、Active Directory との統合、OpenVPN と WireGuard による暗号化 VPN トンネルの構築の知識を得ました。次のモジュールに進んで Linux 管理スキルを拡張してください。

You Missed