従来のVPNの問題点とWireGuardが生まれた理由
VPNが必要になったとき、ほとんどのsysadminがまず思い浮かべるのはOpenVPNです。確かに動きますが、設定が非常に煩雑です。CA証明書、数百行にわたる.ovpnファイル、重いデーモン。さらに、クライアントがWiFiから4Gに切り替えた途端に接続が切れ、最初から再接続しなければなりません。
私自身もこの問題に直面しました。リモートチームが社内システムにアクセスする必要があり、古いCentOS 7サーバーで試行錯誤してまともなパフォーマンスを出そうとしていました。何度もテストを重ねた結果、新たなトラブルを生まずに問題を本当に解決できたのはWireGuardだけでした。
Linux 5.6からWireGuardはカーネルに直接統合されており、サードパーティのモジュールは不要です。コードベース全体でわずか約4,000行——OpenVPN + OpenSSLのスタックが数十万行あるのと比べると圧倒的に少ない。コードが少ないということは、攻撃ポイントが少なく、セキュリティ監査が容易で、パケット処理のオーバーヘッドが大幅に低いことを意味します。
インストール前に知っておくべき基本概念
OpenVPNがサーバー/クライアントを厳密に区別するのとは異なり、WireGuardはピアツーピアモデルを採用しています。ネットワーク上の各マシンは対等なピアとして扱われ、それぞれが独自のキーペア(秘密鍵 + 公開鍵)を持ちます。
- Interface:WireGuardは仮想ネットワークインターフェース(通常は
wg0という名前)を作成します。これはeth0やtun0と同様のインターフェースです。 - Endpoint:ピア間が実際に接続するためのIP:portアドレスです(通常、サーバー側のみ設定が必要です)。
- AllowedIPs:トンネルを通過できるIPアドレスの範囲です。これがOpenVPNとの大きな違いで、WireGuardはこのフィールドをルーティングに直接使用するため、複雑なルーティングテーブルが不要です。
- PersistentKeepalive:N秒ごとにキープアライブパケットを送信します。クライアントがNAT配下にある場合に重要な設定です。
重要なポイント:WireGuardはローミング機能によりネットワーク変更を越えて接続状態を維持します。クライアントのIPが変わっても、2つのピア間でパケットの交換が可能な限りトンネルは切断されません。
実践:WireGuardサーバーの構築
ステップ1:WireGuardのインストール
Ubuntu 20.04/22.04の場合:
sudo apt update
sudo apt install -y wireguard wireguard-tools
CentOS 7/8またはRHEL(EPELリポジトリが必要):
# CentOS 7
yum install -y epel-release
yum install -y kmod-wireguard wireguard-tools
# CentOS 8 / Stream
dnf install -y epel-release elrepo-release
dnf install -y kmod-wireguard wireguard-tools
カーネルモジュールのロード確認:
modprobe wireguard
lsmod | grep wireguard
ステップ2:サーバーのキーペア生成
WireGuardはキー交換にCurve25519を使用しています——Signal Protocolと同じアルゴリズムです。キーの生成はたった1つのコマンドで完了します:
cd /etc/wireguard
umask 077 # 重要:秘密鍵が他のユーザーに読まれないようにする
wg genkey | tee server_private.key | wg pubkey > server_public.key
cat server_private.key # この値を保存しておく
cat server_public.key # クライアント設定に使用する
umask 077コマンドにより、生成されるキーファイルのパーミッションが600になります。このステップを省略すると、秘密鍵が同じサーバー上の任意のユーザーに読まれてしまい、トンネル全体が危険にさらされます。
ステップ3:サーバー設定ファイルの作成(/etc/wireguard/wg0.conf)
以下の内容で設定ファイルを作成します:
cat > /etc/wireguard/wg0.conf << 'EOF'
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
# クライアントがVPN経由でインターネットに出られるようIPフォワーディングとNATを有効化する
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
[Peer]
PublicKey = <CLIENT1_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32
EOF
注意:eth0はサーバーの実際のインターフェース名に置き換えてください(ip route | grep defaultで確認)。<...>のプレースホルダーは実際のキーに置き換えてください。
IPフォワーディングを永続的に有効化:
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
ステップ4:WireGuardの起動と自動起動設定
systemctl enable --now wg-quick@wg0
systemctl status wg-quick@wg0
# トンネルの状態を確認
wg show
wg showの出力にはwg0インターフェース、リスニングポート、接続済みピアの一覧が表示されます。
クライアント側の設定
クライアントのキーペア生成
クライアントマシンで実行します(Linux、macOS、Windowsいずれも同じ方法です):
wg genkey | tee client_private.key | wg pubkey > client_public.key
クライアント設定ファイル(wg0.confまたはtunnel.conf)
[Interface]
Address = 10.0.0.2/24
PrivateKey = <CLIENT_PRIVATE_KEY>
DNS = 1.1.1.1 # オプション:VPN経由でDNSを使用する
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = <SERVER_PUBLIC_IP>:51820
AllowedIPs = 0.0.0.0/0 # すべてのトラフィックをVPN経由でルーティング
# または社内サブネットのみルーティングする場合:
# AllowedIPs = 10.0.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25
クライアントでトンネルを起動:
sudo wg-quick up ./tunnel.conf
# 接続確認
ping 10.0.0.1 # サーバーへのping
curl ifconfig.me # パブリックIPを確認(VPNサーバーのIPが表示されるはず)
再起動なしで新しいピアを追加する
WireGuardで特に気に入っている点がこれです——新しいクライアントの追加にサービスの再起動が不要なことです:
# 動的にピアを追加する(既存の接続は維持)
wg set wg0 peer <CLIENT2_PUBLIC_KEY> allowed-ips 10.0.0.3/32
# 現在の設定をファイルに保存する
wg-quick save wg0
WireGuardポートのファイアウォール設定
サーバーのファイアウォールでUDPポート51820を開放することを忘れずに:
# UFW (Ubuntu)
ufw allow 51820/udp
# firewalld (CentOS/RHEL)
firewall-cmd --permanent --add-port=51820/udp
firewall-cmd --reload
# iptablesで直接設定する場合
iptables -A INPUT -p udp --dport 51820 -j ACCEPT
サーバーがNAT配下にある場合(クラウドVPSなど)、クラウドプロバイダーのセキュリティグループやネットワークACLでもポートを開放してください。
よくあるトラブルシューティング
私が実際に経験した問題とその解決方法をまとめます:
- クライアントは接続できるがインターネットに出られない:
ip_forwardが有効かどうか確認し(sysctl net.ipv4.ip_forward)、NAT MASQUERADEルールのインターフェース名が正しいか確認してください。 - トンネルはupだがpingが通らない:
wg showを実行して、latest handshakeの行が表示されているか確認してください。表示されていればハンドシェイクは成功しています。表示されない場合は公開鍵またはエンドポイントの設定が誤っています。 - CentOS 7でモジュールがロードできない:CentOS 7のデフォルトカーネル(3.10.x)はWireGuardをネイティブサポートしていません。DKMSを使用するか、ELRepo経由でカーネルをメインラインに更新してください(ELRepoリポジトリから
yum install -y kernel-ml)。 - 数分後に接続が切れる:クライアント側のピア設定に
PersistentKeepalive = 25を追加してください。
まとめ
数週間実際に使ってみた結果、チーム全員がVPNの切断に悩まなくなりました。オフィスから自宅へ、WiFiから4Gへネットワークを切り替えても、トンネルはそのまま維持されます。新しいメンバーの追加も数分で完了し、稼働中のサービスを触る必要もありません。
WireGuardはOpenVPNの改良版ではありません——まったく異なるアプローチです。ユーザースペースで動く数十万行のコードではなく、カーネル内で動く4,000行のコードです。スケールアップが必要な場合は、AllowedIPsを特定のサブネット範囲に変更してスプリットトンネリングを実現するか、クライアントの[Interface]セクションにDNSを追加してIPアドレスではなくドメインで社内サービスにアクセスできるようにしましょう。
