Rocky Linux 伺服器安全設定指南
新安裝 Rocky Linux 或 AlmaLinux 後的首小時必做事項:執行 dnf update、建立 wheel 帳號、設定 SSH 金鑰、啟用 firewalld 與 SELinux。
新安裝 Rocky Linux 伺服器的首小時作業
若要保護新安裝的 Rocky Linux 伺服器,在安裝任何軟體前需完成六項作業:執行完整的 dnf upgrade、建立屬於 wheel 群組的管理員帳號、僅限金鑰驗證的 SSH、僅開放必要服務的 firewalld 區域、透過 dnf-automatic 進行自動更新,以及保持 SELinux 於 enforcing 模式。以下指令在 AlmaLinux 上同樣適用,因為兩者皆為基於相同 Red Hat Enterprise Linux 原始碼的重建版本。請在仍可透過其他方式存取伺服器的情況下執行這些指令,並在調整 SSH 或防火牆時,務必保持另一個 SSH 連線開啟。
該鎖定哪個 Rocky Linux 版本
本文基於 2026 年 5 月 28 日發布的 Rocky Linux 10.2 編寫,相同的指令亦適用於 Rocky Linux 9 與 AlmaLinux 10。Rocky 10 仍隨附 DNF 4.20 作為 dnf,因此您熟悉的旗標運作方式皆如預期。請在 10 分支上啟動新伺服器,而非 8 分支:8 分支在所有支援的分支中擁有最舊的 Python 與 OpenSSL 版本,每多維護一年,您就得花更多時間繞過這些限制。在信任任何指南(包括本文)之前,請先確認您實際啟動的版本。
cat /etc/rocky-release
uname -r發行版本檔案會顯示類似 Rocky Linux release 10.2 的內容,而 10.2 隨附 6.12 核心。在 AlmaLinux 上,該檔案為 /etc/almalinux-release,且 /etc/os-release 同時存在於兩者中。如果您尚未決定使用哪一個,Rocky Linux 與 AlmaLinux 之間的實際差異 比行銷宣傳的要小,且本頁內容在兩者間並無不同。這兩個發行版之所以存在,是因為 Red Hat 在 2020 年終止了作為下游重建版的 CentOS,如果您仍在考慮是否要在伺服器上使用重建版,閱讀 此家族如何從 Red Hat Linux 演變至 CentOS 再到 Rocky 與 AlmaLinux 是值得的。
在進行任何操作前先更新所有項目
sudo dnf upgrade --refresh -y
sudo dnf install -y dnf-plugins-core
sudo dnf needs-restarting -r--refresh 會捨棄已快取的儲存庫中繼資料。這對於在您開機前數週就已建置好的供應商映像檔至關重要,否則 dnf 會重複使用過時的索引,並在系統並非最新時回報為已更新。接著 needs-restarting -r 會回答後續問題:當核心或核心函式庫有變更時,它會顯示 Reboot is required to fully utilize these updates;若無任何變更,則顯示 Reboot should not be necessary。請立即重新開機,此時機器上並未執行任何服務,且沒有任何使用者依賴此系統。
建立 wheel 群組的管理員帳號
透過 SSH 以 root 身分登入意味著一旦金鑰遭竊,系統將全面失守,且網際網路上的所有掃描器都已鎖定該使用者名稱。請建立一個一般帳號,將其加入 wheel,並透過 sudo 取得 root 權限。
sudo useradd -c 'admin account' deploy
sudo passwd deploy
sudo usermod -aG wheel deploy
id deploy若您的習慣源自 Debian,這兩個 Rocky 的細節可能會讓您感到意外。useradd 在此會自動建立家目錄,因此無需記憶 -m,且 adduser 是指向 useradd 的符號連結,而非 Debian 所提供的互動式腳本。id deploy 必須將 wheel 列入群組清單中。該群組即為授權核心:Red Hat 預設的 /etc/sudoers 包含 %wheel ALL=(ALL) ALL 這一行,因此成員身分即賦予帳號 root 權限,而 sudo grep -n '^%wheel' /etc/sudoers 則證明該行確實已啟用且未被註解。記錄後續透過 sudo 執行的指令同樣重要,稽核伺服器上的使用者指令 一節涵蓋了相關內容。
現在,請在密碼登入功能仍有效時,將您的公開金鑰從本機複製到伺服器。
ssh-copy-id deploy@203.0.113.10
ssh deploy@203.0.113.10執行第二個指令後,您應能進入 shell 而無需輸入密碼。在該工作階段中執行 sudo -v。系統會要求輸入您剛設定的帳號密碼,若 wheel 群組成員身分已生效,則執行後不會有任何輸出。請保持該工作階段開啟。
為何在 Rocky 上金鑰登入失敗,即使檔案看起來正確
ssh-copy-id 能正確設定 SELinux 標籤,因為它以檔案擁有者的身分寫入檔案。手動建立 authorized_keys 往往無法做到這一點,這是 Red Hat 家族特有的陷阱,Ubuntu 並無此問題。若以 root 身分建立 /home/deploy/.ssh,或是從 /tmp 或 /root 複製檔案過來,該檔案會帶有錯誤的 SELinux 標籤。隨後 sshd 會被拒絕讀取該檔案,導致金鑰驗證失敗,且 ls -l 顯示一切正常。
ls -Z /home/deploy/.ssh/authorized_keys
sudo restorecon -Rv /home/deploy/.ssh
sudo ausearch -m AVC -ts recentls -Z 應顯示 ssh_home_t 類型。若檔案顯示為 user_home_t,或在從 /root 複製出來後顯示為 admin_home_t,即為錯誤所在,此時應使用 restorecon 根據原則重新標記。ausearch 會將相符的拒絕訊息列印為 avc: denied { read } 行,並標註 comm="sshd",這是區分 SELinux 問題與一般權限問題的方法。一般權限設定依然適用,儘管 sshd 對權限的要求不如多數指南所稱的那麼嚴格。當 StrictModes 處於預設值 yes 時,只有在檔案、.ssh 或家目錄可由群組或其他使用者寫入,或是擁有者非該使用者或 root 時,才會拒絕該金鑰檔案。在這種情況下,它會將 Authentication refused: bad ownership or modes for file(或 for directory)寫入日誌。權限為 755 的 .ssh 內存放權限為 644 的檔案仍可通過驗證。無論如何,請將目錄設為 700 並將檔案設為 600,這樣系統上的其他帳號便無法讀取您信任的金鑰清單。
以 Rocky Linux 的方式停用 sshd 密碼登入
/etc/ssh/sshd_config 在 Rocky 9 與 10 上,會先載入目錄中的額外設定檔(drop-in files)。
Include /etc/ssh/sshd_config.d/*.confsshd 對於任何關鍵字,只會採用它找到的第一個值。由於 include 指令位於檔案最上方,因此額外設定檔的優先級高於主設定檔;而在多個額外設定檔中,檔名排序在前的優先級較高。供應商與雲端映像檔通常會在該目錄放置一個 50-cloud-init.conf,並將 PasswordAuthentication yes 設為啟用。編號大於 50 的檔案會被該設定靜默覆蓋。請先檢查現有檔案,再建立一個排序更靠前的檔案。
ls -l /etc/ssh/sshd_config.d/
sudo tee /etc/ssh/sshd_config.d/01-hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
EOF
sudo chmod 600 /etc/ssh/sshd_config.d/01-hardening.conf
sudo sshd -tKbdInteractiveAuthentication 是大多數指南遺漏的設定行。PasswordAuthentication no 關閉了標準密碼驗證路徑,但 PAM 的 keyboard-interactive 是通往相同密碼提示的第二條路徑,若未停用,將導致先前的變更失效。sshd -t 會解析設定檔,若語法正確則不會輸出任何訊息。接著請向 daemon 查詢其實際採用的設定,而非僅檢查自己編輯的檔案。
sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication) '這四行設定應與您寫入的內容一致。若 passwordauthentication yes 的結果不符,代表有其他額外設定檔優先級較高,請查看上方的 ls 以確認是哪一個檔案。確認無誤後再重新載入,且務必保持當前的 SSH 連線。
sudo systemctl reload sshd在關閉第一個終端機之前,請先開啟第二個終端機並嘗試登入。若因設定錯誤導致無法連線,復原 VPS 的唯一方式是使用供應商提供的控制台,其操作效率遠低於其他方式。sshd_config 中尚有其他需調整的項目,請參考 強化 VPS 的 SSH 安全性 以完成其餘設定。
僅開啟您所執行的服務 (使用 firewalld)
Rocky 預設已安裝並啟用 firewalld,這與本檢查清單的 Ubuntu 版本不同(Ubuntu 雖有 ufw 但預設為停用)。各供應商提供的映像檔設定不盡相同,請在變更前先確認目前狀態。
sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --list-all--state 會顯示 running 或 not running。標準映像檔的預設區域為 public,而 --list-all 則會列出該區域中允許的服務。ssh 是其中之一,這也是您能登入的原因。請僅加入您實際提供的服務,不要多加其他項目。
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services--permanent 旗標會將設定寫入區域檔案,但不會變更當前運作中的防火牆。若未加上此旗標,規則僅會套用到當前防火牆,並在下次 --reload 或重新開機後失效。忘記使用 --reload 是導致您確認已加入的規則卻未出現在 --list-services 中的常見原因。若您希望先測試再套用,可先不加 --permanent 加入規則,確認服務回應正常後,再執行 sudo firewall-cmd --runtime-to-permanent。區域與豐富規則 (rich rules) 的應用範圍更廣,相關內容請參閱 firewalld VPS 基礎教學。
有一點是伺服器防火牆無法顯示的:大多數供應商會在您的伺服器前端,於其網路層執行第二層封包過濾器。若 firewall-cmd --list-all 顯示連接埠已開啟,但外部連線仍遭拒絕,通常是被該層阻擋,因此在對伺服器進行除錯前,請先檢查供應商的控制面板。
EPEL 與 CRB:僅在套件有需求時啟用
Rocky 的原生儲存庫刻意保持精簡,並由兩個額外儲存庫補足需求。CRB (CodeReady Builder) 儲存庫包含基礎儲存庫所省略的開發標頭檔與函式庫。EPEL (Extra Packages for Enterprise Linux) 則是 Fedora 專案為此系列發行版所建置的社群軟體集,fail2ban 與數千個其他套件皆存放於此。
sudo dnf config-manager --set-enabled crb
sudo dnf install -y epel-release
sudo dnf repolistcrb 是 Rocky 與 AlmaLinux 上的儲存庫識別碼。Rocky 8 將相同的儲存庫稱為 powertools,而在 Red Hat Enterprise Linux 本身則稱為 codeready-builder-for-rhel-10-x86_64-rpms;這就是為何直接複製指令會出現 Error: No matching repo to modify: crb 錯誤的原因。epel-release 套件位於 Rocky 的 extras 儲存庫中,該儲存庫預設已啟用,因此無需手動匯入金鑰。請僅在有需求時才啟用這兩個儲存庫,因為每增加一個額外儲存庫,都會增加自動更新時的來源節點。在 Rocky 與 AlmaLinux 上啟用 EPEL 與 CRB 一文涵蓋了優先級與鎖定套件版本的相關說明。
使用 dnf-automatic 進行自動安全性更新
若伺服器停止接收修補程式,上述所有設定在三週後將毫無意義。Rocky 沒有 unattended-upgrades。其對應工具為 dnf-automatic,僅包含一個設定檔與一個 systemd 計時器,Rocky 10.2 隨附版本為 4.20。
sudo dnf install -y dnf-automatic編輯 /etc/dnf/automatic.conf。以下關鍵設定決定了執行行為。
[commands]
upgrade_type = default
random_sleep = 3600
download_updates = yes
apply_updates = yes
reboot = never
[emitters]
emit_via = stdioapply_updates 在預設安裝的檔案中為 no。這是本節最常見的陷阱:安裝套件並啟用計時器後直接離開,機器每天早上只會下載更新,卻不會安裝任何一個。請將其設為 yes,隨後檢查執行結果以確認是否生效。
sudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timer
journalctl -u dnf-automatic.service --since -7dlist-timers 應在隔天顯示 NEXT 時間,若執行失敗或未執行任何動作,請查看 journal 以了解原因。有兩個細節容易出錯。該套件同時隨附了 dnf-automatic-install.timer、dnf-automatic-download.timer 與 dnf-automatic-notifyonly.timer,這些單元會以其固定的行為覆蓋您的設定檔,因此請僅啟用 dnf-automatic.timer,否則您編輯的設定檔將被忽略。
第二個細節是 upgrade_type。將其設為 security 聽起來是謹慎的選擇,但在重建發行版上這反而風險較高,因為它會根據隨套件發布的諮詢元資料 (updateinfo.xml) 進行篩選,而 Rocky 的元資料在某些分支上曾被回報為過時。在正式依賴此功能前,請務必先在您的機器上進行測試。
sudo dnf updateinfo list --available --security若系統有待更新項目但清單為空,代表元資料未將任何項目標記為安全性修復,因此 upgrade_type = security 將不會安裝任何東西。default 會升級所有項目,在企業穩定分支上,這通常是一組規模較小且經過充分測試的變更。在 Rocky 與 AlmaLinux 上執行 dnf-automatic 涵蓋了發送器、重新開機設定以及如何保留特定套件版本的方法。
在僅限金鑰驗證的伺服器上,是否需要暴力破解防護?
在啟用 PasswordAuthentication no 與 KbdInteractiveAuthentication no 的情況下,SSH 暴力破解攻擊無法成功,因為沒有密碼可供猜測。此時剩下的問題僅是日誌雜訊,以及拒絕連線時消耗的少量 CPU 資源。這是在小型伺服器上使用 fail2ban 的合理理由:它能讓 journalctl -u sshd 恢復可讀性。若該伺服器上執行了任何使用密碼驗證的服務,則此需求會變得更加迫切。
fail2ban 來自 EPEL 儲存庫,因此請先啟用該儲存庫。Rocky 10 將會取得 1.1.0 版本。
sudo dnf install -y fail2ban-server fail2ban-firewalld fail2ban-selinux fail2ban-systemdfail2ban-firewalld 是此處關鍵的子套件。若未安裝,fail2ban 會使用 iptables 指令執行封鎖;在啟用 firewalld 的系統上,這會導致兩個工具在互不知情的情況下同時寫入相同的 nftables 規則集。fail2ban-selinux 提供了必要的 SELinux 政策模組,讓 daemon 在 SELinux 維持 enforcing 模式下正常運作。預設不會啟用任何 jail,且 jail.conf 會在套件更新時被覆寫,因此請將您的設定放置在同目錄下的獨立檔案中。
sudo tee /etc/fail2ban/jail.d/sshd.local >/dev/null <<'EOF'
[sshd]
enabled = true
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshdbackend = systemd 會讀取 journal 而非 /var/log/secure,這是在最小化映像檔上的正確選擇,因為 journal 始終存在,而 log 檔案僅在安裝 rsyslog 時才會產生。fail2ban-client status sshd 應會顯示包含 filter 與 action 區段的 jail 設定,以及一份初始為空的封鎖位址清單。在擁有公開 IP 的伺服器上,該清單很快就會填入資料。請使用 sudo firewall-cmd --list-rich-rules 確認封鎖規則確實已寫入防火牆。請將 bantime 設定為以小時為單位的時間長度,而非天數,並將您自己的固定 IP 位址加入至同檔案中的 ignoreip,因為設定錯誤的 jail 第一個鎖定的對象通常就是您自己。
保持 SELinux 為 enforcing 模式,以及變更連接埠所需的 semanage 操作
網路上關於 Rocky 最常見的建議就是將 SELINUX=disabled 設為 disabled 並重新開機。請勿這樣做。選擇此系列發行版而非 Ubuntu 的主要原因之一就是 SELinux,其內建的原則是針對這些儲存庫中的軟體所編寫,且 nginx 或 podman 的預設安裝在該原則下執行時,無需進行任何修改。Docker 是常見的例外,因為它來自這些儲存庫之外,且其綁定掛載(bind mounts)在您標記它們之前會被拒絕,這也是 在 Rocky 或 AlmaLinux 上安裝 Docker 一文花費最多篇幅說明的部分。請先確認您目前的狀態。
getenforce
sudo sestatusgetenforce 應顯示 Enforcing。部分供應商提供的映像檔會預設為 Permissive,這只會記錄拒絕存取事件而不會阻擋任何動作,因此請直接讀取該數值,切勿預設。當發生故障時,拒絕存取的紀錄早已為您寫入。
sudo ausearch -m AVC -ts recent在初期系統強化過程中,唯一會觸發原則限制的情況是將 SSH 從 22 埠移出。sshd 原則僅允許綁定標記為 ssh_port_t 的連接埠,而 22 是唯一帶有該標記的連接埠。若未進行其他設定直接修改 Port 2222,SSH daemon 將無法啟動,並會在 journalctl -u sshd 中產生以下錯誤:
error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.解決方法只需一道指令,外加安裝提供該指令的工具。
sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reloadsemanage 在 Rocky 10 中並非預設安裝,因此大多數人遇到的第一個錯誤是 semanage: command not found,而非任何提及 SELinux 的訊息。包含在驗證新連接埠運作正常前保持 22 埠開啟的完整操作流程,請參閱 透過 SELinux 與 firewalld 變更 SSH 連接埠。關於 context、boolean 以及當您安裝的服務觸發原則限制時該如何處理,伺服器 SELinux 基礎 有更深入的說明。
在小型 VPS 上可省略的項目
並非所有項目都適合放在單一台小型機器上。
- 維持 SELinux 為 enforcing 模式。保持預設狀態不會消耗額外資源,且上述的
semanage指令已涵蓋您在初期最可能遇到的情況。 - 維持
dnf-automatic並搭配apply_updates = yes。未修補的伺服器才是真正會導致系統故障的原因。 - 若伺服器僅監聽 SSH 埠且僅限金鑰登入,可省略
fail2ban。它雖能減少日誌雜訊,但代價是多執行一個 daemon,且增加將自己鎖在門外的風險。systemctl status fail2ban可顯示該單位的記憶體用量,讓您評估其在您機器上的資源成本。 - 除非有套件需求,否則無須啟用 EPEL 與 CRB。啟用軟體庫是關於更新來源的長期決策。
- 省略更改 SSH 埠的步驟。這僅能減少日誌中的掃描雜訊,無法阻擋任何刻意針對您伺服器的攻擊者。
唯一絕對不能省略的是最枯燥的步驟:在修改 SSH 或防火牆設定時,務必保持另一個 SSH 連線開啟,並在需要之前學會如何使用服務供應商提供的 serial console。若您習慣使用 Debian 或 Ubuntu,dnf 與 apt 指令對照表能協助您快速建立肌肉記憶,而 Ubuntu 的 unattended-upgrades 則是在該系統上執行相同任務的工具。本清單的發行版通用版本為 新 VPS 的前十分鐘設定,而 VPS 上的最小權限使用者帳號 則進一步探討了比 wheel 成員更深入的帳號管理議題。
FAQ
我應該在 Rocky Linux 伺服器上停用 SELinux 嗎?
不應該。拒絕存取(denial)是一則訊息,它會指出策略未預期的檔案或連接埠。請使用 sudo ausearch -m AVC -ts recent 閱讀該訊息,接著使用 restorecon 修復標籤,或設定服務所需的 boolean 值。若必須放寬限制,請在除錯期間將 /etc/selinux/config 中的 SELINUX=permissive 設為 permissive,這會記錄拒絕事件但不會阻擋任何動作。請避免使用 SELINUX=disabled,因為停用的系統會停止維護檔案標籤,導致日後恢復 enforcing 模式時,必須在下次開機時對磁碟進行完整的重新標籤(relabel)。
如果 SSH 僅限金鑰登入,我還需要 fail2ban 嗎?
SSH 本身不需要。當 PasswordAuthentication no 與 KbdInteractiveAuthentication no 已設定,並在 sudo sshd -T 中確認後,暴力破解攻擊因沒有密碼可猜測,無論嘗試多少次皆無法成功。此時 fail2ban 能為您帶來的是更乾淨的日誌,並稍微減少處理拒絕連線所消耗的 CPU。一旦伺服器上有其他服務接受密碼(例如郵件伺服器或網頁應用程式登入),執行 fail2ban 就變得有意義。
為什麼以 root 建立 .ssh 目錄後,金鑰登入會失敗?
因為該檔案帶有錯誤的 SELinux 標籤,導致 sshd 被拒絕讀取。請使用 ls -Z /home/deploy/.ssh/authorized_keys 檢查。類型應為 ssh_home_t,而以 root 建立或從 /root 複製出來的檔案通常會顯示為 admin_home_t。請執行 sudo restorecon -Rv /home/deploy/.ssh 根據策略重新標籤。使用 sudo ausearch -m AVC -ts recent 確認診斷結果,它會印出一行包含 comm="sshd" 的 avc: denied { read } 訊息。同時請檢查擁有權與一般權限。sshd 會拒絕任何群組或其他使用者可寫入,或由其他使用者擁有的路徑,但將目錄設為 700、檔案設為 600 是最安全的選擇。
Rocky Linux 上有什麼可以取代 unattended-upgrades?
是 dnf-automatic,透過 sudo dnf install -y dnf-automatic 安裝,並由 /etc/dnf/automatic.conf 加上 dnf-automatic.timer 驅動。請在 [commands] 區段中設定 apply_updates = yes,因為預設值為 no,否則計時器將會持續下載更新而不進行安裝。請僅啟用 dnf-automatic.timer,不要啟用其他單元,因為該套件提供的額外計時器會以其固定的行為覆蓋您的設定檔。
我應該在新伺服器上使用 Rocky Linux 8 嗎?
請優先選擇 10 系列,若您依賴的軟體尚未提供 10 的建置版本,則選擇 9。Rocky 8 搭載了支援版本中最舊的 Python 與 OpenSSL,導致越來越多新軟體不再提供對應的套件,最終您將被迫在原本想保持單純的機器上從原始碼編譯,或加入第三方儲存庫。請使用 cat /etc/rocky-release 檢查執行中的系統版本,因為供應商標示為 "Rocky Linux" 的映像檔,有時版本比控制面板顯示的還要舊。