今天因為要維護一個 11 年前完工的專案,特別把當時的 VM 還原到 Hyper-V 裡面執行,而 SQL Server 的部分我就打算直接跑在容器中。因為我的 VM 跑在 External network 網路下,所以等同於是區域網路的另一台電腦要連到我的 SQL Server on Linux 容器。照理說這應該只是個很簡單的問題,但是我的 VM 就是怎樣也連不到我這台電腦的 SQL Server 容器,網路就是打不通!最後搞了一整個上午,才真正釐清真相!
直接公布答案
本次事件最大的元兇其實就是「Windows Firewall」,有兩條 Inbound rules (連入規則) 明確阻擋了 Docker Desktop Backend
程式 (C:\program files\docker\docker\resources\com.docker.backend.exe
) 從 Public
網路進來的連線!
唉~你一定覺得很蠢對不對!請繼續看一下,事情通常不是憨人想得這麼簡單!
關於 Windows 安全性警訊 (Windows Security Alert)
我相信很多人都看過以下的 Windows 安全性警訊畫面:
尤其是電腦剛安裝好之後,這種畫面會經常出現,有時候還會覺得有點煩,不就是要叫我按個「允許存取」嗎,幹嘛每次都要問我?但隨著電腦越用越久,這個視窗出現的頻率也會日益下降,所以也就不以為意了。
許多人不知道,一台電腦其實可能會有很多網路介面(Network Interface),每個網路介面決定了你的網路封包的出入口。如果你只有一個網路介面,那就意味著只有這個介面會接收到其他電腦傳來的封包。
以我的電腦為例,我就有 10 個網路介面。有 2 個是 VPN 網路,撥接的時候才會通。有 6 個是 Hyper-V 的虛擬網路介面,主要由 Hyper-V 進行管理。另外有 2 張實體的網路卡,但只有使用一張而已,另一張並沒有接上網路線。
你可以從我上圖的畫面看到,目前我這台電腦真正對外的網路介面其實只有 vEthernet (LAN_Bridge)
這項。
你也從我的上述截圖發現,其實我主要的網路介面預設已經選用了 公用網路 (Public networks) 這個網路類別。
這裡我就要先問大家一個問題:
請問你的 PC 擺在家裡,家裡有一個封閉的區域網路,當你只有一個網路介面時,應該設定為哪一種網路類別?
- 公用網路 (Public networks)
- 私人網路 (Pviate networks)
我覺得應該很多人沒認真想過這個問題,連我自己都沒有特別在意,反正電腦可以上網就好,家裡也只有一個網段,選擇哪一個有差嗎?我告訴你:還真的有差!
學習如何切換網路介面的網路類別
變更網路類別很有可能會影響你目前的應用程式連接網路的狀況,主要影響的範圍還是在「從其他電腦連到你的電腦」的情況,如果你的電腦有跑許多需要遠端存取的服務,很有可能會導致服務突然連不上的狀況,這個部分稍後會做說明。不過,這對大部分使用者來說不會受到太多影響。
-
取得目前網路介面的連線設定資訊
Get-NetConnectionProfile
Name : 網路
InterfaceAlias : vEthernet (LAN_Bridge)
InterfaceIndex : 11
NetworkCategory : Private
IPv4Connectivity : Internet
IPv6Connectivity : LocalNetwork
-
將現有的連線設定從 Public
切換到 Private
Set-NetConnectionProfile -Name "網路" -NetworkCategory Private
建議你在切換完現有網路介面的網路類別後,全部重置 Windows Firewall 的所有規則,然後進行一次重開機!
請認真選擇 Windows 安全性警訊視窗中的選項
好了,本文的重點來了,最雷的地方就在這裡!🔥
為了能讓 Windows 安全性警訊視窗再次出現,我們有兩種方法:
-
刪除掉原本建立好的防火牆規則
因為連入規則很多,你可能不知道該刪除哪一個,所以第二個選項也不錯。
-
重置 Windows Firewall 所有連入規則(重置之前建議可以先匯出備份)
這裡我們用 Python 3.x 來執行 http.server
應用,直接開啟一個監聽 Port 8000
的 HTTP 伺服器:
python -m http.server 8000
當你第一次執行 python
命令時,Windows 10 會自動開啟 Microsoft Store 自動幫你下載安裝 Python 工具。
以下就是開啟 Windows 安全性警訊視窗的各種魔鬼細節:
-
認識幾個重要欄位
名稱:應用程式的名稱
發行者:應用程式的發行者名稱
路徑:要「允許」或「封鎖」的應用程式路徑
-
預設值的勾選邏輯
我以前並沒有特別注意為什麼有些電腦預設會勾選 私人網路,有些電腦會預設勾選 公用網路,但這次事件讓我相當清楚了。
如果你的預設網路介面被歸類在公用網路 (Public networks),這個視窗預設就會幫你勾選公用網路 (Public networks) 選項。
如果你的預設網路介面被歸類在私人網路 (Private networks),這個視窗預設就會幫你勾選私人網路 (Private networks) 選項。
你可以兩個都勾選,畢竟大部分人的桌上型電腦並不會一直頻繁的移動,所以選哪個都沒關係!
如果你用筆電的話,大部分的 Wi-Fi 上網用的網路介面預設會被選在公用網路 (Public networks),當你不希望用 Wi-Fi 上網時「可能」會有人連到你的電腦,那你的有線網路就選擇 私人網路 類型吧!
像我的電腦預設網路介面就被選在公用網路,我今天已經手動調整為私人網路了,畢竟是家裡的網路嘛!
-
如果你直接按下 取消 按鈕
按下 取消 的背後,並不是真的 取消,而是建立一筆 封鎖 的規則,很意外吧!🔥
除此之外,如果你手賤按到 ESC
按鍵,跳開了這個 Windows 安全性警訊視窗,也是一樣得到 封鎖 的命運!
發生本次事件的主因
其實每個人的電腦用了幾年之後,Windows 防火牆的規則數量少說都兩三百條以上,你根本不可能一條一條看完。我在解決本次問題的時候,並不是沒有想到這裡的設定,我確實也看了,真的有 Docker Desktop Backend
這條防火牆規則,而且也是啟用且允許的狀態,所以我就直覺的往其他地方排查問題。
我真的再次把 Windows Containers 的官方文件再看完一遍,尤其是網路的部分,看有沒有遺漏的部分,結果看不出異樣。
然後再把 Docker Desktop for Windows 的官方文件也看過一輪,真的認真看完了,還是無解。
我也到處搜尋各種解決方法,也到 Docker Desktop for Windows 的 GitHub Repo 查找問題,也完全找不到相關的問題,完全苦手。
讓我最納悶的地方,就是為什麼我遇到的問題,完全沒有人在討論?我又再次陷入膠著,滿腦子充滿著奇怪的想法:
- 什麼爛東西,肯定沒什麼人在用 Windows Container 才沒人討論吧!
- Windows Container 就是爛,我用 Linux Container 從來沒遇到這麼多鳥事!
- Docker Desktop for Windows 出了好幾代,每代的網路架構都不同,這次肯定又遇到了什麼詭異問題!
由於我從一開始就排除了 Windows Firewall 的問題,這是最大的敗筆!😢
最後,我嘗試找出我的 Windows Firewall 的所有連入規則,這才發現一個驚人的規則:
Get-NetFirewallRule | where { $_.Name -like "*docker*" } | ft
原來我的電腦不是只有兩條名為 Docker Desktop Backend
的允許規則,還有兩條不知道何年何月何日加入的 com.docker.backend
規則,重點是這兩條 com.docker.backend.exe
是封鎖規則啊,是封鎖,是封鎖,是封鎖!
我猜想應該是 Docker Desktop for Windows 早期的版本沒有設定「應用程式名稱」,所以直接拿執行檔名稱當作應用程式名稱,這才會造成不同時期建立了兩份不同的防火牆規則名稱!
重點是你在 具有進階安全性的 Windows Defender 防火牆 視窗中,這兩條規則根本不會排序在一起(一個是 D
開頭、一個是 c
開頭),在我的電腦裡面,所有 D
開頭的 Rules 就快一頁,而 c
開頭的 Rules 有兩頁之多啊!
最後,我將這兩條名為 com.docker.backend.exe
的封鎖規則刪除,所有 Docker 網路的問題就全部恢復正常了!😃
後記
當我最後知道是 Windows Firewall 搞的鬼之後,我的心情五味雜陳。一來覺得自己怎麼這麼笨,這麼簡單的問題都沒想到。二來覺得很生氣,他娘親的不知道是誰把我的防火牆設定調整成封鎖遠端連接(應該是之前的我),而且前後版本的防火牆規則名稱竟然不一樣(氣)。三來覺得很開心,釐清問題之後,相同的問題大概不會再困擾我了。
最後總結一下幾點本文重點:
- 我覺得更換網路類別之後重置 Windows Firewall 所有連入規則是個不錯的作法,這樣可以讓你重新檢視整台電腦所有應用程式使用網路的狀況!
- 防火牆規則包含 啟用/停用 與 允許/封鎖 狀態,然後還有 設定檔 與 網路介面的網路類別 之間的關係也非常重要!
- 看到 Windows 安全性警訊 視窗千萬要注意你到底要允許或封鎖,而且不能不選擇!
- 如果真的選錯設定,可以立刻透過
wf.msc
命令開啟 具有進階安全性的 Windows Defender 防火牆 介面進行調整!(不馬上調整日後肯定就忘了)
相關連結