iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
IT Operation

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

Day 15|SSH 跳板機的部署與權限設計(上):Linux 路由切換與建立安全入口

  • 分享至 

  • xImage
  •  

前幾日的部署中,我們將管理介面暫時連接既有的上游路由器。現在防火牆與管理網段已經完成,本篇會先說明 Linux 如何選擇路由,再把管理位址、預設閘道與 DNS 逐台切換到正式管理網路。接著建立跳板機,把外部 SSH 集中到單一受控入口,避免逐台公開內部主機。本文會依序處理安全區域、公鑰驗證、OpenSSH、主機防火牆、目的地 NAT 與 WAN 規則,最後以正向與負向測試完成驗證。

今天要解決的問題

今天先完成先前保留的管理網路切換,再建立唯一公開的 SSH 管理入口。這兩項工作需要回答以下五個問題:

  1. Linux 如何選擇路由,為什麼本次切換要移除舊預設路由,而不能把兩條預設路由直接視為備援?
  2. 如何逐台切換管理位址、預設閘道與 DNS,同時維持管理、叢集與儲存流量?
  3. 跳板機是甚麼,為什麼要減少直接公開的 SSH 入口?
  4. 目的地 NAT、通訊埠轉換與 WAN 防火牆規則如何共同把外部連線送到跳板機?
  5. 公鑰驗證、OpenSSH、主機防火牆與正向、負向測試如何共同保護並驗證這個入口?

本文先介紹跳板機的用途,再分別說明 Linux 路由與安全切換方法,以及入站轉送、SSH 身分驗證與主機防護,最後才進入實作。本文只完成外部管理者到跳板機的第一段連線。跳板機能夠前往哪些內部主機,以及管理者在目標主機上擁有哪些權限,留到下一篇處理。

本文閱讀方式

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

⭐ 什麼是跳板機

跳板機(Jump Host)是管理者連線到受管主機以前,必須先登入的中介主機。管理者先從自己的電腦建立第一段 SSH 連線,再由跳板機建立前往受管主機的第二段 SSH 連線。受管主機只需要接受來自跳板機的管理連線,不必直接開放給管理者所在的每一種來源網路。當跳板機位於網路邊界、經過特別強化並準備承受外部攻擊時,也常稱為堡壘主機(Bastion Host)。NIST 將 Bastion Host 定義為為了承受攻擊而特別設計與設定的專用主機。

管理者透過跳板機建立前往內部受管主機的兩段 SSH 連線

圖(一)管理者先登入跳板機,再由跳板機建立前往受管主機的第二段 SSH 連線。

管理者如何抵達跳板機,取決於環境的網路設計。跳板機可以只供內部管理網路使用,也可以透過 VPN、專線或其他受控路徑連線。若必須從網際網路進入,才需要由邊界防火牆(位於外部網路與內部網路交界的防火牆)建立公開入口、執行網路位址轉換(NAT),並用過濾規則限制允許的流量。路由器、防火牆與 VPN 控制哪些來源可以抵達跳板機,跳板機上的 OpenSSH 驗證管理者身分,受管主機則繼續判斷管理者能否登入。這些元件各自負責不同位置,跳板機不會取代前方的網路控制,也不會自動取得所有內部權限。

假設一個環境有 8 台需要遠端管理的伺服器,全部直接公開 SSH,就會形成 8 個需要個別更新、限制來源、管理金鑰與監看 Log 的端點。改由跳板機承接外部管理後,公開 SSH 端點可由 8 個縮減為 1 個,其餘主機只接受內部管理路徑。當然入口集中也會讓跳板機成為高價值目標。實際上可依安全區域、正式與測試環境、管理團隊或權限範圍設置不同的跳板機,並優先強化、更新及監控這些管理入口。

馬克斯普朗克資訊研究所(Max Planck Institute for Informatics)與台夫特理工大學(Delft University of Technology)研究團隊在 2025 年 ACM 網際網路量測研討會(Internet Measurement Conference,IMC)發表的 SSH 長期量測研究中,利用 221 個蜜罐觀察約三年,共記錄超過 5.46 億個 SSH 工作階段,其中 2.58 億個工作階段曾嘗試登入但未成功。蜜罐會刻意模擬可受攻擊的服務,因此這些數字不能直接換算成一般伺服器的入侵率。它們仍清楚顯示,只要公開 SSH,便會持續收到大量自動掃描與登入嘗試。這也說明了保護跳板機與公開 SSH 入口的重要性。

將外部入口改用非標準連接埠,可以減少只掃描 TCP 22 的自動化雜訊。PasswordAuthentication no 會關閉 SSH 密碼驗證,KbdInteractiveAuthentication no 會關閉可能由 PAM 提供的密碼或 OTP 提示。PermitRootLogin no 則禁止直接以 root 身分登入。這些設定能切斷常見的登入路徑,但不能阻止完整的連接埠掃描、遭竊的私鑰、OpenSSH 漏洞或錯誤設定,因此仍須配合來源限制、公鑰保護、安全更新與持續監控。

把公開 SSH 入口收斂後,還能取得以下管理效果:

  • 集中套用來源限制、公鑰政策、安全更新與登入告警。
  • 在進入內部網路前留下統一的第一段登入紀錄。
  • 撤銷管理者存取權時,先封鎖單一公開入口,再處理內部主機的細部授權。

理解跳板機的角色後,接下來分別處理今天的兩項工作:

  • 完成管理網路切換:確認 Linux 如何選擇路由,再把日常管理路徑、預設閘道與 DNS 從臨時建置網路移到正式管理網路,並準備驗證與回復方法。
  • 建立 SSH 入口:將跳板機放入獨立安全區域,設定公鑰驗證、OpenSSH 與主機防火牆,最後才建立外部轉送與過濾規則。

⭐ 將主機切換到正式管理網路

切換前,主機仍透過上游路由器所在網段接受日常管理。正式管理網段雖已預先建立,尚未承接管理路徑。現在要先理解 Linux 如何選擇路由,再逐台切換管理位址、DNS 與一般對外流量。Lab 部分會進行實際切換。完成後,管理流量便能集中通過防火牆,使用直接連線路由的叢集與儲存網路則不會跟著改走預設路由。

Linux 依路由表決定封包出口

一台主機可以同時擁有多張網路介面、多個 IPv4 位址與多張路由表。Linux 先依路由政策資料庫(Routing Policy Database,RPDB)的規則選擇路由表,再從該表找出最符合目的位址的路由。

ip rule show 會依優先序列出 RPDB 規則。數字越小,規則越早處理。一般 Linux 主機預設包含:

0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
  • local table 保存主機自己的位址與廣播位址,由核心自動維護。
  • main table 保存一般路由,包括介面建立的直接連線路由、管理者或網路設定加入的靜態路由,以及常見的預設路由。
  • default table 是編號 253 的保留路由表,預設通常沒有內容。它和 default via ... 這種預設路由不是同一件事。

規則查詢某張路由表後,若沒有找到符合目的位址的路由,才會繼續處理下一條 ip rule。找到可用路由後便停止查找,取得下一跳、送出介面與偏好的來源位址。

Linux 使用 ip rule 與不同路由表查詢本機及外部目的位址

圖(二)Linux 主機的路由政策規則、local/main 路由表與實際路由查詢結果。

接著逐一查看圖(二)中的規則。範例主機使用 10.77.30.11/24,查詢 local table 時可以看到:

local 10.77.30.11 dev eth0 proto kernel scope host src 10.77.30.11
broadcast 10.77.30.255 dev eth0 proto kernel scope link src 10.77.30.11

第一筆表示目的地就是本機的 10.77.30.11 時,封包留在本機處理。第二筆是 10.77.30.0/24 的廣播位址。ip route get 10.77.30.11 因此得到:

local 10.77.30.11 dev lo src 10.77.30.11

這裡顯示 dev lo,是因為封包已被判定交給本機網路堆疊,不需要真的從 eth0 送出。

main table 則包含:

default via 10.77.30.1 dev eth0 proto static
10.77.30.0/24 dev eth0 proto kernel scope link src 10.77.30.11

10.77.30.0/24 是介面設定 10.77.30.11/24 後由核心建立的直接連線路由,所以標示 proto kerneldefault 等同 IPv4 的 0.0.0.0/0,由系統網路設定加入,因此這裡標示 proto staticstatic 描述路由的來源,default 描述它涵蓋的目的前綴。兩者可以同時出現在同一筆路由上。

在同一張路由表中,Linux 先使用最長前綴比對(Longest Prefix Match)。目的地若位於 10.77.30.0/24/24 會比預設路由的 /0 更精確,因此直接從 eth0 送出。1.1.1.1 不屬於這個網段,只能符合 /0,所以 ip route get 1.1.1.1 顯示:

1.1.1.1 via 10.77.30.1 dev eth0 src 10.77.30.11

ip -4 route show table all 可以列出所有 IPv4 路由表的內容,ip route get <目的位址> 則讓核心實際計算使用的路由。後者比只看介面是否有 IP,更能證明封包會使用哪一個下一跳、介面與來源位址。

真正容易造成事故的設定包括:

  • 在舊介面與新介面同時保留預設閘道,使出口選擇、故障切換與回程路徑更難判斷。
  • 替叢集通訊或儲存專用介面加入不必要的閘道。
  • 一次修改全部節點,失敗後失去可登入的健康節點。
  • 只測試網際網路連線,沒有重新確認管理介面、名稱解析、時間同步、叢集與儲存服務。
  • 變更前沒有保留本機或虛擬化平台 Console、原始設定與回復指令。

⭐ 管理網路切換完成後,建立與強化 SSH 入口

完成管理網路的規劃與切換方法後,接著處理獨立的 SSH 入口工作:先決定跳板機所在的安全區域,再設定 SSH 身分驗證、OpenSSH 與主機防火牆。所有本機防護完成後,才評估是否需要建立網際網路公開入口。

跳板機應放在獨立安全區域(Bastion DMZ)

入口收斂後,還要避免跳板機成為繞過區域間政策的捷徑。跳板機應放在獨立的安全區域,讓外部管理流量與一般服務流量分開,並讓它前往其他網段的連線繼續通過防火牆路由與檢查。這裡延續前篇的安全區域規劃,進一步把管理入口放入 Bastion DMZ。

跳板機同時也是高價值目標。本文採用以下設計原則:

  • 只安裝管理工作需要的套件與服務。
  • 只有一張連接 Bastion DMZ 的 vNIC,不直接接入其他內部 VLAN。
  • 不啟用 IP Forwarding,主機防火牆的 Forward Chain 採預設丟棄。
  • SSH 只允許明確帳號使用公鑰驗證,不開放 root 與密碼登入。
  • 保留登入失敗、成功登入與系統變更紀錄。
  • 持續安裝安全更新,避免公開管理服務長期停留在已知漏洞版本。

跳板機只有一張連接獨立安全區域的網路介面時,前往其他網段的流量必須交給防火牆路由與檢查。若另外把管理或資料庫網路介面直接接到跳板機,流量可能繞過原本設計的跨區域規則,讓跳板機變成難以稽核的旁路。

SSH 金鑰的用途與讀取方式

SSH 公鑰驗證使用一組互相對應的私鑰與公鑰。私鑰留在管理者的電腦,公鑰則安裝到遠端帳號。登入時,用戶端使用私鑰簽署本次連線的驗證資料,伺服器再以已授權的公鑰驗證簽章。驗證成功代表用戶端當下能使用對應私鑰。私鑰不會傳送到伺服器。

SSH 連線中有多種用途不同的金鑰

SSH 連線會使用多種用途不同的金鑰:

金鑰 驗證對象 保存位置與用途 實際使用範例
使用者驗證金鑰(User Authentication Key) 使用者 私鑰留在用戶端。公鑰放入遠端帳號的 authorized_keys 管理者以 ~/.ssh/id_ed25519 登入跳板機,sshd 使用 authorized_keys 內的公鑰驗證簽章。
伺服器主機金鑰(Host Key) SSH 伺服器 伺服器保存私鑰。用戶端將伺服器公鑰記錄在 known_hosts 用戶端第一次連線時確認主機指紋並記錄公鑰。日後若主機金鑰改變,SSH 會提出警告。
工作階段金鑰(Session Key) 本次連線 兩端臨時協商,用來持續加密本次連線的資料。 加密通道建立後,身分驗證封包、Shell 指令、輸出與檔案傳輸都會受到保護。連線結束後即不再使用。
SSH CA 金鑰 使用者或主機憑證 用來簽發 SSH 憑證,適合集中管理大量帳號或主機。 組織使用 CA 私鑰簽發短效使用者憑證,伺服器只需信任 CA 公鑰,不必把每位管理者的公鑰逐一加入 authorized_keys

使用者金鑰確認誰正在登入,主機金鑰確認連到哪一台伺服器,工作階段金鑰負責加密連線內容。SSH CA 則把大量使用者或主機的信任集中到同一個簽發來源。

常用的 SSH 使用者金鑰種類

使用者可以在命令列執行 ssh-keygen 產生一組私鑰與公鑰。-t 選項用來指定金鑰演算法。常見類型如下:

類型 建立指令 優點與限制 使用情境
Ed25519 ssh-keygen -t ed25519 金鑰短、簽章速度快。較舊的用戶端、伺服器或設備可能不支援。 現代 OpenSSH 的一般新部署。
RSA ssh-keygen -t rsa -b 3072 相容性廣,但金鑰與簽章較大。應使用 RSA-SHA2,避免已停用的 SHA-1 ssh-rsa 簽章。 必須連接不支援 Ed25519 的舊設備。
ECDSA ssh-keygen -t ecdsa 金鑰短且速度快。使用 NIST 曲線,要確認兩端支援與組織的密碼政策。 既有環境已採用 ECDSA,或政策指定使用相應曲線。
FIDO 硬體金鑰 ssh-keygen -t ed25519-sk 私密材料保留在硬體中,通常可要求觸碰確認。需要相容硬體與軟體,也要準備替代金鑰。 高權限管理帳號或希望降低私鑰檔案遭複製風險的環境。
DSA 不應建立 ssh-dss 受限於較弱的 1024-bit DSA,現代 OpenSSH 預設停用。 只用於辨識及淘汰舊金鑰,不應為了相容性重新啟用。

Linux 與 OpenSSH 如何讀取金鑰

Linux 核心不負責解析 SSH 金鑰。實際讀取工作由用戶端的 ssh 與伺服器的 sshd 完成:

用戶端
  ├─ ~/.ssh/id_ed25519       私鑰
  ├─ ~/.ssh/id_ed25519.pub   公鑰
  └─ ~/.ssh/known_hosts      曾連線伺服器的主機公鑰

伺服器
  └─ /home/<管理帳號>/.ssh/
       └─ authorized_keys    每一行代表一把允許登入的公鑰

登入時,sshd 先依使用者名稱找到該帳號的家目錄,再讀取 .ssh/authorized_keys,逐行尋找用戶端提出的公鑰。公鑰通常由金鑰類型、Base64 編碼資料與用途註解組成:

authorized_keys 每一行包含金鑰類型、公鑰資料與用途註解

圖(三)authorized_keys 內一筆 SSH 公鑰的三個主要欄位。

用途註解不參與驗證,只協助辨認金鑰。sshd 也會檢查家目錄、.sshauthorized_keys 的所有權及權限。常見設定是 .ssh 使用 700authorized_keys 使用 600,並由該帳號持有。

公鑰驗證如何證明使用者持有私鑰

公鑰驗證開始前,SSH 傳輸層已完成金鑰交換並建立加密通道。接下來的使用者驗證封包都在這條通道內傳送:

SSH 用戶端提交帳號與公鑰,經伺服器接受後再提交私鑰簽章

圖(四)SSH 公鑰驗證的簡化封包往返流程。

前面的公鑰試探不是必要步驟。用戶端也可以直接送出公鑰與簽章。私鑰只在用戶端本機執行簽署,不會傳送到伺服器。

OpenSSH 設定要先驗證再重新載入

公開 SSH 服務至少要限制可登入帳號、驗證方式與不需要的轉送功能:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowAgentForwarding no
X11Forwarding no
PermitTunnel no
GatewayPorts no
MaxAuthTries 3
LoginGraceTime 30
AllowUsers <管理帳號>
設定 用途
PermitRootLogin no 禁止直接使用 root 登入。
PasswordAuthentication no 關閉 SSH 密碼驗證。
KbdInteractiveAuthentication no 關閉鍵盤互動式驗證,包括透過 PAM 提供的密碼或 OTP。
PubkeyAuthentication yes 允許使用公鑰驗證登入。
AllowAgentForwarding no 禁止把用戶端的 SSH 驗證代理程式提供給遠端工作階段。
X11Forwarding no 禁止透過 SSH 轉送 X11 圖形介面。
PermitTunnel no 禁止透過 SSH 建立 TUN/TAP Tunnel。
GatewayPorts no 讓遠端轉送建立的監聽 Port 只綁定伺服器的 Loopback 位址。
MaxAuthTries 3 每條連線最多允許三次驗證嘗試。
LoginGraceTime 30 三十秒內未完成驗證便中斷連線。
AllowUsers <管理帳號> 只允許列出的帳號登入。

這組設定將登入方式收斂為指定帳號的公鑰驗證。未來若要加入 PAM 提供的 OTP,需要重新啟用鍵盤互動式驗證,並使用 AuthenticationMethods 明確要求公鑰與 OTP 都通過。

GatewayPorts no 不會關閉遠端轉送,只限制轉送出的 Port 監聽在哪個位址。ProxyJump 仍需要 TCP Forwarding,下一篇會再使用 AllowTcpForwarding 與 PermitOpen 限制轉送方向與目的地。

設定完成後先執行 sshd -t 檢查語法,再用 sshd -T 檢查展開後的有效值。套用設定前先保持 PVE Console 開啟。完成目的地 NAT 與 WAN 規則後,再由另一個 PowerShell 視窗驗證 opsadmin 金鑰登入。若驗證失敗,可透過 Console 回復 OpenSSH 設定。使用 Reload 使 sshd 套用新設定。

主機防火牆提供第二道入口限制

網路防火牆控制跨區域與外部進入的流量,跳板機上的主機防火牆則限制真正抵達本機的封包。OpenSSH 最後再驗證登入身分與可使用的 SSH 功能。三者分屬不同控制位置:

控制位置 負責範圍
網路防火牆 決定哪些來源可以進入 Bastion DMZ。
跳板機的主機防火牆 決定本機接受哪些通訊協定與服務連接埠。
OpenSSH 驗證帳號與金鑰,並限制轉送、Tunnel 等 SSH 功能。

跳板機的 Input Chain 應採預設丟棄,只接受已建立或相關連線、Loopback、必要的 ICMP 與 TCP 22。Forward Chain 採預設丟棄,避免主機成為路由器。Output Chain 可先依更新與內部管理需求盤點,再逐步收斂。

這種分工讓單一控制失誤不會直接移除全部保護。DNAT 指向錯誤主機、WAN 規則過寬、主機多開一個服務或 OpenSSH 設定偏離時,其他層仍可能阻止連線並留下紀錄。

需要從網際網路進入時,最後才建立公開入口

跳板機的 OpenSSH 與主機防火牆完成後,才判斷管理者的第一段連線要從哪裡進入。本節只適用於需要從網際網路直接抵達跳板機的環境。內部管理網路或 VPN 路徑不需要另外公開 WAN 連接埠。

跳板機使用私有 IPv4 位址時,防火牆以 DNAT 將 WAN 的外部 SSH 連接埠轉送到跳板機:

管理者透過防火牆 WAN TCP 45222 連線,經 DNAT 轉送至跳板機 TCP 22

圖(五)防火牆檢查來源並執行 DNAT,跳板機再由主機防火牆與 sshd 處理連線。

外部入口使用 TCP 45222,可以和防火牆本身或其他 SSH 服務的 TCP 22 分開,也能減少只掃描標準連接埠產生的雜訊。跳板機內部仍監聽標準 TCP 22。更換外部連接埠不能阻止完整的連接埠掃描,也不能取代來源限制、公鑰驗證與安全更新。

DNAT 決定封包要送到哪裡,WAN 過濾規則才決定是否允許通過。OPNsense 的手動 WAN 規則要比對轉換後的跳板機私有位址與 TCP 22。只有 DNAT 而沒有允許規則時,封包仍會被預設拒絕。

若公網 IPv4 位於上游路由器,還要先將外部連接埠轉送到防火牆 WAN,再由防火牆轉送到跳板機。完成後應從真正的外部網路測試完整路徑。

驗證必須同時包含成功與失敗結果

將 SSH 服務公開到網際網路會增加遭到掃描與嘗試登入的機會,因此設定完成後必須進行測試。只證明正確金鑰能登入,無法證明 root、密碼與錯誤金鑰已被拒絕。公開入口完成後至少要確認:

測試 預期結果 主要觀察位置
正確的管理帳號與金鑰 成功 OpenSSH Log、防火牆 State
錯誤金鑰 失敗 OpenSSH Log
密碼登入 失敗 SSH 用戶端與 OpenSSH Log
root 登入 失敗 SSH 用戶端與 OpenSSH Log
未開放的 WAN 連接埠 失敗 防火牆 Log
跳板機上的非 SSH 服務 失敗 主機防火牆 Ruleset/Counter

規則修改後,既有連線可能繼續使用舊 State。重新測試前應只清除與本次外部 SSH 連接埠有關的 State,避免清除全部連線而影響其他服務。

本次 Lab:切換管理出口並建立 SSH 管理入口

這次實作要驗證兩件正文中的核心敘述:Linux 會依路由表選擇封包出口,而且切換管理出口不應改變 Corosync 與 Ceph 的直接連線路徑。SSH 入口由 WAN 規則、目的地 NAT、主機防火牆與 OpenSSH 共同限制。本次以成功與失敗結果作為驗證依據,單次操作時間不列入效能指標。

GitHub 詳細實作文件:Day 15|切換 PVE 出口並部署 jump01

本次實作摘要

  1. 在 OPNsense 建立 PVE 節點所需的 DNS、NTP、更新與內部阻擋規則。
  2. 逐台把 PVE 管理網路的預設閘道與 DNS 切換到 OPNsense,並驗證 Cluster 與 Ceph 未受影響。
  3. 在 Bastion DMZ 建立 jump01,完成 OpenSSH、公鑰驗證與 nftables 強化。
  4. 建立 WAN 端的目的地 NAT 與過濾規則,把 TCP 45222 轉送到 jump01 的 TCP 22
  5. 從 WAN 側執行成功與失敗測試,交叉確認防火牆、OpenSSH 與主機防火牆紀錄。

驗證一:預設出口經過 OPNsense,叢集與儲存路徑維持正常

建立 PVE_NODES Host Alias,內容為 10.77.10.1110.77.10.1210.77.10.13。這三個位址都從 OPNsense 的 LAN 介面進入,因此規則建立在 LAN,順序如下:

PVE_NODES to OPNsense DNS
PVE_NODES ping OPNsense gateway
PVE_NODES outbound NTP
未來明確允許的 PVE 管理或監控流量
Block PVE_NODES to routed internal networks
PVE_NODES HTTP HTTPS updates
Block other PVE_NODES egress
原本 Default allow LAN to any

先允許必要服務,再阻擋其他內部與外部流量。最後一條 Block other PVE_NODES egress 位於原本 LAN Default Allow 上方,確保 PVE 不會落入較廣泛的允許規則。其他尚未盤點的 LAN 管理主機則不會在本次變更中一起斷線。

切換與檢查方式

切換前先備份 /etc/network/interfaces,並記錄 ip routepvecm statuschronyc trackingceph -s。三台節點已在 VLAN-aware vmbr1 上建立 Host VLAN 介面 vmbr1.10,這次只調整閘道:

節點 Management 位址 新預設閘道 DNS
pve01 10.77.10.11/24 10.77.10.1 10.77.10.1
pve02 10.77.10.12/24 10.77.10.1 10.77.10.1
pve03 10.77.10.13/24 10.77.10.1 10.77.10.1

pve01 的 vmbr1.10 使用管理位址與 OPNsense 預設閘道

圖(六)pve01vmbr1.10 使用 10.77.10.11/24,並將預設閘道設為 10.77.10.1

vmbr0192.168.0.x/24 位址暫時保留,但移除 Gateway。每次只 Apply 一台,再執行:

ip route
ip route get 1.1.1.1
ping -c 3 10.77.10.1
getent hosts download.proxmox.com
curl -4I https://download.proxmox.com/
apt update
chronyc tracking
pvecm status
ceph -s

pve01 經 vmbr1.10 與 10.77.10.1 送出預設路由流量

圖(七)路由查詢與連線測試顯示外部流量經 vmbr1.10 送往 10.77.10.1

pve01 切換出口後可更新套件並維持時間同步

圖(八)APT 更新與 Chrony 狀態確認一般對外連線及時間同步均可正常運作。

PVE Cluster 維持三個節點與 Quorate 狀態

圖(九)切換 pve01 後,PVE Cluster 仍維持三個節點並具備 Quorum。

Ceph Cluster 在管理出口切換後維持 HEALTH_OK

圖(十)管理出口切換後,Ceph Cluster 仍維持 HEALTH_OK

預期 ip route get 1.1.1.1 顯示經 10.77.10.1vmbr1.10 送出。確認 OPNsense Live View、Web UI、APT、時間同步、Cluster 與 Ceph 全部正常後,才切換下一台。

圖(七)確認一般對外流量已改走 OPNsense。圖(九)、圖(十)則確認 Quorum 與 Ceph 同時維持正常。因此這組結果能驗證管理出口已完成切換,且沒有連帶中斷既有的叢集與儲存路徑。

若切換失敗,從 L0 Console 暫時恢復舊出口:

ip route replace default via 192.168.0.1 dev vmbr0

這條指令只修改目前執行中的路由。永久回復仍要移除 vmbr1.10 Gateway、恢復 vmbr0 Gateway,並核對變更前備份。

驗證二:jump01 只連接 Bastion DMZ

從 Debian Template 建立 Full Clone,使用 VMID 231、1 vCPU、1 GB RAM 與至少 8 GiB Disk。網卡連到 vmbr1 並設定 VLAN Tag 50,Cloud-Init 設定:

IP:10.77.50.11/24
Gateway:10.77.50.1
DNS:10.77.50.1

jump01 使用一個 vCPU、一 GiB 記憶體、八 GiB 磁碟及 VLAN 50 網卡

圖(十一)jump01 的虛擬硬體與唯一一張 VLAN 50 網卡。

jump01 的 Cloud-Init 帳號、DNS 與固定網路參數

圖(十二)jump01 的 Cloud-Init DNS 與固定網路參數。帳號與驗證欄位保留建置時的畫面狀態。

這張圖只用來驗證 DNS 與固定網路參數。畫面中的 SSH public key: none 與 Password 是建置當時留下的狀態。後續會另外建立 opsadmin 與專用 Ed25519 金鑰,不以這組密碼作為正式登入方式。

jump01 只保留這張 Bastion DMZ vNIC。完成更新後安裝 OpenSSH、Fail2ban、auditd 與 nftables,確認主機名稱、位址、預設路由與 Cloud-Init 狀態。本日的安全驗證範圍為 OpenSSH 與 nftables。Fail2ban 與 auditd 先完成安裝,相關規則留待後續設定。

驗證三:OpenSSH 與主機防火牆限制 jump01 的本機入口

在 Windows PowerShell 產生 jump01 專用金鑰:

$Jump01KeyDirectory = Join-Path $env:USERPROFILE '.ssh\ithome_jump01_ed25519'
$Jump01Key = Join-Path $Jump01KeyDirectory 'id_ed25519'
New-Item -ItemType Directory -Force -Path $Jump01KeyDirectory | Out-Null
ssh-keygen -t ed25519 -a 100 -f $Jump01Key -C 'opsadmin@jump01'
ssh-keygen -lf "${Jump01Key}.pub"
Get-Content "${Jump01Key}.pub" | Set-Clipboard

這組命令會在 Windows 使用者的 .ssh\ithome_jump01_ed25519 目錄建立一組專用 Ed25519 金鑰。可以調整儲存目錄、檔名與金鑰演算法,但不要覆蓋仍在使用的既有私鑰。
沒有 .pub 的檔案是私鑰,只留在管理電腦。將 .pub 的完整一行放入 jump01 的 /home/opsadmin/.ssh/authorized_keys,並設定目錄 700、檔案 600 與正確擁有者。

套用 OpenSSH 強化設定以前,先保持 PVE Console 開啟。依實作文件建立設定後執行:

sudo sshd -t && echo 'sshd_config syntax: OK'
sudo systemctl reload ssh
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|allowusers|allowagentforwarding|x11forwarding|permittunnel|gatewayports|maxauthtries|logingracetime'
sudo stat -c '%U:%G %a %n' /home/opsadmin/.ssh /home/opsadmin/.ssh/authorized_keys

OpenSSH 有效設定與 opsadmin SSH 目錄權限

圖(十三)OpenSSH 設定語法正確,root、密碼及鍵盤互動式驗證均已關閉,公鑰驗證已啟用。opsadmin.sshauthorized_keys 權限分別為 700600

畫面中的 alicebob 是後續多人管理實作加入的帳號,不是 Day15 建立的帳號。這張圖在本篇只用來確認 opsadmin、驗證方式與檔案權限。

檢查 jump01 的 nftables 規則

Input Chain 只允許 established,related、Loopback、ICMP 與 TCP 22。Forward Chain 使用 policy drop。Output Chain 暫時使用 policy accept。載入前先以 nft -c 檢查語法,再啟用 nftables 並列出有效 Ruleset。

要確認 jump01 沒有成為跨 VLAN 路由器,而且本機只監聽預期的 SSH 入口,執行:

sudo sysctl net.ipv4.ip_forward
sudo nft list chain inet filter input
sudo nft list chain inet filter forward
sudo ss -lntp | grep ':22 '

jump01 的 IPv4 轉送、nftables Chain 及 SSH 監聽狀態

圖(十四)IPv4 Forwarding 已關閉。nftables 的 Input Chain 採預設丟棄並允許 TCP 22,Forward Chain 採預設丟棄,sshd 則監聽 IPv4 與 IPv6 的 TCP 22。

畫面中的 TCP 9100 允許規則是後續監控實作加入,不屬於 Day15 的初始規則。

驗證四:目的地 NAT 與 WAN 規則共同建立 SSH 入口

在 OPNsense 建立:

Destination NAT
  WAN address:45222
    → 10.77.50.11:22

WAN Pass Rule
  Source:any(有固定管理來源時改用 Alias)
  Destination:BASTION_HOST/10.77.50.11
  Destination Port:22
  Log:Enabled

Destination NAT 將 WAN TCP 45222 轉送至 10.77.50.11 的 SSH 連接埠

圖(十五)Destination NAT 將防火牆 WAN TCP 45222 轉送至 10.77.50.11:22

WAN Pass Rule 允許流量抵達 BASTION_HOST 的 SSH 連接埠

圖(十六)WAN Pass Rule 比對轉換後的 BASTION_HOST 與 SSH 連接埠。

本 Lab 的 Windows 測試端與 fw01 WAN 位於同一網段,因此這條 WAN 規則要停用 reply-to,並在重新測試前刪除 TCP 45222 的舊 State。正式網際網路或 Multi-WAN 環境的回程路徑不同,不應直接套用這項設定。

若上游路由器持有公網 IPv4,再將上游 TCP 45222 轉送到 fw01 WAN IP,最後使用行動網路或其他真正外部連線完成驗證。

驗證五:正確金鑰成功,其餘登入條件遭到拒絕

從 WAN 側的 Windows PowerShell 執行:

$Jump01Key = Join-Path $env:USERPROFILE '.ssh\ithome_jump01_ed25519\id_ed25519'
$Fw01WanIp = Read-Host '請輸入 fw01 目前顯示的 WAN IP'
ssh -i $Jump01Key -p 45222 -o PasswordAuthentication=no "opsadmin@$Fw01WanIp"

管理者透過防火牆 WAN TCP 45222 使用專用金鑰登入 jump01

圖(十七)正確的管理帳號與專用私鑰可透過 fw01 WAN TCP 45222 登入 jump01

圖(十七)確認正向路徑成立,接著再以四種不符合政策的條件執行負向測試。

root、密碼、錯誤私鑰與未開放連接埠均無法通過 SSH 入口

圖(十八)root、密碼及錯誤私鑰均被 SSH 拒絕,未開放的 TCP 45223 也顯示 TcpTestSucceeded: False

圖(十七)與圖(十八)合計檢查五種條件:正確的 opsadmin 金鑰成功一次,其餘四種不符合政策的條件全部失敗。這組正向與負向結果驗證 WAN 側只有符合帳號、金鑰與連接埠政策的連線能進入 jump01。

Lab 驗證對照

正文敘述 驗證方式 目前結果
Linux 依路由表選擇出口 ip route get 1.1.1.1 vmbr1.10、下一跳 10.77.10.1
管理出口切換不應中斷專用叢集路徑 pvecm statusceph -s 三個節點維持 Quorum,Ceph 為 HEALTH_OK
jump01 只連接 Bastion DMZ PVE Hardware 與 Cloud-Init 一張 VLAN 50 vNIC,位址為 10.77.50.11/24
OpenSSH 與 nftables 共同限制本機入口 sshd -T、檔案權限、sysctl、nftables Chain 與監聽 Socket SSH 與 nftables 符合預期,IPv4 Forwarding 為 0
WAN 規則與目的地 NAT 缺一不可 Destination NAT、WAN 規則與實際 SSH 連線 設定已建立,圖(十七)的連線已經通過完整路徑
身分驗證要同時測試允許與拒絕 正確金鑰、root、密碼、錯誤金鑰與未開放 Port 一項允許成功,四項拒絕全部符合預期

今天完成了什麼

  • 理解 Linux 如何依 RPDB、路由表與最長前綴比對選擇封包出口。
  • 將三台 PVE 的預設閘道與 DNS 逐台切換到 OPNsense,同時確認 Cluster 與 Ceph 維持正常。
  • 在 Bastion DMZ 建立只有一張 vNIC 的 jump01,並建立專用的 Ed25519 管理金鑰。
  • 以 OpenSSH 與 nftables 限制登入方式、可用功能及跳板機接受的流量。
  • 透過目的地 NAT 與 WAN Pass Rule,將 fw01 WAN:45222 轉送到 jump01:22
  • 以五種條件完成正向與負向測試:正確金鑰可以登入,root、密碼、錯誤金鑰與未開放連接埠均遭到拒絕。

下一篇預告

下一篇會在已經安全對外的 jump01 上加入多人管理模型,拆開「可以登入跳板機」、「可以轉送到哪些目標」與「目標主機允許執行哪些操作」,再使用 ProxyJump、無 Shell 帳號與 PermitOpen 實作權限隔離。


參考資料


上一篇
Day 14|從預設拒絕到最小權限:OPNsense 防火牆的別名與規則順序
系列文
從裸機到叢集:以 Proxmox VE、Ceph、OPNsense 與 PostgreSQL HA 建立可驗證的安全私有雲15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言