🧭 一、問題背景
在內部測試 OPNsense 時,我建立了如下的測試環境:
[測試主機] → OPNsense → UserGW → Internet
| 節點 | IP / 功能 |
|---|---|
| 測試主機 | 192.168.100.250(GW: 192.168.100.253) |
| OPNsense LAN | 192.168.100.253 |
| OPNsense WAN | 172.16.100.253(GW: 172.16.100.251) |
| UserGW LAN | 172.16.100.251 |
| UserGW WAN | PPPoE 外網連線 |
測試主機透過 OPNsense → UserGW → 外網連線至外部 SSH Server。
結果外部主機收到封包(可在 iptables log 中看到),
但測試主機端 SSH 連線卻一直顯示 “Connection timed out”。
🧩 二、問題分析
從外部伺服器的日誌可看到封包來源為:
UserGW PPPoE IP
這代表:
- OPNsense 有進行第一次 NAT(192.168.100.250 → 172.16.100.253)
- UserGW 再進行第二次 NAT(172.16.100.253 → 公網 IP)
也就是典型的「雙層 NAT」架構。
雖然封包能送出,但回程封包無法正確對應回 OPNsense 的狀態表。
🔍 結果:
- 外部看起來連線請求有到(SYN)
- 但 OPNsense 沒有正確接收回來的 SYN/ACK
- 測試主機最終超時(timeout)
⚙️ 三、排查過程
1️⃣ 檢查 NAT 設定
在 OPNsense 中 NAT 規則設定為:
來源:LAN 192.168.100.0/24
出口:WAN 172.16.100.253
Translation:Interface address
確認 NAT 本身運作正常。
2️⃣ 檢查防火牆規則
在 LAN 介面有放行規則,但 WAN 預設封鎖 inbound。
因為使用 stateful firewall(pf),回程流量理論上會自動被允許。
但雙層 NAT 造成 state 表 mismatch,導致回包被丟棄。
3️⃣ 測試 “sloppy state”
在 WAN 規則中加入:
State Type: sloppy state
容許外部回包與 state 參數稍有不同。
結果仍不穩定。
4️⃣ 抓封包分析
在 OPNsense 執行:
tcpdump -ni wan host <ssh_server_ip> and port 22
觀察只看到 SYN →,但沒有 SYN/ACK ←
證實問題不是 NAT 沒轉,而是回程封包被 UserGW 的狀態追蹤機制丟棄。
🧠 四、根本原因
問題出在「兩層 stateful NAT」。
當外層(UserGW)與內層(OPNsense)都在維護連線狀態表時,
回包若被外層防火牆先處理、修改後轉發回來,內層的狀態表不再匹配,
導致 TCP 三向交握無法完成。
✅ 五、最終解法
我決定讓 OPNsense 直接撥 PPPoE 上網,
取代 UserGW 這層 NAT。
新的架構如下:
[測試主機] → OPNsense → PPPoE (Internet)
| 節點 | IP / 功能 |
|---|---|
| 測試主機 | 192.168.100.250(GW: 192.168.100.253) |
| OPNsense LAN | 192.168.100.253 |
| OPNsense WAN | PPPoE(由 ISP 分配公網 IP) |
測試後:
✅ SSH、Ping、Web 全部正常。
封包流向清晰、狀態表正常同步,
再也沒有 timeout 問題。
🧩 六、技術總結
| 項目 | 說明 |
|---|---|
| 問題原因 | 雙層 NAT 導致 TCP 狀態追蹤不同步 |
| 現象 | 外部有連線請求,內部卻 timeout |
| 臨時解法 | sloppy state、NAT 重新設定 |
| 根本解法 | 改由 OPNsense 直接撥 PPPoE,移除第二層 NAT |
| 結果 | 內外連線完全正常,封包流向簡化 |
💡 七、後續建議
- 在 OPNsense 開啟 Insight (Netflow) 分析流量。
- 用 Unbound DNS Resolver 管理內部 DNS。
- 維持 WAN 預設封鎖策略,只放行必要服務。
- 若未來需要多 WAN,可考慮再建立 Policy Routing。