Linux Network Namespace（その７：Wireguard）

# Network NamespaceにてWireguard
「[Wireguard（その１）＆久しぶりにGNS3（その40）](https://qiita.com/infinite1oop/items/7cea6339e186cead993e)」でも触れたように、Network Namespaceにて、Wireguardを実現。

## ネットワーク
下記が対象とする環境である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/a49a0742-a4e5-cf8f-1596-8807dcdefd75.png)

- WireguardによるVPNをRouter間で確立
    - Router間ネットワーク：172.16.1.0/24
    - Wireguardトンネルネットワーク：10.1.1.0/24
    - 両端ネットワーク192.168.10.0/24および192.168.20.0/24がトンネル対象ネットワーク

これを、Network Namespaceで表現すると下記となる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/6a1d2611-04de-d097-cc7a-7130e2c484a9.png)

## 設定
### Network Namespace関連の設定

```shell
sudo ip netns add ns1
sudo ip netns add ns2
sudo ip netns add ns3
sudo ip netns add ns4
sudo ip netns exec ns1 ip link set lo up
sudo ip netns exec ns2 ip link set lo up
sudo ip netns exec ns3 ip link set lo up
sudo ip netns exec ns4 ip link set lo up
```

- Namespace ns1-ns4作成
- すべてのNamespaceのループバックアドレスUp

```shell
sudo ip link add name ns1-veth0 type veth peer name ns2-veth0
sudo ip link set ns1-veth0 netns ns1
sudo ip netns exec ns1 ip link set ns1-veth0 up
sudo ip netns exec ns1 ip addr add 172.16.1.1/24 dev ns1-veth0
sudo ip link set ns2-veth0 netns ns2
sudo ip netns exec ns2 ip link set ns2-veth0 up
sudo ip netns exec ns2 ip addr add 172.16.1.2/24 dev ns2-veth0
```

- 仮想ネットワークインターフェースPairであるns1-veth0およびns2-veth0作成
- ns1-veth0をns1へ配置
- ns1にてns1-veth0をUpしIPアドレスアサイン
- ns2-veth0をns2へ配置
- ns2にてns2-veth0をUpしIPアドレスアサイン

```shell
sudo ip link add name ns1-veth1 type veth peer name ns3-veth
sudo ip link set ns1-veth1 netns ns1
sudo ip netns exec ns1 ip link set ns1-veth1 up
sudo ip netns exec ns1 ip addr add 192.168.10.1/24 dev ns1-veth1
sudo ip link set ns3-veth netns ns3
sudo ip netns exec ns3 ip link set ns3-veth up
sudo ip netns exec ns3 ip addr add 192.168.10.11/24 dev ns3-veth
```

- 仮想ネットワークインターフェースPairであるns1-veth1およびns3-veth作成
- ns1-veth1をns1へ配置
- ns1にてns1-veth1をUpしIPアドレスアサイン
- ns3-vethをns3へ配置
- ns3にてns3-vethをUpしIPアドレスアサイン

```shell
sudo ip link add name ns2-veth2 type veth peer name ns4-veth
sudo ip link set ns2-veth2 netns ns2
sudo ip netns exec ns2 ip link set ns2-veth2 up
sudo ip netns exec ns2 ip addr add 192.168.20.2/24 dev ns2-veth2
sudo ip link set ns4-veth netns ns4
sudo ip netns exec ns4 ip link set ns4-veth up
sudo ip netns exec ns4 ip addr add 192.168.20.22/24 dev ns4-veth
```

- 仮想ネットワークインターフェースPairであるns2-veth2およびns4-veth作成
- ns2-veth2をns2へ配置
- ns2にてns2-veth2をUpしIPアドレスアサイン
- ns4-vethをns4へ配置
- ns4にてns4-vethをUpしIPアドレスアサイン

```shell
sudo ip netns exec ns1 sysctl -w net.ipv4.ip_forward=1
sudo ip netns exec ns2 sysctl -w net.ipv4.ip_forward=1
```

- ns1にてIP Forward有効化（ルーティング化）
- ns2にてIP Forward有効化（ルーティング化）

```shell
sudo ip netns exec ns3 ip route add default via 192.168.10.1
sudo ip netns exec ns4 ip route add default via 192.168.20.2
```

- ns3にてデフォルトルート設定（ns1へ）
- ns4にてデフォルトルート設定（ns2へ）

### Wireguard実行前のRouting Table
上記設定までの、ns1およびns2のルーティングテーブルの状況は下記となる。目新しいところなしだが、Wireguard設定後と比較するために記述。

```shell
$ sudo ip netns exec ns1 ip route
172.16.1.0/24 dev ns1-veth0 proto kernel scope link src 172.16.1.1 
192.168.10.0/24 dev ns1-veth1 proto kernel scope link src 192.168.10.1

$ sudo ip netns exec ns2 ip route
172.16.1.0/24 dev ns2-veth0 proto kernel scope link src 172.16.1.2 
192.168.20.0/24 dev ns2-veth2 proto kernel scope link src 192.168.20.2 
```

### Wireguard
ここからは本題であるWireguardの設定である。

#### 秘密鍵および公開鍵作成

```shell
$ wg genkey | sudo tee /etc/wireguard/wgA.key | wg pubkey | sudo tee /etc/wireguard/wgA.pub
$ wg genkey | sudo tee /etc/wireguard/wgB.key | wg pubkey | sudo tee /etc/wireguard/wgB.pub
```

#### Wireguard設定ファイル
ns1の設定ファイルは下記となる。

```shell:/etc/wireguard/wgA.conf
[Interface]
PrivateKey = 0O45HUaDCrgvt7fAeO+xqzWnBwPF+WQ6ajVQWt67hkg=
Address = 10.1.1.1/30
ListenPort = 51000

[Peer]
PublicKey = RaGnIfJjduN/GiVfBdbR6FL5FAS0MYCVk49yDQvfbGQ=
AllowedIPs = 10.1.1.2/32,192.168.20.0/24
Endpoint = 172.16.1.2:51000
```

- Interface：自身の情報
    - PrivateKey：秘密鍵
    - Address：Wireguardで利用されるIPアドレス
    - ListenPort：待ち受けポート（UDP）
- Peer：対向機の情報
    - PublicKey：公開鍵
    - AllowedIPs：Wireguard（トンネル）対象となるIPアドレス
    - Endpoint：IPアドレスおよび接続ポート

ns2の情報は下記。内容は同等。

```shell:/etc/wireguard/wgB.conf
[Interface]
PrivateKey = GAy5Gxb9sM0YOrkZxkLFJX5lx4lD+tEjwB8KTtVZSkw=
Address = 10.1.1.2/30
ListenPort = 51000

[Peer]
PublicKey = na2jjpCaVJYtdlVA2evS6P1Y1JNSpuI/uwEljEwprRM=
AllowedIPs = 10.1.1.1/32,192.168.10.0/24
Endpoint = 172.16.1.1:51000
```

## 検証（Wireguard実行）
コマンドレベルでWireguardを実行する（ns1およびns2にて）。

```shell
$ sudo ip netns exec ns1 wg-quick up wgA
[#] ip link add wgA type wireguard
[#] wg setconf wgA /dev/fd/63
[#] ip -4 address add 10.1.1.1/30 dev wgA
[#] ip link set mtu 1420 up dev wgA
[#] ip -4 route add 192.168.20.0/24 dev wgA

$ sudo ip netns exec ns2 wg-quick up wgB
[#] ip link add wgB type wireguard
[#] wg setconf wgB /dev/fd/63
[#] ip -4 address add 10.1.1.2/30 dev wgB
[#] ip link set mtu 1420 up dev wgB
[#] ip -4 route add 192.168.10.0/24 dev wgB
```

### Wireguard実行後のRouting Table
ns1およびns2のルーティングテーブルは下記となる。

```shell
$ sudo ip netns exec ns1 ip route
10.1.1.0/30 dev wgA proto kernel scope link src 10.1.1.1 
172.16.1.0/24 dev ns1-veth0 proto kernel scope link src 172.16.1.1 
192.168.10.0/24 dev ns1-veth1 proto kernel scope link src 192.168.10.1 
192.168.20.0/24 dev wgA scope link

$ sudo ip netns exec ns2 ip route
10.1.1.0/30 dev wgB proto kernel scope link src 10.1.1.2 
172.16.1.0/24 dev ns2-veth0 proto kernel scope link src 172.16.1.2 
192.168.10.0/24 dev wgB scope link 
192.168.20.0/24 dev ns2-veth2 proto kernel scope link src 192.168.20.2
```

Wireguardの対象となるIPアドレスへのルートが、Wireguardのネットワークインターフェース（wgAおよびwgB）となっていることがわかる。

### ping実行
末端どうしの疎通を実行（ns3からns4のping）。

```shell
$ sudo ip netns exec ns3 ping 192.168.20.22 -c 3
PING 192.168.20.22 (192.168.20.22) 56(84) bytes of data.
64 bytes from 192.168.20.22: icmp_seq=1 ttl=62 time=0.345 ms
64 bytes from 192.168.20.22: icmp_seq=2 ttl=62 time=0.448 ms
64 bytes from 192.168.20.22: icmp_seq=3 ttl=62 time=0.727 ms
```

この時のWireguardネットワークインターフェース（ns2-veth0）のtcpdumpの状況を紹介。

```shell
$ sudo ip netns exec ns2 tcpdump -nel -i ns2-veth0

16:42:48.816230 d6:54:ae:b7:04:48 > 8e:3e:f5:de:56:f9, ethertype IPv4 (0x0800), length 170: 172.16.1.1.51000 > 172.16.1.2.51000: UDP, length 128
16:42:48.816464 d6:54:ae:b7:04:48 > 8e:3e:f5:de:56:f9, ethertype IPv4 (0x0800), length 190: 172.16.1.1.51000 > 172.16.1.2.51000: UDP, length 148
16:42:48.816479 8e:3e:f5:de:56:f9 > d6:54:ae:b7:04:48, ethertype IPv4 (0x0800), length 170: 172.16.1.2.51000 > 172.16.1.1.51000: UDP, length 128
16:42:48.816860 8e:3e:f5:de:56:f9 > d6:54:ae:b7:04:48, ethertype IPv4 (0x0800), length 134: 172.16.1.2.51000 > 172.16.1.1.51000: UDP, length 92
16:42:48.817044 d6:54:ae:b7:04:48 > 8e:3e:f5:de:56:f9, ethertype IPv4 (0x0800), length 74: 172.16.1.1.51000 > 172.16.1.2.51000: UDP, length 32
16:42:49.845655 d6:54:ae:b7:04:48 > 8e:3e:f5:de:56:f9, ethertype IPv4 (0x0800), length 170: 172.16.1.1.51000 > 172.16.1.2.51000: UDP, length 128
16:42:49.845841 8e:3e:f5:de:56:f9 > d6:54:ae:b7:04:48, ethertype IPv4 (0x0800), length 170: 172.16.1.2.51000 > 172.16.1.1.51000: UDP, length 128
16:42:50.869977 d6:54:ae:b7:04:48 > 8e:3e:f5:de:56:f9, ethertype IPv4 (0x0800), length 170: 172.16.1.1.51000 > 172.16.1.2.51000: UDP, length 128
16:42:50.870191 8e:3e:f5:de:56:f9 > d6:54:ae:b7:04:48, ethertype IPv4 (0x0800), length 170: 172.16.1.2.51000 > 172.16.1.1.51000: UDP, length 128
```

tcpdumpだと、UDPポート51000のみの表示となり、少々わかりにくい。そこで、tcpdumpの結果をファイル化し、Wiresharkで読み込む。下記はネットワークインターフェースns2-veth0の状況。

![ns2-veth0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/dc10372c-08d9-bca0-6905-a91f02f3a718.png)

Wireguardであることがわかる。下記はネットワークインターフェースwgBの状況。

![wgB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/588535b0-5f0f-9156-1cf1-97d9eb64edc9.png)

こちらは、トンネル化前の暗号化されていない生のデータが見える。トレビアン。

EOF