strongSwanでIPv4 over IPv6のVPNトンネルを構成する

strongSwanを利用してIPv4 over IPv6のVPNトンネルを構築します。最終目標はYAMAHAルーターとの拠点間接続ですが、今回は検証のためにAWSにインスタンスを立てて検証します。

# 構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/a703b204-0c17-dcc8-a7bc-31f579d8b927.png)
Terminal AとTerminal Bを通信させるため、strongSwan AとstrongSwan Bの2台のマシンでIPSecトンネルを張ります。今回の構成例では、VPC A(172.31.0.0/16)とSubnet B-1(192.168.0.0/24)に属する端末相互間で自由に接続ができるようにします。

- strongSwan A,Bのスペック
 - AMI : Ubuntu Server 20.04 LTS (ami-0d1f7bec0e294ef80)
 - インスタンスタイプ : t4g.nano
 - strongSwan 5.8.2

# 構築手順

### 初期設定

```
# OSの初期アップデート
sudo apt update
sudo apt upgrade -y

# strongSwanとswanctlのインストール
sudo apt install strongswan strongswan-swanctl -y

# インターフェース間のパケット転送を許可
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```

swanctl を利用するため、charon.confのstart-scriptsに以下の内容を追記します。

```plaintext:/etc/strongswan.d/charon.conf
charon {
 （省略）
 start-scripts {
   swanctl = /usr/sbin/swanctl -q
 }
 （省略）
}
```

また、strongSwanをSystemctlで起動できるようにするため、構成ファイルを作成します。

```plaintext:/etc/systemd/system/strongswan.service
[Unit]
Description=strongSwan

[Service]
Type=forking
ExecStart=/usr/sbin/ipsec start
ExecStop=/usr/sbin/ipsec stop

[Install]
WantedBy=multi-user.target
```

```
sudo systemctl start strongswan
sudo systemctl enable strongswan
```


### 接続設定

以下はstrongSwanAの設定です。strongSwanBの設定をする場合は、自身と接続先の表記を入れ替える必要があります。

```plaintext:/etc/swanctl/conf.d/connection.conf
connections {

   net-net {
      local_addrs  = XXXX:XXXX::10 #自身(strongSwanA)のIPv6アドレス
      remote_addrs = YYYY:YYYY::10 #接続先(strongSwanB)のIPv6アドレス

      local {
         auth = psk
         id = XXXX:XXXX::10 #自身(strongSwanA)のIPv6アドレス
      }
      remote {
         auth = psk
         id = YYYY:YYYY::10 #接続先(strongSwanB)のIPv6アドレス

      }
      children {
         net-net {
            local_ts  = 172.31.0.0/16 #自身(strongSwanA)側のCIDR
            remote_ts = 192.168.0.0/24 #接続先(strongSwanB)側のCIDR
            esp_proposals = aes128-sha256-x25519
         }
      }
      version = 2
      mobike = no
      proposals = aes128-sha256-x25519
   }
}

secrets {
 ike-1 {
  id = XXXX:XXXX::10 #自身(strongSwanA)のIPv6アドレス
  secret = "pre-shared-key-password"
 }
}
```

参考：https://www.strongswan.org/testing/testresults/ipv6/net2net-ip4-in-ip6-ikev2/

### VPNセッションを張る
今回は、strongSwanAからstrongSwanBへセッションを張ります。まず、strongSwanB側で設定を読み込むためstrongSwanを再起動します。その後、ログを確認するために```sudo swanctl --log```を実行します。このコマンドを実行することで、ログをリアルタイムで確認できます。

```plaintext:strongSwanB
sudo systemctl restart strongswan
sudo swanctl --log
```

次に、strongSwanA側で設定を読み込み、VPNセッションを張ります。

```plaintext:strongSwanA
sudo systemctl restart strongswan
sudo swanctl -i -c net-net 
```

# AWS側の設定
ここまでの設定で、strongSwanAとstrongSwanB間でpingが通るようになっているはずです。Terminal AとTerminal B間で接続できるようにするためには、AWS側で宛先チェックの無効化と、ルートテーブルの設定が必要です。

# 未解決事象
OS再起動時に以下のログが表示され、strongSwanが立ち上がりません。```systemctl restart strongswan```で治るため、とりあえず放置しています。

```
 systemd[1]: Starting strongSwan...
 ipsec[529]: Starting strongSwan 5.8.2 IPsec [starter]...
 ipsec_starter[529]: Starting strongSwan 5.8.2 IPsec [starter]...
 ipsec[529]: starter is already running (/var/run/starter.charon.pid exists) -- no fork done
 ipsec_starter[529]: starter is already running (/var/run/starter.charon.pid exists) -- no fork done
 ipsec[545]: Stopping strongSwan IPsec...
 systemd[1]: strongswan.service: Succeeded.
 systemd[1]: Started strongSwan.
```

# 参考にしたサイト
[IPv6 Configuration Examples - strongSwan][1]
[swanctl - strongSwan][2]

[1]:https://wiki.strongswan.org/projects/strongswan/wiki/IPv6Examples
[2]:https://wiki.strongswan.org/projects/strongswan/wiki/Swanctl