Linux Network Namespace（その５：GRE）

# Network NamespaceでGRE
その５では、GREを実現する。

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/f06a2cc2-902b-3404-732a-021b67ac848f.png)

両端のPC間の通信を、ルーター間でGREでトンネルする。

## Network Namespace
上記ネットワークをNetwork Namespaceで実現したものが下記となる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/574bbb57-7def-4293-23cc-278f727bfd29.png)

以降、設定内容の説明。

```shell
sudo ip netns add ns1
sudo ip netns add ns2
sudo ip link add name ns1-veth0 type veth peer name ns2-veth0
sudo ip link set ns1-veth0 netns ns1
sudo ip link set ns2-veth0 netns ns2
sudo ip netns exec ns1 ip link set lo up
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 netns exec ns2 ip link set lo up
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
```
- Namespace ns1およびns2作成
- 仮想ネットワークインターフェースPairであるns1-veth0およびns2-veth0作成
- ns1-veth0をns1へ、ns2-veth0をns2へ配置
- ns1にて、loおよびns1-veth0をUpし、ns1-veth0にIPアドレスアサイン
- ns2にて、loおよびns2-veth0をUpし、ns2-veth0にIPアドレスアサイン

```shell
sudo ip netns exec ns1 ip link add name ns1-veth type dummy
sudo ip netns exec ns1 ip link set ns1-veth up
sudo ip netns exec ns1 ip addr add 10.1.1.11/24 dev ns1-veth
```
- ns1にて、仮想ネットワークインターフェースns1-veth作成
- それをUpし、IPアドレスアサイン

```shell
sudo ip netns exec ns2 ip link add name ns2-veth type dummy
sudo ip netns exec ns2 ip link set ns2-veth up
sudo ip netns exec ns2 ip addr add 10.1.2.22/24 dev ns2-veth
```
- ns2にて、上記ns1と同様を実施

```shell
sudo ip netns exec ns1 ip tunnel add tun0 mode gre local 172.16.1.1 remote 172.16.1.2
sudo ip netns exec ns1 ip addr add 10.1.1.1/24 dev tun0
sudo ip netns exec ns1 ip link set tun0 up
```
- ns1にて、GREトンネル（ネットワークインターフェース：tun0）作成
- GREトンネルインターフェースにIPアドレスアサイン
- GREトンネルインターフェースUp

```shell
sudo ip netns exec ns2 ip tunnel add tun0 mode gre local 172.16.1.2 remote 172.16.1.1
sudo ip netns exec ns2 ip link set tun0 up
sudo ip netns exec ns2 ip addr add 10.1.2.1/24 dev tun0
```
- ns2にて、上記ns1と同様を実施

```shell
sudo ip netns exec ns1 ip route add 10.1.2.0/24 dev tun0
sudo ip netns exec ns2 ip route add 10.1.1.0/24 dev tun0
```
- 両端PCが属するネットワークへのスタティックルートを作成したトンネルインターフェース（tun0）を宛先として設定

## 検証
左端PCから右端PCへpingを実施する。
```shell
$ sudo ip netns exec ns1 ping 10.1.2.22 -c 1
PING 10.1.2.22 (10.1.2.22) 56(84) bytes of data.
64 bytes from 10.1.2.22: icmp_seq=1 ttl=64 time=0.093 ms

--- 10.1.2.22 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.093/0.093/0.093/0.000 ms
```

この時のトンネルインターフェースが利用するネットワークインターフェース”ns1-veth0”のtcpdumpの結果が下記である。

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

8e:3e:f5:de:56:f9, ethertype IPv4 (0x0800), length 122: 172.16.1.1 > 172.16.1.2: GREv0, proto IPv4 (0x0800), length 88: 10.1.1.1 > 10.1.2.22: ICMP echo request, id 2653, seq 1, length 64
17:51:35.217994 8e:3e:f5:de:56:f9 > d6:54:ae:b7:04:48, ethertype IPv4 (0x0800), length 122: 172.16.1.2 > 172.16.1.1: GREv0, proto IPv4 (0x0800), length 88: 10.1.2.22 > 10.1.1.1: ICMP echo reply, id 2653, seq 1, length 64
```

GREにてカプセル化（トンネル化）されているのがわかる。また、この時のトンネルインターフェース”tun0”のtcpdumpの結果は下記となる。

```shell
$ sudo ip netns exec ns1 tcpdump -nel -i tun0

17:52:05.909214 Out ethertype IPv4 (0x0800), length 100: 10.1.1.1 > 10.1.2.22: ICMP echo request, id 2662, seq 1, length 64
17:52:05.909273  In ethertype IPv4 (0x0800), length 100: 10.1.2.22 > 10.1.1.1: ICMP echo reply, id 2662, seq 1, length 64
```
トンネルインターフェースでは、単なるIPパケットであり、Ethernetヘッダ情報であるMacアドレスは含まれていない。

なお、Namespace ns1のルーティングテーブルは下記である。

```shell
$ sudo ip netns exec ns1 ip route
10.1.1.0/24 dev ns1-veth proto kernel scope link src 10.1.1.11 
10.1.2.0/24 dev tun0 scope link 
10.1.2.1 dev tun0 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 
```

また、GREトンネルの状況は下記となる。

```shell
$ sudo ip netns exec ns1 ip tunnel show
gre0: gre/ip remote any local any ttl inherit nopmtudisc
tun0: gre/ip remote 172.16.1.2 local 172.16.1.1 ttl inherit
```

EOF