strongSwanを利用したAzure VPN GatewayへのP2S接続

# 背景
Azureで構築した仮想マシンにAWSのEC2インスタンスからアクセスしたい、だけどAzure,AWS環境の仮想マシンにグローバルIPを割り当てることは社内規定上禁止されているのでクラウドプラットフォーム間での通信はできない。。。といった事態に遭遇しました。
VPN Gateway間でS2S接続できれば一番良いのですが、今回は諸事情によりstrongSwanを利用しAzure VPN GatewayへP2S接続することとなったので、その方法について記載したいと思います。

## 前提
- EC2インスタンスはRedhat7.x系を利用

※P2S接続については[こちら](https://docs.microsoft.com/ja-jp/azure/vpn-gateway/point-to-site-about)を参照

## 構成

![ToBe.png](https://qiita-image-store.s3.amazonaws.com/0/318172/aa484a97-8d7b-de89-e0cb-1c93b5f3df67.png)

## 事前準備
1. [こちら](https://docs.microsoft.com/ja-jp/azure/vpn-gateway/vpn-gateway-howto-point-to-site-resource-manager-portal)の手順に沿ってAzure VPN Gatewayを構成
1. [こちら](https://docs.microsoft.com/ja-jp/azure/vpn-gateway/point-to-site-vpn-client-configuration-azure-cert#generate)の**Azure Portal を使用してルールを生成する**を参考にVPN クライアントをダウンロードしておく

## 設定
以下EC2インスタンスでの作業

1. strongSwanインストール

    ```
    sudo yum install -y strongswan
    ```

1. IPSec設定
    1. 事前準備の2番で取得したVPNクライアントを解凍
    1. VpnServerRoot.cerを**Generic**ディレクトリから**/etc/strongswan/ipsec.d/cacerts/**へコピー
    1. 事前準備の1番で作成したクライアント証明書を**client.p12**として保存
    1. **client.p12**を**/etc/ipsec.d/private/**へコピー
    1. **Generic**ディレクトリに保存されている**VpnSettings.xml**ファイルを開き**VPNServer**に設定されている値をコピー
    1. **/etc/strongswan/ipsec.conf**に設定追加
 
    ```
    conn azure
            keyexchange=ikev2
            type=tunnel
            leftfirewall=yes
            left=%any
            leftauth=eap-tls
            leftid=%P2SChildCert
            right=<VPNServerの値を記載>
            rightid=%<VPNServerの値を記載>
            rightsubnet=0.0.0.0/0
            leftsourceip=%config
            auto=add
    ```

1.  **/etc/strongswan/ipsec.secrets**に設定追加

    ```
     # ipsec.secrets - strongSwan IPsec secrets file
     : P12 client.p12 '<クライアント証明書のパスワード>'
    ```

## 接続確認
connection `azure` established successfullyと表示されればOK

```
sudo systemctl start strongswan
sudo strongswan up azure
```

## 接続確認スクリプトの作成
意図せずVPN接続が切れていることがあったので、接続確認スクリプトを作成

作ったもの：
- VPNStartUp.sh
- StartUp.func
- CheckStatus.func
- Logs.func

実行方法

```shell-session
mkdir logs
nohup ./VPNStartUp.sh &
```

```bash:VPNStartUp.sh
#!/bin/bash

shelldir=`dirname $BASH_SOURCE`
timestamp=`date +%FT%H-%M-%S`
serverIP="<Azure上の仮想マシンIPアドレスを記載>"
logFile="./logs/log_${timestamp}"

#Change Current Directory
cd ${shelldir}

source ./CheckStatus.func
source ./StartUp.func
source ./Logs.func

startUpVPN

checkStatus
```

```bash:StartUp.func
function startUpVPN(){

   #Start Strongswan
   systemctl restart strongswan

   if [ $? -ne 0 ]; then
      log "Failed to Start Strongswan."
      exit 1
   fi

   sleep 80

   #Up Azure VPN Session
   strongswan up azure

   if [ $? -ne 0 ]; then
      log "Failed to Establish Connection."
      exit 1
   fi
}
```

```bash:CheckStatus.func
#!/bin/bash

function checkStatus(){

   while true
     do
        sleep 30
   
        ping ${serverIP} -c 5 > /dev/null

        if [ $? -ne 0 ]; then
           log "Target server is not up"
           log "Disconnecting session"

           strongswan down azure

           startUpVPN
        else
           log "Target Server is Up"
        fi
      done
}
```

```bash:Logs.func
function log() {
   logtimestamp=`date +%FT%H-%M-%S`

   echo "${logtimestamp} $*" >> ${logFile}
}
```