ubuntu 20.04 LTS にて strongswan を使用したVPNを構築する(サーバ証明書)

ubuntuにstrongswanをインストールし、サーバ証明書を使用したVPN接続を構成します。

PSKを利用した接続は以下から。

https://qiita.com/Higemal/items/b134bf98f3744e432d23


# ■環境
**OS:** `Ubuntu 20.04.6 LTS`
**strongswan:** `5.8.2-1ubuntu3.5`

# ■構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/d28bff8e-5c86-d46b-6fee-72cbaa6b734b.png)

VM環境につき、複数のセグメントを使用しています。

LAN | IP/MASK | 用途 | Left-VM | Right-VM
--- | --- | --- | --- | ---
Management | 192.168.142.0/24 | 管理用ネットワーク | 〇 | 〇
Internal | 10.0.1.0/24 | VPN接続用ネットワーク | 〇 | 〇
Service1 | 172.16.1.0/24 | Left側独立セグメント | 〇 | －
Service2 | 172.16.2.0/24 | Right側独立セグメント | － | 〇


# ■手順概要
1.サーバ証明書準備
2.VM/OS作成　※割愛
3.カーネルパラメータ設定
4.strongswanインストール
5.strongswan設定
6.証明書配置
7.strongswan起動

設定後に接続試験として以下を行います。

8.ルーティング設定
9.ping疎通確認


# 1.サーバ証明書準備
サーバ証明書について、以下の種類を準備します。

ルート証明書：`ca.crt`
サーバ証明書(Left)：`server1.crt`
サーバ秘密鍵(Left)：`server1.key`
サーバ証明書(Right)：`server2.crt`
サーバ秘密鍵(Right)：`server2.key`

証明書の発行方法は複数あるため、適宜環境に合わせて発行ください。

https://qiita.com/Higemal/items/6048ae2ed001a87237f2


<br>



# 2.VM/OS作成
VPN用のVMの作成およびOSインストールを行います。
※特別な設定を行わないため割愛

:::note warn
本環境ではファイアウォールを無効化して構成します。
必要に応じて有効化・通信設定追加を行ってください。

```text:FW無効化
# ufw disable
```
:::

<br>

# 3.カーネルパラメータ設定
カーネルパラメータの設定変更を行います。

:::note warn
以降は`root`権限で操作を実行します。
:::

```text:カーネルパラメータ設定
# vi /etc/sysctl.conf
----------------------------
net.ipv4.ip_forward = 1 
net.ipv6.conf.all.forwarding = 1 
net.ipv4.conf.all.accept_redirects = 0 
net.ipv4.conf.all.send_redirects = 0
```

```text:カーネルパラメータ更新
# sysctl -p
```

```text:カーネルパラメータ一覧表示
# sysctl -a
```
parameter | 設定内容
--- | ---
net.ipv4.ip_forward = 1 | あるNICから来たパケットを別のNICへ送出する(IPv4)
net.ipv6.conf.all.forwarding = 1  | あるNICから来たパケットを別のNICへ送出する(IPv6)
net.ipv4.conf.all.accept_redirects = 0  | ICMPリダイレクトされたパケットの受入無効化
net.ipv4.conf.all.send_redirects = 0 | ICMPリダイレクトされたパケットの送出無効化


<br>





# 4.strongswanインストール
以下コマンドにてインストールを実施します。
```text:strongswan-install
# apt update
# apt install -y strongswan
```

<br>

# 5.strongswan設定
strongswan設定として、以下ファイルを操作します。
`/etc/ipsec.conf` : VPN設定ファイル
`/etc/ipsec.secrets` : VPN接続情報ファイル

### 5-1. /etc/ipsec.conf設定
以下設定をLeft側/Right側のサーバに設定します。

```text:/etc/ipsec.conf(Left)
# vi /etc/ipsec.conf
----------------------------
config setup
        charondebug="all"
        uniqueids=yes
conn left-to-right
        type=tunnel
        auto=start
        keyexchange=ikev2
        authby=rsasig
        left=10.0.1.111
        leftsubnet=172.16.1.0/24
        leftcert=server1.crt
        right=10.0.1.112
        rightsubnet=172.16.2.0/24
        rightid="C=JP, ST=Tokyo, O=Default Company Ltd, CN=vpn.test2"
        ike=aes256-sha256-modp4096
        esp=aes256-sha256-modp4096
        aggressive=no
        keyingtries=%forever
        ikelifetime=28800s
        lifetime=3600s
        dpddelay=30s
        dpdtimeout=120s
        dpdaction=restart
```

```text:/etc/ipsec.conf(Right)
# vi /etc/ipsec.conf
----------------------------
config setup
        charondebug="all"
        uniqueids=yes
conn right-to-left
        type=tunnel
        auto=start
        keyexchange=ikev2
        authby=rsasig
        left=10.0.1.112
        leftsubnet=172.16.2.0/24
        leftcert=server2.crt
        right=10.0.1.111
        rightsubnet=172.16.1.0/24
        rightid="C=JP, ST=Tokyo, O=Default Company Ltd, CN=vpn.test1"
        ike=aes256-sha256-modp4096
        esp=aes256-sha256-modp4096
        aggressive=no
        keyingtries=%forever
        ikelifetime=28800s
        lifetime=3600s
        dpddelay=30s
        dpdtimeout=120s
        dpdaction=restart
```

parameter | 設定内容
--- | ---
charondebug | ログ出力量設定
uniqueids | 接続IDについて枯渇時に再利用を許可するか
conn | 接続名
type | 接続タイプ(tunnel,transport,passthrough,drop)
auto | 接続自動設定(start,add,ignore)
keyexchange | ikeプロトコルバージョン(ikeのみ)
authby | 認証方式(secret,never,null,rsasig,...)
left | 自身のVPN用IPアドレス
leftsubnet | 自身側のプライベートサブネット
leftcert | 自身側で使用するサーバ証明書名
right | 他方のVPN用IPアドレス
rightsubnet | 他方側のプライベートサブネット
rightid | 他方側のサーバ証明書のSubject
ike | アルゴリズム指定（※）
esp | アルゴリズム指定（※）
aggressive | アグレッシブモードの使用
keyingtries | 認証試行回数
ikelifetime | 再認証間隔
lifetime | 接続最長時間
dpddelay | ハートビート間隔
dpdtimeout | タイムアウト間隔
dpdaction | タイムアウト時の動作(restart,hold,clear)

>(※)アルゴリズム指定については以下のような形式で記載
　　`encryption - integrity[-prf] - dhgroup`
>
>dhgroupについては以下形式で表記
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/12a4fea1-9eed-80aa-eb96-4cae5bdabfc0.png)
>https://docs.strongswan.org/docs/5.9/config/IKEv2CipherSuites.html


その他詳細は以下のマニュアルを参照のこと。

https://libreswan.org/man/ipsec.conf.5.html

https://wiki.strongswan.org/projects/strongswan/wiki/ConfigSetupSection






### 5-2. /etc/ipsec.secrets設定
`/etc/ipsec.secret`ファイルに認証設定を追加します。
左側アドレス、右側アドレス、認証方式、サーバ証明書名を記載します。

```text:/etc/ipsec.secret(Left)
# vi /etc/ipsec.secrets
----------------------------
10.0.1.111 10.0.1.112 : RSA server1.key
```

```text:/etc/ipsec.conf(Right)
# vi /etc/ipsec.secrets
----------------------------
10.0.1.112 10.0.1.111 : RSA server2.key
```

:::note warn
VPN構成時に`/etc/ipsec.secret`ファイルは権限が`600`となっている必要があります。
```text:check
# ls -l /etc/ipsec.secrets
-rw------- 1 root root 237 10月 29 20:47 /etc/ipsec.secrets
```
:::


<br>

# 6.証明書配置
ルート証明書およびサーバ証明書を所定のディレクトリに配置します。

ルート証明書：`ca.crt`
サーバ証明書(Left)：`server1.crt`
サーバ秘密鍵(Left)：`server1.key`
サーバ証明書(Right)：`server2.crt`
サーバ秘密鍵(Right)：`server2.key`

```text:Left
/etc/ipsec.d/cacerts/ca.crt
/etc/ipsec.d/certs/server1.crt
/etc/ipsec.d/private/server1.key
```

```text:Right
/etc/ipsec.d/cacerts/ca.crt
/etc/ipsec.d/certs/server2.crt
/etc/ipsec.d/private/server2.key
```



<br>

# 7.strongswan起動
`ipsec`コマンドを利用してVPN接続を構成します。

```text:ipsec-restart
# ipsec restart
```

ステータス確認にて`Security Associations (1 up, 0 connecting):`と表示されればVPN接続されています。

```text:ipsec-status(left)
# ipsec status
Security Associations (1 up, 0 connecting):
left-to-right[2]: ESTABLISHED 2 hours ago, 10.0.1.111[C=JP, ST=Tokyo, O=Test, OU=Test, CN=vpn.test1]...10.0.1.112[C=JP, ST=Tokyo, O=Test, OU=Test, CN=vpn.test2]
left-to-right{4}:  INSTALLED, TUNNEL, reqid 1, ESP SPIs: c188372c_i c6de8b03_o
left-to-right{4}:   172.16.1.0/24 === 172.16.2.0/24
```

```text:ipsec-status(right)
# ipsec status
Security Associations (1 up, 0 connecting):
right-to-left[1]: ESTABLISHED 2 hours ago, 10.0.1.112[C=JP, ST=Tokyo, O=Test, OU=Test, CN=vpn.test2]...10.0.1.111[C=JP, ST=Tokyo, O=Test, OU=Test, CN=vpn.test1]
right-to-left{3}:  INSTALLED, TUNNEL, reqid 1, ESP SPIs: c6de8b03_i c188372c_o
right-to-left{3}:   172.16.2.0/24 === 172.16.1.0/24
```

<br>
<br>

# ■接続確認構成
接続確認用の構成として、Left側／Right側にそれぞれ追加でVMを作成して通信を発生させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/2e5dd748-6d1b-88d1-eaa0-8da6c6c2b50f.png)

<br>

# 8.ルーティング設定
追加した疎通試験用VMにて、Left側/Right側のVPNサーバのNICをゲートウェイとするルーティング設定を実施します。

nmcliコマンドで接続名に対しルーティングを設定し、接続名の停止/起動を行います。
（`Wired connection 2`はnmcli接続名になります）
```text:Routing(Left)
# nmcli conn mod "Wired connection 2" +ipv4.routes "172.16.2.0/24 172.16.1.111"
# nmcli c d "Wired connection 2" 
# nmcli c u "Wired connection 2" 

# ip route
default via 192.168.142.2 dev ens34 proto static metric 100
default via 172.16.1.111 dev ens35 proto static metric 20101
169.254.0.0/16 dev ens34 scope link metric 1000
172.16.1.0/24 dev ens35 proto kernel scope link src 172.16.1.101 metric 101
172.16.2.0/24 via 172.16.1.111 dev ens35 proto static metric 101
192.168.142.0/24 dev ens34 proto kernel scope link src 192.168.142.101 metric 100
```

```text:Routing(Right)
# nmcli conn mod "Wired connection 2" +ipv4.routes "172.16.1.0/24 172.16.2.112"
# nmcli c d "Wired connection 2" 
# nmcli c u "Wired connection 2" 

# ip route
default via 192.168.142.2 dev ens34 proto static metric 102
default via 172.16.2.112 dev ens35 proto static metric 20103
169.254.0.0/16 dev ens34 scope link metric 1000
172.16.1.0/24 via 172.16.2.112 dev ens35 proto static metric 103
172.16.2.0/24 dev ens35 proto kernel scope link src 172.16.2.102 metric 103
192.168.142.0/24 dev ens34 proto kernel scope link src 192.168.142.102 metric 102
```

<br>

# 9.ping疎通確認
pingおよびtracertouteで疎通確認を実施します。
問題なく疎通できることが確認できました。

```text:ping/traceroute(Left)
# ping 172.16.2.102
PING 172.16.2.102 (172.16.2.102) 56(84) bytes of data.
64 bytes from 172.16.2.102: icmp_seq=1 ttl=62 time=3.11 ms
64 bytes from 172.16.2.102: icmp_seq=2 ttl=62 time=1.41 ms
64 bytes from 172.16.2.102: icmp_seq=3 ttl=62 time=1.32 ms
64 bytes from 172.16.2.102: icmp_seq=4 ttl=62 time=1.29 ms
--- 172.16.2.102 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 1.287/1.781/3.114/0.770 ms

# traceroute 172.16.2.102
traceroute to 172.16.2.102 (172.16.2.102), 30 hops max, 60 byte packets
 1  _gateway (172.16.1.111)  0.599 ms  0.536 ms  0.513 ms
 2  172.16.2.112 (172.16.2.112)  1.702 ms  1.692 ms  1.628 ms
 3  172.16.2.102 (172.16.2.102)  2.026 ms *  1.864 ms
```

```text:ping/traceroute(Right)
# ping 172.16.1.101
PING 172.16.1.101 (172.16.1.101) 56(84) bytes of data.
64 bytes from 172.16.1.101: icmp_seq=1 ttl=62 time=2.43 ms
64 bytes from 172.16.1.101: icmp_seq=2 ttl=62 time=1.36 ms
64 bytes from 172.16.1.101: icmp_seq=3 ttl=62 time=1.94 ms
64 bytes from 172.16.1.101: icmp_seq=4 ttl=62 time=1.27 ms
--- 172.16.1.101 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3006ms
rtt min/avg/max/mdev = 1.271/1.748/2.427/0.467 ms

# traceroute 172.16.1.101
traceroute to 172.16.1.101 (172.16.1.101), 30 hops max, 60 byte packets
 1  _gateway (172.16.2.112)  0.623 ms  0.573 ms  0.567 ms
 2  172.16.1.111 (172.16.1.111)  1.528 ms  1.519 ms  1.491 ms
 3  172.16.1.101 (172.16.1.101)  2.321 ms  2.279 ms  2.226 ms
```


# ■参考

**ipsec.conf.5**
https://libreswan.org/man/ipsec.conf.5.html

**ipsec.conf: conn <name>**
https://wiki.strongswan.org/projects/strongswan/wiki/connsection

**IKEv2 Cipher Suites**
https://docs.strongswan.org/docs/5.9/config/IKEv2CipherSuites.html

**Debian および Ubuntu で Strongswan を使用して IPsec ベースの VPN をセットアップする方法**
https://ja.linux-console.net/?p=890