iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
IT Operation

從裸機到叢集:以 Proxmox VE、Ceph、OPNsense 與 PostgreSQL HA 建立可驗證的安全私有雲系列 第 14

Day 14|從預設拒絕到最小權限:OPNsense 防火牆的別名與規則順序

  • 分享至 

  • xImage
  •  

VLAN、IP 網段與 OPNsense 介面已經建立清楚的路由邊界,接下來要把流量需求轉成可以執行、驗證與維護的防火牆政策。

今天要解決的問題

一筆新連線進入 OPNsense 後,狀態表(State Table)與防火牆規則會如何處理?規則應放在哪個介面?浮動規則(Floating Rule)、介面群組規則(Interface Group Rule)與單一介面規則的先後順序是什麼?Alias 如何降低維護成本,又為什麼不等於權限?

本文閱讀方式

  • 完整理解技術與底層原理:依序閱讀全文。
  • 掌握完成部署所需的基本概念:優先閱讀標有「⭐」的章節。
  • 快速了解當天的部署內容:閱讀文末的 Lab/實作章節。
  • 跟著系列建立完整系統:依照 GitHub 詳細部署文件 的天數順序操作。

⭐ 從封包進入介面開始

前文已介紹狀態式防火牆、安全區域與最小權限。今天先複習必要概念,再從 OPNsense 底層使用的 pf 說明封包如何比對狀態與規則,最後把規則模型套用到已建立的 VLAN 介面。

封包抵達防火牆時,第一個可觀察位置是入站介面(Inbound Interface)。規則預設在封包進入 OPNsense 的方向比對,因此來源位於 SERVICE 的連線通常從 SERVICE 介面開始判斷。由 Internet 進入的連線則從 WAN 開始判斷。

封包依進入 OPNsense 的介面查詢狀態表,再比對對應的規則表

圖(一)新連線從入站介面進入規則表,既有連線則可直接符合狀態表

第一個符合允許規則(Pass Rule)的封包會建立連線狀態,後續屬於同一筆連線的封包可以直接符合狀態表,不必每次重新比對完整規則集(Ruleset)。因此一般只需允許連線發起方向,合法的回程封包會沿用既有狀態。

第一個封包符合規則後建立狀態,回程封包沿用既有狀態

圖(二)狀態式防火牆只需允許連線發起方向,回程封包可沿用既有狀態

這也會影響測試。修改規則或 Alias 後,既有連線可能繼續符合舊狀態,看起來像是新規則沒有生效。排錯時應先確認 Firewall → Diagnostics → States,必要時只移除相關狀態。清除全部狀態會中斷其他連線。

同 VLAN 主機可能直接交換訊框,不會進入 OPNsense。這裡建立的政策只能控制實際跨越 OPNsense 介面的流量。同 VLAN 的限制由更細的網路分段、PVE 防火牆或主機防火牆(Host Firewall)補足。

⭐ 一條規則最少要有什麼

建立防火牆規則時,依實際流量需求設定下列欄位:

規則欄位 設定原則
動作(Action) 必要流量使用 Pass。需要明確阻擋時使用 BlockReject
介面/方向(Interface/Direction) 選擇封包進入 OPNsense 的介面,方向通常使用 in
IP 版本/協定(IP Version/Protocol) 只選實際使用的 IPv4、IPv6、TCP、UDP 或 ICMP。
來源(Source) 限定真正獲准發起連線的主機、網段或 Alias。
來源連接埠(Source Port) 用戶端通常使用臨時連接埠,因此多數規則保持 any
目的(Destination) 限定實際服務主機、網段、VIP 或防火牆本身。
目的連接埠(Destination Port) 只填入伺服器實際提供的服務連接埠。
紀錄(Log) 只替需要稽核、排錯或驗證拒絕結果的規則啟用。
說明(Description) 寫明流量用途、來源、目的與服務,讓規則可以稽核。

三種常見動作的差異如下:

  • Pass:允許封包,預設會建立連線狀態。
  • Block:直接丟棄,用戶端通常等待到逾時。不受信任來源常使用這種方式。
  • Reject:拒絕並主動回覆。TCP 通常回覆 RST,UDP 則回覆 ICMP Unreachable。內部排錯時可以更快顯示連線遭拒。

⭐ 防火牆如何決定規則的實際比對順序?

OPNsense 會依規則所屬區段決定處理優先序。系統自動規則之外,主要順序為:

OPNsense 依序處理浮動規則、介面群組規則、單一介面規則與預設拒絕

圖(三)OPNsense 各規則區段的主要處理優先序

每個區段內還要再看順序(Sequence)。一般規則預設啟用 Quick,表示由上往下比對,第一條符合的規則立即決定結果。若取消 Quick,則會繼續比對並採用最後一條符合的規則。沒有明確需求時,維持 Quick,用「較精確的規則在上、較廣泛的規則在下」閱讀最容易稽核。

新版 OPNsense 的 Firewall → Rules [new] 中,一條規則選擇單一介面時是介面規則。選擇介面群組時是群組規則(Group Rule)。同時選擇多個介面或反向選取介面,會被歸入浮動規則。浮動規則的處理時間早於群組規則與單一介面規則。

介面群組規則又早於單一介面規則。若群組中先出現一條廣泛的 Block,後面單一介面的 Pass 沒有機會命中。共同政策與例外政策必須按照實際優先序設計,審查時應查看完整處理順序與所有相關區段。

介面群組建立的是共同規則入口,不會合併成員介面的廣播域。封包從任一成員介面進入 OPNsense 時,都會先比對該群組的規則。例如 SERVICE 是 LAB_INTERNAL 的成員,10.77.20.31 向 SERVICE 介面的 10.77.20.1 查詢 DNS 時,封包從 SERVICE 進入,便會比對 LAB_INTERNAL → This Firewall TCP/UDP 53 Pass。由管理用 LAN 進入的封包不屬於這個群組,因此不會套用這條群組規則。

⭐ 別名(Alias)與介面群組分別抽象不同資料

Alias 是可以重複引用的命名集合,常見類型包括:

  • Host(s):單一主機、位址範圍或完整網域名稱。
  • Network(s):使用 CIDR 表示的一個或多個網段。
  • Port(s):單一連接埠或連接埠範圍。
  • Network Group:組合其他 Host 或 Network 類型的 Alias。

Host、Network、Port 與 Network Group Alias 的內容與組合方式

圖(四)不同 Alias 類型保存不同形式的位址或連接埠資料

圖中由左至右分別是 Alias 類型、可供規則引用的名稱,以及實際展開內容。Host Alias 可以集合多台主機,Network Alias 保存一個或多個 CIDR 網段,Port Alias 集合服務連接埠。Network Group 則把既有的 Host、Network 或其他 Network Group Alias 再組成較大的位址集合,不能混入 Port Alias。

例如 PG_NODES 代表 10.77.30.1110.77.30.13,比在多條規則中散落三個 PostgreSQL IP 更容易閱讀。圖中的 WEB_PORTS 則集中表示 TCP 80 與 443。Alias 只保存資料。防火牆規則引用 Alias 後才會形成實際權限。

名稱應描述穩定角色,Description 則記錄用途。修改一個 Alias 會同時影響所有引用它的規則,因此變更前要先查詢引用關係,變更後再到 Firewall → Diagnostics → Aliases 檢查實際展開內容。

介面群組組合的是介面,目的是讓多個介面套用共同規則。本系列把 SERVICE、DATABASE、BACKUP 與 BASTION 加入 LAB_INTERNAL,只用來承接 DNS、NTP、內部網段阻擋與套件更新等共同基準。

⭐ 預設拒絕要從流量需求轉成例外

前面提到,網路層的最小權限要同時縮小來源、目的、協定與目的連接埠。沒有符合明確允許條件的流量,則交由預設拒絕或明確的阻擋規則處理。

製作防火牆規則時,可以依下列流程把業務需求拆成規則欄位,並規劃完成後的驗證方式:

從業務需求確認入站介面、來源、目的、協定、連接埠、紀錄與驗證方式

圖(五)從業務需求拆解防火牆規則條件並規劃驗證方式

DNS、NTP、套件更新、監控、備份與管理連線都要明確記錄,並以具體的來源、目的與服務取代 any to any。必要流量尚未盤點完成前,直接收緊規則可能中斷名稱解析、校時、更新或管理路徑。

規則順序應先放必要而精確的允許規則,再放明確的區域間阻擋規則,最後才放較廣泛的外部服務允許規則。例如內部網段阻擋規則必須位於「到任何目的地的 TCP 80/443」之前,否則後者也可能允許存取其他內部區域的 Web 服務。

規則紀錄顯示哪一條規則被命中

規則紀錄(Log)保存啟用紀錄的規則命中結果。Firewall → Log Files → Live View 可以查看介面、來源、目的、動作與規則 ID(Rule ID),適合確認封包是被哪一條規則允許或阻擋。

狀態式規則(Stateful Rule)通常只在建立狀態的第一個封包留下規則紀錄,後續封包沿用狀態時不會持續出現在 Live View。因此沒有新紀錄不代表沒有流量。紀錄應保留給重要管理入口、預期遭拒的負向測試與需要稽核的區域邊界,避免大量低價值紀錄干擾排錯。

狀態表顯示目前存在的連線

Firewall → Diagnostics → States 顯示目前由 pf 追蹤的連線狀態,以及來源、目的、協定、連接埠與命中的規則。它適合判斷回程流量是否正在沿用既有狀態,也能解釋規則修改後舊連線為何仍可通過。

狀態表只顯示已建立且尚未逾時的連線。需要重新測試規則時,只移除與測試流量相關的狀態,避免中斷其他使用者連線。

封包擷取顯示封包實際經過的介面

Interfaces → Diagnostics → Packet Capture 直接擷取指定介面上的封包,能確認封包是否抵達 OPNsense、從哪個介面進入,以及是否從預期介面離開。封包擷取看得見實際流量,但不會直接告訴管理者是哪一條防火牆規則做出決定,需要與規則紀錄及狀態表交叉比對。

OPNsense Packet Capture 可選擇介面、位址家族、協定、主機與連接埠

圖(六)封包擷取可依介面與流量條件縮小觀察範圍

排錯時先用規則紀錄確認規則命中結果,再用狀態表確認既有連線。若路徑不清楚,最後使用封包擷取比較各介面。三種工具各自提供不同證據,排錯時應交叉使用。

每一條重要允許規則都要搭配負向測試。除了確認正確來源能連線,也要改用錯誤來源、錯誤目的地或錯誤連接埠,確認預設拒絕或明確的 Block 確實接住不符合條件的流量。

本次 Lab:建立別名、介面群組與共同規則

不同 VLAN 已經形成可路由的介面邊界,今天接著把重複使用的網段、主機與連接埠整理成 Alias,再將四個服務 VLAN 納入 LAB_INTERNAL 介面群組,建立共同的 DNS、NTP、內部網段阻擋與套件更新規則。

服務端點尚未全部建立,因此今天只驗證 Alias、群組成員與規則順序是否正確套用。跨 VLAN 成功結果與服務專屬規則、WAN Port Forward 留待服務端點建立後測試與設定。

GitHub 詳細實作文件:Day 14|從預設拒絕到最小權限:OPNsense 防火牆的別名與規則順序

本次實作摘要

  1. 建立內部網段、主機與服務連接埠 Alias。
  2. 將 SERVICE、DATABASE、BACKUP 與 BASTION 加入 LAB_INTERNAL
  3. 在介面群組上建立四條共同規則。
  4. 核對 DNS、NTP、內部網段阻擋與外部更新規則的順序。
  5. 確認規則只套用於 LAB_INTERNAL,沒有誤建成較早比對的浮動規則。
  6. 下載完成 Alias 與規則後的 config.xml 備份。

驗證一:Alias 保存可重複引用的網路條件

FirewallAliases 建立 INTERNAL_NETWORKS,Type 選 Network(s),並將五個 CIDR 分別加入 Content:

10.77.10.0/24
10.77.20.0/24
10.77.30.0/24
10.77.40.0/24
10.77.50.0/24

INTERNAL_NETWORKS 使用 Network Alias 保存五個內部網段

圖(七)INTERNAL_NETWORKS 將五個內部網段集中成一個 Network Alias

接著建立已規劃主機使用的 Host Alias:

Alias Content
PROXY_NODES 10.77.20.2110.77.20.22
APP_NODES 10.77.20.3110.77.20.32
PG_NODES 10.77.30.1110.77.30.1210.77.30.13
CA_NODE 10.77.30.10
BACKUP_NODE 10.77.40.11
BASTION_HOST 10.77.50.11
WEB_VIP 10.77.20.10
DB_RW_VIP 10.77.20.11
DB_RO_VIP 10.77.20.12
BASTION_TARGETS 10.77.20.2110.77.20.2210.77.30.1110.77.30.1310.77.40.11

Port Alias 則保存規則會重複引用的目的連接埠:

Alias Content
WEB_PORTS 80、443
PGSQL_PORT 5432
PATRONI_API 8008
ETCD_PORTS 2379、2380
BASIC_OUTBOUND_TCP 80、443

OPNsense Alias 清單顯示已建立的部分 Host 與 Port Alias

圖(八)Alias 清單顯示已建立的部分 Host 與 Port Alias

Alias 只替條件命名,本身不會建立主機或放行流量。Port Alias 也只保存連接埠號碼。TCP 或 UDP 由引用它的規則決定。BASTION_TARGETS 則是跳板機在網路層可接近的主機上限,個別使用者由 OpenSSH 設定、目標帳號與公鑰繼續限制。

驗證二:介面群組只包含四個服務 VLAN

FirewallGroups 建立 LAB_INTERNAL,Members 選擇 SERVICE、DATABASE、BACKUP 與 BASTION,不加入管理用 LAN。No GUI groups 保持未勾選,儲存後按下 Apply

LAB_INTERNAL 群組包含 SERVICE、DATABASE、BACKUP 與 BASTION,並排除管理用 LAN

圖(九)LAB_INTERNAL 只包含四個服務 VLAN,不包含管理用 LAN

介面群組讓四個成員介面共用一組基礎規則。各 VLAN 保持獨立廣播域,跨 VLAN 流量依防火牆規則決定。

驗證三:共同規則依照範圍由窄到寬排列

FirewallRules,Interface 只選 LAB_INTERNAL,依序建立並排列以下四條規則:

順序 Action Protocol Source Destination Destination Port 用途
1 Pass TCP/UDP LAB_INTERNAL network This Firewall 53 使用防火牆提供的 DNS
2 Pass UDP LAB_INTERNAL network This Firewall 123 使用防火牆提供的 NTP
3 Block+Log any LAB_INTERNAL network INTERNAL_NETWORKS any 接住未明確允許的跨區流量
4 Pass TCP LAB_INTERNAL network any BASIC_OUTBOUND_TCP 允許 HTTP/HTTPS 對外更新

LAB_INTERNAL 的 DNS、NTP、內網阻擋與外部更新四條群組規則

圖(十)四條共同規則位於 LAB_INTERNAL 的 Group rules 區段

規則啟用 Quick 後,第一條符合條件的規則就會決定結果。內部網段 Block 必須位於外部 HTTP/HTTPS Pass 之前,否則目的為其他內部網段 TCP 80/443 的流量可能先被較寬的對外規則允許。後續若建立服務專屬的跨區 Pass,要使用明確的來源、目的與連接埠,並放在內部網段 Block 上方。

驗證四:規則位於正確的比對區段

在規則畫面以 LAB_INTERNAL 篩選,確認四條規則顯示在 Group rules,順序與上表一致。再開啟其中一條規則,確認 Interface 只有 LAB_INTERNAL。同時選取 SERVICE、DATABASE、BACKUP 與 BASTION 會讓規則進入較早處理的浮動規則區段,改變原本規劃的比對順序。

圖(七)至圖(十)可以證明設定結構與順序已建立。規則是否真的依條件允許或阻擋封包,還要從實際來源端送出流量,並配合用戶端結果與 OPNsense 規則紀錄交叉確認。

驗證五:允許與阻擋結果符合規則順序

以下畫面是在 app01 與 pg01 建立後補測,用來驗證本日規則的實際行為。從 SERVICE 網段的 app01 測試防火牆的 TCP 53 連線,再嘗試連向 DATABASE 網段未授權的 TCP 5433。前者應成功,後者應逾時:

nc -vz -w 3 10.77.20.1 53
nc -vz -w 3 10.77.30.11 5433

app01 連向 OPNsense TCP 53 成功,連向 pg01 TCP 5433 則逾時

圖(十一)從 SERVICE 網段驗證允許的 TCP 53 連線與未授權的跨 VLAN 連線

接著到 FirewallLog FilesLive View,使用來源 10.77.20.31 與目的 10.77.30.11 篩選,再執行一次 TCP 5433 測試。畫面應顯示封包被 Block LAB_INTERNAL to internal networks 規則阻擋:

OPNsense Live View 顯示 app01 前往 pg01 TCP 5433 的封包遭到內網 Block 規則阻擋

圖(十二)Live View 確認未授權跨 VLAN 流量命中內部網段阻擋規則

成功連到 TCP 53 只驗證 TCP 路徑與監聽端點。完整 DNS 驗證應實際送出查詢。TCP 5433 逾時搭配 Live View 的 Block 紀錄後,可以確認未授權跨區流量確實被第三條規則接住。

Lab 驗證對照

驗證 主要證據 可以得到的結論
驗證一:Alias Alias 編輯畫面與清單 網段、主機與連接埠條件已建立並可供規則引用
驗證二:介面群組 LAB_INTERNAL 的 Members 四個服務 VLAN 共用基礎政策,管理用 LAN 不在群組內
驗證三:共同規則 LAB_INTERNAL 規則清單 DNS、NTP、內部網段阻擋與外部更新規則依序存在
驗證四:比對區段 Group rules 與規則的 Interface 規則套用於介面群組,沒有誤建成浮動規則
驗證五:規則行為 app01 連線結果與 Live View 允許的 TCP 53 連線可通過,未授權跨 VLAN 流量命中內網 Block

完成後到 SystemConfigurationBackups 下載 config.xml。設定備份可能含有敏感資料,不應提交到 Git。

今天完成了什麼

  • 將內部網段、規劃主機與服務連接埠整理成可重複引用的 Alias。
  • 建立只包含 SERVICE、DATABASE、BACKUP 與 BASTION 的 LAB_INTERNAL 介面群組。
  • 建立共同的 DNS、NTP、內部網段阻擋與 HTTP/HTTPS 對外更新規則。
  • 將內部網段阻擋放在較寬的對外更新規則之前。
  • 確認共同規則位於介面群組規則區段,沒有誤建成浮動規則。
  • 從實際來源端交叉驗證允許的 TCP 53 連線與遭阻擋的跨 VLAN 流量。

下一篇預告

下一篇〈Day 15|SSH 跳板機的部署與權限設計(上):Linux 路由切換與建立安全入口〉會先替 PVE 建立必要的出口規則,再逐台將一般對外路徑切換到 OPNsense。確認管理路徑可用後,再部署並強化唯一公開的 SSH 跳板入口。


參考資料


上一篇
Day 13|從 VLAN 到安全區域:802.1Q、跨網段路由與 OPNsense 介面
下一篇
Day 15|SSH 跳板機的部署與權限設計(上):Linux 路由切換與建立安全入口
系列文
從裸機到叢集:以 Proxmox VE、Ceph、OPNsense 與 PostgreSQL HA 建立可驗證的安全私有雲15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言