Ubuntu ServerへのWireGuard VPN構築:インストールから設定まで完全ガイド

Security tutorial - IT technology blog
Security tutorial - IT technology blog

現実の問題:チームのリモートアクセスはどうなっていますか?

さまざまなプロジェクトの10台以上のサーバーに対してセキュリティ監査を行った結果、ほぼすべてに共通の問題があることがわかりました:VPNがない、またはVPNを「なんとなく」使っているかのどちらかです。具体的には:

  • SSHポート22をそのままインターネットに公開しており、ボットにすぐスキャンされてしまう
  • OpenVPNを使っているものの設定が煩雑で、エンドユーザーが.ovpnファイルをあれこれとコピーしなければならない
  • 一部のチームはTeamViewerやngrokを使っており、「暫定」のはずの解決策が永続的になってしまっている

結果は想像に難くありません:昼夜問わずボットがポートをスキャンし、深夜3時にSSHブルートフォースが走り、サーバーのログがゴミであふれます。あるステージングサーバーのauth.logを確認したことがあるのですが、24時間で中国やロシアのIPから15,000件ものログイン試行がありました。そのサーバーはdev環境を動かしているだけでしたが、侵害されることは不要なトラブルでしかありません。

答えは明らかです:パブリックポートをすべて閉じて、VPN経由でのみアクセスを許可する。しかし、使いやすく、高速で、設定に半日もかからないVPNはどれでしょうか?

なぜOpenVPNが常に答えではないのか?

OpenVPNが悪いと言っているわけではありません。実績があり、安定していて、長年使われてきました。ただ、新しいセットアップをする際に気になる点がいくつかあります:

  • 必要以上に遅い:OpenVPNはユーザースペースで動作するため、各パケットがkernel → userspace → kernelと移動しなければなりません。実際のベンチマークでは、OpenVPNは通常100〜200Mbpsしか出ないのに対し、WireGuardは同じハードウェアで1Gbpsの回線を使い切れます。この差は、VPN越しにデータベースやファイルサーバーにアクセスする際に顕著に現れます
  • 設定が複雑:PKIインフラ、CA、証明書、.ovpnファイル — 新しいクライアントを追加するたびに一連の手順が必要です
  • デバッグが難しい:問題が発生した際、OpenVPNのログがあまり役に立たないことがあります

すでに安定して動いているOpenVPNインフラがあれば、移行する必要はありません。ただし、新しくセットアップするならWireGuardを真っ先に提案します。

WireGuard:次世代VPN、驚くほど小さなコードベース

Jason DonenfeldはWireGuardをわずか約4,000行のコードで書きました。OpenVPNの約70,000行と比べると一目瞭然です。コードが少ない = 攻撃面が小さい = 監査しやすい。Linus Torvaldsはこれを「a work of art」と称し、Linux kernelバージョン5.6から直接統合されました。つまりUbuntu 20.04以降では最初から使えて、追加モジュールのインストールは不要です。

以下がWireGuardをすべての新規セットアップで使う理由です:

  • kernel内で動作:OpenVPNのようなユーザースペースのオーバーヘッドがなく、スループットが格段に高い
  • 超高速ハンドシェイク:接続確立まで約100ms — OpenVPNは通常1〜2秒かかります
  • 最新の暗号技術:ChaCha20、Poly1305、Curve25519 — 古いRSA/AESではありません
  • シンプルな設定:各ピアに必要なのはpublic keyだけ — CAも証明書も不要
  • デフォルトでステルス:WireGuardは不正なパケットに応答せず、ポートスキャンでは閉じているように見えます

WireGuardのインストールと設定:ステップバイステップ

セットアップ構成:Ubuntu Server 1台をVPNゲートウェイ(パブリックIPあり)とし、Nクライアント(開発用ノートPC、オフィスPC等)を接続します。テスト環境:Ubuntu 22.04 LTS。

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

sudo apt update
sudo apt install wireguard -y

Ubuntu 20.04以降では、WireGuardは公式リポジトリに含まれているため、PPAの追加は不要です。

ステップ2:サーバーの鍵ペアを生成する

WireGuardはpublic/private keyを使用します — ユーザー名やパスワードは不要です。各ピア(サーバーまたはクライアント)はそれぞれ独自の鍵ペアを持ちます。

sudo mkdir -p /etc/wireguard
cd /etc/wireguard

# 秘密鍵を生成し、そこから公開鍵を導出する
wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key

# 鍵の内容を確認する
sudo cat server_private.key
sudo cat server_public.key

重要:秘密鍵は誰とも共有してはいけません。公開鍵は自由に共有できます — これが非対称暗号の原則です。

ステップ3:サーバー設定ファイルを作成する

sudo nano /etc/wireguard/wg0.conf

設定ファイルの内容:

[Interface]
# server_private.keyの内容をここに貼り付ける
PrivateKey = <SERVER_PRIVATE_KEY>

# トンネルインターフェースのIPアドレス(VPN内部IP、パブリックIPではない)
Address = 10.0.0.1/24

# WireGuardがリッスンするポート(UDP)
ListenPort = 51820

# トンネル起動時にIPフォワーディングとNATを有効にする
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# クライアントごとに[Peer]ブロックを追加する
[Peer]
# クライアント1の公開鍵
PublicKey = <CLIENT1_PUBLIC_KEY>
# このクライアントに割り当てるトンネル内IPアドレス
AllowedIPs = 10.0.0.2/32

注意eth0はサーバーの実際のネットワークインターフェース名に置き換えてください。事前にip aで確認しましょう — VPSプロバイダーによってens3enp0s3eth0などの場合があります。推測せず、必ず確認してください。

ステップ4:IPフォワーディングを有効にする

# 即時に有効化する
sudo sysctl -w net.ipv4.ip_forward=1

# 永続的に有効化する(再起動後も維持)
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

ステップ5:クライアントの鍵ペアを生成する

Linuxクライアントマシンで:

sudo apt install wireguard -y
wg genkey | tee client_private.key | wg pubkey | tee client_public.key

クライアントがWindowsまたはmacOSの場合は、公式のWireGuardアプリを使用します — アプリのUIに「Generate keypair」ボタンがあるので、ターミナルは不要です。

ステップ6:クライアントを設定する

クライアントにこの設定ファイルを作成します(またはWindows/macOSのWireGuardアプリにインポートします):

[Interface]
# client_private.keyの内容をここに貼り付ける
PrivateKey = <CLIENT_PRIVATE_KEY>

# クライアントに割り当てられるVPNトンネル内のIPアドレス
Address = 10.0.0.2/24

# VPN接続時に使用するDNS(任意)
DNS = 1.1.1.1

[Peer]
# サーバーの公開鍵
PublicKey = <SERVER_PUBLIC_KEY>

# サーバーのパブリックIPとポート
Endpoint = <SERVER_PUBLIC_IP>:51820

# VPN経由でルーティングするトラフィック:
# 0.0.0.0/0 = すべてのトラフィック(フルトンネル)
# 10.0.0.0/24 = VPN内部トラフィックのみ(スプリットトンネル)
AllowedIPs = 10.0.0.0/24

# NAT(家庭用ルーター、4G等)の背後にいる場合の接続維持
PersistentKeepalive = 25

ステップ7:サーバーでWireGuardを起動する

# トンネルを起動する
sudo wg-quick up wg0

# 起動時に自動的に開始するよう設定する
sudo systemctl enable wg-quick@wg0

# 状態を確認する
sudo wg show

wg showの出力にはトンネル情報とピアの一覧が表示されます。ピアのセクションにlatest handshakeの行が表示されれば、クライアントが正常に接続されています。

ステップ8:サーバーのファイアウォールでポートを開放する

# UFWを使用している場合
sudo ufw allow 51820/udp
sudo ufw reload

# iptablesを直接使用している場合
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT

実際の接続を確認する

クライアントが接続したら、ターミナルからすばやくテストします:

# VPN IP経由でサーバーにpingする(パブリックIPではない)
ping 10.0.0.1

# VPN IP経由でサーバーにSSH接続する
ssh [email protected]

10.0.0.1へのpingとSSHが成功すれば、VPNは正常に動作しています。ハンドシェイクは通常1秒以内に完了します — 初めて接続したとき、その速さに驚くはずです。これでSSHポート22をファイアウォールで閉じることができます — WireGuardの鍵を持つ人だけがサーバーにアクセスできるようになります。

新しいクライアントを追加する:サービスの再起動不要

これがWireGuardで最も気に入っているところです。新しいクライアントを追加する際に、証明書に署名したりトンネルを再起動する必要はありません:

# 新しいピアを即時追加する(再起動なしで有効になる)
sudo wg set wg0 peer <CLIENT2_PUBLIC_KEY> allowed-ips 10.0.0.3/32

# 再起動後も維持するため、/etc/wireguard/wg0.confにも追記する:
# [Peer]
# PublicKey = <CLIENT2_PUBLIC_KEY>
# AllowedIPs = 10.0.0.3/32

よくあるトラブルのトラブルシューティング

  • 10.0.0.1にpingできるがインターネットにアクセスできないcat /proc/sys/net/ipv4/ip_forwardを実行して、出力が1であることを確認してください。正しくてもまだ問題がある場合は、PostUpのインターフェース名がip aの出力と一致しているか確認してください
  • 何も接続できないsudo wg showを実行して、latest handshakeが表示されなければ、UDPポート51820がブロックされています。UFWまたはVPSのセキュリティグループを確認してください
  • 数分後に接続が切れる:クライアント設定にPersistentKeepalive = 25を追加してください — NATの背後にいるクライアントでは必須です
  • 「invalid key」エラー:設定ファイルには実際の鍵の内容(base64文字列)を記述する必要があります。ファイル名server_private.keyではありません

チーム全体のセットアップが完了すると、サーバーのログはすっきりします。SSHブルートフォースも、毎日何千件もの失敗したログイン試行もなくなります。サーバーのパブリックポートはほぼすべて閉じられ、51820/UDPと443/TCPだけが開いています — 最初から目指していたセキュリティの形です。

Share: