從「能互通」到「想出去」#
上一章把多個 Network Namespace 透過 Linux bridge 串起來,但 namespace 內仍然只認識同網段的 IP。要連到外網,需要兩個前提:
- namespace 知道「不在本地網段的封包要丟給誰」
- 那個被丟到的下一站,本身連得到外面
第一件事由 routing table(路由表)解決,第二件事下一章再處理。
看一下 routing table 長什麼樣#
在 host 上:
ip route典型輸出包含兩種條目:
default via <gateway> dev <iface>:default gateway(預設閘道),所有不認識的目的地都丟給它<network>/<prefix> dev <iface> proto kernel scope link src <ip>:直連網段(directly connected),同網段內封包直接從這張介面送
如果是用 namespace 模擬出來的環境,ip netns exec ns1 ip route 一開始會「只有」直連網段那條,因為從未設過 default gateway。
給 bridge 一個 IP,當作 namespace 的 gateway#
在前一章的拓撲中,br0 還沒有 IP。給它一個位於同一個子網的位址,例如 10.0.0.254:
sudo ip addr add 10.0.0.254/24 dev br0
sudo ip link set br0 up這時 host 自己也成為 10.0.0.0/24 這個子網的成員,封包能從 host 的 br0 介面送進這個網段。
在 namespace 裡 ping bridge#
namespace 內部已經有 10.0.0.1,br0 是 10.0.0.254,兩者同網段,可以直接 ping:
sudo ip netns exec ns1 ping -c 3 10.0.0.254預期能收到回覆。背後流程:
ns1比對路由表,發現10.0.0.254在10.0.0.0/24,是直連網段- 透過 ARP 取得
br0的 MAC - 封包從
veth-c1出 →veth-h1進 → bridge 把它送進 host 的br0介面 - host 看到目的 IP 是自己的
br0,回 ICMP echo reply
在 namespace 設 default gateway#
下一步,要讓 namespace 把「非本地封包」丟給 br0:
sudo ip netns exec ns1 ip route add default via 10.0.0.254
sudo ip netns exec ns1 ip route第二行應該會看到:
default via 10.0.0.254 dev veth-c110.0.0.0/24 dev veth-c1 proto kernel scope link src 10.0.0.1
同樣的設定要為每個 namespace 各做一次,否則只有
ns1知道 default gateway。
試著 ping 外部 IP#
例如 ping 一個公開的 DNS:
sudo ip netns exec ns1 ping -c 3 8.8.8.8這時很可能會發生兩種狀況:
- 發出去之後完全沒有回應,逾時
- 顯示
Destination Host Unreachable或類似錯誤
封包確實有離開 namespace、有抵達 host,但「出不了 host」。要弄清楚為什麼,需要用 tcpdump 觀察封包到底走到哪一步、為什麼回不來。
用 tcpdump 觀察#
可以同時開兩個視窗,一個看 host 主要對外介面(例如 eth0),一個看 br0:
sudo tcpdump -i br0 -nn icmp
sudo tcpdump -i eth0 -nn icmp預期觀察到的封包樣貌:
br0上會看到10.0.0.1 > 8.8.8.8: ICMP echo requesteth0上可能會看到一個來源 IP 仍然是10.0.0.1的封包試著要出去- 對端就算收得到,回應也回不來,因為外網根本不認識
10.0.0.1
這個觀察結果就是下一章要解的問題:封包出得了 host,但來源 IP 是私有位址,網際網路無從回覆。
路由 vs. 轉送#
到這裡要區分兩個概念:
- routing:「我要把這個封包送去哪一站」,由 routing table 決定
- forwarding:「我這台機器願不願意幫別的來源把封包轉出去」,由
ip_forwardsysctl 決定
光有路由不夠,host 還必須被允許做 IP forwarding,這也是下一章的主題之一。
延伸閱讀#
man 8 ip-routeman 8 tcpdump- 「Linux Advanced Routing & Traffic Control HOWTO」