01

總覽與定位

私有網段裡的主機如何共用少數公有 IP 上網?外面又怎麼連回內網服務?

我們在 IP 定址篇學會解讀 IPv4 與子網路遮罩,知道同網段直送、跨網段交 Gateway。真實家用/公司網路幾乎都長這樣:

  • 內網一堆主機用 192.168.x.x / 10.x.x.x 這種私有 IP
  • 路由器對外只有少數(常是一個)公有 IP向 ISP 註冊
  • 內網要上網 → 路由器做 NAT(Network Address Translation)改寫來源位址
  • 外面要連內網服務(自家 NAS、開發機 webhook)→ 靠 Port Forwarding(DNAT)
  • 哪些流量能過 → 由防火牆規則把關

本篇把這三件事串成一條可面試、可除錯的因果鏈:公私有 IP 為什麼要分 → NAT 表怎麼記映射 → Port Forwarding 怎麼反向開洞 → 防火牆預設拒/允許的心智模型。

座標這篇在系列中的位置

承接「IPv4 定址與子網路劃分」:你已會算網段與 Gateway,本篇回答「Gateway 對外怎麼改寫位址」。區域網路設備(Switch/MAC)與 DNS 解析留給鄰近主題;本篇只在網路層+傳輸層 port 的層次談 NAT/防火牆。

一句話答法私有 IP 不可在網際網路路由;NAT 在邊界把內網位址/port 映射成公有位址/port,讓多台主機共用出口,並用同一張表把回程封包還原。

02

公有 IP vs 私有 IP

不是「能不能 ping」,而是「網際網路上的路由器肯不肯幫你轉」。

私有 IP(Private / RFC 1918)刻意留給組織內部重複使用。網際網路上的骨幹路由器不會把目的地落在這些網段的封包轉出去——這叫「不可全域路由(non-globally routable)」。反過來說,公有 IP在 IANA/RIR 分配體系裡是唯一的,可由 ISP 公告到全球 BGP。

面向私有 IP公有 IP
範圍10/8、172.16/12、192.168/16其餘可分配空間(含文件用 203.0.113.0/24 等)
可重複?每個公司/家庭可各自再用同一段全球唯一(同一時間)
網際網路路由被過濾/不公告可經 BGP 到達
典型角色LAN 主機、K8s Pod、VPC 內網NAT Gateway、LB、對外 API

面試陷阱:127.0.0.0/8 是 loopback、169.254.0.0/16 是 link-local(APIPA),都不是 RFC 1918 私有網段,但同樣不應出現在「對外來源 IP」。

為什麼要這樣設計?IPv4 位址不夠用。若每台筆電都要一顆全球唯一公有 IP,位址空間早耗盡。私有+NAT 讓「組織內部任意擴張」,對外只消耗少數公有 IP——這是 IPv4 時代的務實妥協,不是長期銀彈(長期方向是 IPv6 端到端定址)。

陷阱「我有公網 IP」≠「任何人都能連到我的服務」

雲主機常有公有 IP,但安全群組/防火牆預設只開 22/443。家用則是整段 LAN 藏在一個公有 IP 後面:外面看到的是路由器,不是你的 192.168.1.20。要對外提供服務,還得 Port Forwarding(或反向代理/Tunnel)。

一句話答法私有 IP 供內部重複使用且不可在網際網路路由;公有 IP 全球唯一可路由;邊界用 NAT 銜接兩邊。

03

NAT 怎麼轉換內外網

核心不是「改 IP」 alone,而是「記一張連線狀態表,讓回程找得回路由」。

最常見的家用/辦公室場景是 NAPT(Network Address Port Translation),也常被叫成 PAT 或「IP masquerading」:多台內網主機共用同一個公有 IP,靠不同的來源 port區分連線。

內:10.0.0.8:54321 → SNAT → 外:203.0.113.50:40001 → Internet → 目標:93.184.216.34:443

路由器在轉出時改寫封包的 來源 IP(+常改來源 port),並在 NAT 表(conntrack / translation table)留下一列映射。回程封包目的地是公有 IP:40001 時,路由器查表還原成 10.0.0.8:54321 再送進 LAN——否則內網主機根本收不到回應。

方向改寫什麼別名典型用途
內 → 外來源 IP/portSNAT / Masquerade上網、呼叫外部 API
外 → 內目的 IP/portDNAT / Port Forward對外公開內網服務

Masquerade 是 SNAT 的動態版:出口 IP 隨介面位址變(DHCP 換 IP 時規則不用重寫)。

NAT 表一列通常至少包含:協議(TCP/UDP)、內網五元組資訊、對外映射的公有 IP:port、對端位址、以及逾時。TCP 有連線狀態可跟較久;UDP 通常用較短 idle timeout。在 Linux 上可用 conntrack -L 直接看這張表:

$ conntrack -L
tcp  6  431999 ESTABLISHED \
    src=10.0.0.8   dst=93.184.216.34 sport=54321 dport=443   \  # 原始方向(內→外)
    src=93.184.216.34 dst=203.0.113.50 sport=443 dport=40001 \  # 回程方向(外→內)
    [ASSURED]

同一筆連線用「原始 + 回程」兩個方向的五元組描述:回程的 dport=40001 就是路由器替 10.0.0.8:54321 分配的對外 port,回來的封包靠它還原。

這也點出 NAPT 的天花板:單一公有 IP 對每個「協議 × 對端 IP:port」大約只有 ~64K 個可用來源 port。連線暴增(大量短連線、P2P、掃描)時 port 會耗盡,或 conntrack 表達到 nf_conntrack_max 上限,表現就是偶發、難重現的連線失敗——正式環境除錯時常見的盲點。

關鍵NAT 破壞了端到端原則

對端伺服器只看得到路由器的公有 IP,看不到真實客戶端。這影響來源 IP 限流、地理定位、雙向 peer 連線(P2P/WebRTC 常需 STUN/TURN 穿透)。系統設計時要把 NAT 當成預設存在的中間盒,而不是例外。

一句話答法NAPT 用「公有 IP + 唯一來源 port」區分多台內網主機的連線,並靠 NAT 表把回程封包還原到正確私有位址。

04

Port Forwarding:讓外面連到內網

DNAT 在邊界把「打到公有 IP:port」的流量轉寫成「內網主機:port」。

假設你家路由器公有 IP 是 203.0.113.50,內網有一台開發機 10.0.0.20 跑 HTTP :8080。你設定 Port Forwarding:

外網 203.0.113.50:8080 → DNAT → 10.0.0.20:8080

外部客戶連 203.0.113.50:8080 時,路由器改寫目的 IP(必要時也改目的 port),送進 LAN;回程再做對應的來源改寫,讓客戶端以為一直在跟公有 IP 說話。

設定項範例說明
外部 port8080 或 443對端實際連的 port;可與內部不同
內部 IP10.0.0.20必須是穩定位址(建議 DHCP reservation/靜態)
內部 port8080服務實際 listen 的 port
協議TCP / UDPNAT 表與防火牆都按協議分開
陷阱開洞=擴大攻擊面

Port Forwarding 把內網服務暴露到整個網際網路。正式做法通常是:只轉必要 port、前置反向代理/WAF、強制 TLS、搭配防火牆白名單,或改用 VPN/Cloudflare Tunnel/SSH reverse tunnel,避免把整台機器裸露在公網。

雲端對應觀念:Security Group/NLB Listener/Ingress 規則,本質也是「在邊界決定哪些外→內流量被改寫或放行」。家用路由器的 Port Forward 面板,只是同一設計的精簡版。

陷阱設好了卻連不到?先懷疑 CGNAT/雙 NAT

「Port Forward 明明設對了,外面就是連不進來」——最常見的真兇是你的路由器根本沒有公有 IP。當 IPv4 位址枯竭,許多 ISP 改發私有 IP(如 100.64.0.0/10)給用戶,再於機房用一層 CGNAT(Carrier-Grade NAT,營運商級 NAT)共用少數公網 IP。這時封包會經過兩層 NAT:家用路由器一層、ISP 一層。你在自家路由器開的洞,外部流量根本到不了那台你看不見、也無權設定的 ISP NAT。同理,把數據機接到自己的路由器 WAN 口卻沒設 Bridge 模式,也會在自家造成雙 NAT。破解法:向 ISP 申請公有/固定 IP、把前段設備切 Bridge 模式,或改用不需入站洞的反向 Tunnel/VPN(見第 7 節)。

一句話答法Port Forwarding 是 DNAT:把打到公有 IP:外部 port 的封包目的改寫成內網主機:服務 port,並依賴狀態表處理回程;若卡在 CGNAT/雙 NAT 之後,開洞也沒用,得改走 Tunnel 或申請公網 IP。

05

防火牆基礎心智模型

NAT 負責「怎麼改寫」;防火牆負責「允不允許這類流量存在」。

實務上 NAT 與防火牆常落在同一台路由器/同一套 netfilter(iptables/nftables)規則鏈,但概念要分開:

  • 防火牆:依規則決定 ACCEPT/DROP/REJECT(誰可以從哪進、到哪出)
  • NAT:在已允許的路徑上改寫位址/port
面向建議預設為什麼
入站(WAN → LAN)預設拒絕只放行明確 Port Forward/管理 port
出站(LAN → WAN)多數家用允許企業常做出站白名單/代理
已建立連線允許 RELATED,ESTABLISHED回程封包必須能回來
規則順序由上而下、先匹配先生效錯序會造成「規則寫了卻沒擋到」

除錯口訣:先問「封包有沒有被防火牆丟掉」,再問「NAT 有沒有改對」。兩者混淆時,常見現象是:tcpdump 在 WAN 口看到 SYN,但 LAN 口沒有對應封包——可能是入站規則沒放行,或 DNAT 目標寫錯。

封包抵達 → DNAT 改寫目的
(PREROUTING)
→ 路由決策 → 防火牆過濾
(FORWARD)
→ 轉發到目標區

以 Linux netfilter 入站轉發為例:DNAT 在 PREROUTING(路由決策前)先改寫目的,過濾則在 FORWARD 鏈判定。順序依 hook 而定,但面試重點不變——「改寫」與「過濾」是兩層獨立決策,別混成一句「開了 port 就好」。

把上述心智模型落成一組最小 iptables 規則,正好看出「改寫(nat 表)」與「過濾(filter 表)」是分開的兩件事:

# 出站放行、入站預設拒絕;永遠放行已建立/相關連線的回程
iptables -P FORWARD DROP
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 改寫:Port Forward 外部 :8080 → 內網 10.0.0.20:8080(DNAT 在 nat 表)
iptables -t nat -A PREROUTING -i wan0 -p tcp --dport 8080 \
         -j DNAT --to-destination 10.0.0.20:8080

# 過濾:還得在 filter 表放行這條新入站,否則 FORWARD 預設 DROP 會擋掉
iptables -A FORWARD -p tcp -d 10.0.0.20 --dport 8080 -j ACCEPT

只寫了 DNAT 卻忘了那條 FORWARD ACCEPT,就是「規則寫了卻沒通」的經典陷阱——改寫成功,但過濾把它擋下。

一句話答法防火牆決定允不允許,NAT 決定如何改寫;入站預設拒絕、只開必要洞,並永遠放行已建立連線的回程。

06

互動 · NAT 表映射模擬

自己發一筆出站或入站連線,看 NAT 表如何新增列、封包欄位如何被改寫。

互動 · NAT Translation Table 切換 SNAT/DNAT,送出連線並觀察映射列
新建映射 命中既有 被拒/無規則
選擇模式後按「送出連線」,觀察 NAT 表與封包欄位變化。
改寫前
src—
dst—
protoTCP
方向—
改寫後(wire / 下一跳所見)
src—
dst—
protoTCP
動作—

路由器公有 IP 固定為 203.0.113.50。SNAT 會分配對外 port;DNAT 模式下請先「設定轉發規則」開洞,再「送出連線」——若把外部 Port 改成沒開洞的值再送,會示範防火牆預設拒絕、封包被丟棄(DROP)。

# 類型 內網 公網映射 對端 狀態
尚無映射列 — 送出連線後會出現
一句話答法NAT 表是狀態:出站建立「內→外」映射供回程還原;入站則需預先 DNAT/Port Forward 規則,否則外部連線沒有對應列可走。

07

面試折衷與實務選型

何時靠 NAT/Port Forward,何時改用 Tunnel、IPv6 或雲負載均衡。

方案優點代價適用
NAPT 出站 省公有 IP、部署簡單 破壞端到端、除錯難、連線數受 port 上限 家用/辦公室上網
Port Forward 快速暴露單一服務 攻擊面大、動態 IP/雙 NAT 易失敗 臨時 demo、家庭 Lab
反向 Tunnel/VPN 不必開入站洞、可繞過雙 NAT 多一跳延遲、依賴隧道服務 遠端開發、IoT、零信任
雲 LB + 私有後端 TLS/健康檢查/水平擴展 成本與供應商耦合 正式對外 API
IPv6 端到端 恢復端到端定址 生態與雙堆疊複雜度 長期方向、新網路
面試常被追問的延伸

「為什麼 WebRTC 需要 STUN?」——因為雙方都可能在 NAT 後,得先透過 STUN 問出「我對外的公網 IP:port 長怎樣」,再交換給對方嘗試打洞。而打不打得通,取決於 NAT 類型:

  • Full-cone:對外映射固定,任何外部主機都能循該 port 回連——最好打洞。
  • Restricted / Port-restricted:只放行「你先連過的」對端(IP/IP+port),需雙方近乎同時對打。
  • Symmetric:對每個不同目的地都分配不同對外 port,STUN 問到的映射對 peer 不成立,打洞多半失敗,只能退回 TURN 中繼。

「為什麼微服務在 K8s 還要再談 NAT?」——NodePort/kube-proxy/Cloud NAT 都是同一類邊界改寫,只是控制面不同。

一句話答法NAT 用位址重寫換取 IPv4 節約與拓樸隱藏;對外服務優先用受管 LB/Tunnel,Port Forward 只當可控的小洞,並用防火牆縮小攻擊面。