iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 13
0
自我挑戰組

30 天不間斷-資工隨筆大雜燴系列 第 13

[Day 13] Docker 莫名奇妙的行爲 -DNAT

正文

之前使用 Docker 架了一個服務,使用 iptables 限制只有某個網段才能進入,本來想說應該不會太複雜,像是這樣:

sudo iptables -t filter -p tcp -s xxx.xxx.xxx/xx --dport 8000 -j REJECT

這行指令就是在 filter 這個 Table 的 INPUT Chain 上面新增一個 Rule,寫說當在 tcp 協定底下 xxx.xxx.xxx/xx 網段的使用者連進我們的主機存取 8000 port 這個服務的時候拒絕讓他存取,此時頁面就會顯示無法存取這個網站。

補充:REJECT vs DROP

剛剛提到使用 REJECT 拒絕讓他存取,如果是在網路正常的情況下就能夠知道這個頁面出現的原因是被防火牆阻擋了。就像是被論壇上很多男生被發好人卡,明確的被拒絕交往請求,就代表他其實不喜歡你。

如果使用 DROP 行爲的話,代表把 xxx.xxx.xxx/xx 網段的使用者的封包丟掉,這個時候他送出的請求就不會有回應,永遠顯示正在加載網頁,就像是聊天室正在洗澡的女生一樣,永遠停留在上線中但未讀的狀態,未讀這種行爲很容易讓人誤會,到底是不喜歡你,還是剛好有事? 而網頁正在加載也代表可能是網速過慢、伺服器的硬體設備出問題、防火牆阻擋等等原因。

因此如果站在防禦的角度通常會使用 DROP 因爲可以混淆潛在的攻擊性使用者,但如果是站在測試的角度還是用 REJECT,比較明確瞭解防火牆的規則是否生效。

結果服務依然可以順利透過限制之外的網段存取

後來無意間跟別人的閒聊內容提到 "好像蠻多人覺得 Docker 的坑有點多,哈哈。"

突然靈光乍現:

sudo iptables  -t nat-L | grep DOCKER

終於在隔壁棚的 nat table 的 DOCKER Chain (這條 Chain 是 DOCKER 自己新增的,不過行爲類似 PREROUTING) 的上面找到一條 Rule

target     prot opt source               destination         
DNAT       tcp  --  anywhere          anywhere             tcp dpt:8000 to:172.23.0.2:8000

不過由於 nat Table 的優先級大於 filter Table,因此一開始在 filter Table 新增的 Rule 就會被 Docker 搶先一步,當使用者請求連線到 8000 Port 的時候就會透過 DNAT 轉到 172.23.0.2:8000 上面的正常服務了。

怎麽辦?

其實很簡單,就只要把上面 DOCKER 那條規則(假設行號是 1)的來源改成要限制的網段,但是 iptables 沒辦法只更新單獨欄位的值,因此要寫成完整的規則並取代:

sudo iptables -t nat -R DOCKER 1 -p -tcp -s xxx.xxx.xxx.xxx --dport 8000 -j DNAT --to-destination 172.23.0.2:8000

這樣就能達成阻擋的需求了。

One more thing

不過實際測試之後功能相當於文章前面提到的 DROP 的行爲,也就是網頁會一直顯示加載中,而不是明確的拒絕連線。

➜  ~ sudo ss -tunlp | grep 8000
tcp   LISTEN   0        128                      *:8000                 *:*      users:(("dockerd",pid=26609,fd=22))

原來是 DOCKER 會自動聽 8000 port ,雖然抓到兇手了,不過不是很瞭解他爲什麼要這麼做就是了。


上一篇
[Day 12] Intro to Tensorflow (1)
下一篇
[Day 14] Intro to Tensorflow (2)
系列文
30 天不間斷-資工隨筆大雜燴30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言