【エンジニア０年生】ローカルとAzure 仮想ネットワーク間のVPN接続

こんにちは。インフラエンジニア歴マイナス２週間のdessinです。
今回は、ローカルPCとAzureの仮想マシンとの通信をパブリックIPアドレスで実現する、VPN接続（P2S）を実装したので記事にします。座学でWANを学んだときはよくわからなかったので、手を動かして何がつかめるか楽しみながらやりました。
# 概要

* Azure仮想マシンはLinuxサーバー（接続テストマシン兼WEBサーバー）とWindowsサーバー（DNSサーバー）を立て、同じサブネットに収容。
* VPNゲートウェイ用のサブネットを作成。
* 上記サブネットを一つの仮想ネットワークに収容。
* Azure VPN Gatewayを作成し、ローカルPCとP2S接続する。
* 検証としては、自分で立てたDNSサーバーを指定してローカルの名前解決、すなわちWEBサーバーに与えたドメイン名を使ってブラウザからWEBページを表示できたら終了。

一応、図を貼りますがGatewayがどのように動作して通信を実現するかはまだ知らないので細かいところは省略します。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/71e10310-cbc5-8192-fd61-d27f1a8f1347.png)
# 環境
* Azure（無料サブスクリプションだとVPNgatewayが作成できないかも。後述）
* ローカルPCはWindows 11

# 作業
やることは以下の通り。
* 仮想ネットワーク、サブネット、セキュリティグループ作成
* 仮想マシン作成
* VPNGateway作成
* 自己署名証明書の発行
* LocalPCにクライアント証明書をダウンロードして接続

VPNGatewayの作成に関する記事は他にもたくさんありましたが、自分なりに再解釈した内容にしていきます。


## 仮想マシン作成まで
概要で示した構成図の通り作っていきます。
何回か仮想環境を構築してみて感じたことを書きます。
* ネットワークセキュリティグループは、一般的に言って仮想マシンに関連付けるのではなく、サブネットに関連付けるべきといえる。
* プライベートIPアドレスの自動取得について、例えば10.100.0.0/24の環境には10.100.0.4から取得された。構成図書く時に役立ちそう。
* 仮想ネットワーク作成時にサブネットを同時に作成し、仮想マシンを作成するとすごく楽。これまでは一個一個作ってた
* リソースグループは何回でも消してやり直せばいい。やり直した部分から覚えられる。

私自身慣れてきたので構成の情報については最低限だと思う分を載せます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/8bfba875-8e36-188a-35c3-29b9a7b7470b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/8cfc050f-8614-e8d3-2b59-26e277899862.png)
****

DNSServerの管理・監視・詳細については初期設定のままです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/ddb12e24-3a5a-8024-e019-4cbc39c3f93b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/fbd2cc91-ff24-d977-b6d6-e9e83c27d83a.png)
****
WEBServerも同じく。ただしこちらはUbuntuです。Linuxならばサイズが小さくても気にならないのでB1sにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/f4c5aa08-6b0c-4a51-3817-e408aac9155b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/306a98ac-b325-3520-50cc-f93ffbe359c9.png)
パブリックIPアドレスを手元にメモして、以降の作業をしましょう。
## サーバーの設定
[WEBサーバーの立て方](https://qiita.com/dessin/items/7aa20b9e9a2b1301ba01)、[DNSサーバーの立て方](https://qiita.com/dessin/items/ebfea655a82a809af866)はこれまでの記事通りにやります。DNSサーバーにリモートデスクトップ接続し、ソフトをインストールし構成、WEBサーバーは簡単にhtmlファイルをサーブするやりかたです。
ローカルPCから、このWEBサーバーに、ドメイン名を指定して接続できる、すなわちブラウザでWEBページが見られることを確認して終了です。
これらサーバーの構成より先にVPN Gatewayを作成することもできますが、VPNGatewayは仮想マシンよりもはるかに高額になるので、構成が終わってから作成することをお勧めします。
## VPN Gatewayの作成
公式DOCは[こちら](https://learn.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-howto-point-to-site-resource-manager-portal)
リソースの検索窓に、VPNと打ち込んで「仮想ネットワークゲートウェイ」を探します。
下のように作成します。重要なのはSKUだと思います。VpnGw1にしました。デプロイには時間が結構かかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/ff650147-34b9-dad0-6e72-1a0f491a6729.png)
### 補足
注意点があり、無料のサブスクリプションだと、仮想マシン２個と仮想ネットワークゲートウェイ１個を作成することができないようです。クオータ不足だとかでエラーが出ました。
これについて友人に「SKUをBasicにダウングレードすれば作成できるのではないか」と言われ、コマンドを使ってGUIでは選択できないSKUにするのにも挑戦しました。かなり大変な思いをしたのでまた別記事にします。
もう一点、概要の構成図で、Gateway-Subnetというサブネットを作成しましたが、名前は"GatewaySubnet"（ハイフンなし）でなければ仮想ネットワークゲートウェイが作成できないようです。
## 証明書
ここからはローカルPCでの作業です。その前にざっくりVPNの概念について。
* VPNはインターネットを使ってあたかも専用線が敷かれたように挙動するネットワークを構築する手法である。
* インターネットを介する以上は、なりすまし、盗聴などに注意が必要である。今回の場合では、Azure側から見たときにVPN接続する相手が、本当に自分個人のローカルPCなのか、という点は重大である。そこで証明書を利用する。

### 作業
さて作業です。[こちらの記事](https://qiita.com/kk31108424/items/badebf69de81c7a10c2b#4-vpn-gateway-%E3%81%AE%E4%BD%9C%E6%88%90)が参考になりました。人のふんどしですが、初心者の目線から補足しながら書きます。
この記事の「５．root証明書、クライアント証明書の作成」をローカルPCのpowershellから行います。そうして発行された証明書は、証明書ストアという、普段使用しているファイルとは違う場所に格納されているようです。そこで、Azureにアップロードする前準備として、エクスポートして普段使用しているファイルと同じく扱えるようにします。その手順が「７．root証明書をAzureにアップロード」に書かれています。文字列だけ抜き取るところには私はVisual Studio Codeを使用しました。エクスポートしたファイルを右クリックし、「プログラムから開く」＞Visual Studio Codeを選択。

先頭行と最終行の部分は除いてコピーします。
アドレスプールには、ローカルPCに設定したいアドレス範囲を設定します。gatewayを挟んだネットワークセグメント同士で（というかどのセグメントでも）アドレス範囲が重複することはできません。ということなので、自分なりにプライベートアドレスの中から重複しないように設定してみます。10.0.0.0/16としました（ローカルにそんな広大なアドレス空間いらない）。こうすると、VPN接続相手に対して振り分けるIPアドレスの範囲が決まるわけですね。
参考記事の通りできると思っていたら、どうもVPNGatewayの設定を間違っていたようで、パブリックIPアドレスをさらにもう一つ取得しなければならぬようです。アクティブーアクティブの設定は不要ということで、仮想ネットワークゲートウェイを作成しなおします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/94eeeb7b-a52f-9b7e-547c-3458e7cd9c23.png)
そして、再びポイント対サイトの構成にいくと、IPアドレスなしで構成ができそうです。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/d51249a9-1343-084d-50e4-c43aed2e6da7.png)
構成が終わったら、VPNクライアントのダウンロードです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/abfaa90e-50a5-bb34-85bd-58585450ec79.png)
証明書ストアからエクスポートした証明書をダブルクリックすると、ウィザードが開きます。私は最初勘違いして、ダウンロードしたVPNクライアントのファイルから探したのですが、それではありません。
初期設定のままウィザードを進めると、最後に警告が出ますがインストールを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/9785a4f9-f19c-8b59-61db-508980f49e4d.png)
今度はダウンロードしたVPNクライアントのファイルを展開し、WindowsAmd64の中身を実行します。
これで準備が完了しました。
Windowsの設定画面の、「ネットワークとインターネット」から、VPNが見られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/0eb69cab-e460-85e9-2927-579682dd151e.png)

### 疎通確認
VPNを接続したら、ローカルPCでpowershellを開きます。ipconfigを見てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/ceca8342-8a9e-34df-89b5-04c78ad03c37.png)
設定したアドレスプール内のアドレスが割り当てられていることが確認できました。VPNとは、論理的にNICを追加するようなものだということがわかります。これ見たときはめっちゃうれしかったです。
続いてはローカルPCからwebサーバーが見られるかを確認します。ネットワークセキュリティグループが8080やその他の通信を許可しているか、webサーバーがサーブ状態であるかを確認してください。
どうやらプライベートIPアドレスを指定してアクセスができています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/71f0d3b3-41c6-38c1-e290-bebccee91abd.png)

続いて、ドメイン名指定です。DNSサーバーに登録したAレコードを確認します。リモートデスクトップ接続し、サーバーマネジャーからDNSサーバーを選択し右クリック、Forward Lookup Zoneに設定したのでしたね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/dfe8f171-64cc-e62e-6b6b-888ecc5e6ea9.png)
webserver.VPNtest.comで登録されています。
ブラウザに入れてみると・・・おや？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617557/5d04c7e1-2704-1505-c671-495612061984.png)
そういえばローカルPCのDNSサーバーの設定を忘れていました。設定変更しなければ既定のDNSサーバー（おそらくインターネットにある）にwebserver.vpntest.comという存在しないドメイン名の名前解決を要求することになります。そんなものは知られていないので通信ができないのでせう。
****
ところが、ローカルPCの設定をいじってもこの問題は解決できませんでした。設定変更後にnslookupコマンドで確認しても、168.63.129.16というサーバーに問い合わせしており、自分で立てたDNSサーバーに行ってくれません。
これはどうも、DNSメトリックが関係しているようです。[参考記事](https://turningp.jp/server-client/windows/dns-multiple)
私はここで力尽きたのでまたの機会に。
とりあえず、ブラウザからプライベートIPアドレス指定でアクセスできたので、VPN接続は実現できました。お疲れさまでした。
# 証明書について
証明書の動きに注目してみます。
* ローカルで証明書を作成した時のコマンドからは、"P2SRootCert"をもとに"P2SChildCert"という証明書を作成していることがわかる。
* "P2SRootCert"をエクスポートした。
* "P2SRootCert"の中身を見て、先頭行と最終行を除いた文字列をAzureにアップロードした。
* Azure側から「VPNクライアント」ファイルというものをダウンロードした。
* エクスポートした"P2SRootCert"から証明書をインストールした。（？）
* "VPNClientSetupAmd64"を実行するとVPN接続ができるようになった。（？？）
わからないことだらけですが、ローカルPCと、Azure側の両方に "P2SRootCert"というファイル（文字列？）があることは確からしいです。「同じ文字列を持ってる両者なら信頼できるな！通信ヨシ！」ってな感じですかね。自己署名証明書だと証明書の本質的なところがぼやけてしまうのかしら。
また（？）の項目で行ったインストールについては、出したものをまた戻すような動きに感じました。やらなくてもよかったのでは？それとも自分のやり方が違うかも？個人的には通信のセキュリティは業界的に重大な位置づけになると思っているので、ぜひ深掘りしたいと考えています。今回は力尽きました。
# まとめ
* 仮想マシンを２つ立て、それぞれWEBサーバーとDNSサーバーとして構成した。
* 仮想ネットワークゲートウェイを作成した。（この記事では紹介していないが、コマンドで作成する方法も試した。）
* VPNのために証明書を作成し、Azureにアップロードした。
* ローカルPCから、プライベートIPアドレス指定でWEBサーバーにアクセスした。
* ローカルPCのDNS設定をいじっても、プライベートの名前解決はできなかった。