為什麼內網連内網對外 IP 會不通?淺談 NAT Loopback (Hairpin NAT) 運作原理
對於許多剛接觸網路架構或自建服務的工程師來說,設定 Port Forwarding (DNAT) 讓外部網路能夠存取內網的 Web 服務是家常便飯。然而,當我們嘗試「在內網環境中,直接透過外部 IP (Public IP) 連線到內網伺服器」時,卻常常會遇到一種詭異的現象:有些環境可以通,有些環境卻完全連不上。
最近這篇文章看到有人說這個問題。這讓我回想起自己的經驗:以前在家裡使用中華電信數據機加上 ASUS Router 時,設定好 DNAT 後,內網直接打 Public IP 就能無縫連上 Web 服務。但同樣的操作,在我朋友家那台企業級的 Fortigate 防火牆上卻行不通。
為什麼會有這樣的差異?答案其實藏在一個名為 NAT Loopback(或稱 Hairpin NAT、NAT Reflection)的路由器功能中。
缺乏 NAT Loopback 時,封包發生了什麼事?
要理解 NAT Loopback,我們先來看看「沒有」這個功能時,封包的流向會發生什麼致命的錯誤。
假設我們的網路環境如下:
- Router WAN IP (外部 IP):
203.0.113.1 - Router LAN IP (閘道器):
192.168.1.1 - Web Server (內網伺服器):
192.168.1.20 - Client (內網測試機):
192.168.1.10 - Router 規則: 已設定 DNAT,將
203.0.113.1:80導向192.168.1.20:80。
當內網的 Client (192.168.1.10) 嘗試連線到外部 IP (203.0.113.1) 時,流程如下:
- 發出請求: Client 送出封包,來源是
192.168.1.10,目的地是203.0.113.1。因為目的地不是同網段,封包被送到 Default Gateway (Router)。 - Router 處理 DNAT: Router 收到封包,觸發了 DNAT 規則,將目的地 IP 改為 Web Server 的
192.168.1.20,並將封包從 LAN 介面丟給 Web Server。 - 非對稱路由的災難: Web Server 收到封包,看到來源 IP 是 Client 的
192.168.1.10。因為 Client 跟 Server 處於同一個內網網段,Server 在回覆時,不會將封包交還給 Router,而是透過 Layer 2 (MAC Address) 直接把回覆封包丟給 Client。 - 連線中斷: Client 送出請求給
203.0.113.1,卻收到來自192.168.1.20的回覆。對於 Client 的 TCP/IP 堆疊來說,這是一個未知的連線(這不是我要的對象!),於是直接把封包丟棄(Drop)或發送 TCP RST 終止連線。
結果就是:連線逾時,你看不到網頁。
技術解析:NAT Loopback 是如何拯救這一切的?
為了讓上述的封包能夠順利「有去有回」,路由器需要同時對這個封包做「兩次 NAT」處理,這個過程就像髮夾彎一樣(Hairpin),封包從 LAN 進來,又從 LAN 出去。
當 Router 有開啟 NAT Loopback 時,流程會變成這樣:
- 發出請求: Client (
192.168.1.10) 請求203.0.113.1。 - Router 處理 DNAT + SNAT:
- DNAT (目的地位址轉換): 將目的地
203.0.113.1改為192.168.1.20(Web Server)。 - SNAT (來源位址轉換): 同時,將來源 IP
192.168.1.10改為 Router 自己的 LAN IP192.168.1.1。
- 伺服器回覆: Web Server 收到封包,這次它看到的來源 IP 是 Router (
192.168.1.1)。因此,Web Server 會乖乖地把回覆封包交還給 Router。 - Router 解譯並回傳: Router 收到回覆後,反向解除剛剛的 SNAT 與 DNAT,將來源改回
203.0.113.1,目的地改回192.168.1.10,然後傳給 Client。
Client 成功收到來自 203.0.113.1 的回覆,TCP Three-way Handshake 順利完成,Web 服務正常顯示!
設備哲學的差異:ASUS vs. Fortigate
了解原理後,就能解釋為什麼不同設備有不同結果了:
-
家用路由器 (如 ASUS Router): 設計理念是「隨插即用、使用者體驗優先」。因此,這類設備通常在底層預設開啟 NAT Loopback 功能。對一般用戶來說,他們只管設定好 Port Forwarding,不管在內網還是外網輸入同一個 Domain Name 或 IP,都能無縫連上,這減少了極大的客服成本。
ASUS Router預設是打開的,參考: [規格] 哪些華碩路由器型號支援NAT Loopback ? | 官方支援 | ASUS Hong Kong -
企業級防火牆 (如 Fortigate):
設計理念是「預設拒絕 (Default Deny)、嚴格的安全控管」。Hairpin NAT 本質上是一種路由的「欺騙」與額外消耗設備資源的行為(流量明明不用出網關,卻硬要繞一圈做兩次 NAT)。因此,企業級防火牆預設通常是關閉此功能的。工程師必須手動撰寫明確的 Policy 或開啟 NAT Reflection 選項,允許這條流量通過。
可參考: Hairpin NAT | FortiGate / FortiOS 8.0.0 | Fortinet Document Library
替代方案:除了 NAT Loopback 還能怎麼做?
雖然 NAT Loopback 很方便,但在大型網路環境中會增加 Router 的負載。比起讓內網流量硬繞去 Router 做轉換,更專業的做法是設定 Split DNS (內部 DNS 解析)。可以參考我研究這篇(Split DNS 架構整理與小實驗)文章。
透過架設內部 DNS Server (例如 AdGuard Home 或 Pi-hole):
- 當你在外網查詢
web.example.com時,公共 DNS 回傳 Public IP (203.0.113.1)。 - 當你在內網查詢
web.example.com時,內部 DNS 直接回傳 Server 的 LAN IP (192.168.1.20)。
這樣一來,內網的流量就會直接在 Layer 2 進行端對端通訊,完全不需要依賴 Router 的 NAT 轉換,不僅速度最快,也最節省網路資源。
參考資源
- RustDesk 官方文件:NAT Loopback 議題
- 網友經驗分享:AdGuard Home DNS Server 設定探討
- https://zhuanlan.zhihu.com/p/629895428
- https://just4coding.com/2016/12/04/virtualnetworkdevice/
- https://www.hwchiu.com/docs/2017/nat-loopback
- Hairpin NAT vs Split DNS:哪種才是正確做法? - Nuface Blog