---
# System prepended metadata

title: 網路練習題 Part 2

---

# 網路練習題 Part 2

## 預備知識

==Step2== 的部分是在其他都完成以後，才開始做的。

1. 關於 Container 與 Container Networking
    * Container 和 VM 的差別是？
    * 什麼是 Network Namespace？
    * 什麼是 cgroup？
    * Docker 和 Container 哪裡不同？
2. 關於 Bridge
    * Brctl
    * ovs-vsctl / ovs-ofctl ... （optional，有時間再看）
3. 關於 ip 指令
    * ip netns
    * ip link
    * ip addr
4. IPTABLE 與 NetFilter 學習 ==Step 2==
    * iptables 中的 Packet Flow
    * 最常被使用到的 SNAT 與 DNAT

## CodeLab

使用 `docker` 指令與 `brctl` 指令，建立以下拓樸：

```graphviz
graph G {
a [shape=box, label="h1"]
b [shape=box, label="h2"]
c [shape=box, label="switch"]
a -- c;
b -- c;
}
```

建立拓樸之後，設定 h1 的 IP 為 `192.168.0.1/24`，h2 為 `192.168.0.2/24`，並且確定兩者可以 ping 通。

```bash
# Command Example
docker create --net='none' --name='h1' --privilege -it ubuntu
brctl addbr switch
ip link add veth0 type veth peer name veth_net0
```

上述有一些可能能夠幫助你 "快速" 進入狀況的 command，例如：建立一個沒有任何網路的 Docker Container、建立一個 Bridge、建立一對 Veth Pair。
```bash
# 完整解法
sudo brctl addbr switch
sudo ifconfig switch up
sudo ip link set switch up
docker run -i -t --rm --name='h1'  --net='none' juamorous/ubuntu-ifconfig-ping /bin/bash
docker run -i -t --rm --name='h2'  --net='none' juamorous/ubuntu-ifconfig-ping /bin/bash
pid=docker inspect -f '{{.State.Pid}}' container_name
sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
# Below is an example for h1, h2 should not named duplicate veth pair
sudo ip link add veth0 type veth peer name veth_net0
sudo brctl addif switch veth0
sudo ip link set veth0 up
sudo ip link set veth_net0 netns $pid
sudo ip netns exec $pid ip link set dev veth_net0 name eth0
sudo ip netns exec $pid ip link set eth0 up
sudo ip netns exec $pid ip addr add 192.168.0.1/24 dev eth0

# Now you can try ping each host
```

### Some hint for you

這邊有一些關於這個題目的提示，如果解不開來，就拿這些關鍵字去 Google 並弄懂他吧。

1. How to find Docker container's PID (Process ID)
    * 這又與 Container 的 Network Namespace 有什麼關係呢？
2. Attach veth to Docker

## CodeLab 2 ==Step 2==

使用 `docker` 指令與 `brctl` 指令，建立以下拓樸：

```graphviz
graph G {
a [shape=box, label="h1"]
b [shape=box, label="h2"]
c [shape=box, label="switch"]
d [shape=box, label="gateway"]
a -- c;
b -- c;
c -- d;
}
```

設定與 CodeLab 1 大致相同，但多出了一個特別的 Gateway ，Gateway 是一個 veth pair，一端連接在 Switch 上，另一端則放在 **Host Namespace** 當中，且 IP 為 `192.168.0.254/24`。

請設定 h1 及 h2 的 default gateway 為 `192.168.0.254`，並在 Host 上 config SNAT rules，使 h1 及 h2 能夠經由 gateway ping 到 Google DNS。
```bash
# 完整解法
sudo ip link add dev vmh1 type veth peer name vmh2 
sudo brctl addif switch vmh1
sudo ip addr add 192.168.0.254/24 dev vmh2
sudo ip link set vmh1 up
sudo ip link set vmh2 up
# try ping 192.168.0.254 in host also ping 192.168.0.254 in h1 and h2
# delete default gateway and set 192.168.0.254 for gateway to h1 and h2
sudo ip netns exec $pid ip route del default
sudo ip netns exec $pid ip route add default via 192.168.0.254
echo 1 > /proc/sys/net/ipv4/ip_forward
# Replace wlp3s0 to the interface which you using for connecting to the internet
sudo iptables -t nat -A POSTROUTING -s 192.168.0.254/24 -o wlp3s0 -j MASQUERADE
```