# 網路練習題 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
```