65 人が閲覧(直近 30 日) インフラ・クラウド

WireGuardとは?仕組み・使い方と設定手順、繋がらない時の切り分け【2026年10月】

WireGuardとは?仕組み・使い方と設定手順、繋がらない時の切り分け【2026年10月】

WireGuard(ワイヤーガード)は、公開鍵を交換したピア同士をUDPで結ぶVPNプロトコルです。2020年3月リリースのLinux 5.6でカーネルに統合され、Windows・macOS・Android・iOS向けの公式クライアントもあります。この記事では、暗号とハンドシェイクの仕組み、料金とライセンス、Linuxでの設定手順、スマートフォンとWindowsのアプリ、OpenVPN・IPsecとの違いを順に説明します。後半では、検証環境に2台のピアを作り「繋がらない」状態を4通り再現した結果をもとに、wg show の表示から原因を絞り込む方法を示します。

まとめ:WireGuardの要点

  • WireGuardはNoise_IKpsk2を土台にしたVPNプロトコルで、暗号はCurve25519・ChaCha20Poly1305・BLAKE2sなどに固定されている。暗号方式を選ぶ設定はない。
  • 料金は無料。Linuxカーネル実装とwireguard-toolsはGPLv2、wireguard-go・Windows・iOS/macOS版はMIT、Android版はApache 2.0で公開されている。
  • 設定は鍵ペアを作り、wg0.confに自分の秘密鍵・トンネル内アドレスと相手の公開鍵・AllowedIPsを書いて wg-quick up wg0 を実行するだけ。
  • ハンドシェイクは開始148バイト・応答92バイトの1往復。送信時に鍵が120秒より古くなっていれば、開始側が鍵を作り直す。
  • 通信はUDPのみでTCPは使えない。ユーザー認証やIPアドレスの自動割り当ても持たないため、多人数ならTailscaleなどの管理層と組み合わせる。
  • 繋がらないときは、pingなどで通信を発生させてから wg show の latest handshake が更新されるかを見る。更新されなければ鍵・PresharedKey・UDPの到達性、更新されるのに通信できなければAllowedIPs・ルーティング・MTUの順に疑う。

以下、仕組み・料金・設定手順・アプリ・比較・制約・切り分けの順に根拠を示します。

WireGuardとは:開発の経緯と料金・ライセンス

WireGuardはJason A. Donenfeld氏が開発したVPNプロトコルと、その実装群の名前です。使う暗号を1組に固定し、設定項目を鍵とアドレスと経路に絞っています。

Linux 5.6への統合とWireGuard 1.0.0

Linus Torvalds氏がLinux 5.6のリリースを告知したのは2020年3月29日(LWNに転載された告知)で、翌30日に開発者がWireGuard 1.0.0のリリースをメーリングリストで告知しました。5.6以降のカーネルならモジュールが同梱されているので、追加のカーネルパッチは要りません。

よく引かれる「約4,000行」は統合前の論文の数字です。2026年10月18日時点のLinux本体(7.3-rc7)の drivers/net/wireguard は、自己テストと自動生成コードを除いて6,071行、空行とコメント行を除くと約4,650行でした(暗号プリミティブの lib/crypto は含まない)。

料金は無料:実装ごとのライセンス

WireGuard自体に利用料はかかりません。費用が出るのはサーバーにするVPSの代金か、WireGuardを使う商用VPNサービスの月額です。製品に組み込むときは実装ごとのライセンスが効いてきます。

実装 用途 ライセンス
Linuxカーネル実装 Linux 5.6以降のモジュール GPLv2
wireguard-tools wg・wg-quick GPLv2
wireguard-go ユーザー空間実装 MIT
wireguard-windows Windowsクライアント MIT
wireguard-apple iOS・macOSクライアント MIT
wireguard-android Androidクライアント Apache 2.0

各リポジトリのCOPYINGで確認しました(例:wireguard-androidのCOPYING)。なお「WireGuard」の名称とロゴはDonenfeld氏の登録商標で、製品名に使うときは商標ポリシーに従う必要があります。

対応OSと公式クライアントの現行版

2026年10月19日時点で確認した公式クライアントの最新版は次のとおりです。iOS・macOS版は2023年2月の1.0.16から更新が止まっていますが、App Storeで配布は続いています。

対象 最新版 日付
wireguard-tools(Linux・macOS等) v1.0.20260223 2026-02-23
Windows 1.1.1 2026-09-20
Android 1.0.20260315 2026-03-15
iOS・macOS 1.0.16 2023-02

Windows版は2021年12月の0.5.3のあと、2026年4月18日に1.0、5月7日に1.1、9月20日に1.1.1のタグが付きました(wireguard-windowsのリポジトリ)。Linuxはディストリビューションのパッケージが最新タグより遅れることがあり、検証に使ったAlpine 3.22のパッケージは v1.0.20250521 でした。

WireGuardの仕組み:暗号・ハンドシェイク・ローミング

Noise_IKpsk2と固定された暗号

公式のプロトコル解説によると、ハンドシェイクはNoise Protocol FrameworkのIKpsk2パターンで組まれ、次の暗号を使います。wireguard-goのソースでも、構成名は Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s と1つの文字列で埋め込まれています。

  • 鍵交換:Curve25519(ECDH)
  • 暗号化と改ざん検知:ChaCha20Poly1305(RFC 7539のAEAD)
  • ハッシュと鍵付きハッシュ:BLAKE2s
  • 鍵導出:HKDF(RFC 5869)
  • ハッシュテーブルの鍵:SipHash24

暗号の交渉が無いので、弱い暗号へのダウングレード攻撃は起こりません。代わりに暗号を設定で差し替えることはできず、破られたらプロトコルの版を上げて対応します。

148バイトと92バイトの1往復と送信時の再鍵条件

接続を始める側は148バイトのハンドシェイク開始メッセージを送り、相手は92バイトの応答を返します。これで双方がセッション鍵を導出し、データ送信が始まります。wireguard-goの device/constants.go に定義されたタイマーは次のとおりで、論文の値と一致します。

定数 値 意味
RekeyAfterTime 120秒 送信時に鍵がこれより古ければ再鍵
RejectAfterTime 180秒 これより古い鍵のパケットは捨てる
RekeyAttemptTime 90秒 ハンドシェイクを再試行し続ける上限
RekeyTimeout 5秒 応答が無いときの再送の基準間隔
KeepaliveTimeout 10秒 受信後に返す空パケットの待ち時間
RekeyAfterMessages 2の60乗 この通数でも鍵を作り直す

再鍵は時計で一律に起きるのではなく、開始側がパケットを送ろうとした時点で鍵が120秒より古ければ行われます。通信が無い間はハンドシェイクも起きません。再送はRekeyTimeoutの5秒に最大334ミリ秒の揺らぎを足した間隔です(wireguard-goの device/timers.go)。セッション鍵を使い捨てるので、長期の秘密鍵が後から漏れても過去の通信は復号できません(前方秘匿性)。検証では、UDPを遮断していたサーバーの遮断を外して6秒後に打ったpingが通りました。再送の間隔そのものは測っていません。

UDPのみ・送信元が変わっても追従するローミング

WireGuardのパケットはすべてUDPで運ばれ、公式の既知の制約にあるとおりTCPには対応しません。各ピアは、認証と復号に成功した最新パケットの送信元IPアドレスとポートを、次の送信先として使います。

検証でクライアント側の送信元ポートを35141から40000へ変えたところ、サーバー側の wg show wg0 endpoints は1回のpingで 172.30.0.3:40000 に書き換わりました。Wi-Fiとモバイル回線を切り替えても張り直しが要らず、サーバー側にクライアントの Endpoint を書かなくてよいのはこの仕組みのためです。

WireGuardの使い方:Linuxでのサーバーとクライアントの設定手順

ここではLinuxのサーバー1台とクライアント1台を、トンネル内アドレス 10.8.0.0/24 で結ぶ最小構成を作ります。ポートはwg(8)マニュアルの例と同じ51820/UDPにします。ListenPortは省略するとランダムに決まるので、待ち受ける側だけ固定すれば足ります。

OS別のwireguard-toolsのインストール

# Ubuntu / Debian
sudo apt install wireguard-tools
# Fedora / RHEL系
sudo dnf install wireguard-tools
# Alpine
sudo apk add wireguard-tools
# macOS(Homebrew)
brew install wireguard-tools

WireGuardの鍵ペアの生成

サーバーとクライアントのそれぞれで秘密鍵と公開鍵を作ります。公開鍵はBase64で44文字です。

umask 077
wg genkey | tee privatekey | wg pubkey > publickey

umaskを077にしておくと、作られるファイルは所有者しか読めません。wg genkey > privatekey のように通常ファイルへ直接書き出したときに限り、他のユーザーが読める権限だとwgが「Warning: writing to world accessible file.」と警告します。上の例のようにteeへパイプで渡す場合は警告が出ないので、ls -l privatekey で権限が -rw——- になっているかを自分で確かめます。他人に読まれた可能性がある鍵は作り直し、相手側に登録した公開鍵も差し替えます。相手に渡すのは公開鍵だけです。

サーバー側wg0.confの設定

# /etc/wireguard/wg0.conf(サーバー)
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = サーバーの秘密鍵

[Peer]
PublicKey = クライアントの公開鍵
AllowedIPs = 10.8.0.2/32

AllowedIPsは2つの働きを兼ねます。送るときは「この宛先はこのピアへ」という経路表に、受け取るときは「このピアから来てよい送信元」というフィルターになります。サーバー側ではクライアント1台につき /32 を1つ割り当てるのが基本です。範囲の書き方はCIDRとは?表記の読み方と計算方法・サブネット設計とAWS VPCでの使い方を実装者向けに解説で確認できます。

クライアント側wg0.confの設定

# /etc/wireguard/wg0.conf(クライアント)
[Interface]
Address = 10.8.0.2/24
PrivateKey = クライアントの秘密鍵
# DNS = トンネル内で応答するDNSサーバーのアドレス(用意した場合のみ)

[Peer]
PublicKey = サーバーの公開鍵
Endpoint = サーバーのグローバルIP:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25

AllowedIPsを 10.8.0.0/24 にするとVPN内の通信だけがトンネルを通ります。IPv4の通信をすべて通すなら 0.0.0.0/0、IPv6も通すなら ::/0 を並べて書きます。PersistentKeepaliveは、NATの内側のクライアントが、サーバー側から先に届く通信(クライアントへの接続やサーバーからのping)を受ける必要があるときに付けます。25秒は公式Quick Startが挙げる値で、ルーターのNAT対応表が消える前に空パケットを送ります。既定は0(無効)です。DNS行を書く場合、wg-quickは resolvconf コマンドを呼び出してDNSを登録します。検証でresolvconfを外して起動すると「resolvconf: command not found」で止まり、wg-quickは作りかけのwg0を削除しました(終了コード127)。DNS行を使うなら、openresolvなどresolvconf互換のコマンドがあるかを先に確かめてください。

wg-quickでの起動とwg showでの接続確認

次のコマンドはUbuntu(UFWとsystemdを使う環境)の例です。IP転送は、クライアントの通信をサーバーの先のLANやインターネットへ中継する場合だけ必要で、VPN内の10.8.0.0/24同士で通信するだけなら要りません。

sudo ufw allow 51820/udp
sudo sysctl -w net.ipv4.ip_forward=1
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0   # 再起動後も自動で上げる

検証環境(colima上のUbuntuカーネル6.8.0、Alpine 3.22のコンテナ2台)でクライアントを上げたときの出力です。MTUを指定しなくても、wg-quickが外側の経路のMTU 1500から80を引いた1420を設定しています。80は外側のIPv6ヘッダー・UDPヘッダー・WireGuardのヘッダーと認証タグの合計です。

[#] ip link add dev wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.2/24 dev wg0
[#] ip link set mtu 1420 up dev wg0

PersistentKeepaliveを付けたクライアントは、pingを打つ前の時点でハンドシェイクを済ませていました。サーバー側の wg show には、設定に書いていないクライアントの送信元が endpoint として現れます。

peer: ZTLdai47J2N6zC+643nx8GGfed5udyq2RK6O6T1cNVc=
  endpoint: 172.30.0.3:40718
  allowed ips: 10.8.0.2/32
  latest handshake: Now
  transfer: 180 B received, 92 B sent

送信の92バイトはハンドシェイク応答そのものです。latest handshake は過去に成功した時刻なので、その後の遮断までは保証しません。pingなどを打った直後に「Now」や数秒前へ更新されていれば、その時点で鍵とUDPの到達性は確認できます。経路の途中でMTUが1500より小さい回線(PPPoEなど)では、1420でも大きすぎて大きなパケットだけが落ちることがあります。その見分け方はMTUとは?最大転送単位の仕組み・1500とジャンボフレーム・PMTUD/MSS調整と測定手順を実装者向けに解説にまとめています。

Android・iOS・WindowsのWireGuardアプリの設定

Android・iOS:QRコードでの設定の取り込み

スマートフォンでは公式アプリ「WireGuard」を入れ、サーバー側で作ったクライアント設定を読み込みます。アプリの画面にも出てくる方法は、設定ファイルをQRコードにして端末のカメラで読む手順です。QRコードにはクライアントの秘密鍵がそのまま入るので、画面の撮影や共有は秘密鍵を渡すのと同じです。読み取ったら表示を消してください。

qrencode -t ansiutf8 < client.conf

あわせてサーバーのwg0.confに、スマートフォンの公開鍵とトンネル内アドレス(例:10.8.0.3/32)を [Peer] として追記し、sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)' で反映します。プロセス置換の中の wg-quick strip もroot権限で動かす必要があるので、全体をsudoで起動したbashに渡します。syncconfは既存のピアの接続を切らずに差分だけを適用します。

Android版のソースで確かめた機能は次のとおりです。最低対応はAPIレベル24(Android 7.0)です。

  • アプリ単位の除外と「指定アプリだけ通す」設定
  • Android本体の「常時接続VPN」からの起動
  • クイック設定タイルでのオンとオフ
  • 端末起動時に、前回有効だったトンネルを戻す設定
  • root化端末でのカーネル実装の利用(使えなければroot不要のユーザー空間実装で動く)

Windows:トンネルのサービス化と設定の暗号化保存

Windows版は公式サイトのインストーラーで入れ、.confファイルを取り込むか画面で新規作成します。設定は %ProgramFiles%\WireGuard\Data\Configurations\ にDPAPIで暗号化した .conf.dpapi として保存されます。このフォルダへ平文の .conf を置くと、マネージャーが暗号化して元のファイルを削除するので、配布スクリプトからの追加にも使えます。

トンネルを有効にすると、サービス名 WireGuardTunnel$トンネル名、表示名「WireGuard Tunnel: トンネル名」のWindowsサービスが作られます。このサービスはトンネルを有効にしている間だけ存在し、無効にすると削除されます。サービス一覧で見かける「WireGuard Tunnel」はこれです。画面を使わずに配布するときは、企業向けの説明にある次のコマンドを管理者権限で実行します。

wireguard /installtunnelservice C:\path\to\wg0.conf
wireguard /uninstalltunnelservice wg0

WireGuardとOpenVPN・IPsecの違い

項目 WireGuard OpenVPN IPsec(IKEv2)
外側の通信 UDPのみ UDPかTCP IKEはUDP、データはESP
暗号の交渉 なし(固定) TLSで交渉 IKEで交渉
ハンドシェイク 1往復 TLSの往復 IKE_SA_INIT等で2往復
認証の単位 公開鍵のみ 証明書・ID/パスワード 証明書・PSK・EAP
アドレス割り当て 手動 サーバーから配布 サーバーから配布
回線切り替え 送信元を自動追従 floatの設定で追従 MOBIKEで対応

速度については、公式の性能ページ自身が、掲載しているベンチマークはLinux 4.6.1時代の古いもので、その後WireGuardとIPsecはどちらも速くなったと注記しています。同ページの評価は「WireGuardはマルチスレッドのおかげで場合によってIPsecをやや上回り、OpenVPNは非常に遅いまま」です。数倍の差を断言する記事は古い計測を引いていることが多いので、自分の回線とCPUで iperf3 を回して確かめてください。

UDPが通らない社外ネットワークから443/TCPで入る必要があるならOpenVPN。相手が既存のルーターやクラウドのVPNゲートウェイならIPsecです。AWS・Azure・Google Cloudの拠点間接続用マネージドVPNはIPsecしか受け付けないので、クラウドとの拠点間接続はSite-to-Site VPNとは?3クラウドのIKE既定値とstrongSwan接続手順の方式になります。自前のサーバーや端末同士を少ない設定でつなぐならWireGuardが向きます。

WireGuardのデメリットと公式が挙げる制約

公式の既知の制約ページから、導入前に知っておくべき点を挙げます。

  • TCPで使えない:UDPを止めるネットワークでは通らない。udp2rawのFakeTCPモードはTCPヘッダーを付けた擬似通信で、本物のTCP接続ではないため、プロキシ経由でしか外に出られない環境は通せない。
  • 通信を偽装しない:WireGuardのパケットは見ればそれと分かり、DPIによる遮断を避ける機能は無い。
  • ユーザー認証とアドレス配布が無い:公開鍵1つが1台を表す。退職者の鍵の失効や、端末ごとのアドレス管理は自分で行う。
  • 時刻に依存する:ハンドシェイクのリプレイ対策にシステム時刻を使う。時刻が過去へ戻るとハンドシェイクができなくなるため、RTCが無い機器ではNTPの同期を先に済ませる。
  • 量子計算機への耐性は標準では無い:PresharedKeyを追加すると、その分の耐性が上乗せされる。

PresharedKeyは wg genpsk で作り、両側の [Peer] に同じ値を書きます。検証で片側だけに入れたところ、クライアントは148バイトの開始メッセージを送り続けるだけで、受信は0バイトのまま接続できませんでした。

利用者の入社・退職で鍵の追加と失効が日常的に起きる、端末ごとに通してよい宛先を変えたい、ログイン履歴を残したい、といった要件があるなら、素のWireGuardに鍵とアドレスの台帳を手で持たせる運用では追いつきません。管理画面を足すなら wg-easy(v15.4.0・AGPL-3.0)や wg-portal(v2.3.1・MIT)、IDプロバイダーでのログインやNAT越えまで任せるなら、WireGuardを土台にしたTailscaleが選択肢です。Tailscaleの調整サーバーを自前で持ちたい場合はheadscaleがあります。

逆に、外部に公開したいのが1つのWebアプリだけなら、ネットワークごとつなぐWireGuardは過剰です。ポート開放なしで公開できるCloudflare Tunnelの方が設定は少なく済みます。社内システムとクラウドを含めたネットワーク全体の設計は、インフラ構築(AWS・Google Cloud・Azure)の支援でもご相談いただけます。

WireGuardが繋がらないときの切り分け(wg showの表示別)

WireGuardは認証に失敗したパケットに返事をしないため、「繋がらない」の見た目はどれも同じです。そこで検証環境で4つの失敗を再現し、wg show の表示を記録しました。AllowedIPsの不一致はサーバー側のピア表示、それ以外はクライアント側のピア表示です。鍵の誤り・UDP遮断・PresharedKeyの試験では、クライアントのトンネルかピアの登録を作り直してハンドシェイク履歴を消してから測っています。すでに動いていた接続が途中で切れた場合は、latest handshake に古い時刻が残ったまま更新されない形で現れます。

再現した原因 latest handshake transfer ping
正常 表示あり 送受信あり 成功
サーバー側AllowedIPsの不一致 表示あり 送受信あり 失敗
相手の公開鍵の誤り 行が出ない 受信0 B・送信148 Bの倍数 失敗
サーバーでUDP 51820を遮断 行が出ない 受信0 B・送信148 Bの倍数 失敗
PresharedKeyを片側だけ設定 行が出ない 受信0 B・送信148 Bの倍数 失敗

表から、確認の順番が決まります。

  1. 通信を発生させても latest handshake が出ない・更新されない:鍵・PresharedKey・UDPの到達性のどれか。クライアント側の表示だけでは3つを区別できません。サーバーで sudo tcpdump -ni any udp port 51820 を実行し、パケットが届いていなければファイアウォールやクラウドのセキュリティグループ、届いていれば鍵とPresharedKeyを疑います。
  2. latest handshake は更新されるのにpingが通らない:まずAllowedIPsを見ます。サーバー側の [Peer] のAllowedIPsにクライアントのトンネル内アドレスが入っていないと、届いたパケットは送信元の検査で捨てられます。AllowedIPsが正しければ、相手ホストのファイアウォール(ICMPの拒否)や、トンネル内アドレスへの経路の重複を確認します。
  3. pingは通るがWebが開けない:全通信を流しているならサーバーのIP転送とNAT(MASQUERADE)、名前解決ができないならクライアントのDNS行を確認します。
  4. 小さな通信だけ通り、大きなファイルやHTTPSが止まる:MTUです。wg0.confに MTU = 1380 などと書いて下げてみます。

ログを見るなら、カーネル実装はroot権限で echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control を実行して dmesg を読み、wireguard-goは LOG_LEVEL=verbose を付けて起動します(Quick Startに記載)。

よくある質問

WireGuardの料金はいくらですか?

無料です。オープンソースで商用利用にもライセンス料はかからず、かかるのはサーバーにするVPSなどの費用か、WireGuardを使う商用VPNサービスの料金です。

WireGuardのポート番号は何番ですか?

決まった番号はありません。公式マニュアルの例が51820/UDPなので、それが慣例として広まっています。ListenPortを省略するとランダムなポートで待ち受けるため、接続を受ける側だけ番号を固定し、そのUDPポートを開けます。

Windowsの「WireGuard Tunnel」とは何ですか?

Windows版WireGuardがトンネルごとに作るサービスの表示名です。「WireGuard Tunnel: トンネル名」として登録され、サービス名は WireGuardTunnel$トンネル名 になります。トンネルを有効にすると作られ、無効にすると削除されます。

AndroidでWireGuardを使うにはどうすればよいですか?

Google Playで公式アプリ「WireGuard」を入れ、クライアント設定をQRコードかファイルで取り込みます。対応はAndroid 7.0以降です。

WireGuardはTCPで使えますか?

使えません。TCPの中にTCPを通すと再送が二重に起きて遅くなるため、公式は意図的にUDPだけにしています。UDPだけを止めるファイアウォールなら udp2raw のFakeTCPモードで通せることがありますが、本物のTCP接続やHTTPプロキシが必須の環境では、TCPで動くOpenVPNを選びます。

関連記事

お気に入りに入れた記事の一覧

一創の公式 SNS

X では毎朝の新着記事と IT ニュースの速報を、YouTube・TikTok・Instagram・LinkedIn・Facebook では記事の解説動画を配信しています。

この記事は以下の記事からリンクされています

ほか 3 件の記事からもリンクされています。

資料請求

RELATED POSTS 関連記事

目次