投稿日

オープンソースVPN 「WireGuard」とは?ホワイトペーパーから読み解く仕組みや実用性

こんにちは、ソラコムのテクノロジー・エバンジェリスト 松下(ニックネーム: Max)です。

IoT プラットフォーム「SORACOM」には、Wi-Fi や 有線LAN といった IP 通信を、LTE/5G通信と同様に扱うことができる、セキュアリンクサービス「SORACOM Arc (アーク)」があります。このサービスは「WireGuard (ワイヤーガード)」という、オープンソースの VPN によって実現されていますが、ここで初めて聞いたという方もいらっしゃるのではないでしょうか。

そこで本ブログでは WireGuard の概要や利用にあたっての疑問点を、ホワイトペーパーや実際の動作を基に確認していきます。後半では WireGuard を実際に使う方法を解説します。

WireGuardとは?

WireGuardとは、オープンソースの VPN プロトコル / ソフトウェアです。

WireGuardのページの冒頭にあるとおり「最先端の暗号技術を採用した、シンプルかつ高速なVPN」で、VPN でよく使われている IPSec VPN や OpenVPN と比較して実装がシンプルで高速であり、置き換えを目指しています。

WireGuard の仕組みや実用性

WireGuardのホームページテクニカルホワイトペーパー(PDF)を基に、特徴を確認していきます。

  • 最先端の暗号技術を採用した、オープンソース VPN
  • 幅広い動作環境
  • 通信は UDP を使用
    • WireGuard は UDP 上の VPN プロトコルです。NAT/NAPTを越えた通信(NATトラバーサル)に対応しています。

それでは、検討時によく出る疑問点を確認していきましょう。

WireGuard のセキュリティ

VPN で気になるのがセキュリティです。WireGuard に使われている暗号化や鍵交換には、すでに広く使われている技術が採用されています。

接続の識別(認証)は、Curve25519 による公開鍵認証(ECDH)です。
Curve25519 による公開鍵は32バイト(Base64エンコーディング後で44バイト)という短い文字列であり、これにより設定ファイルがシンプルです。ちなみに公開鍵認証以外の手法、例えばユーザーID/パスワードでの認証方式はありません。

暗号化とメッセージ認証は、ChaCha20-Poly1305 による認証付き暗号(AEAD)です。
ChaCha20-Poly1305とは、ChaCha20というストリーム暗号とPoly1305というメッセージ認証(検証)を組み合わせた暗号アルゴリズムを表しています。この組み合わせは RFC(インターネット技術の標準的な仕様)になっておりTLS でも使われています。また、IPSec VPNでも ChaCha20-Poly1305 が指定できたりと、すでに広く使われている技術です。

その他、WireGuard で採用されている技術の一覧は Primitives をご覧ください。

また、シンプルな実装を目指しており、実際にプログラムサイズもコンパクト(4,000行程度)でソースコードレベルでの検証や監査についても、現実的な透明性を持っています。

WireGuard の実用性

VPN は速度や接続性も重要です。WireGuard は、これらにおいても十分実用的です。

スループットと応答速度

スループットや応答速度の比較は WireGuard のページに掲載されています。総じて高速です。

https://www.wireguard.com/performance/#benchmarking より引用

また CPU 使用率が IPSec VPN や OpenVPN と比較して低い事も挙げられます。逆の見方をすれば、より軽量な環境でも使えます。その結果、特徴のところで紹介した lwIP 向け実装や、それをベースにした ESP32(マイコン) 向け実装 もあります(例えば M5Stack Basic で動作します)。

接続の安定性

WireGuard は IP アドレスの変化や再接続に強く、接続性が高い設計です。

WireGuard のクライアントは、WireGuard サーバーの IP アドレス(エンドポイント)設定を用いて VPN 接続を開始します。その後は設定内のエンドポイントは使わずに、受信メッセージの “送信元のIPアドレス” を参照するため、クライアント・サーバー双方の IPアドレスが変わっても通信ができます。例えば、IPアドレスが頻繁に変わるスマートフォン等でも安定的につながります。

また、鍵交換(ハンドシェークイニシエーション)が1往復(1-RTT)と低コストなため、普段から頻繁に鍵交換をしています。このおかげで安全性が向上し、再接続も速やかです。

以下は、WireGuard で VPN 接続しているスマートフォンのネットワークを、 ping の途中で Wi-Fi から LTE に切り替えてみた様子です。ネットワークを一時的に OFF にしたため、その間(11〜13)のパケットは欠落していますが、その後はすぐに回復できています。

この動作の詳細は Built-in Roaming や、テクニカルホワイトペーパーの 5.4.1 Protocol Overview(PDF) 、 6.1 Preliminaries(PDF) をご覧ください。

動画の様子は、IPv4 から他の IPv4 アドレスに切り替わったときの様子です。WireGuard は IPv6 に対応していますが、IPv4→IPv6といったIPスタックをまたぐローミングは未検証です。

UDPの順不同到達対策

UDPはパケットの到達順序が保証されない(順不同到達)ため、確実な通信を必要とするプロトコルでは懸念があると言われますが、WireGuardはプロトコル内にパケットカウンター(msg.counter)が実装されており、受信側でパケット順番を再構成する仕組みとなっており、順不同到達の対策がされています。

この動作の詳細は Nonce Reuse & Replay Attacks や、テクニカルホワイトペーパーの 5.4.6 Subsequent Messages: Transport Data Messages(PDF) をご覧ください。

WireGuard の注意点

WireGuard の採用については注意点もあります。

Known Limitations やテクニカルホワイトペーパーの 1 Introduction & Motivation(PDF) にもいくつか記載されていますが、その中でも以下2点は検討時の注目点になるでしょう。

  • 通信はUDPのみ
  • クリプトアジリティが排除されている
    • クリプトアジリティとは、VPNで採用しているアルゴリズムで問題があった場合に、他のアルゴリズムへ簡単に変更できることを指します。これは、VPN自体を長く安全に使うための設計ですが、実装や設定が複雑になるデメリットがあります。
      WireGuardは、クリプトアジリティ(の設計)を採用しないことでシンプルさを実現しました。WireGuard で使用している技術(Primitives)に問題があったら、WireGuard 自体をバージョンアップすることで対応します。

UDP が使えないネットワーク環境や、採用要件に「クリプトアジリティ必須」がある時はご注意ください。

WireGuard を使う

ここからは WireGuard を使うための手順を紹介します。

WireGuard では、WireGuard が動くコンピューターやルーターの事を Peer といいます。そして、接続を開始する Peer をクライアント、接続の受け付け側の Peer をサーバーと分類しています。

  1. クライアント、サーバーそれぞれの Peer に、 WireGuard をインストールする
  2. それぞれの Peer で `wg` コマンドによる秘密鍵・公開鍵のペアを作成する
  3. それぞれの Peer の公開鍵を相手方にコピーする
  4. それぞれの Peer で設定(ファイル作成)を行う
  5. サーバーで WireGuard を起動し、待ち受ける
  6. クライアントでWireGuard を起動し、VPN 接続を開始

サーバーとクライアント双方を準備するのは大変です。
WireGuard では動作確認用の WireGuard サーバー(デモサーバー)が公開されています。そこで、今回はLinux(Raspberry Pi OS) からWireGuard デモサーバーに接続するクライアント側の手順を紹介します。

WireGuard デモサーバー側のネットワークは 192.168.4.0/24 です。このネットワークがお使いのネットワーク内に存在する場合は、デモサーバーの利用を控えたほうが良いでしょう。

WireGuard のインストール

以下のコマンドでインストールできます。

sudo apt install wireguard-tools

wg コマンドで秘密鍵・公開鍵のペアを作成

クライアント側で使う秘密鍵と公開鍵のペアを作成します。これは wg コマンドで行います。

秘密鍵の作成:

wg genkey | sudo tee /etc/wireguard/wg_demo_client.key
sudo chmod 400 /etc/wireguard/wg_demo_client.key

公開鍵の作成:

sudo cat /etc/wireguard/wg_demo_client.key | wg pubkey | sudo tee /etc/wireguard/wg_demo_client.pub

これで /etc/wireguard/ の中に wg_demo_client.key(秘密鍵) と wg_demo_client.pub(公開鍵) が作成されました。

Linux 上の wg コマンドで作成した秘密鍵・公開鍵は、Windows や Android といった他の OS でも利用できます。
他には curve25519tool という CLI ツールもあります。WireGuard の設定ファイル内での鍵指定はBase64エンコードですが、このツールの出力はHEX文字列で表現する方式です。HEX文字列を xxd や base64 コマンドを使って Base64 エンコーディングしてください。

公開鍵を相手方にコピー

WireGuard デモサーバーへ、クライアントの公開鍵をコピーします。

WireGuard デモサーバー demo.wireguard.comtcp:42912 へ公開鍵をテキストで送信すると、デモサーバーの公開鍵やクライアント設定用の情報が返却されます。テキスト送信には netcat(nc) コマンドが利用できます。

apt install netcat-openbsd
sudo cat /etc/wireguard/wg_demo_client.pub | nc demo.wireguard.com 42912

正しく受け付けられると、以下のように “:” 文字区切りの文字列が得られます。

$ sudo cat /etc/wireguard/wg_demo_client.pub | nc demo.wireguard.com 42912
OK:JRI8Xc0z(省略)n4g+/PFs=:12912:192.168.84

内容は以下の通りです。

  • OK: 正常処理ができたことを表す固定文字
  • JRI8Xc0z(省略)n4g+/PFs=: サーバーの公開鍵
  • 12912: サーバー側の待ち受けポート番号
  • 192.168.4.84: クライアント側のインターフェイスに割り当てる IP アドレス

この例は WireGuard のデモサーバーとのやり取りでしたが、実際の WireGuard サーバーと通信する場合も、同様の情報を交換し合う事になります。

設定(ファイル作成)を行う

クライアント側で /etc/wireguard/wg_demo0.conf を作成します。このファイル名は wg コマンドでの操作やOS上でのインターフェイス名にも使われます。

[Interface]
PrivateKey = クライアントの秘密鍵(wg_demo_client.key の内容)
Address = サーバー側から得たクライアントへの割り当てIPアドレス

[Peer]
PublicKey = サーバーの公開鍵
EndPoint = demo.wireguard.com:サーバー側から得たポート番号
AllowedIPs = 0.0.0.0/0

さきほどのデモサーバーから得た値を基にすると、以下のような wg_demo0.conf になります。

[Interface]
PrivateKey = wDrivqCtCslS(省略)VFysOWM=
Address = 192.168.4.84

[Peer]
PublicKey = JRI8Xc0z(省略)n4g+/PFs=
EndPoint = demo.wireguard.com:12912
AllowedIPs = 0.0.0.0/0

ファイルを作成したら wg_demo0.conf を読み取り専用にしておきます。

sudo chmod 400 /etc/wireguard/wg_demo0.conf

設定ファイルを作り終えたら wg_demo_client.key や wg_demo_client.pub は不要となるため、削除可能です。公開鍵が再度必要となったら、設定ファイル内の PrivateKey から wg pubkey で再生成できます。

クライアントでWireGuard を起動し、VPN 接続をする

コマンドラインでの接続には wg-quick コマンドを使います。テスト接続やオンデマンドでつなげたい時に利用できるコマンドです。

sudo wg-quick up wg_demo0

引数の wg_demo0 は、先ほど作成した設定ファイル名が基になります。

wg-quickの実行例です。

$ sudo wg-quick up wg_demo0
[#] ip link add wg_demo0 type wireguard
[#] wg setconf wg_demo0 /dev/fd/63
[#] ip -4 address add 192.168.4.84 dev wg_demo0
[#] ip link set mtu 1420 up dev wg_demo0
[#] wg set wg_demo0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg_demo0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] nft -f /dev/fd/63
確認方法

ip addr コマンドで Linux 上に wg_demo0 インターフェースができていることが確認できます。

$ ip addr show dev wg_demo0
6: wg_demo0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 192.168.4.84/32 scope global wg_demo0
      valid_lft forever preferred_lft forever

接続ができていれば、デモサーバーのネットワーク内にあるサーバーの1つ「192.168.4.1」に対して ping が通ります。

$ ping 192.168.4.1
PING 192.168.4.1 (192.168.4.1) 56(84) bytes of data.
64 bytes from 192.168.4.1 (192.168.4.1): icmp_seq=1 ttl=64 time=74.195 ms
64 bytes from 192.168.4.1 (192.168.4.1): icmp_seq=2 ttl=64 time=37.120 ms
64 bytes from 192.168.4.1 (192.168.4.1): icmp_seq=3 ttl=64 time=50.099 ms
^C

http://demo.wireguard.com の “wg show demo” のところにも、クライアント側の公開鍵文字列(wg_demo_client.pub) が表示されており、接続できたことがわかります。

“wg show” からもわかるように、デモサーバーへは様々なところから接続されています。IP アドレス間のフィルタリングは一切無いため、接続確認が終わり次第切断しましょう。

どうしてもつながらない場合は、ルーターやファイアウォールでのパケットフィルタの設定を確認してください。UDP が通過できないと WireGuard は動作しません。

WireGuard の切断

wg-quickdown サブコマンドで切断できます。インターフェースも削除されます。

sudo wg-quick down wg_demo0

実際はこのようになります。

$ sudo wg-quick down wg_demo0
[#] ip -4 rule delete table 51820
[#] ip -4 rule delete table main suppress_prefixlength 0
[#] ip link delete dev wg_demo0
[#] nft -f /dev/fd/63

念のため ip addr でも確認しておきましょう。

$ ip addr show dev wg_demo0
Device "wg_demo0" does not exist.

WireGuard サーバーや、自動起動など運用に向けて

サーバーに関しては、実はクライアントとほぼ同じ設定となります。具体的には、クライアント側の設定ファイル内 [Peer] での EndPoint = が無い程度の違いです。それだけでサーバーとして待ち受けます。Raspberry Pi OS であれば PiVPN で、サーバーのインストールから設定もできます。

本格的な運用に向けては、サーバー・クライアント共に OS 起動時の自動接続も必要となります。この件は WireGuard の範疇を超えるため割愛しますが、例としては systemd を利用する方法があります。

WireGuard を採用「SORACOM Arc」の利点

冒頭で紹介した「SORACOM Arc」は、ソラコムが提供する WireGuard サーバーサービスと言えます。
ここで SORACOM Arc の利点を紹介します。

  • フルマネージド提供
    • WireGuard サーバーの構築や運用の手間がありません。
  • 初期設定・開始までが容易
    • SORACOM Arc では、設定済みのクライアント向け WireGuard 設定ファイル(バーチャルSIMと呼んでいます)をオンラインで発行・ダウンロードできます。
    • SORACOM Arc に接続できる Linux 向けエージェントソフトウェア「soratun」は、1つのファイルだけで動作します。設定ファイルと soratun の2ファイルだけ準備できれば開始可能です。 
  • 異なる通信技術を一元管理、併用利用
    • WireGuard の VPN 接続を、 LTE/5Gといったセルラー通信と同様に扱えます。例えば LTE モデルと Wi-Fi(+WireGuard) モデルといった製品の通信を SORACOM 上で一元管理できます。
    • LTE と Wi-Fi(+ WireGuard) の併用もできます。1つのデバイス内に Wi-Fi(+WireGuard) とLTE を用意し、例えば普段は Wi-Fi(+ WireGuard)をメインにしておきつつ、バックアップやメンテナンス用として LTE を利用する構成が考えられます。
  • プライベートネットワーク (閉域網) の構築と相互通信
    • SORACOM Gate D2D を有効化することで、SORACOM Arc に接続された WireGuard 機器間での閉域通信が可能です。また、 LTE <-> Wi-Fi(+ WireGuard) といった通信も可能です。(参照: デバイス間で通信する (SORACOM Gate D2D)

SORACOM Arc は有料のサービスですが無料枠があります。例えば、同じく無料枠のあるオンデマンドリモートアクセスサービス「SORACOM Napter」を使い、WireGuard で SORACOM Arc につながっている NAPT 内の Raspberry Pi へ、SORACOM Napter を経由して SSH できます。

料金については SORACOM Arc 料金プランをご覧ください。

おわりに

モダンなオープンソース VPN 「WireGuard」について、さまざまな文献や実際の利用を基に紹介してきました。

インターネットは固定的な設備やサーバー・IPアドレスの時代から、クラウドやモバイル、そしてIoTと、利用シーンのバリエーションが増えており、ネットワークに求められる機能も変化しています。例えば HTTP/3 は UDP ベースの QUIC を使い、HTTP をより高速かつ様々な環境に適用できるようにしています。

VPN にも「モダン」化の波が来ているようです。そんな中、手軽かつ実用性がある VPN として、WireGuard はこれから取り組むのに値するプロダクトではないでしょうか。
SORACOM Arc 共々、ぜひ試してみてください!

参考文献

― ソラコム松下 (Max / @ma2shita)