iT邦幫忙

2022 iThome 鐵人賽

DAY 29
1

昨天我們試著錄封包,並由此觀察到封包是有從 ns 送到 docker1,再由 docker1 送到 host 的 ens5,最後由 ens5 在送出去,同時我們也觀察到,從 ens5 送出去的封包,其 src IP 會是 172.18.0.2,這個 IP 是我們自己為了實驗 net namespace 所設定的,網路上是無法認得這個 IP 的,我們推測很有可能是因為這樣導致無法跟 host 以外的世界溝通。

你可能會覺得,那奇怪了,host 的 IP 是 172.31.59.121,那這也是一個 private IP 啊,外面的世界應該也不認得這個 IP,那為什麼在 host 可以對外溝通呢?

# 在 host ping 8.8.8.8,並錄製封包:
ubuntu@ip-xxx:~$ sudo tcpdump -i ens5 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens5, link-type EN10MB (Ethernet), capture size 262144 bytes
# 可以觀察到 src IP 是 172.31.59.121
14:09:49.421981 IP 172.31.59.121 > 8.8.8.8: ICMP echo request, id 58, seq 1, length 64
14:09:49.431320 IP 8.8.8.8 > 172.31.59.121: ICMP echo reply, id 58, seq 1, length 64
14:09:50.423668 IP 172.31.59.121 > 8.8.8.8: ICMP echo request, id 58, seq 2, length 64
14:09:50.432716 IP 8.8.8.8 > 172.31.59.121: ICMP echo reply, id 58, seq 2, length 64
^C
4 packets captured
4 packets received by filter
0 packets dropped by kernel

我們的實驗環境是在 AWS EC2 上,如果沒有自行建立 VPC,是用每個 region 預設的那個 VPC,那這個 VPC 裡的 subnet 預設也都是 public subnet,這些 public subnet 會關聯到一個 route table,裡頭會有以下的設定:
https://ithelp.ithome.com.tw/upload/images/20221014/20151857r13S18s739.png

跟在 Linux 裡看到的 routing table 有點像,總之就是,要往 172.31.0.0/16 去的,走 local,其他走 igw-b5xxxx,這個 igw-b5xxxxInternet Gateway,這是 AWS 提供的一種元件,他會執行 NAT 這個功能,NAT 的全名是 network address translation,顧名思義,他會進行網路位址的轉換。事實上,我們實驗的這台機器實際上也會有一個 public IP,但在 EC2 instance 裡,只會知道 privvate IP,例如我們執行 ip addr 時,看到 ens5 上的 IP 是 172.31.59.121 這個 private IP,而非被賦予的那個 public IP,這時候就會由 Intenet Gateway 負責來做這個 private IP 與 public IP 的一對一轉換了,大概是這樣:
https://ithelp.ithome.com.tw/upload/images/20221014/20151857VUv4sL7mUS.png

當然這邊只是很簡化地說明,實際的運作還有很多細節,但讓我們先回來我們的實驗中。這時候你可能會想,因為 host 是 EC2 instance,AWS 會有一些網路的元件來協助這些運作,但 ns1, ns2 這些是我們自己在 host 裡頭建立出來的,AWS 想當然耳不會幫我們做什麼轉換,那該怎麼辦呢?還好我們之前提過的 iptables (文件)除了會負責處理網路封包的過濾(可以扮演防火牆),也能扮演 NAT 的角色。

現在就讓我們來觀察一下目前的 iptables 裡 NAT 的設定:
https://ithelp.ithome.com.tw/upload/images/20221014/201518577ALjOYuDVZ.png

雖然看起來好像有點複雜,但可以看到 DOCKER 相關的字眼,我們可以合理猜測,這些都跟 docker 有關!

現在就來幫我們自己建立的 ns 加上 NAT 規則:

sudo iptables -t nat -I POSTROUTING -s 172.18.0.0/24 -o ens5 -j MASQUERADE

這指令的意思是,我們在 nat table 的 POSTROUTING 這個 chain 裡 insert (-I)了一條規則,POSTROUTING 是封包要離開 host 時去做事的,那做什麼事呢?就是只要來源(-s)是來自 172.18.0.0/24 的,且要往 ens5 這個介面送出去(-o),就對這個封包做一個動作(-j: what to do if the packet matches it,我們這邊指定做什麼呢?就是 masquerade 這個封包一下,更直接地說,就是把封包的 src IP 改成 host 的。

這個指令執行後,iptables 會多一條規則:
https://ithelp.ithome.com.tw/upload/images/20221014/20151857IQhCrgZorZ.png

然後就可以從 ns1 中去 ping 到 8.8.8.8 啦!

ubuntu@ip-xxx:~$ sudo ip netns exec ns1 bash
root@ip-xxx:/home/ubuntu# ping 8.8.8.8 -c 2
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=42 time=7.54 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=42 time=7.53 ms

--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 7.526/7.535/7.544/0.009 ms

在 ping 的時候我們也同時來錄個封包:

ubuntu@ip-xxx:~$ sudo tcpdump -i ens5 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens5, link-type EN10MB (Ethernet), capture size 262144 bytes
15:32:17.373878 IP 172.31.59.121 > 8.8.8.8: ICMP echo request, id 33016, seq 1, length 64
15:32:17.381461 IP 8.8.8.8 > 172.31.59.121: ICMP echo reply, id 33016, seq 1, length 64
15:32:18.375689 IP 172.31.59.121 > 8.8.8.8: ICMP echo request, id 33016, seq 2, length 64
15:32:18.383174 IP 8.8.8.8 > 172.31.59.121: ICMP echo reply, id 33016, seq 2, length 64
^C
4 packets captured
4 packets received by filter
0 packets dropped by kernel

嘿,是不是看到來源 IP 已經變成是 172.31.59.121 了,這是 AWS 的網路會處理的 IP,最後會被成功地送達 8.8.8.8,然後 8.8.8.8 會回覆回來,一路再從 AWS 的網路元件走回我們的 host 來,回來 host 後,dst IP 會再被轉換回 172.18.0.2,然後再一路回到 ns1 裡。


好啦,到這邊我們終於成功出國了,這邊其實有點作弊啦,還記得我們在 Day 26 時偷偷把 FORWARD policy 從 DROP 改成 ACCEPT 嗎?但 docker 安裝後是 DROP 喔,可以試試看改回來,一但改回來,橋就不通了,應該說,封包還是可以到橋,也可以到 host,但無法到 ns2 跟外部了。所以,到目前為止,我們可以說很接近 docker 了,但並不完全是。此外,還有一個問題是,那如果是想在 container 中架設 server,例如啟動一個 nginx,這個網路的走向就完全相反了,這是要從外部連近來我們的 container 裡,那又要怎麼做呢?


上一篇
Day 28: 為什麼出不了國呢?
下一篇
Day 30: 讓我們關掉無條件轉發吧 & 完賽感想
系列文
那些關於 docker 你知道與不知道的事32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言