Dockerと同様な仮想ネットワークを構築する

# はじめに

前回はDockerのネットワークを確認しました。今回はDockerと同様な仮想ネットワークを構築していきたいと思います。

https://qiita.com/ymktmk/items/0234e54abd16d3a4f029

## 仮想ブリッジの作成

bridge0という名前で仮想ブリッジを作成します。そして、IPアドレスを割り当てます。
```
sudo ip link add bridge0 type bridge
sudo ip link set bridge0 up
sudo ip address add 192.168.0.100/24 dev bridge0
```

## Network Namesaceの作成

Network Namesaceを作成します。Dockerはコンテナ1つに対してnamespaceを1つ確保しています。
```
sudo ip netns add namespace1
sudo ip netns add namespace2
```

downしているのでupします。
```
sudo ip netns exec namespace1 ip link set lo up
sudo ip netns exec namespace2 ip link set lo up
```

## vath-pairの作成と接続

仮想ブリッジとnamespaceを接続するveth-pairを作成します。
```
sudo ip link add name namespace-veth1 type veth peer name bridge-veth1
sudo ip link add name namespace-veth2 type veth peer name bridge-veth2
```

namespaceへ接続します。
```
sudo ip link set namespace-veth1 netns namespace1
sudo ip link set namespace-veth2 netns namespace2
```

仮想ブリッジへ接続します。
```
sudo ip link set dev bridge-veth1 master bridge0
sudo ip link set dev bridge-veth2 master bridge0
```

downしているのでupします。
```
sudo ip netns exec namespace1 ip link set namespace-veth1 up
sudo ip netns exec namespace2 ip link set namespace-veth2 up
sudo ip link set bridge-veth1 up
sudo ip link set bridge-veth2 up
```

namespaceにIPアドレスを付与
```
sudo ip netns exec namespace1 ip addr add 192.168.0.1/24 dev namespace-veth1
sudo ip netns exec namespace2 ip addr add 192.168.0.2/24 dev namespace-veth2
```

## Namespaceから外部ネットワークへの接続を有効化

IPフォワードの有効化
```
sudo chmod 777 /etc/sysctl.conf
sudo echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
```

デフォルトゲートウェイの設定
```
sudo ip netns exec namespace1 ip route add default via 192.168.0.100
sudo ip netns exec namespace2 ip route add default via 192.168.0.100
```

ルーティング後に、送信元が192.168.0.0/24で、eth0から出ていくパケットの送信元アドレスをeth0のIPに変換することで外部ネットワークに通信できます。
```
sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE
```

## 現状確認

namespaceが作成されているかどうか確認します。
```console
$ ip netns list

namespace1
namespace2
```

仮想ブリッジとveth-pairが作成されているかどうか確認します。
```console:
$ ip a

10: bridge0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ee:20:6b:32:fd:a4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.100/24 scope global bridge0
       valid_lft forever preferred_lft forever
    inet6 fe80::ec20:6bff:fe32:fda4/64 scope link 
       valid_lft forever preferred_lft forever
11: bridge-veth1@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UP group default qlen 1000
    link/ether 7a:dc:aa:4d:19:e5 brd ff:ff:ff:ff:ff:ff link-netns namespace1
    inet6 fe80::78dc:aaff:fe4d:19e5/64 scope link 
       valid_lft forever preferred_lft forever
13: bridge-veth2@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UP group default qlen 1000
    link/ether 76:50:1d:7e:57:a2 brd ff:ff:ff:ff:ff:ff link-netns namespace2
    inet6 fe80::7450:1dff:fe7e:57a2/64 scope link 
       valid_lft forever preferred_lft forever
```

新しくルーティングが追加されています。

```console:
$ ip r
192.168.0.0/24 dev bridge0 proto kernel scope link src 192.168.0.100
```

## 動作確認

ホストからnamespace1へping

```
ping 192.168.0.1
```

namespace1からnamespace2へping

```
sudo ip netns exec namespace1 ping 192.168.0.2
```

namespace1からGoogleのDNSへping

```
sudo ip netns exec namespace1 ping 8.8.8.8
```

# おわりに

このように、Dockerと同じようなネットワークが作成できます。今後はリソース管理やファイルシステムなども深ぼっていきたいと思います。

# 参考文献

https://news.mynavi.jp/techplus/article/k8ssecurity-3/4

https://christina04.hatenablog.com/entry/network-namespace-with-bridge