Day 22 最後留下了一個很實際的問題。
假設我家裡真的有一台 Web Server:
192.168.1.30:80
它在 LAN 裡完全正常。
我的筆電可以開:
http://192.168.1.30
也能看到網頁。
但是朋友在 Internet 上輸入:
http://203.0.113.10
卻什麼都連不到。
第一個直覺很容易是:
可是我家 Router 明明有 Public IP 啊,為什麼不能把封包送進來?
Day 22 已經知道,內部主機主動上網時:
192.168.1.20:51000
↓
Router 做 PAT
↓
203.0.113.10:61001
↓
Internet
Router 會建立 Translation Entry。
所以回程封包來到:
203.0.113.10:61001
Router 查表,就知道要送回:
192.168.1.20:51000
但今天完全反過來。
Internet 上有一台 Client,第一次主動送:
198.51.100.20:53000
↓
203.0.113.10:8080
Router 收到之後,腦袋裡其實會冒出一個問題:
203.0.113.10:8080 到底代表我內網的哪一台設備?
如果沒有事先設定,它根本不知道。
這就是今天要拆的東西:
Port Forwarding / DNAT,其實是在「外部主動連進來之前」,先建立一條固定的目的地翻譯規則。
Day 22 的情境是:
Inside Host
192.168.1.20:51000
↓
Router
↓
Internet Server
93.184.216.34:443
Router 在封包出去時,把 Source 改成:
203.0.113.10:61001
所以原本:
Source
192.168.1.20:51000
Destination
93.184.216.34:443
出去後變成:
Source
203.0.113.10:61001
Destination
93.184.216.34:443
最重要的是:
這條連線是 Inside 先發起的。
Router 是在看到這個 Outbound Flow 之後,才建立:
203.0.113.10:61001
↔
192.168.1.20:51000
所以回來的封包有地方可以查。
現在朋友從 Internet 主動來:
198.51.100.20:53000
↓
203.0.113.10:8080
Router 收到封包。
但 NAT Table 裡如果只有之前某些 Outbound Connection:
203.0.113.10:61001
↔
192.168.1.20:51000
203.0.113.10:61002
↔
192.168.1.10:52000
根本沒有:
203.0.113.10:8080
↔
???
所以 Router 沒辦法憑空猜:
203.0.113.10:8080
到底要送給:
192.168.1.10?
192.168.1.20?
192.168.1.30?
192.168.1.40?
這跟 Routing Table 不是同一個問題。
Routing Table 可以告訴 Router:
192.168.1.0/24
在 LAN Interface
但它沒有告訴 Router:
Public IP 的 TCP 8080 應該代表 LAN 裡哪一台 Host 的哪一個 Port?
所以需要一條額外的 Translation Rule。
假設我要讓外面的人連:
203.0.113.10:8080
最後送到家裡:
192.168.1.30:80
那我可以先告訴 Router:
Public Side
203.0.113.10:8080
↓
Private Side
192.168.1.30:80
這就是很常見的:
Port Forwarding
從封包翻譯角度看,也可以把它理解成:
Destination NAT,DNAT
因為封包從 Internet 進來時,原本的 Destination 是:
203.0.113.10:8080
Router 會把 Destination 改成:
192.168.1.30:80
所以:
DNAT
=
改 Destination
Day 22 的上網情境最直覺的是改 Source:
192.168.1.20:51000
↓
203.0.113.10:61001
今天則是在 Inbound 時改 Destination:
203.0.113.10:8080
↓
192.168.1.30:80
這兩個方向一對照,突然就比較清楚了。
假設:
Internet Client
198.51.100.20
Home Router Public IP
203.0.113.10
Internal Web Server
192.168.1.30:80
Router 已經設定:
203.0.113.10:8080
→
192.168.1.30:80
現在朋友瀏覽器連:
203.0.113.10:8080
封包概念上是:
Source
198.51.100.20:53000
Destination
203.0.113.10:8080
這個 Destination 是 Public IP,所以 Internet 可以把封包一路送到我家的 Router。
Router 看到:
Destination
203.0.113.10:8080
接著比對事先設定好的 Port Forwarding Rule:
203.0.113.10:8080
→
192.168.1.30:80
Router 把 Destination 改掉:
原本
198.51.100.20:53000
↓
203.0.113.10:8080
翻譯後
198.51.100.20:53000
↓
192.168.1.30:80
注意:
Client 的 Source 沒有因為這一步就消失。
Server 仍然需要知道:
198.51.100.20:53000
是誰來連它。
Router 已經知道:
192.168.1.30
在自己的 LAN 裡。
所以接下來又回到以前學過的流程:
Destination IP
192.168.1.30
↓
ARP / Neighbor Resolution
↓
找到 Server 的 MAC
↓
Ethernet Frame
↓
送進 LAN
Web Server 看到:
Client
198.51.100.20:53000
↓
Server
192.168.1.30:80
如果 TCP 80 的服務真的有 Listen,而且 Host Firewall 允許,Server 就會回應。
Server 回:
192.168.1.30:80
↓
198.51.100.20:53000
但 Internet Client 一開始連的明明是:
203.0.113.10:8080
如果回程直接拿:
192.168.1.30:80
當 Source,Internet 根本不會把它當成剛才那個公開端點。
所以 Router 在回程還要做對應的反向 Translation。
概念上:
192.168.1.30:80
變回
203.0.113.10:8080
最後 Internet Client 看到的 Connection 仍然是一致的:
198.51.100.20:53000
↔
203.0.113.10:8080
Client 不需要知道真正的 Server 是:
192.168.1.30:80
這裡很容易跟 Routing 混在一起。
其實兩件事不同。
Routing 在問:
這個 Destination IP 應該往哪個 Interface / Next Hop 送?
DNAT / Port Forwarding 在問:
這個 Destination Address / Port 應該先被翻譯成什麼?
可以先這樣拆:
Internet 封包進來
↓
203.0.113.10:8080
↓
NAT / Port Forwarding Rule
↓
改成 192.168.1.30:80
↓
Routing Table
↓
知道 192.168.1.30 在 LAN
↓
ARP
↓
送到 Server
也就是:
NAT 決定地址怎麼翻,Routing 決定翻完之後往哪裡送。
有點像,但不要直接畫等號。
最簡單先這樣想。
偏向固定 IP 對 IP:
Inside Local
192.168.1.30
↔
Inside Global
203.0.113.30
可以先看成:
1 Private IP
↔
1 Public IP
更常見的是利用:
Public IP + Port
指定到:
Private IP + Port
例如:
203.0.113.10:8080
→
192.168.1.30:80
甚至另一個服務:
203.0.113.10:2222
→
192.168.1.50:22
這樣同一個 Public IP 可以根據不同 Port,導向不同內部服務。
所以可以先建立這個畫面:
Static NAT
Public IP
↔
Private IP
Port Forwarding
Public IP:Port
→
Private IP:Port
在設備實作上,Port Forwarding 常常就是某種 Static PAT / Static NAT Rule。
例如我可以設定:
203.0.113.10:8080
→
192.168.1.30:80
外面用:
8080
裡面服務卻是:
80
因為 NAT Rule 本來就可以同時改:
IP
Port
所以進來時:
Destination
203.0.113.10:8080
↓ DNAT
192.168.1.30:80
這有一個很實際的用途。
例如我有兩台 SSH Server:
Server A
192.168.1.50:22
Server B
192.168.1.60:22
外面只有一個 Public IP:
203.0.113.10
可以做:
203.0.113.10:2222
→
192.168.1.50:22
203.0.113.10:2223
→
192.168.1.60:22
所以從 Internet 看起來:
同一個 Public IP
不同 Port
Router 就能把它們送去不同 Host。
完全不是。
這是今天最重要的一個地方。
很多時候設定畫面明明寫著:
8080
→
192.168.1.30:80
外面卻還是連不到。
因為 Port Forwarding 只回答:
這個封包要翻成哪個內部目的地?
它沒有保證整條路上的其他條件都正確。
至少還要同時滿足幾件事。
假設你以為 Public IP 是:
203.0.113.10
但 Router WAN 實際拿到的是:
100.64.x.x
或另一個 Private Address。
那可能代表你的 Router 外面還有另一層 NAT。
也就是:
Internet
↓
ISP NAT
↓
你的 Router
↓
家裡 LAN
這時你只在自己的 Router 做 Port Forwarding,Internet 封包甚至可能還沒到你這台 Router。
這會接到之後很重要的:
CGNAT
今天先知道:
Port Forwarding
要有封包真的到得了這台 NAT Router
才有意義
Day 21 才剛講過:
NAT
≠
Firewall
即使 NAT Rule 是:
203.0.113.10:8080
→
192.168.1.30:80
Firewall 還是可能判斷:
Inbound TCP 8080
DENY
那封包一樣進不去。
所以實際 Router / Firewall 常常同時有:
NAT Rule
+
Firewall Policy
兩個都要看。
可以先這樣想:
Port Forwarding
→ 送去哪裡?
Firewall
→ 准不准送?
假設最後送到:
192.168.1.30:80
但 Server 上根本沒有程式 Listen TCP 80。
那 NAT 設得再漂亮都沒用。
例如 Web Server 實際聽的是:
3000
但你卻轉到:
192.168.1.30:80
當然會失敗。
所以排查時要把:
Network
和:
Application
分開。
可以問:
LAN 裡直接連 192.168.1.30:80
到底通不通?
如果 LAN 裡都不通,就先不要怪 NAT。
即使服務真的 Listen:
0.0.0.0:80
Linux Firewall、Windows Firewall 或其他 Host Firewall 仍然可能擋掉。
所以整條其實是:
Internet Client
↓
ISP
↓
WAN Public IP
↓
Edge Firewall
↓
DNAT / Port Forwarding
↓
LAN Routing
↓
Host Firewall
↓
Application Listen Port
少任何一層都不行。
這個問題如果往不同廠牌、不同平台、不同 Packet Processing Pipeline 深挖,順序可能會變得很細。
目前這個系列先不要硬背某台設備的內部 Pipeline。
先抓住邏輯就好:
NAT 與 Firewall 是兩個不同判斷。
排錯時要確認:
1. 封包有沒有到 Edge?
2. NAT Rule 有沒有 Match?
3. Security Policy 有沒有允許?
4. 翻譯後的目的地有沒有 Route?
5. Server 有沒有收到?
6. 回程有沒有回到同一條 NAT 路徑?
這比只背某個產品的 GUI 順序更重要。
假設 Internet Client 進來:
198.51.100.20
↓
Router A
↓
192.168.1.30
Router A 做了 DNAT。
但 Server 回 Internet 時,Default Gateway 卻不是 Router A,而是 Router B:
192.168.1.30
↓
Router B
↓
Internet
這時可能出現:
進來走 A
回去走 B
Router A 建立的 NAT / Connection State,回程根本看不到。
這類 Asymmetric Routing 很容易讓:
NAT
Stateful Firewall
一起出問題。
所以 NAT 不只是「改一次 IP」。
它通常非常依賴:
同一條 Flow 的雙向封包,能回到知道這筆 Translation / State 的設備。
不能簡單回答「危險」或「安全」。
但它確實改變了一件事情。
原本:
Internet
X
無固定 Mapping
X
Inside Server
設定 Port Forwarding 後:
Internet
↓
Public IP:Port
↓
固定 DNAT Rule
↓
Inside Server:Port
也就是:
你主動把某一個內部服務變成 Internet 可以嘗試連線的入口。
所以一旦 Forward:
203.0.113.10:22
→
192.168.1.50:22
Internet 上任何能到這個 Public IP 的人,都可能來敲:
TCP 22
接下來安全性就不能只靠:
「反正它在內網」
而要真的考慮:
Firewall
Allowed Source
Authentication
Patch
TLS
Rate Limit
VPN
Reverse Proxy
WAF
等設計。
也再次說明:
NAT 不是安全邊界本身。
如果是最傳統的 IPv4 家用網路,而且:
Server 在 Private LAN
+
Router 擁有可被 Internet 到達的 Public IPv4
+
外部 Client 要直接連進來
那通常確實需要某種 Inbound Mapping。
最典型就是:
Port Forwarding
但現代實務還有很多其他做法,例如:
Reverse Proxy
VPN
Tunnel
Overlay Network
Cloud Load Balancer
Zero Trust Access
這些設計不一定會叫「Port Forwarding」。
所以今天學 Port Forwarding,不是代表所有公開服務都應該這樣做。
而是先搞懂最底層的問題:
Private Address 背後的 Server,要怎麼讓外部第一次主動找到它?
這裡剛好可以接回 Day 22。
AWS NAT Gateway 的典型用途是:
Private Subnet Resource
↓
NAT Gateway
↓
Internet
也就是:
Private Resource 主動往外。
它不是拿來做:
Internet
↓
NAT Gateway
↓
Private EC2 Web Server
的 Inbound Publishing。
所以如果我要讓 Internet 使用者打到 AWS 裡的 Web Service,思考方向通常會變成:
Internet
↓
Internet Gateway
↓
Public-facing Entry
↓
Security Policy
↓
Application
這個 Public-facing Entry 可能是:
Public IPv4 / Elastic IP
Application Load Balancer
Network Load Balancer
具體架構依需求不同。
重點是:
AWS NAT Gateway 解決的是 Private Subnet 的 Egress,不是把 Private Server 直接 Forward 給 Internet。
這和家用 Router GUI 裡的:
Port Forwarding
角色完全不一樣。
不要硬做一對一映射,但可以先抓問題類型。
家用網路
Private PC
↓
Router NAT / PAT
↓
Internet
用途:
Inside 主動出去
對應到 AWS 的問題類型:
Private EC2
↓
NAT Gateway
↓
Internet
用途:
Private Resource 主動出去
而家用:
Internet
↓
Public IP:8080
↓
Port Forwarding / DNAT
↓
192.168.1.30:80
到了 AWS,比較接近的是:
Internet
↓
公開入口
↓
Security Policy
↓
Target
不是:
Internet
↓
NAT Gateway
↓
Private EC2
這一點如果分清楚,之後看 AWS Architecture 會少很多混亂。
可以利用 Port。
例如:
203.0.113.10:80
→
192.168.1.30:80
203.0.113.10:443
→
192.168.1.30:443
203.0.113.10:2222
→
192.168.1.50:22
203.0.113.10:8443
→
192.168.1.60:443
所以一個 Public IP 可以對應多個:
Public Port
再導向不同:
Private IP + Port
但同一個:
Public IP + Protocol + Port
一般不能同時直接 Forward 到兩個不同目的地。
例如:
203.0.113.10:443
不能單靠最單純的 L4 Port Forwarding 同時說:
給 192.168.1.30:443
又給 192.168.1.40:443
Router 需要有更高層資訊才能再分。
這時才會開始遇到:
Reverse Proxy
Host Header
SNI
Load Balancer
等概念。
但那是另一層問題。
先只建立最粗的畫面。
Port Forwarding 比較像:
看到 TCP/UDP Port
↓
直接轉去某個 IP:Port
例如:
203.0.113.10:443
→
192.168.1.30:443
Reverse Proxy 則通常站在應用層入口:
Internet
↓
Reverse Proxy
↓
讀 HTTP Host / Path
↓
決定送給哪個 Backend
例如:
app.example.com
→ App Server
api.example.com
→ API Server
所以:
Port Forwarding
偏 L3/L4 Translation
Reverse Proxy
偏 L7 Application Routing
今天先知道差異,不往下展開。
假設我做:
203.0.113.10:8080
→
192.168.1.30:80
外面還是連不到。
我以前可能只會一直重按 Router 的:
Enable Port Forwarding
但現在可以一層一層問。
Router WAN Address
真的是 Public IPv4 嗎?
外部封包
真的能到這個 Public IP 嗎?
TCP 8080
有沒有 Match 到 DNAT Rule?
Edge Firewall
允不允許?
192.168.1.30
在 LAN 裡能不能正常到?
Server 的 TCP 80
真的有 Listen 嗎?
Host Firewall
有沒有擋?
回程 Default Gateway
是不是回到同一台 NAT Router?
這時就不再是:
Port Forwarding 壞了。
而是:
到底是哪一層沒有成立?
現在這四天其實已經是一條完整的 Edge Traffic Story。
Day 20:
Routing Table
→ 有路
ACL
→ 還可以決定 Packet 能不能過
Day 21:
Stateless
→ Packet 各自判斷
Stateful
→ 記得 Connection
Day 22:
Inside 主動出去
↓
PAT
↓
Public IP + Port
↓
建立 Translation State
↓
Return Traffic 找得回來
Day 23:
Outside 主動進來
↓
沒有既有 Mapping
↓
事先建立 Port Forwarding / DNAT Rule
↓
Public IP:Port
轉成
Private IP:Port
合起來:
Routing
→ 往哪裡走?
Firewall
→ 准不准走?
State
→ 這是不是既有 Connection?
NAT / PAT
→ Address / Port 怎麼翻?
Port Forwarding / DNAT
→ 外面第一次主動進來時,
要翻成哪個內部目的地?
外部 Client:
198.51.100.20:53000
要連我家:
203.0.113.10:8080
Router 有:
203.0.113.10:8080
→
192.168.1.30:80
完整故事就是:
Internet Client
198.51.100.20:53000
↓
Public Internet
↓
Home Router
203.0.113.10:8080
↓
Firewall Policy
允許?
↓
DNAT / Port Forwarding
203.0.113.10:8080
→
192.168.1.30:80
↓
Routing Table
192.168.1.0/24 在 LAN
↓
ARP
找 192.168.1.30 的 MAC
↓
Web Server
192.168.1.30:80
↓
回程經過同一台 Router
↓
反向 Translation
192.168.1.30:80
→
203.0.113.10:8080
↓
Internet Client
到這裡,Port Forwarding 就不再只是 Router 後台的一格設定。
它其實是在做:
把一個 Public Endpoint 固定映射成一個 Private Endpoint。
為什麼 Day 22 的 Outbound PAT 不需要我事先幫每一台電腦設定 Port Forwarding?
Internet Client 第一次送:
203.0.113.10:8080
如果 Router 沒有任何 Mapping,為什麼不能自己猜成:
192.168.1.30:80
?
做了:
203.0.113.10:8080
→
192.168.1.30:80
是不是代表 Firewall 一定會讓它過?
為什麼:
203.0.113.10:2222
→
192.168.1.50:22
外部 Port 可以和內部 Port 不一樣?
AWS Private Subnet 裡的 EC2 有 NAT Gateway,代表 Internet 就可以透過 NAT Gateway 主動連進 EC2 嗎?
第一件:
Outbound NAT 是內部先建立 Flow;Inbound 第一次主動進來時,如果沒有固定 Mapping,Router 不知道要送給哪一台內部 Host。
第二件:
Port Forwarding / DNAT
Public IP:Port
↓
Private IP:Port
它是在建立一個固定的目的地翻譯規則。
第三件:
Port Forwarding
≠
Firewall
≠
Application
有 Translation,不代表 Security Policy 一定允許,也不代表 Server 真的有在 Listen。
現在假設我已經設定:
203.0.113.10:8080
→
192.168.1.30:80
Server 也正常。
Firewall 也放行。
結果朋友還是連不進來。
我打開 Router 的 WAN Status,卻發現它拿到的根本不是我查 IP 網站看到的 Public IPv4。
那下一個問題就來了:
明明做了 Port Forwarding,為什麼外面還是連不進來?Public IP、Double NAT、CGNAT 到底在哪一層把封包擋住了?