VyOS で OpenVPN してみる

# 前書き
「[Raspberry Pi 4 Model B 上で VyOS を動かす](https://qiita.com/DJ_Kaosun/items/6fc072e8490725e6c037 "6fc072e8490725e6c037")」で作った VyOS と、自宅の VyOS 間で OpenVPN を使ってみる。ネットワーク図は以下の通り。

物理寄りの図
![物理寄りの図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1026594/394922c0-6723-e0ef-25f7-227c98fd9583.png)

論理寄りの図
![論理寄りの図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1026594/92658b2c-0df1-cced-5c11-6f44aeb2c8de.png)

あと、各種証明書の準備方法は特に触れません。[Let's Encrypt](https://letsencrypt.org/ja/) を使うなり、独自認証局を openssl で作るなり、お好きなように。

# 自宅側 VyOS (on VM)

## 基本設定

### 外側 ethernet の設定 (eth0)
```text:コマンド
set interfaces ethernet eth0 address 192.168.11.254/24
set interfaces ethernet eth0 address dhcpv6
set interfaces ethernet eth0 ipv6 address autoconf
```

### 内側 ethernet の設定 (eth2)
X のところは、IPv6 の ULA について調べて、[ここらへん](https://www.jdoodle.com/a/20tR)の Stdin Inputs に使う機器の MAC アドレスでも入れてください。
```text:コマンド
set interfaces ethernet eth2 address 192.168.12.1/24
set interfaces ethernet eth2 address 'fdXX:XXXX:XXXX:c::1/64'
set service router-advert interface eth2 prefix ::/64
```

### PPPoE の設定
うちは MAP-E じゃないので、PPPoE を使わざるを得ないorz
```text:コマンド
set interfaces pppoe pppoe0 authentication user 'PPPoE 接続ユーザー名'
set interfaces pppoe pppoe0 authentication password 'PPPoE 接続パスワード'
set interfaces pppoe pppoe0 source-interface eth0
```

### NAPT や DHCP サーバーや DNS フォワーディングの設定
いつもの。
```text:コマンド
set nat source rule 10 outbound-interface pppoe0
set nat source rule 10 translation address masquerade

set nat66 source rule 10 outbound-interface eth0
set nat66 source rule 10 translation address masquerade

set service dhcp-server shared-network-name 192-168-12-0_24 subnet 192.168.12.0/24 default-router 192.168.12.1
set service dhcp-server shared-network-name 192-168-12-0_24 subnet 192.168.12.0/24 name-server 192.168.12.1
set service dhcp-server shared-network-name 192-168-12-0_24 subnet 192.168.12.0/24 range range0 start 192.168.12.130
set service dhcp-server shared-network-name 192-168-12-0_24 subnet 192.168.12.0/24 range range0 stop 192.168.12.189

set system name-server 'pppoe0'
set service dns forwarding allow-from 0.0.0.0/0
set service dns forwarding listen-address 192.168.12.1
set service dns forwarding system
```

### ルートの設定

PPPoE で渡されるルートは勝手に設定されるので、使わないローカル アドレスを飲み込む設定だけ入れておく。
```text:コマンド
set protocols static route 10.0.0.0/8 blackhole
set protocols static route 127.16.0.0/12 blackhole
set protocols static route 192.168.0.0/16 blackhole
set protocols static route6 fc00::/7 blackhole
```

ただ、eth2 からの通信を pppoe0 のほうに流すと無駄にクッソ遅いルートに流れるので、PBR で eth0 方面へ流す設定をする。(主題じゃないので細かいことは説明しない)
```text:コマンド
set policy route pbr2 interface eth2
set policy route pbr2 rule 999996 destination address 10.0.0.0/8
set policy route pbr2 rule 999996 set table main
set policy route pbr2 rule 999997 destination address 172.16.0.0/12
set policy route pbr2 rule 999997 set table main
set policy route pbr2 rule 999998 destination address 192.168.0.0/16
set policy route pbr2 rule 999998 set table main
set policy route pbr2 rule 999999 set table 100
set protocols static table 100 route 0.0.0.0/0 next-hop 192.168.11.1
```

## OpenVPN の設定
### 各種証明書の準備
以下のファイルを準備する。SFTP で /home/vyos に置く。
- **ルート CA 証明書と中間 CA 証明書**
サーバー証明書とクライアント証明書とで認証局が異なる場合は両方とも。以降では、`rootca.crt`, `interca.crt` というファイル名とする。
- **サーバー証明書とその鍵**
サーバー側だけで使い、クライアント側では使わない。以降では、`server.crt`, `server.key` というファイル名とする。Subject の CN は、外から接続するときに使用するドメイン名である必要がある。(ここでは `vpn.example.com` とする)
- **クライアント証明書とその鍵**
クライアント側だけで使い、サーバー側では使わない。以降では、`client.crt`, `client.key` というファイル名とする。Subject の CN は、外から接続するときに使用するクライアント名である必要がある。(ここでは `vpnclient@example.com` とする)

### ルート証明書と中間証明書のインポート
ここでインポートした CA 証明書でサーバー証明書とクライアント証明書が署名されているか検証される。
```text:コマンド
run import pki ca rootca-cert file /home/vyos/rootca.crt
run import pki ca interca-cert file /home/vyos/interca.crt
commit
save
```

### サーバー証明書と鍵のインポート
ここでインポートした証明書がサーバー証明書として使われる。
```text:コマンド
run import pki certificate openvpn-server file /home/vyos/server.crt
run import pki certificate openvpn-server key-file /home/vyos/server.key
commit
save
```

### DH param の生成
```text:コマンド
run generate pki dh install openvpn-dh
commit
save
```

### TLS-Auth key の生成
TLS-Auth key を生成する。ここで生成したファイルは、クライアント側でも利用するので、SFTP で取り出しておく。(`show configuration commands` で出力される `set pki openvpn shared-secret openvpn-ta key ’～’` って行を取っておいて、それをクライアント側で流しても OK)
```text:コマンド
run generate pki openvpn shared-secret file /home/vyos/ta.key
run import pki openvpn shared-secret openvpn-ta file /home/vyos/ta.key
commit
save
```

### OpenVPN サーバーの設定
`vtun?` というインターフェイスを設定する形になる。まずは mode を server とする。
```text:コマンド
set interfaces openvpn vtun0 mode 'server'
```

各種証明書などを設定していく。
```text:コマンド
set interfaces openvpn vtun0 tls ca-certificate rootca-cert
set interfaces openvpn vtun0 tls ca-certificate interca-cert
set interfaces openvpn vtun0 tls dh-params openvpn-dh
set interfaces openvpn vtun0 tls auth-key openvpn-ta
set interfaces openvpn vtun0 tls certificate openvpn-server
```

お次に、接続ポートやプロトコルの設定。IPv6 で待ち受けたかったら、明示的に `set interfaces openvpn vtun0 local-host '～'` で設定してやる必要がある。(既定だと、IPv4 のすべてのアドレスで待ち受け。明示的に指定すると、指定されたアドレス以外では待ち受けなくなる。既定でも、IPv4 だけでなく IPv6 でも待ち受けてもいいのでは…)
```text:コマンド
set interfaces openvpn vtun0 protocol udp
set interfaces openvpn vtun0 local-port 35234
```

そして、OpenVPN 内部で使用されるネットワークの設定。(図中で緑色の部分)
```text:コマンド
set interfaces openvpn vtun0 server subnet 10.8.0.0/24
```

加えて、クライアント側に注入する静的ルートの設定。`192.168.11.0/24` と `192.168.12.0/24` は OpenVPN サーバー側の配下ネットワーク。(ネットワーク図参照)
```text:コマンド
set interfaces openvpn vtun0 server push-route 192.168.11.0/24
set interfaces openvpn vtun0 server push-route 192.168.12.0/24
set interfaces openvpn vtun0 server push-route fdXX:XXXX:XXXX:c::/64
```

あとは各種パラメータ。
```text:コマンド
set interfaces openvpn vtun0 encryption cipher aes256gcm
set interfaces openvpn vtun0 encryption ncp-ciphers aes256gcm
set interfaces openvpn vtun0 hash sha512
set interfaces openvpn vtun0 tls tls-version-min 1.2
set interfaces openvpn vtun0 persistent-tunnel
set interfaces openvpn vtun0 keep-alive failure-count '2'
set interfaces openvpn vtun0 keep-alive interval '20'
```

### OpenVPN クライアントの受け入れ設定 (client-config-dir / ccd-exclusive 相当)
クライアントの受け入れ設定は以下の通り。`192.168.255.0/24` はクライアントの配下ネットワーク。(ネットワーク図参照)
配下ネットワークがない場合は、subnet 以降は不要。
```text:コマンド
set interfaces openvpn vtun0 server client 'vpnclient@example.com'
set interfaces openvpn vtun0 server client 'vpnclient@example.com' subnet 192.168.255.0/24
set interfaces openvpn vtun0 server client 'vpnclient@example.com' subnet fdXX:XXXX:XXXX:ff::/64
```

### CRL の適用方法
クライアント側の機器を紛失した場合は、CRL を設定することになる。設定方法は以下の通り。
```text:コマンド

```

### 静的ルートの追加設定

クライアント側の配下ネットワークや OpenVPN で使用されるネットワークへの静的ルートを設定する。
```text:コマンド
set protocols static route 10.8.0.0/24 interface vtun0
set protocols static route 192.168.255.0/24 interface vtun0
```

### 設定の適用と保存
OpenVPN の設定が一通り終わったので、また設定適用＆保存。
```text:コマンド
commit
save
```

# 出先 VyOS (on Raspberry Pi)
## 基本設定
### 外側 ethernet の設定 (eth0: ipheth)
```text:コマンド
set interfaces ethernet eth0 address dhcp
set interfaces ethernet eth0 address dhcpv6
set interfaces ethernet eth0 ipv6 address autoconf
```

### 内側 ethernet の設定 (eth1: オンボード)
```text:コマンド
set interfaces ethernet eth1 address 192.168.255.254/24
set interfaces ethernet eth1 address fdXX:XXXX:XXXX:ff::1/64
set service router-advert interface eth1 prefix ::/64
```

### NAPT や DHCP サーバーや DNS フォワーディングの設定
```text:コマンド
set nat source rule 10 outbound-interface eth0
set nat source rule 10 translation address masquerade
set nat66 source rule 10 outbound-interface eth0
set nat66 source rule 10 translation address masquerade

set service dhcp-server shared-network-name 192-168-255-0_24 subnet 192.168.255.0/24 default-router 192.168.255.254
set service dhcp-server shared-network-name 192-168-255-0_24 subnet 192.168.255.0/24 name-server 192.168.255.254
set service dhcp-server shared-network-name 192-168-255-0_24 subnet 192.168.255.0/24 range range0 start 192.168.255.130
set service dhcp-server shared-network-name 192-168-255-0_24 subnet 192.168.255.0/24 range range0 stop 192.168.255.189

set system name-server eth0
set service dns forwarding allow-from 0.0.0.0/0
set service dns forwarding listen-address 192.168.255.254
set service dns forwarding system
```

### ルートの設定
```text:コマンド
set protocols static route 10.0.0.0/8 blackhole
set protocols static route 127.16.0.0/12 blackhole
set protocols static route 192.168.0.0/16 blackhole
set protocols static route6 fc00::/7 blackhole
```

## OpenVPN の設定

### ルート証明書と中間証明書のインポート
ここでインポートした CA 証明書でサーバー証明書とクライアント証明書が署名されているか検証される。
```text:コマンド
run import pki ca rootca-cert file /home/vyos/rootca.crt
run import pki ca interca-cert file /home/vyos/interca.crt
commit
save
```

### クライアント証明書と鍵のインポート
ここでインポートした証明書が、接続時のクライアント証明書として使われる。
```text:コマンド
run import pki certificate openvpn-client file /home/vyos/client.crt
run import pki certificate openvpn-client key-file /home/vyos/client.key
commit
save
```

### TLS-Auth key のインポート
サーバー側で生成した TA 鍵をインポートする。
```text:コマンド
run import pki openvpn shared-secret openvpn-ta file /home/vyos/ta.key
commit
save
```


### OpenVPN クライアントの設定

まずは mode を server とする。
```text:コマンド
set interfaces openvpn vtun0 mode client
```

各種証明書などを設定していく。
```text:コマンド
set interfaces openvpn vtun0 tls ca-certificate issuerca-cert
set interfaces openvpn vtun0 tls ca-certificate rootca-cert
set interfaces openvpn vtun0 tls auth-key openvpn-ta
set interfaces openvpn vtun0 tls certificate openvpn-client
```

お次に、接続ポートやプロトコル、接続先の OpenVPN サーバーの設定。
```text:コマンド
set interfaces openvpn vtun0 protocol udp
set interfaces openvpn vtun0 remote-port 35234
set interfaces openvpn vtun0 remote-host vpn.example.com
```

あとは各種パラメータ。
```text:コマンド
set interfaces openvpn vtun0 encryption cipher aes256gcm
set interfaces openvpn vtun0 encryption ncp-ciphers aes256gcm
set interfaces openvpn vtun0 hash sha512
set interfaces openvpn vtun0 tls tls-version-min 1.2
set interfaces openvpn vtun0 persistent-tunnel
```

### 設定の適用と保存
OpenVPN の設定が一通り終わったので、また設定適用＆保存。
```text:コマンド
commit
save
```

# 確認
サーバー側 VyOS で接続を確認してみる。
```text:コマンド
show openvpn server
```
```text:show openvpn server
Client CN              Remote Host  Tunnel IP  Local Host  TX bytes  RX bytes  Connected Since
---------              -----------  ---------  ----------  --------  --------  ---------------
vpnclient@example.com  XXXXXXXXXXX  10.8.0.6   XXXXXXXXXX   14.6 KB   20.4 KB  2022-12-30 21:19:42
```

クライアント側 VyOS でルート テーブルを確認してみる。192.168.11.0/24 とか 192.168.12.0/24 とかがあれば OK。(気が向いたら `route -6` も確認してみる)
```text:コマンド
route
```
```text:route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.16.0.1      0.0.0.0         UG    20     0        0 eth0
10.0.0.0        0.0.0.0         255.0.0.0       U     20     0        0 *
10.8.0.1        10.8.0.5        255.255.255.255 UGH   0      0        0 vtun0
10.8.0.5        0.0.0.0         255.255.255.255 UH    0      0        0 vtun0
127.16.0.0      0.0.0.0         255.240.0.0     U     20     0        0 *
172.16.0.0      0.0.0.0         255.255.255.240 U     0      0        0 eth0
192.168.0.0     0.0.0.0         255.255.0.0     U     20     0        0 *
192.168.11.0    10.8.0.9        255.255.255.0   UG    0      0        0 vtun0
192.168.12.0    10.8.0.9        255.255.255.0   UG    0      0        0 vtun0
192.168.255.0   0.0.0.0         255.255.255.0   U     0      0        0 eth1
```
なんかうまくいってないようなら、ログを眺めてみる。
```text:コマンド
show log all | grep openvpn
```
うまくいってるっぽかったら、laptop から desktop にリモート デスクトップ接続してみたりする。

しばらく使ってみて、Raspberry Pi の温度がどんなもんかみたりもして。なお、ここで見れる温度は 1/1000 ℃。いまのところ、大体 50 ℃ くらい。

```bash:コマンド
sudo -i
cat /sys/class/thermal/thermal_zone0/temp
```

おわり。