Network NamespaceとvethでVXLANを作ってみる

<img width="801" alt="network.drawio.png (41.4 kB)" src="https://img.esa.io/uploads/production/attachments/5809/2025/02/26/19598/c9a0afc5-84e4-4625-8267-98c6c5642ff4.png">


# Network Namespaceの作成とvethの接続

`ns1` `ns2` `router` という3つのNetwork Namespaceを作成し、それぞれをvethで接続します。
`ns1` と `router` を接続するvethには `192.0.2.1` と `192.0.2.254` のIPアドレスをそれぞれ割り当てます。
`ns2` と `router` を接続するvethには `198.51.100.1` と `198.51.100.254` のIPアドレスをそれぞれ割り当てます。

```bash
# nsの作成
sudo ip netns add ns1
sudo ip netns add router
sudo ip netns add ns2

# vethの作成
sudo ip link add ns1-veth0 type veth peer name gw-veth0
sudo ip link add ns2-veth0 type veth peer name gw-veth1

# ns1とrouterを接続
sudo ip link set ns1-veth0 netns ns1
sudo ip link set gw-veth0 netns router
# ns2とrouterを接続
sudo ip link set gw-veth1 netns router
sudo ip link set ns2-veth0 netns ns2

# ns1のIPアドレス設定 (192.0.2.1/24)
sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
# ns2のIPアドレス設定 (198.51.100.1/24)
sudo ip netns exec ns2 ip address add 198.51.100.1/24 dev ns2-veth0
# routerのIPアドレス設定 (192.0.2.254/24, 198.51.100.254/24)
sudo ip netns exec router ip address add 192.0.2.254/24 dev gw-veth0
sudo ip netns exec router ip address add 198.51.100.254/24 dev gw-veth1

# ns1のMACアドレスの設定
sudo ip netns exec ns1 ip link set dev ns1-veth0 address 00:00:5E:00:53:11
# ns2のMACアドレス設定
sudo ip netns exec ns2 ip link set dev ns2-veth0 address 00:00:5E:00:53:22
# routerのMACアドレス設定
sudo ip netns exec router ip link set dev gw-veth0 address 00:00:5E:00:53:12
sudo ip netns exec router ip link set dev gw-veth1 address 00:00:5E:00:53:21

# vethのUP
sudo ip netns exec ns1 ip link set ns1-veth0 up
sudo ip netns exec router ip link set gw-veth0 up
sudo ip netns exec router ip link set gw-veth1 up
sudo ip netns exec ns2 ip link set ns2-veth0 up
```

作成したNetwork Namespaceが存在するかを確認

```bash
sudo ip netns list
# ns1 (id: 1)
# router (id: 2)
# ns2 (id: 3)
```

`ns1`に `ns1-veth0` インターフェースが存在するかを確認

```bash
sudo ip netns exec ns1 ip a
# 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
#     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# 184: ns1-veth0@if183: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
#     link/ether 00:00:5e:00:53:11 brd ff:ff:ff:ff:ff:ff link-netns router
#     inet 192.0.2.1/24 scope global ns1-veth0
#        valid_lft forever preferred_lft forever
#     inet6 fe80::200:5eff:fe00:5311/64 scope link
#        valid_lft forever preferred_lft forever
```


`ns2`に `ns2-veth0` インターフェースが存在するかを確認

```bash
sudo ip netns exec ns2 ip a
# 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
#     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# 186: ns2-veth0@if185: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
#     link/ether 00:00:5e:00:53:22 brd ff:ff:ff:ff:ff:ff link-netns router
#     inet 198.51.100.1/24 scope global ns2-veth0
#        valid_lft forever preferred_lft forever
#     inet6 fe80::200:5eff:fe00:5322/64 scope link
#        valid_lft forever preferred_lft forever
```


`router`に `gw-veth0` `gw-veth1` インターフェースが存在するかを確認

```bash
sudo ip netns exec router ip a
# 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
#     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# 183: gw-veth0@if184: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
#     link/ether 00:00:5e:00:53:12 brd ff:ff:ff:ff:ff:ff link-netns ns1
#     inet 192.0.2.254/24 scope global gw-veth0
#        valid_lft forever preferred_lft forever
#     inet6 fe80::200:5eff:fe00:5312/64 scope link
#        valid_lft forever preferred_lft forever
# 185: gw-veth1@if186: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
#     link/ether 00:00:5e:00:53:21 brd ff:ff:ff:ff:ff:ff link-netns ns2
#     inet 198.51.100.254/24 scope global gw-veth1
#        valid_lft forever preferred_lft forever
#     inet6 fe80::200:5eff:fe00:5321/64 scope link
#        valid_lft forever preferred_lft forever
```



# ルーティング設定

```bash
# ns1にns1 -> ns2 へのルートを追加
sudo ip netns exec ns1 ip route add default via 192.0.2.254
# ns2にns2 -> ns1 へのルートを追加
sudo ip netns exec ns2 ip route add default via 198.51.100.254

# 複数のネットワークインターフェース間でパケットを転送する設定。(ルーターとして動かすための設定)
sudo ip netns exec router sysctl net.ipv4.ip_forward=1
```

`ns1` に default のルーティング設定が追加されたことを確認

```bash
sudo ip netns exec ns1 ip route show
# default via 192.0.2.254 dev ns1-veth0
# 192.0.2.0/24 dev ns1-veth0 proto kernel scope link src 192.0.2.1
```

`ns2` に default のルーティング設定が追加されたことを確認

```bash
sudo ip netns exec ns2 ip route show
# default via 198.51.100.254 dev ns2-veth0
# 198.51.100.0/24 dev ns2-veth0 proto kernel scope link src 198.51.100.1
```

`router` のルーティング設定

```bash
sudo ip netns exec router ip route show
# 192.0.2.0/24 dev gw-veth0 proto kernel scope link src 192.0.2.254
# 198.51.100.0/24 dev gw-veth1 proto kernel scope link src 198.51.100.254
```


# 疎通確認

```bash
#  ns1 -> ns2
sudo ip netns exec ns1 ping -c 3 198.51.100.1 -I 192.0.2.1
# ns2 -> ns1
sudo ip netns exec ns2 ping -c 3 192.0.2.1 -I 198.51.100.1
```


# VXLANインターフェースの作成

```bash
# ns1 の ns1-veth0 に VXLAN インターフェースを作成
#   vxlan0 : 作成する VXLAN インターフェース名
#   type vxlan : VXLAN インターフェースを作成
#   id 100: VNI(仮想ネットワークを識別するためのID)
#   dev ns1-veth0 : インターフェース ns1-veth0 に vxlan インターフェースをくっつける
#   remote 198.51.100.1: VXLANピアのIPアドレス
#   dstport 4789 : UDP ポート 4789 (VXLAN のデフォルトポート)
sudo ip netns exec ns1 ip link add vxlan0 type vxlan id 100 dev ns1-veth0 remote 198.51.100.1 dstport 4789

# ns2 の ns1-veth0 に VXLAN インターフェースを作成
#   vxlan0 : 作成する VXLAN インターフェース名
#   type vxlan : VXLAN インターフェースを作成
#   id 100: VNI(仮想ネットワークを識別するためのID)
#   dev ns2-veth0 : インターフェース ns1-veth0 に vxlan インターフェースをくっつける
#   remote 192.0.2.1: VXLANピアのIPアドレス
#   dstport 4789 : UDP ポート 4789 (VXLAN のデフォルトポート)
sudo ip netns exec ns2 ip link add vxlan0 type vxlan id 100 dev ns2-veth0 remote 192.0.2.1 dstport 4789

# VXLANインターフェースにIPアドレスを設定
sudo ip netns exec ns1 ip addr add 172.30.0.1/16 dev vxlan0
sudo ip netns exec ns2 ip addr add 172.30.0.2/16 dev vxlan0

# VXLANインターフェースのUP
sudo ip netns exec ns1 ip link set vxlan0 up
sudo ip netns exec ns2 ip link set vxlan0 up
```

# VXLANの疎通確認

`172.30.0.*` のIPで `ns1` と `ns2` がつうしんできることをかくにｎ

```bash
# ns1のvxlan0 -> ns2のvxlan0
sudo ip netns exec ns1 ping -c 3 172.30.0.2
# ns2のvxlan0 -> ns1のvxlan0
sudo ip netns exec ns2 ping -c 3 172.30.0.1
```

## ns1のtcpdump

```bash
sudo ip netns exec ns1 tcpdump -tnel -i any icmp
# tcpdump: data link type LINUX_SLL2
# tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
# listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
# vxlan0 Out ifindex 2 b6:90:b7:7e:62:00 ethertype IPv4 (0x0800), length 104: 172.30.0.1 > 172.30.0.2: ICMP echo request, id 28257, seq 1, length 64
# vxlan0 In  ifindex 2 16:a2:81:37:66:36 ethertype IPv4 (0x0800), length 104: 172.30.0.2 > 172.30.0.1: ICMP echo reply, id 28257, seq 1, length 64
# vxlan0 Out ifindex 2 b6:90:b7:7e:62:00 ethertype IPv4 (0x0800), length 104: 172.30.0.1 > 172.30.0.2: ICMP echo request, id 28257, seq 2, length 64
# vxlan0 In  ifindex 2 16:a2:81:37:66:36 ethertype IPv4 (0x0800), length 104: 172.30.0.2 > 172.30.0.1: ICMP echo reply, id 28257, seq 2, length 64
# vxlan0 Out ifindex 2 b6:90:b7:7e:62:00 ethertype IPv4 (0x0800), length 104: 172.30.0.1 > 172.30.0.2: ICMP echo request, id 28257, seq 3, length 64
# vxlan0 In  ifindex 2 16:a2:81:37:66:36 ethertype IPv4 (0x0800), length 104: 172.30.0.2 > 172.30.0.1: ICMP echo reply, id 28257, seq 3, length 64
```

vxlanのデータグラム(UDP port 4789)をキャプチャする

```bash
sudo ip netns exec ns1 tcpdump -tnel -i ns1-veth0  udp port 4789
```

## ns2のtcpdump

```bash
sudo ip netns exec ns2 tcpdump -tnel -i any icmp
# tcpdump: data link type LINUX_SLL2
# tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
# listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
# vxlan0 In  ifindex 2 b6:90:b7:7e:62:00 ethertype IPv4 (0x0800), length 104: 172.30.0.1 > 172.30.0.2: ICMP echo request, id 28257, seq 1, length 64
# vxlan0 Out ifindex 2 16:a2:81:37:66:36 ethertype IPv4 (0x0800), length 104: 172.30.0.2 > 172.30.0.1: ICMP echo reply, id 28257, seq 1, length 64
# vxlan0 In  ifindex 2 b6:90:b7:7e:62:00 ethertype IPv4 (0x0800), length 104: 172.30.0.1 > 172.30.0.2: ICMP echo request, id 28257, seq 2, length 64
# vxlan0 Out ifindex 2 16:a2:81:37:66:36 ethertype IPv4 (0x0800), length 104: 172.30.0.2 > 172.30.0.1: ICMP echo reply, id 28257, seq 2, length 64
# vxlan0 In  ifindex 2 b6:90:b7:7e:62:00 ethertype IPv4 (0x0800), length 104: 172.30.0.1 > 172.30.0.2: ICMP echo request, id 28257, seq 3, length 64
# vxlan0 Out ifindex 2 16:a2:81:37:66:36 ethertype IPv4 (0x0800), length 104: 172.30.0.2 > 172.30.0.1: ICMP echo reply, id 28257, seq 3, length 64
```

vxlanのデータグラム(UDP port 4789)をキャプチャする

```bash
sudo ip netns exec ns2 tcpdump -tnel -i ns2-veth0  udp port 4789
```

# 削除

```bash
# nsの削除
sudo ip --all netns delete
```