LinuxにWireGuard VPNサーバーを構築する方法(高速・安全)

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

従来のVPNソリューションの問題点

セルフホストのVPNが必要になる場面は多い。ホームラボへのリモートアクセス、拠点間の接続、信頼できる出口ノード経由のトラフィックルーティングなど、用途はさまざまだ。従来の選択肢はOpenVPNかIPsecだったが、どちらかを設定したことがある人なら、その苦労は身に染みているだろう――何千行もの設定ファイル、認証局、時代遅れの暗号方式、そして夜中まで続くデバッグ作業。

問題の本質は、VPNが本質的に複雑なのではない。古いプロトコルは「暗号の柔軟性」と称してあらゆる暗号方式を詰め込み、「設定の自由度」と称してすべてのパラメータをユーザーに露出させるよう設計された。その結果、正しく設定するのが難しく、監査はさらに難しいソフトウェアが生まれた。

WireGuardはその逆のアプローチを取る――意図的に「シンプルに絞る」のだ。コードベースはわずか約4,000行。OpenVPNは10万行を超える。WireGuardは固定された最新の暗号プリミティブを使い、すべての設定を1つのファイルにまとめる。月5ドルのVPSに導入して、10分以内に動作するトンネルを構築できた。一度使ったら、OpenVPNには戻れない――ダイヤルアップに戻るようなものだ。

アプローチ比較:WireGuard vs OpenVPN vs IPsec

それぞれに適した用途がある。どこで使えて、どこでは使えないかを整理する。

OpenVPN

  • 実績があり、幅広いクライアントに対応
  • ユーザースペースで動作――rootなしでインストールしやすいが、速度は遅め
  • TLSベース:ほとんどのファイアウォールを通過できる(ポート443も利用可)
  • 複雑なPKI設定が必要(証明書、CA)
  • CPU負荷が高く、高スループット接続ではオーバーヘッドが顕著

IPsec / IKEv2

  • 追加アプリなしでiOSとmacOSにネイティブ対応
  • カーネルで動作――高速
  • 設定ミスが起きやすいことで悪名高い
  • デバッグが困難;エラーメッセージが不可解
  • エンタープライズやモバイルクライアントには向くが、手軽なセルフホスト環境には不向き

WireGuard

  • Linux 5.6以降はカーネルに組み込み済み(旧カーネルではユーザースペースモジュールとして利用可)
  • 非常に高速:暗号化にChaCha20 + Poly1305、鍵交換にCurve25519を使用
  • 証明書不要:公開鍵・秘密鍵のペアだけ
  • ステートレス設計――持続的な接続なし、ハンドシェイクタイムアウトの問題なし
  • 攻撃対象面が小さい:約4,000行は週末に1人のエンジニアが監査できる規模

WireGuardのメリットとデメリット

メリット

  • 速度: ベンチマークでは一貫してWireGuardが同一ハードウェア上でOpenVPNの2〜3倍の性能を発揮する。1 Gbpsリンクでは、OpenVPNは通常200〜300 Mbps止まりだが、WireGuardは700〜900 Mbpsに達することが多い。
  • シンプルさ: サーバーとクライアントの設定が10分以内に完了する。設定全体が画面1枚に収まる。
  • 設計レベルのセキュリティ: 暗号スイートは固定されており最新だ。ネゴシエーションがないため、誤った設定をしてしまう余地がない。
  • ローミング対応: クライアントがネットワークを切り替えても(WiFi → LTE)再接続不要。トンネルが自動的に復帰する。
  • 低リソース消費: 月5ドルのVPSやRaspberry Pi 3でも快適に動作する。

デメリット

  • UDPのみ: WireGuardはUDPのみを使用する。企業のファイアウォールでUDPが完全にブロックされている場合は、udp2rawやTCPトンネルラッパーなどの回避策が必要になる。
  • 難読化機能なし: トラフィックがWireGuardと識別可能だ。検閲が厳しい環境では、難読化レイヤーを上乗せする必要がある。
  • 手動のピア管理: ピアの追加・削除は設定ファイルを直接編集する必要がある。規模が大きくなる場合はwg-easyheadscaleが管理レイヤーを提供してくれる。
  • デフォルトでは動的IPアドレス割り当てなし: 各ピアにIPを手動で割り当てる必要がある。大規模な環境ではwg-easyがこれを自動化できる。

推奨構成

個人用VPNや小規模チームなら、静的なピア設定を持つLinux VPS上のWireGuardサーバー1台で十分だ。管理UIもデータベースも不要。設定ファイルは短いので、GUIを覚えるよりも直接編集する方が速い。

このガイドではUbuntu 22.04 LTSを使用するが、手順は最新のDebian/Ubuntuシステムならどれでも動作する。サーバーは以下のように設定する:

  • UDPポート51820でリッスン
  • VPNトンネルのサブネットに10.0.0.0/24を使用
  • すべてのクライアントトラフィックをサーバー経由でルーティング(フルトンネルモード)

実装手順

ステップ1:WireGuardのインストール

Ubuntu 22.04以降では、デフォルトのリポジトリに含まれている:

sudo apt update
sudo apt install wireguard -y

カーネルモジュールが読み込まれていることを確認する:

lsmod | grep wireguard
# wireguard             86016  0

ステップ2:サーバー鍵の生成

cd /etc/wireguard
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key
cat server_private.key   # wg0.conf に記載する
cat server_public.key    # 各クライアントに配布する

server_private.keyはサーバー上に保管し、絶対に外部に漏らさないこと。公開鍵は安全に配布できる。

ステップ3:IPフォワーディングの有効化

これがないと、サーバーはクライアントとインターネット間のトラフィックをルーティングできない:

echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

ステップ4:サーバー設定ファイルの作成

YOUR_PRIVATE_KEYserver_private.keyの内容に置き換える。eth0は実際のネットワークインターフェース名に変更すること――ip aで確認できる:

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = YOUR_PRIVATE_KEY

# NAT: eth0 を実際のインターフェース名に変更
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

# 以下にピアブロックを追加(クライアント1つにつき1ブロック)

ステップ5:クライアントピアの追加

クライアントマシン上で、同じ方法で鍵ペアを生成する:

wg genkey | tee client_private.key | wg pubkey > client_public.key

サーバーに戻り、wg0.confにクライアントをピアとして追加する:

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32

サーバー側のAllowedIPsはWireGuardに対して「10.0.0.2宛てのパケットはこのピアへ転送する」と指示する。フルトンネルクライアントの場合、サーバー側は/32が正しい。

ステップ6:WireGuardの起動

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
sudo systemctl status wg-quick@wg0

次にファイアウォールポートを開放する:

sudo ufw allow 51820/udp
sudo ufw reload

ステップ7:クライアントの設定

クライアントマシン上に/etc/wireguard/wg0.confを作成する:

[Interface]
Address = 10.0.0.2/24
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = YOUR_SERVER_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

AllowedIPs = 0.0.0.0/0はフルトンネルを意味する:すべてのパケットがVPN経由でルーティングされる。VPNサブネット宛てのトラフィックだけをトンネルするスプリットトンネルにしたい場合は10.0.0.0/24を指定する。

トンネルを起動する:

sudo wg-quick up wg0

ステップ8:接続の確認

サーバー上でアクティブなピアを確認する:

sudo wg show
# interface: wg0
#   public key: ...
#   listening port: 51820
# 
# peer: CLIENT_PUBLIC_KEY
#   endpoint: CLIENT_IP:PORT
#   allowed ips: 10.0.0.2/32
#   最終ハンドシェイク: 5秒前
#   転送量: 1.23 KiB 受信, 4.56 KiB 送信

クライアントからサーバーのVPN IPにpingを実行する:

ping 10.0.0.1
# 64 bytes from 10.0.0.1: icmp_seq=0 ttl=64 time=12.3 ms

ハンドシェイクのタイムスタンプが表示され、pingの応答が返ってきたらトンネルは正常に動作している。これで完了だ。

よくある問題と対処法

  • ハンドシェイクが発生しない: サーバーのファイアウォールでUDP 51820が開放されているか確認する。クライアントのEndpointフィールドにサーバーの正しいパブリックIPが設定されているか確認する。
  • VPN IPにはpingできるがインターネットに出られない: IPフォワーディングが無効になっている可能性が高い。sysctl net.ipv4.ip_forwardを実行し、1が返ることを確認する。またPostUpのiptables NATルールが実際に適用されているかも確認する。
  • DNSリーク: クライアントの[Interface]ブロックにDNS = 1.1.1.1を設定するか、VPNサブネット内で動作するDNSサーバーを指定する。
  • ピアの追加: 新しいクライアントにはそれぞれ独自の鍵ペアと一意のIPアドレス(例:10.0.0.3/3210.0.0.4/32)が必要だ。完全な再起動なしにリロードするには:sudo wg addconf wg0 <(wg-quick strip wg0)
Share: