WireGuardでAzure、オンプレミス、iPhoneを閉域接続しまくる

はじめに

最近流行っているVPNプロダクトである「WireGuard」ですが、お手軽に拠点間を閉域接続できるので便利ですよね。

VPN接続の方法は各種ありますが、特にWireGuardがお手軽である特徴を個人的な感想レベルで以下に示します。

  • VPN「サーバ」「クライアント」の区別なく同じWireGuardのサービスで利用可能
    →WireGuardの設定で挙動を自由に変えられる
  • 拠点間を相互に接続し合う必要なし。片方向から接続すれば繋がる
    →つまり接続元はWANの内側でもOK
  • 接続先もUDP/51820(デフォルト)のポートが空いているだけでOK

今回ためしたこと

  • オンプレミス拠点間を繋いで、どちらの拠点からも対向拠点のサーバ類にアクセス可能にする
  • Azure仮想ネットワーク上にもWireGuardを構築して、Azure File Storageをオンプレミスから参照する
  • iPhone上にWireGuardを導入して出先からもオンプレミス(どの拠点にも)にアクセス可能にする

オンプレミス拠点は自宅と実家の2箇所あり、それぞれのネットワーク上にRaspberry Pi(2B+, 4B)があり、Raspbianが導入されています。

Raspberry Pi(Raspbian)の導入方法、WireGuardのインストール方法については、本記事では省略します。先人の方々の知恵がネット上に大量にありますので、そちらを参照してください。

本記事では、次章の構成に基づいて、各拠点のWireGuardの設定ファイル内容については詳細に説明していきます。

全体構成

以下に図を示します。

拠点としては、左にあるAzure仮想ネットワーク、右上のオンプレミス#1(自宅)、右下のオンプレミス#2(実家)、中央下のモバイル端末があります。

WireGuardのトンネル間通信には専用のセグメント(10.0.0.x/32)を定義します。このネットワークセグメントとピアIPアドレスが、各拠点に設定するWireGuard設定ファイル内でとても重要になります。

拠点名ネットワークセグメントWireGuardピアIPアドレス
Azure192.168.2.0/2410.0.0.3/32
オンプレミス拠点#1192.168.0.0/2410.0.0.2/32
オンプレミス拠点#2192.168.1.0/2410.0.0.1/32
モバイル10.0.0.4/32

上の構成図上で、オレンジの線はWireGuard間のトンネルを示しており、そこにある赤い矢印はピアの接続を開始する方向となります。

今回はパブリックIPアドレスを固定で持つAzure仮想ネットワーク内のVMをハブとして利用しますが、オンプレミス#1,#2の間については直接#2のRaspberry PiのIPv6アドレスに対してピアを張っています。

モバイル端末であるiPhoneはAzure仮想ネットワークに繋がりますが、WireGuardのルーティング設定にてオンプレミス#1,#2にも接続できるようにしました。(Azure仮想ネットワークを経由してそれぞれのオンプレミスに繋がる)

Azure上にはStorage Accountを作成して、プライベートエンドポイントにて仮想ネットワーク上からプライベートIPアドレス(この例では192.168.2.132)にてアクセス可能な設定をしています。SMBによるファイル共有をオンプレミス#1,#2から行う目的です。

WireGuardの準備

Raspberry Pi

先にお伝えしたとおり、ネット上に大量にノウハウがすでにあるので省略します。

以下サイトを参考にされるのが良いかと思います。

https://github.com/adrianmihalko/raspberrypiwireguard

基本的にはWireGuardパッケージを追加して、/etc/sysctl.confの「net.ipv4.ip_forward = 1」に変更するくらいでしょうか。

Azure

適当なリソースグループを作成して、その中に仮想ネットワークを作成します。今回は全体セグメントとして192.168.2.0/24で作成して、中にサブネットとしてWireGuard仮想マシンを入れるdmz-subnet(192.168.2.0/26)の他に、将来用にprivate-subnet(192.168.2.64/26)、プライベートエンドポイント用のazure-subnet(192.168.2.128/26)を作成しています。

WireGuard用の仮想マシンはdmz-subnet上にUbuntu Server 20.04 LTSのVMイメージで作成します。Public IPアドレスも付けます。

通常、Azureポータル上でVMを作成すると、パブリックIPアドレス、プライベートIPアドレス共に動的設定となってるため、それぞれ静的設定に変更してIPアドレスを固定します。

NICの設定で、IP転送を有効化します。

NICに紐付いているNSGにて、UDP/51820を許可する受信規則を追加します。

WireGuardのインストールは普通にaptで導入可能です。

$ sudo apt install wireguard

あとは、/etc/sysctl.confの「net.ipv4.ip_forward = 1」に変更して再起動しておきます。

接続用キーペアの作成

4拠点全てのPrivate Key, Public Keyを作成します。

以下はAzure WireGuard向けのキー作成手順です。

$ mkdir wgkeys
$ cd wgkeys  
$ wg genkey > azure_private.key  
$ wg pubkey > azure_public.key < azure_private.key

これで、Azure WireGuardのazure_private.key, azure_public.keyが wgkeysディレクトリに作成されます。

同じ手順で、オンプレミス#1,#2,モバイル向けのキーもそれぞれ作成します。

拠点名Private keyPublic key
Azureazure_private.keyazure_public.key
オンプレミス拠点#1onpremises1_private.keyonpremises1_public.key
オンプレミス拠点#2onpremises2_private.keyonpremises2_public.key
モバイルmobile_private.keymobile_public.key

WireGuardの設定

各拠点毎に設定する設定ファイルについて説明します。(iPhoneは設定画面にて)

Azure

/etc/wireguard/wg0 の設定内容は以下のとおりです。

[Interface]
Address = 10.0.0.3/32
ListenPort = 51820
PrivateKey = <azure_private.keyファイル内容>

PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

#On-premises 1
[Peer]
PublicKey = <onpremises1_public.keyファイル内容>
AllowedIPs = 10.0.0.2/32, 192.168.0.0/24

#On-premises 2
[Peer]
PublicKey = <onpremises2_public.keyファイル内容>
AllowedIPs = 10.0.0.1/32, 192.168.1.0/24

#Mobile
[Peer]
PublicKey = <mobile_public.keyファイル内容>
AllowedIPs = 10.0.0.4/32

[Interface] セクションでは自身のIPアドレスとして 10.0.0.3/32 を定義しているほか、PostUp, PostDownにてWireGuardサービスの起動・停止時にiptablesコマンドを実行して、仮想ネットワーク内の任意のサーバからのアクセスもルーティングする設定を行っています。

[Peer] セクションはそれぞれの対向拠点毎に定義しています。

AllowdIPsには、対向拠点からのアクセスを許容するアドレスを指定します。
オンプレミス#1,#2からの接続は、WireGuardのピア用IPアドレス(10.0.0.x/32)の他に、それぞれの拠点のLAN側のセグメント(192.168.x.x/24)にあるWindows クライアントからのアクセスも許容させます。

Azure拠点のWireGuardは自身から対向拠点に繋げにはいきません。

オンプレミス拠点#1

/etc/wireguard/wg0 の設定内容は以下のとおりです。

[Interface]
Address = 10.0.0.2/32
ListenPort = 51820
PrivateKey = <onpremises1_private.keyファイル内容>

PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

#On-premises 2
[Peer]
PublicKey = <onpremises2_public.keyファイル内容>
EndPoint = [240d:1a:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:51820 <オンプレミス#2のIPv6 Address>
AllowedIPs = 10.0.0.1/32, 192.168.1.0/24
PersistentKeepAlive = 30

#Azure
[Peer]
PublicKey = <azure_public.keyファイル内容>
Endpoint = xx.xx.xx.xx:51820 <Azure側のPublic IP Address>
AllowedIPs = 10.0.0.3/32, 192.168.2.0/24, 10.0.0.4/32
PersistentKeepAlive = 30

[Interface] セクションでは基本的にAzure側のものと同じです。

[Peer]セクションの1つめはオンレミス拠点#2の接続設定ですが、EndPointの指定をIPv6アドレスで指定しています。これは、オンプレミス拠点#1,#2共にIPv6による通信が可能となっているためこのようにしています。

もしIPv4しか使えない場合はお手持ちのルータでUDP/51820を内側のWireGuardサーバに向けるなどすれば行けると思います。

PersistentKeepAliveは無通信中にもKeep Aliveを30秒毎に送る設定を入れて、ルータで無通信中に切断されないように指定しています。

AllowedIPsですが、Azure側からの許可IPに、モバイルの10.0.0.4/32を追加で入れています。
これは、モバイル(iPhone)が以下の経路での接続に対応するためです。

[iPhone(10.0.0.4/32)] → [Azure WireGuard] → [オプレミス拠点#1 WireGuard] → [オンプレミス拠点#1 セグメント(192.168.0.0/24)]

オンプレミス拠点#2

/etc/wireguard/wg0 の設定内容は以下のとおりです。

[Interface]
Address = 10.0.0.1/32
ListenPort = 51820
PrivateKey = <onpremises2_private.keyファイル内容>

PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

#On-premises 1
[Peer]
PublicKey = <onpremises1_public.keyファイル内容>
AllowedIPs = 10.0.0.2/32, 192.168.0.0/24

#Azure
[Peer]
PublicKey = <azure_public.keyファイル内容>
AllowedIPs = 10.0.0.3/32, 192.168.2.0/24, 10.0.0.4/32
Endpoint = xx.xx.xx.xx:51820 <Azure側のPublic IP Address>
PersistentKeepAlive = 30

基本的にオンプレミス拠点#1のものと似ていますが、Peerセクションではオンプレミス拠点#1にはEndpoint、PersistentKeepAiveの指定はせずに、オンプレミス拠点#1からの接続を待つ形にしています。

Azureへ向けたPeerの設定はオンプレミス拠点#1と同じ内容です。

モバイル

iPhone用クライアントアプリをApp Storeからダウンロードしてきます。

WireGuard

アプリを立ち上げて接続の追加のための「+」を押すと、設定方法として色々出てきますが私は「空の状態から作成」にしました。

事前にazure_public.key、mobile_private.keyはiCloudのメモなどにいれて、iPhoneからのコピペできるようにしておきました。

インターフェースのセクションでは、名前は適当に。秘密鍵にはmobile_private.keyのファイル内容をペーストします。あとはIPアドレスと待受ポートを入力します。

「ピアを追加」をタップして、接続先として公開鍵にazure_public.keyのファイル内容をペースト、エンドポイントにはAzure側のPublic IP Addressを入力します。

AllowedIPsは10.0.0.3/32, 192.168.0.0/24, 192.168.1.0/24を入れました。
キープアライブは30秒で。

WireGuardの起動

Azure拠点、オンプレミス拠点はLinuxなので、systemctlコマンドを使って自動起動を有効化した上で、手動でまずは起動します。

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

iPhoneではWireGuardアプリから先に登録した登録名の右側のスライドをONにして接続します。

3拠点(モバイル以外)のwgコマンド実行結果を以下に示します。
まあ、見た感じはそれぞれの拠点間でトラヒックが発生しており、通信しているようですね。(図が小さくて見づらいと思いますが)

ルーティング設定

お手持ちのブロードバンドルータ(死語?)が通常はデフォルトゲートウェイになっていると思いますが、ルータの機種によってはカスタムルートを追加する機能がなかったりします。

WireGuardをインストールしたサーバ上から他拠点に対してアクセスする場合には特に上記までの設定で問題なくルーティングしてくれるのですが、オンプレミス拠点#1,#2のWindows PCから利用する場合には他拠点である192.168.x.0/24については自分の拠点にあるWireGuardにルーティングさせる必要があります。

カスタムルート設定がある場合

私のオンプレミス拠点#1はBuffaloのWXR-5950AX12の場合は、[詳細設定]-[LAN]-[経路情報]にて、追加のルート設定を行う機能があったため、こちらで他拠点(192.168.1.0/24, 192.168.2.0/24)に対してはWireGuardを入れたRaspberry PiのIPアドレスに転送するよう指定しました。

カスタムルート設定が無い場合

ルータをちゃんとしたものに買い換える、、、と行きたいところですが、とりあえず接続元のWindows 10で管理者権限でコマンドプロンプトを開き、以下のrouteコマンドで一時的にルーティングを追加しました。

C:\>route add 192.168.2.0 mask 255.255.255.0 192.168.1.80
C:\>route add 192.168.0.0 mask 255.255.255.0 192.168.1.80

接続確認

オンプレミス拠点#2のWindows 10クライアント(192.168.1.2)から各拠点のPing応答するサーバに色々pingを打ってみます。

iPhoneでもWireGuard接続後には、Azure VM上のnginxや、オンプレミス拠点のルータ設定画面へアクセスができました。

Azure File Storageへ接続

Azure拠点にStorage Accountを作って、Azure仮想ネットワークとプライベートピアリングをすることで、オンプレミス拠点のWindows 10からSMBのマウントに挑戦します。

Storage Accountの準備

Storage Accountを先ず作成しましょう。

SMBマウント用の共有を作成しておきます。

ストレージアカウントのネットワーク設定にて、プライベートエンドポイント接続を追加します。仮想ネットワークにはAzure拠点用仮想ネットワークのazure-subnetを指定しました。

実際にストレージアカウントに割り当てられたプライベートIPアドレスは仮想ネットワークリソースの接続デバイス一覧から確認しました。(今回のケースでは 192.168.2.132)

ストレージアカウント名とキー(パスワード)は、ストレージアカウントの「アクセスキー」から確認して控えておきます。

オンプレミスのWindows 10からマウント

エクスプローラからアドレス欄に「\\192.168.2.132\share」を入力します。

ID、パスワードの入力を求められたら先に控えたストレージアカウント名、キーをそれぞれ入力します。
(画面キャプチャがなくてすみません)

無事共有できました。のでファイルやフォルダをWindows 10側から追加してみました。

ここでは手順を省略しますが、Azure側のLinuxサーバからも同じAzure File Storageをcifsでマウントして、中身を表示してみますが、ちゃんと他拠点のWindows 10から書き込んだファイルが見えていますね。

おわりに

今回はWireGuardの疎通性能や可用性といった本気でビジネスで利用するための部分については触れていません。
セキュリティ観点では、Azure File Storageをプライベートエンドポイント利用で閉域ネットワーク内からのみの利用に限定していますが、他の部分についてはWireGuardの機能に準じます。

少なくとも構築時に作成した各拠点のPrivate Keyは安全な場所に退避しておくのが良いと思います。

今回のWireGuardの検証ですが、実際は本当にサクサクと進めることができて(それほど事前にネットワーク設計ができていれば実設定は簡単)、このブログ記事を書く時間の方が多くかかった感じです。

自分の構築メモとして公開しますが、参考になれば幸いです。