熱門分類
載入中…
目錄0%

🔐 Linux 伺服器防禦第一線:SSH 安全加固、MFA 二階段驗證與 Fail2Ban 實戰

    🔐 Linux 伺服器防禦第一線:SSH 安全加固、MFA 二階段驗證與 Fail2Ban 實戰

    如果你的 Linux 伺服器有對外開 SSH,那它幾乎一定每天都在被掃描、被撞密碼、被嘗試弱口令。 真正能「長期穩定」扛住第一線的做法,不是只做單點設定,而是把三件事串起來: SSH 本體硬化MFA(二階段驗證)Fail2Ban 自動封鎖

    這篇會用「能直接上線」的角度,把設定拆成可複製的段落:你照著做完,SSH 的攻擊面會立刻縮小一大截。


    ✅ 目標與建議路線

    項目 建議設定 目的
    登入方式 只允許 SSH Key(必要時加 MFA) 直接砍掉「密碼被猜到」這條路
    帳號與來源 限制 AllowUsers / AllowGroups,必要時限制來源 IP 減少可被嘗試的範圍
    MFA 使用 TOTP(Google Authenticator / Authy / 其他 OTP App) 就算私鑰外洩也多一道門
    暴力破解防護 Fail2Ban 封鎖失敗登入 IP(含 systemd journal 模式) 把機器人打到「自己放棄」
    實務提醒: 做 SSH hardening 前,請先保持「第二個 SSH 連線」或「主控台/ILO/IPMI」可用,避免改錯設定把自己鎖在門外。

    1) SSH 基礎安全加固(sshd_config)

    以下以常見路徑 /etc/ssh/sshd_config 為主。每次修改後,先做語法檢查再 reload。

    # 1) 先做語法檢查(很重要)
    sudo sshd -t
    
    # 2) 再做 reload(比 restart 安全)
    sudo systemctl reload sshd

    1-1. 關掉 root 直接登入 + 關掉密碼登入

    # /etc/ssh/sshd_config
    
    # 禁止 root 直接登入(建議用一般帳號 + sudo)
    PermitRootLogin no
    
    # 關掉密碼登入(核心防線)
    PasswordAuthentication no
    
    # 啟用金鑰登入(通常預設就開)
    PubkeyAuthentication yes
    
    # 需要 PAM(後面要做 MFA 會用到)
    UsePAM yes

    如果你有「必須暫時保留密碼登入」的場景,至少也要把允許範圍縮到最小(例如只允許內網、或只允許特定帳號), 等你確認 Key + MFA 都穩了,再把密碼通道關掉。

    1-2. 限制可登入的帳號 / 群組

    # 只允許這些使用者登入(範例)
    AllowUsers admin ops
    
    # 或用群組控管(更好維護)
    # AllowGroups sshusers

    1-3. 縮短嘗試窗口、降低撞門效率

    # 降低暴力破解效率(依需求調整)
    MaxAuthTries 3
    LoginGraceTime 20
    
    # 保活(避免長連線卡住;也能降低某些資源佔用)
    ClientAliveInterval 60
    ClientAliveCountMax 2

    1-4. 可選:改 Port(降低掃描雜訊)

    # 可選:改成高位 Port(不是核心安全,但可降雜訊)
    Port 2222

    如果你改了 Port,記得同步調整防火牆(firewalld/ufw/nftables)與 Fail2Ban jail 的 port 設定。


    2) 加上 MFA(二階段驗證):TOTP(PAM Google Authenticator 模組)

    這裡示範「最常見、部署成本最低」的 TOTP:手機 OTP App 掃 QR code 後,每 30 秒產生一次碼。 你也可以換成 Duo、硬體金鑰或公司既有 IdP,但概念相同:把 SSH 的驗證拆成兩道門

    2-1. 安裝套件

    Debian / Ubuntu:

    sudo apt update
    sudo apt install -y libpam-google-authenticator

    RHEL / Rocky / Alma(常見作法是啟用 EPEL):

    # 先啟用 EPEL(若你環境已啟用可略)
    sudo dnf install -y epel-release
    
    # 安裝 Google Authenticator PAM
    sudo dnf install -y google-authenticator

    2-2. 對要登入的帳號產生 secret(每個帳號都要做一次)

    # 用「該使用者」身分執行(不要用 root 代跑)
    google-authenticator

    跑完後會得到 QR code 與備援碼,請立即存到安全位置(例如密碼管理器)。 OTP 若失效,通常是時間不同步造成的,伺服器務必維持 NTP 正常。

    2-3. 設定 PAM:/etc/pam.d/sshd

    # /etc/pam.d/sshd
    # 加在適當位置(通常在 @include common-auth 之前/附近)
    auth required pam_google_authenticator.so

    你也可以加上參數(例如允許小幅時間漂移、或允許沒有 secret 的帳號先不套用),但建議上線時採「嚴格」策略。

    2-4. 設定 sshd:強制「Key + OTP」,不要再要密碼

    重點是兩句:KbdInteractiveAuthentication yesAuthenticationMethods。 這會讓流程變成:先驗證 SSH Key,再跳出 OTP(keyboard-interactive)挑戰。

    # /etc/ssh/sshd_config
    
    UsePAM yes
    PasswordAuthentication no
    
    # 啟用鍵盤互動(OTP 走這條)
    KbdInteractiveAuthentication yes
    
    # 強制同時通過:publickey + keyboard-interactive(OTP)
    AuthenticationMethods publickey,keyboard-interactive

    套用前請先保留一個已登入的 SSH 連線窗口,並用另一個終端測試登入成功後再 reload sshd。


    3) Fail2Ban:把暴力破解「自動封鎖」

    Fail2Ban 會分析登入失敗的紀錄(log 或 systemd journal),當某個 IP 在指定時間內失敗次數過多,就自動下防火牆規則封鎖。 你可以把它想成「針對撞門行為的自動反制」。

    3-1. 安裝 Fail2Ban

    Debian / Ubuntu:

    sudo apt update
    sudo apt install -y fail2ban

    RHEL / Rocky / Alma:

    sudo dnf install -y fail2ban
    sudo systemctl enable --now fail2ban

    3-2. 建議用 jail.d/ 自訂(避免覆寫)

    建立一個專門管 SSH 的檔案:

    sudo mkdir -p /etc/fail2ban/jail.d
    sudo nano /etc/fail2ban/jail.d/sshd.local

    範例(偏通用、可直接用):

    # /etc/fail2ban/jail.d/sshd.local
    
    [DEFAULT]
    # 若系統主要用 systemd journal,建議直接用 systemd backend
    backend = systemd
    
    # 忽略白名單(把你的管理來源 IP / VPN 出口加進來)
    ignoreip = 127.0.0.1/8
    
    # 失敗統計窗口(10 分鐘內)
    findtime = 10m
    
    # 允許失敗次數
    maxretry = 5
    
    # 封鎖時間(可用 10m/1h/1d 這種格式)
    bantime  = 6h
    
    # 依你的系統選擇 banaction(iptables 或 nftables)
    # banaction = iptables-multiport
    # 若你的系統以 nftables 為主,可改 nftables(不同發行版 action 名稱可能略有差異)
    # banaction = nftables
    
    [sshd]
    enabled = true
    # 若你改 Port,這裡也要跟著改
    port = ssh
    # Debian/Ubuntu 常見 logpath(若你不用 journal)
    # logpath = /var/log/auth.log
    # RHEL 系常見 logpath(若你不用 journal)
    # logpath = /var/log/secure

    3-3. 啟動並檢查狀態

    sudo systemctl enable --now fail2ban
    sudo fail2ban-client status
    sudo fail2ban-client status sshd

    看到 Banned IP list 就表示 jail 正常工作。你也可以直接看 Fail2Ban 自己的 log(多數環境預設在 /var/log/fail2ban.log)。

    3-4. 常用操作:解封、手動封鎖、查被封鎖清單

    # 查看 sshd jail 狀態
    sudo fail2ban-client status sshd
    
    # 解封指定 IP
    sudo fail2ban-client set sshd unbanip 203.0.113.10
    
    # 手動封鎖(少用,但排障時會用到)
    sudo fail2ban-client set sshd banip 203.0.113.10

    4) 上線前最後檢查(我通常會照這份跑)

    # SSH 設定語法檢查
    sudo sshd -t
    
    # 重新載入(不要急著 restart)
    sudo systemctl reload sshd
    
    # 檢查 SSH 監聽(Port 是否正確)
    sudo ss -lntp | grep sshd
    
    # 測試:用另一個終端登入(確認流程是 Key -> OTP)
    ssh -p 2222 admin@your.server
    
    # Fail2Ban 是否啟用、sshd jail 是否啟用
    sudo systemctl status fail2ban --no-pager
    sudo fail2ban-client status sshd

    5) 進階加分(選做,但很值得)

    • 只允許管理網段: 在防火牆 / 雲端 Security Group 限制來源 IP,SSH 不要放全世界。
    • 分層管理: 一般帳號登入 + sudo;嚴禁共用帳號;把可登入名單縮到最小。
    • 金鑰治理: 強制使用者用密碼管理器保存私鑰 passphrase;定期盤點 authorized_keys。
    • 告警與稽核: Fail2Ban 封鎖事件可做寄信/推送;sshd LogLevel 可視需求調高。

    💬 留言聊聊:你的 SSH 防護做到哪一層?

    我很想知道你目前的環境是:

    • ✅ 只用 SSH Key?還是仍保留密碼登入?
    • ✅ 有加 MFA(二階段驗證)嗎?是 TOTP、Duo,還是硬體金鑰?
    • ✅ Fail2Ban 你是用 logpath 還是 systemd journal?bantime / findtime 怎麼設?

    也歡迎直接貼你的 sshd_config(敏感資訊遮掉)或 Fail2Ban jail 設定,我可以幫你一起檢查是否有風險洞。

    延伸閱讀

    🔗 分享這篇 LINE Facebook X

    沒有留言:

    字級