WireGuard でsite-to-site なVPNを張ってみる

# tl;dr
* centos7 (Without SELinux) なVMを利用して site-to-site VPN を wireguard で 構築してみた
* alowed-IPsに対向のネットワークの他に対向のwg0のIPを書かないといけない
* linux 的には wg0 に routing するだけで うまいことやってくれてるようにみえた
* wg を起動してても何もせず ping など wg 経由な通信が発生して初めて handshake するのはちょっと罠かも



## 参考情報
* https://gist.github.com/dockerlead/e9f025264b1b2caeba34f5d85fe1e866
* https://heartbeats.jp/hbblog/2020/05/wireguard.html
* https://blog.asterism.xyz/posts/2020-04-16/


## ゴール
* 直接疎通性を持たない別な プライベートネットワーク に対して WireGuard の VPN 越しに ping が送れるようになる
  * London2 -> London1 -> [WireGuard VPN] <- LosAngels1 <- LosAngels2


## 検証環境
* vultr を利用して VM を作成した
 * vultr は region ごとの private network を払い出してくれるので検証に便利だった
 * CentOS7 without SELinux で作成している
 
|name|役割|global IP(eth0)|private IP(eth1)|
|:---:|:-:|:-----------:|:--------------:|
|London1|WGで話す人|45.63.56.206/23|10.5.96.3/24|
|London2|なんにもしない人|149.28.93.171/23|10.5.96.4/24|
|LosAngels1|WGで話す人|192.248.151.231/23|10.8.96.3/24|
|LosAngels2|なんにもしない人|45.77.57.213/23|10.8.96.4/24|

* 費用
 * クレカを登録する必要があるが、この検証にかかったのは $0.15 なので、 無料の$100でまかなえる
 ![スクリーンショット 2021-09-18 10.10.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32855/7e98fd4f-b504-f413-d4b3-b31e54716d22.png)

## 事前準備
### private IP を割り当てる
* https://www.vultr.com/docs/how-to-configure-a-private-network-on-centos を見ながら ```/etc/sysconfig/network-scripts/ifcfg-eth1``` の編集と ```ifup eth1``` が必要

## wireguard 構築
* まずは London1 と LosAngels1 で wg の vpn を構築する

### wireguard のインストール
* https://www.wireguard.com/install/#centos-7-module-plus-module-kmod-module-dkms-tools に書いてあるとおり 実行。
* 検証時は何もわからず method1,2,3 を実行してしまったが、たぶん これで良い

```
Method 1: a signed module is available as built-in to CentOS's kernel-plus:

$ sudo yum install yum-utils epel-release
$ sudo yum-config-manager --setopt=centosplus.includepkgs=kernel-plus --enablerepo=centosplus --save
$ sudo sed -e 's/^DEFAULTKERNEL=kernel$/DEFAULTKERNEL=kernel-plus/' -i /etc/sysconfig/kernel
$ sudo yum install kernel-plus wireguard-tools
$ sudo reboot
```

### wireguard の鍵生成
* 鍵の扱いは大事なので、 本当はこんなふうにベタベタしてはいけない

```
$ umask 077
$ wg genkey > privatekey
$ wg pubkey < privatekey > publickey
```
```
[root@losangels1 ~]# umask 077
[root@losangels1 ~]# wg genkey > privatekey
[root@losangels1 ~]# wg pubkey < privatekey > publickey
[root@losangels1 ~]# cat privatekey 
WGUnhcQ9wQr0KoEz9Y+Zb4l6DPudoEdNDcD6k5GLDU8=
[root@losangels1 ~]# cat publickey 
GvydjkfH8SXn672goKmBQ/z9C2Fb1y0D734FxQ3Skxk=

[root@london1 ~]# umask 077
[root@london1 ~]# wg genkey > privatekey
[root@london1 ~]# wg pubkey < privatekey > publickey
[root@london1 ~]# cat privatekey 
AEYxnkxF86clBgWDh2PJz9TQyM11DIosIo1l0GEM/VU=
[root@london1 ~]# cat publickey 
T8kHM7uz8K1lnBPLUiTjL4CmGtV5sXKZWo8HN6IwyCc=
```

### IPマスカレードを有効にしたり 外部からの着信を有効にする (London1, LosAngels1)
* wg tunnel を通ってきたものを 自分のprivate network へ 転送する必要がある
* また、 wg 同士は (今回は) 51820/udp で やり取りするので ポートを開放する

```
# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
# sysctl -p 

# firewall-cmd --zone=public --permanent --add-masquerade
# firewall-cmd --permanent --add-port=51820/udp
# systemctl reload firewalld
```

### config を書く
* 今回は London と LosAngels で site-to-site をするので、 どちらも server であり client である
* server と client で ファイル名を分けている場合もあるが、 一個にまとめた
* 注意点
  * 自分のprivateKey と 相手のPublicKey
  * AllowedIPs には 相手のネットワークと 相手のwg0 の IP
  * endpoint は 対向の wg が動いてるホスト の ip

```:LosAngels1の/etc/wireguard/wg0.conf
[Interface]
Address = 10.10.10.1/24
ListenPort = 51820
PrivateKey = WGUnhcQ9wQr0KoEz9Y+Zb4l6DPudoEdNDcD6k5GLDU8=

[Peer]
PublicKey = T8kHM7uz8K1lnBPLUiTjL4CmGtV5sXKZWo8HN6IwyCc=
AllowedIPs = 10.8.96.0/24, 10.10.10.2/32
Endpoint = 45.63.56.206:51820
```

```:London1の/etc/wireguard/wg0.conf
[Interface]
PrivateKey = AEYxnkxF86clBgWDh2PJz9TQyM11DIosIo1l0GEM/VU=
Address = 10.10.10.2/24
ListenPort = 51820

[Peer]
PublicKey = GvydjkfH8SXn672goKmBQ/z9C2Fb1y0D734FxQ3Skxk=
AllowedIPs = 10.5.96.0/24, 10.10.10.1/32
Endpoint = 192.248.151.231:51820
```

### wg を起動する
```
# wg-quick up /etc/wireguard/wg0.conf
```

で起動すると 以下の通り 対象のネットワークあての通信が ip コマンドで wg0 へ 渡される

```
[root@losangels1 ~]#  sudo wg-quick up /etc/wireguard/wg0.conf
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.10.10.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] ip -4 route add 10.8.96.0/24 dev wg0

[root@london1 ~]#  sudo wg-quick up /etc/wireguard/wg0.conf
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.10.10.2/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] ip -4 route add 10.5.96.0/24 dev wg0
```

### 接続してみる
* この状態ではまだ何もやり取りをしていない。
* ここで、お互いに wg 経由な接続になりうる ping を打ったりしてみると handshake されてつながる
  * 例えば London1 -> LosAngels1のPrivateIP (10.5.96.3)
 
```

[root@losangels1 ~]# wg
interface: wg0
  public key: GvydjkfH8SXn672goKmBQ/z9C2Fb1y0D734FxQ3Skxk=
  private key: (hidden)
  listening port: 51820

peer: T8kHM7uz8K1lnBPLUiTjL4CmGtV5sXKZWo8HN6IwyCc=
  endpoint: 45.63.56.206:51820
  allowed ips: 10.8.96.0/24, 10.10.10.2/32
  latest handshake: 44 seconds ago
  transfer: 2.77 KiB received, 9.75 KiB sent

  [root@london1 ~]# wg
interface: wg0
  public key: T8kHM7uz8K1lnBPLUiTjL4CmGtV5sXKZWo8HN6IwyCc=
  private key: (hidden)
  listening port: 51820

peer: GvydjkfH8SXn672goKmBQ/z9C2Fb1y0D734FxQ3Skxk=
  endpoint: 192.248.151.231:51820
  allowed ips: 10.5.96.0/24, 10.10.10.1/32
  latest handshake: 51 seconds ago
  transfer: 9.75 KiB received, 2.77 KiB sent
```

##  WireGuard じゃない人たちもつながる
* london1 と losangels1 はつながった、他のホストもつなげよう

### ルーティングの追加
* wg が動いてるホストは すでに、対向ネットワークへの接続時のルーティングが設定されている。
* そうじゃないホストにはそれがないので、 お互いのネットワークにあるwg へ routing する必要がある
* 例えば こういう具合
    * losangels2 から見た londonのネットワーク(10.8.96.0/24) へは losangels1(10.5.96.3) を経由する
    * london から見た losangels のネットワーク(10.5.96.0/24) へは london1(10.8.96.3) を経由する
   
```
[root@losangels2 ~]# ip route add 10.8.96.0/24 via 10.5.96.3  dev eth1 
[root@london2 ~]# ip route add 10.5.96.0/24 via 10.8.96.3  dev eth1 
```

```
### つながらないところに
[root@london2 ~]# ping 10.5.96.4
PING 10.5.96.4 (10.5.96.4) 56(84) bytes of data.
^C
--- 10.5.96.4 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1000ms

### 経路をいれたら
[root@london2 ~]# ip route add 10.5.96.0/24 via 10.8.96.3  dev eth1

### つながるようになった
[root@london2 ~]# ping 10.5.96.4
PING 10.5.96.4 (10.5.96.4) 56(84) bytes of data.
64 bytes from 10.5.96.4: icmp_seq=1 ttl=62 time=137 ms
64 bytes from 10.5.96.4: icmp_seq=2 ttl=62 time=137 ms
^C
--- 10.5.96.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 137.272/137.381/137.490/0.109 ms

```