2026 年遠端 Mac sshd 主機金鑰輪換:UpdateHostKeys、Ed25519 遷移、雙金鑰窗口與 CI known_hosts 不中斷決策指南
合規審計、映像重建或淘汰老舊 RSA-2048 時,遠端 Mac 上的 OpenSSH 伺服器必須有節奏地輪換主機金鑰。若只改伺服器端而不動 CI 裡已固定的 known_hosts,深夜的 rsync 會集體撞上 REMOTE HOST IDENTIFICATION HAS CHANGED——這不是「安全機制太嚴」,而是變更管理缺了一半。本文把 UpdateHostKeys、Ed25519 遷移、雙金鑰並存窗口與 GitHub Actions 同步寫成可執行的 Runbook,並串聯站內 known_hosts 固定、ControlMaster 與 OIDC 部署 長文。
目錄
為何 2026 年仍要在遠端 Mac 上主動輪換主機金鑰
痛點一:把輪換當成「重裝意外」處理。團隊在 macOS 小版本升級、硬體替換或還原 Time Machine 後,才發現 sshd 已生成全新 /etc/ssh/ssh_host_*,而《known_hosts 決策》裡的指紋仍是三年前那組。此時流水線紅燈會被誤判為「網路抖動」,浪費一整晚 on-call 頻寬在查 rsync 參數。
痛點二:ControlPersist 長連線掩蓋輪換。《ControlMaster》讓多個 rsync 共用已驗證會話;伺服器已換鍵而舊 master 仍活著時,表面能傳、斷開後才集體失敗。輪換窗口應主動清控制路徑或縮短 ControlPersist。
伺服器端:macOS sshd 的 HostKey 清單與 Ed25519 遷移
Apple 隨系統提供的 sshd_config 通常已宣告多個 HostKey 路徑。輪換時不要直接覆寫正在使用的私鑰檔,應以新檔名生成、更新設定、驗證後再封存舊檔。Ed25519 主機金鑰長度短、驗證快,適合作為 2026 年的預設;RSA 可在過渡期保留以供舊客戶端或合規掃描工具讀取。
# 受控維運終端機(非 CI Runner)
sudo ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
sudo shasum -a 256 /etc/ssh/ssh_host_ed25519_key.pub
# 確認 sshd_config 含 HostKey /etc/ssh/ssh_host_ed25519_key
sudo launchctl kickstart -k system/com.openssh.sshd
重載後用離線第二條路徑採集指紋(例如從帶外管理網執行 ssh-keyscan -p 22 -t ed25519),並與 ssh-keygen -lf 對讀。切勿在 GitHub Actions 首次連線時才把新指紋寫進 Secret——那會把 TOFU 交給 Runner 當次網路路徑。
UpdateHostKeys:只服務人類維運路徑,不取代 CI 固定
OpenSSH 8.x 起的 UpdateHostKeys 允許客戶端在伺服器提供新主機金鑰時,依策略更新本機 known_hosts。對工程師筆電可設 UpdateHostKeys ask 或 accept-new,降低輪換當晚「逐台刪 known_hosts 行」的摩擦。
對 CI 則相反:必須維持《known_hosts 固定》中的 StrictHostKeyChecking=yes 與獨立 UserKnownHostsFile。Runner 磁碟每次清空,沒有「累積信任」可言;自動更新只會把不可稽核的變更藏進單次 Job。正確做法是把核准後的指紋片段放 GitHub Secrets,在 Job 開頭寫入 ~/.ssh/ci_known_hosts。
雙金鑰窗口:先擴客戶端,再收斂伺服器
推薦時間線分三階段。(1)T0:伺服器同時載入舊 RSA 與新 Ed25519,對外仍優先協商兩者。(2)T0→T1:在 Secrets、本機維運 known_hosts、監控探針中並列兩行指紋,跑一輪完整 CI(含 rsync 與 sftp 批次)。(3)T1 之後:確認無舊客戶端依賴後,從 sshd_config 移除舊 HostKey 行並刪除 Secret 中的過期行。
窗口長度建議以最長發佈週期 + 週末批次估算:若每週五才有全量建置,至少保留跨一個週末的雙指紋。對《ControlMaster》環境,在 T0 當天排程一次「無 master 的探針 Job」,強制新握手讀到新鍵。
CI known_hosts:讓流水線在輪換期保持綠燈
# Secret SSH_KNOWN_HOSTS 範例(同一 hostname 兩行,輪換後刪舊行)
[build-mac.example.com]:22 ssh-ed25519 AAAA...old...
[build-mac.example.com]:22 ssh-ed25519 AAAA...new...
export RSYNC_RSH='ssh -o BatchMode=yes -o StrictHostKeyChecking=yes \
-o UserKnownHostsFile=$HOME/.ssh/ci_known_hosts'
把「主機金鑰變更」納入與《OIDC》憑證輪換同一套發佈審查:審查表欄位應含 hostname、舊指紋、新指紋、Secrets PR、預計 T1 收斂日、是否影響跳板。合併 Secrets 後先跑唯讀探針(ssh -G + 空命令或 rsync --dry-run),再開放上傳閘門。
決策矩陣:輪換策略怎麼選
| 策略 | 適用 | CI 影響 | 風險 |
|---|---|---|---|
| 週末一刀切換鍵 | 實驗單機 | 全紅直至改 Secret | 高;無回滾 |
| 雙 HostKey + 雙指紋 Secret | 正式遠端 Mac | 可無停機 | 低;需收斂日曆 |
| 僅依 UpdateHostKeys | 人類筆電 | 不適用 Runner | CI 不可稽核 |
| 輪換期暫改 accept-new | 緊急救火 | 短期可綠 | MITM 窗擴大 |
閱讀順序:本文 → known_hosts 固定 → ControlMaster → OIDC → 完整性/原子發佈專文。
FAQ 與 SFTPMAC 收束
問:輪換後只有亞太 Job 失敗?答:查區域 DNS 與 Secret 前綴是否不一致;或該區 Runner 仍快取舊 Control 路徑。
問:能否用 ssh-keyscan 自動修 Secret?答:僅作為受控腳本在維運堡壘機上跑,輸出進 PR 由人審;不要嵌入無人值守 Workflow。
問:bastion 與目標 Mac 同時輪換?答:逐 hop 更新 Secret 區塊;ProxyJump 鏈上任何一跳指紋過期都會在子連線階段失敗,日誌卻只顯示最末跳 hostname。
總結:主機金鑰輪換是伺服器、人類客戶端與 CI 三端同步的變更;UpdateHostKeys 與雙金鑰窗口分工明確,流水線才能在 Ed25519 遷移後仍可信且可稽核。
自建遠端 Mac 需自行維護 HostKey、Secrets 與 on-call;《SFTPMAC 託管伺服器》可把指紋庫、變更窗口與 Apple 原生建置入口寫進套餐 Runbook,讓團隊把頻寬留給產物。查看 方案與首頁。