背景與問題
SSH(Secure Shell)是 Linux 系統(tǒng)遠程管理的首選協(xié)議,幾乎所有服務器的遠程管理都依賴 SSH。從簡單的命令行登錄到文件傳輸(SFTP)、端口轉(zhuǎn)發(fā)、遠程命令執(zhí)行,SSH 是運維工程師每天都要使用的核心工具。
然而,SSH 默認配置存在安全隱患:默認端口 22 面臨大量暴力破解攻擊;允許密碼認證容易被暴力破解或密碼泄露;允許 root 直接登錄風險極高;SSH 密鑰默認沒有設(shè)置過期機制。 另一方面,很多運維人員在配置 SSH 安全策略時過于激進,禁用了所有登錄方式或刪除了所有備份方法,結(jié)果在網(wǎng)絡波動或配置失誤時把自己鎖在系統(tǒng)外面。
本文詳細講解 SSH 的安全配置方法,同時提供防止把自己鎖在系統(tǒng)外面的保障措施。內(nèi)容包括 SSH 協(xié)議原理、認證方式配置、密鑰管理、網(wǎng)絡層防護、配置文件詳解、常見錯誤分析和應急恢復方法。
1 SSH 協(xié)議基礎(chǔ)
1.1 SSH 協(xié)議版本
SSH 有兩個主要版本:SSHv1 和 SSHv2。目前 SSHv1 已完全廢棄,所有現(xiàn)代系統(tǒng)都使用 SSHv2。SSHv2 相比 SSHv1 有顯著的安全改進,包括更強的加密算法(AES、ChaCha20)、完整的密鑰交換協(xié)議(Diffie-Hellman)、支持公鑰認證和證書。
查看 SSH 版本:
# 查看 SSH 客戶端版本 ssh -V # 查看 SSH 服務器版本 sshd -V # 測試 SSH 連接使用的協(xié)議版本 ssh -1 user@host # 應該失敗 ssh -2 user@host # 使用 SSHv2
1.2 SSH 連接過程
SSH 連接建立分為幾個階段:首先是 TCP 握手建立連接;然后是協(xié)議版本交換;接著是密鑰交換階段(Diffie-Hellman 或 ECDH);然后是服務器認證(服務器證明自己的身份);然后是用戶認證(密碼、公鑰或其他方式);最后是會話建立,可以執(zhí)行命令。
理解這個過程有助于排查 SSH 連接問題:
# 詳細查看 SSH 連接過程 ssh -vvv user@host # 輸出分為三段:debug1(連接和密鑰交換)、debug2(認證過程)、debug3(會話建立)
1.3 SSH 密鑰類型
現(xiàn)代 SSH 支持多種密鑰類型:RSA 是最廣泛支持的類型,推薦使用 4096 位;Ed25519 是現(xiàn)代算法,安全性和性能都很好,推薦使用;ECDSA 依賴曲線參數(shù),不同實現(xiàn)可能存在兼容性問題。
生成 SSH 密鑰:
# 生成 RSA 密鑰(2048 位,兼容性好) ssh-keygen -t rsa -b 4096 -C"your_email@example.com" # 生成 Ed25519 密鑰(推薦,性能好,密鑰短) ssh-keygen -t ed25519 -C"your_email@example.com" # 生成 ECDSA 密鑰 ssh-keygen -t ecdsa -b 521 -C"your_email@example.com" # 指定密鑰存放位置 ssh-keygen -t ed25519 -f ~/.ssh/my_server_key -C"my_server" # 添加密碼保護 ssh-keygen -t ed25519 -o -a 100 -C"your_email@example.com" # -o 參數(shù)使用 OpenSSH 新格式(更安全) # -a 參數(shù)指定密鑰推導次數(shù),越高越安全但越慢
2 SSH 服務器配置
2.1 配置文件位置
SSH 服務器配置文件位于/etc/ssh/sshd_config,客戶端配置位于~/.ssh/config。本文重點講解服務器端配置。
配置文件的語法規(guī)則:使用空格分隔的鍵值對;以#開頭的是注釋;空行被忽略;每個配置項一行。
# 查看默認配置 man sshd_config # 查看當前生效的配置 sshd -T # 檢查配置語法(不實際重啟服務) sshd -t # 測試配置文件并顯示會生效的配置 sshd -T -C user=root,host=localhost,addr=127.0.0.1
2.2 核心安全配置項
以下配置項直接影響 SSH 的安全性:
# 編輯 SSH 服務器配置 vim /etc/ssh/sshd_config # 建議的配置: # 1. 更改默認端口(減少自動化攻擊) Port 2222 # 2. 禁用 SSHv1(已廢棄,不安全) Protocol 2 # 3. 監(jiān)聽特定地址(如果有多個網(wǎng)卡,指定只監(jiān)聽內(nèi)網(wǎng)) ListenAddress 0.0.0.0 # 或只監(jiān)聽特定 IP ListenAddress 192.168.1.1 # 4. 禁用空密碼 PermitEmptyPasswords no # 5. 禁用密碼認證(強烈推薦,使用密鑰認證) PasswordAuthentication no ChallengeResponseAuthentication no # 6. 禁用 root 直接登錄 PermitRootLogin no # 7. 限制允許登錄的用戶 AllowUsers admin deploy@192.168.1.0/24 AllowGroups sshusers # 8. 禁用 hosts.equiv 和 .rhosts IgnoreRhosts yes HostbasedAuthentication no # 9. 禁用 GSSAPI 認證(減少攻擊面) GSSAPIAuthentication no # 10. 啟用公鑰認證 PubkeyAuthentication yes # 11. 設(shè)置空閑超時 ClientAliveInterval 300 ClientAliveCountMax 2 # 12. 設(shè)置登錄嘗試限制(配合 Fail2Ban 使用) MaxAuthTries 3 MaxSessions 10 # 13. 設(shè)置空閑連接斷開時間 LoginGraceTime 30 # 14. 禁用用戶環(huán)境 PermitUserEnvironment no # 15. 禁用 .rhosts 文件 IgnoreUserKnownHosts yes # 16. 打印 motd(可選) PrintMotd no # 17. 禁用 TCP 轉(zhuǎn)發(fā) DisableForwarding yes # 18. 禁用 X11 轉(zhuǎn)發(fā)(如果不是必要) X11Forwarding no # 19. 限制子系統(tǒng)(如 SFTP) Subsystem sftp internal-sftp -l INFO # 20. 配置 SFTP 用戶的 chroot Match Group sftpusers ChrootDirectory /var/sftp ForceCommand internal-sftp AllowTcpForwarding no X11Forwarding no
2.3 編輯完配置后驗證
修改 SSH 配置后,必須驗證配置正確才能重啟服務:
# 1. 檢查配置語法 sshd -t # 2. 如果沒有錯誤輸出,說明語法正確 # 3. 查看會生效的配置(詳細) sshd -T | grep -E"^passwordauthentication|^permitrootlogin|^pubkeyauthentication" # 4. 重啟 SSH 服務 systemctl restart sshd systemctl restart ssh # 5. 確認服務狀態(tài) systemctl status sshd
3 公鑰認證配置
3.1 公鑰認證原理
公鑰認證基于非對稱加密:客戶端持有私鑰,公鑰放在服務器上;登錄時,客戶端用自己的私鑰簽名一段隨機數(shù)據(jù);服務器用對應的公鑰驗證簽名;驗證通過則允許登錄。
優(yōu)點:不會被暴力破解(私鑰無法通過猜測獲得);無需在網(wǎng)絡中傳輸密碼;可以禁用密碼認證,消除密碼泄露風險;私鑰可以設(shè)置密碼保護。
3.2 配置服務器接受公鑰認證
# 服務器端配置 # /etc/ssh/sshd_config PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys # 限制 authorized_keys 文件的權(quán)限 # 服務器端應確保 # .ssh 目錄權(quán)限 700 # authorized_keys 文件權(quán)限 600
3.3 用戶端配置和管理
# 生成密鑰對 ssh-keygen -t ed25519 # 將公鑰復制到服務器(最簡單的方式) ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host # 手動復制公鑰 cat ~/.ssh/id_ed25519.pub | ssh user@host"mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" # 服務器端設(shè)置權(quán)限 ssh user@host"chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys" # 驗證權(quán)限是否正確 ssh user@host"ls -la ~/.ssh/"
3.4 管理 authorized_keys
# 查看用戶的 authorized_keys
ssh user@host"cat ~/.ssh/authorized_keys"
# 添加多個公鑰(可以是不同用戶、不同機器的)
ssh user@host"cat >> ~/.ssh/authorized_keys"< ~/.ssh/new_key.pub
# 從 authorized_keys 中刪除某個公鑰
ssh user@host?"grep -v 'ssh-rsa AAAAB3...' ~/.ssh/authorized_keys > /tmp/auth_keys && mv /tmp/auth_keys ~/.ssh/authorized_keys"
# 批量管理腳本
#!/bin/bash
# 添加多個用戶的公鑰到同一個賬號
AUTH_KEYS_FILE="$HOME/.ssh/authorized_keys"
USER_KEYS_DIR="$HOME/.ssh/user_keys"
mkdir -p"$USER_KEYS_DIR"
# 為每個用戶創(chuàng)建子目錄
foruserinalice bob charlie;do
mkdir -p"$USER_KEYS_DIR/$user"
done
# 合并所有公鑰(包含注釋區(qū)分來源)
{
echo"# Alice's keys"
cat"$USER_KEYS_DIR/alice/"*.pub 2>/dev/null
echo"# Bob's keys"
cat"$USER_KEYS_DIR/bob/"*.pub 2>/dev/null
} >"$AUTH_KEYS_FILE"
4 防止把自己鎖在系統(tǒng)外面
4.1 修改 SSH 配置前的準備工作
修改 SSH 配置前,必須確保不會把自己鎖在外面。正確的操作順序:
第一步,創(chuàng)建一個備份會話。在修改配置前,先開一個 SSH 會話并保持不退出。這個會話作為緊急恢復通道。
第二步,備份原配置文件:
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d) cp /etc/ssh/sshd_config /root/sshd_config.backup
第三步,使用sshd -t驗證配置語法:
sshd -t # 如果沒有輸出,說明語法正確
第四步,準備遠程恢復方法。如果有控制臺訪問(云平臺的控制臺、IPMI、iLO、DRAC),確??梢赃h程登錄。記錄下控制臺登錄信息。
4.2 分步修改配置
不要一次性做多個修改,每次只改一個,確認生效后再改下一個:
# 步驟一:只修改端口,保持其他配置不變 # 編輯 /etc/ssh/sshd_config Port 2222 # 驗證并重啟 sshd -t && systemctl restart sshd # 用新端口測試連接(保持舊會話不退出) ssh -p 2222 user@host # 確認新端口工作正常后,再進行下一步
4.3 使用 ansible 或腳本批量修改
批量修改多臺服務器的 SSH 配置時,使用配置管理工具可以減少出錯概率:
# ansible 批量修改 SSH 配置
ansible all -i inventory -m lineinfile
-a"path=/etc/ssh/sshd_config
regexp='^Port'
line='Port 2222'"
# 驗證配置
ansible all -i inventory -mcommand-a"sshd -t"
# 重啟服務
ansible all -i inventory -m systemd -a"name=sshd state=restarted"
4.4 設(shè)置 PermitRootLogin 的正確順序
禁用 root 登錄是高風險操作,必須確保有替代方案:
# 第一步:創(chuàng)建替代的 sudo 用戶 useradd -m -s /bin/bash admin usermod -aG sudo admin # 第二步:為該用戶配置 SSH 公鑰登錄 ssh-copy-id admin@host # 第三步:測試該用戶能否 sudo 到 root ssh admin@host sudo -i # 第四步:確認可以 sudo 后,再禁用 root 登錄 # 編輯 /etc/ssh/sshd_config PermitRootLogin no # 第五步:保留一個可用的 root 登錄方式(物理控制臺或帶外管理)
4.5 使用 Fail2Ban 防護暴力破解
Fail2Ban 可以自動封禁多次登錄失敗的 IP:
# 安裝 Fail2Ban apt-get install fail2ban # Debian/Ubuntu yum install fail2ban # RHEL/CentOS # 配置 Fail2Ban cat > /etc/fail2ban/jail.local <
4.6 緊急恢復方法
如果不幸被鎖在系統(tǒng)外面,按以下步驟恢復:
方法一:通過控制臺登錄(云服務器)
大多數(shù)云平臺提供網(wǎng)頁版控制臺,可以直接用 root 或其他用戶登錄,然后修復 SSH 配置。
方法二:通過云平臺的用戶數(shù)據(jù)腳本
某些云平臺支持在實例啟動時執(zhí)行用戶數(shù)據(jù)腳本,可以用來修復 SSH 配置。
方法三:通過修改啟動參數(shù)進入單用戶模式
重啟服務器,在 GRUB 菜單按e編輯啟動參數(shù),在linux行末尾添加single或init=/bin/bash,以單用戶模式啟動,然后掛載根分區(qū)為可寫,修復 SSH 配置。
方法四:通過云平臺的"救援模式"
大多數(shù)云平臺提供救援模式,可以從 ISO 啟動,掛載原系統(tǒng)磁盤,修改 SSH 配置。
# 以 DigitalOcean 為例 # 1. 在控制臺創(chuàng)建快照 # 2. 從快照創(chuàng)建新 droplet,選救援模式 # 3. 掛載原磁盤 mount /dev/vda1 /mnt # 4. 編輯 SSH 配置 vim /mnt/etc/ssh/sshd_config # 5. 卸載磁盤 umount /mnt # 6. 從原快照創(chuàng)建新 droplet
5 密鑰管理最佳實踐
5.1 密鑰存儲和權(quán)限
# 密鑰文件權(quán)限(非常重要) # 私鑰權(quán)限必須是 600 chmod 600 ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_rsa # 公鑰可以是 644 chmod 644 ~/.ssh/id_ed25519.pub # .ssh 目錄權(quán)限必須是 700 chmod 700 ~/.ssh # 服務器端 authorized_keys 權(quán)限必須是 600 chmod 600 ~/.ssh/authorized_keys # 用戶目錄不能讓其他人有寫權(quán)限 chmod go-w ~/
5.2 密鑰輪換策略
定期更換密鑰是良好的安全習慣:
# 創(chuàng)建新密鑰 ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_2024 -C"rotation 2024" # 在服務器端添加新公鑰 ssh user@host"cat >> ~/.ssh/authorized_keys"< ~/.ssh/id_ed25519_2024.pub # 測試新密鑰可以登錄 ssh -i ~/.ssh/id_ed25519_2024 user@host # 確認新密鑰工作后,從 authorized_keys 中移除舊公鑰 ssh user@host?"grep -v 'old_key_comment' ~/.ssh/authorized_keys > /tmp/auth && mv /tmp/auth ~/.ssh/authorized_keys" # 本地刪除舊私鑰 mv ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.old
5.3 使用 SSH Agent 轉(zhuǎn)發(fā)
SSH Agent 可以緩存解密后的私鑰,避免重復輸入密碼:
# 啟動 SSH Agent eval"$(ssh-agent -s)" # 添加密鑰到 Agent ssh-add ~/.ssh/id_ed25519 # 查看 Agent 中的密鑰 ssh-add -l # 密鑰轉(zhuǎn)發(fā)(從跳板機跳轉(zhuǎn)到內(nèi)網(wǎng)機器,保留密鑰訪問能力) # 在 .ssh/config 中配置 Host jump-server HostName jumphost.example.com User admin Port 2222 ForwardAgent yes # 或者使用 -A 參數(shù) ssh -A admin@jumphost.example.com
5.4 使用 config 文件管理多服務器
# ~/.ssh/config 示例 # 可以為每個服務器定義獨立的配置 # 默認配置 Host * Port 2222 IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 300 ServerAliveCountMax 2 StrictHostKeyChecking ask # 生產(chǎn)服務器 Host prod-* HostName %h.example.com User admin ForwardAgent no LogLevel INFO # 跳板機 Host jump HostName jumphost.example.com User admin Port 2222 ForwardAgent yes # 數(shù)據(jù)庫服務器(只能從跳板機訪問) Host db-1 HostName 192.168.1.100 User dbadmin ProxyJump jump LocalForward 3306 127.0.0.1:3306 # 免密碼快捷登錄 Host github HostName github.com User git IdentityFile ~/.ssh/github_ed25519
6 連接問題排查
6.1 常見連接錯誤及解決
錯誤一:Connection refused
# 檢查 SSH 服務是否運行 systemctl status sshd # 檢查端口是否監(jiān)聽 ss -tlnp | grep sshd netstat -tlnp | grep sshd # 檢查防火墻規(guī)則 iptables -L -n | grep 22 ufw status firewall-cmd --list-all
錯誤二:Permission denied
# 檢查用戶名是否正確 ssh user@host # 檢查密鑰是否正確配置 ssh -vvv user@host # 查看詳細認證過程 # 檢查服務器日志 tail -f /var/log/auth.log journalctl -u sshd -f # 客戶端指定密鑰 ssh -i ~/.ssh/specific_key user@host
錯誤三:Connection timeout
# 檢查網(wǎng)絡連通性 ping -c 4 host traceroute host # Linux tracert host # Windows # 檢查端口是否可達 nc -zv host 22 telnet host 22 # 檢查是否有 ACL 限制 ssh -b bind_ip user@host
6.2 查看詳細連接日志
# 客戶端查看詳細日志 ssh -vvv user@host # 服務器端查看實時日志 tail -f /var/log/auth.log journalctl -u sshd -f # 調(diào)試 SSH 握手 ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 user@host
6.3 檢查 SSH 服務狀態(tài)
# 查看服務狀態(tài) systemctl status sshd # 查看監(jiān)聽端口 ss -tlnp | grep sshd # 測試本地 SSH 連接 ssh localhost # 檢查 SELinux 上下文(RHEL/CentOS) getsebool -a | grep ssh setsebool -P ssh_sysadm_login on
7 完整的 SSH 安全加固腳本
#!/bin/bash # ssh_hardening.sh - SSH 安全加固腳本 set-euo pipefail BACKUP_DIR="/root/ssh_backups" mkdir -p"$BACKUP_DIR" backup_config() { cp /etc/ssh/sshd_config"${BACKUP_DIR}/sshd_config.$(date +%Y%m%d_%H%M%S)" echo"Backup created in$BACKUP_DIR" } verify_sudo() { if["$(id -u)"-ne 0 ];then echo"This script must be run as root" exit1 fi } verify_admin_user() { if! id admin &>/dev/null;then echo"Creating admin user..." useradd -m -s /bin/bash admin usermod -aG sudo admin fi if[ ! -f"/home/admin/.ssh/authorized_keys"];then echo"WARNING: admin user has no SSH keys configured!" echo"Please add your public key to /home/admin/.ssh/authorized_keys before continuing" read-p"Press Enter to continue anyway..." fi } apply_config() { cat > /etc/ssh/sshd_config <<'EOF' # SSH Server Configuration Port 2222 Protocol 2 ListenAddress 0.0.0.0 # Authentication PermitRootLogin no PubkeyAuthentication yes PasswordAuthentication no ChallengeResponseAuthentication no PermitEmptyPasswords no MaxAuthTries 3 LoginGraceTime 30 # Security IgnoreRhosts yes HostbasedAuthentication no ?PermitUserEnvironment no PrintMotd no TCPKeepAlive yes # Idle timeout ClientAliveInterval 300 ClientAliveCountMax 2 # Disable unused features X11Forwarding no AllowTcpForwarding no PermitTunnel no AllowAgentForwarding no # SFTP configuration Subsystem sftp internal-sftp -l INFO # Override for SFTP users Match Group sftpusers ? ? ChrootDirectory /var/sftp ? ? ForceCommand internal-sftp ? ? AllowTcpForwarding no ? ? X11Forwarding no EOF ? ??echo?"Configuration applied" } set_permissions() { ? ? chmod 644 /etc/ssh/sshd_config ? ??# 確保 admin 用戶目錄權(quán)限正確 ? ? chown -R admin:admin /home/admin/.ssh ? ? chmod 700 /home/admin/.ssh ? ? chmod 600 /home/admin/.ssh/authorized_keys } verify_config() { ? ??echo?"Verifying configuration..." ? ? sshd -t &&?echo?"Configuration syntax OK" } restart_service() { ? ??echo?"Restarting SSH service..." ? ? systemctl restart sshd ? ? systemctl status sshd --no-pager } main() { ? ??echo?"SSH Security Hardening Script" ? ??echo?"============================" ? ? verify_sudo ? ? verify_admin_user ? ? backup_config ? ? apply_config ? ? set_permissions ? ? verify_config ? ??echo?"" ? ??echo?"IMPORTANT: Keep your current SSH session open!" ? ??echo?"Test a new connection before closing this session!" ? ??echo?"" ? ??read?-p?"Restart SSH service now? (yes/no): "?confirm ? ??if?[?"$confirm"?=?"yes"?];?then ? ? ? ? restart_service ? ? ? ??echo?"SSH service restarted. Please test a new connection." ? ??else ? ? ? ??echo?"Service restart skipped. Run 'systemctl restart sshd' manually when ready." ? ??fi } main?"$@"
8 結(jié)論
SSH 安全配置需要在安全性和可用性之間取得平衡。過度限制的配置可能導致自己無法登錄,合理的安全配置應該既能防止攻擊,又能保證管理員正常訪問。
核心安全配置建議:更改默認端口減少自動化攻擊;禁用密碼認證,使用公鑰認證;禁用 root 直接登錄,使用 sudo;配置 Fail2Ban 防止暴力破解;定期輪換 SSH 密鑰。
防止把自己鎖在外面的關(guān)鍵:在修改配置前先備份;保持一個不退出 SSH 會話作為恢復通道;分步驟修改配置,每步確認后再進行下一步;使用控制臺或帶外管理作為最終恢復手段。
-
Linux
+關(guān)注
關(guān)注
88文章
11824瀏覽量
219610 -
服務器
+關(guān)注
關(guān)注
14文章
10376瀏覽量
91777 -
端口
+關(guān)注
關(guān)注
4文章
1113瀏覽量
34052 -
SSH
+關(guān)注
關(guān)注
0文章
201瀏覽量
17826
原文標題:SSH 安全配置怎么做,才能既安全又不把自己鎖在門外?
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
如何實現(xiàn)SSH服務器?
VScode終端ssh連接不到Linux服務器問題
服務器集群系統(tǒng)實現(xiàn)方案詳解
以色列政府DNS服務器存在著Open SSH安全漏洞
ssh如何上傳文件到服務器
Linux上保護 SSH 服務器連接的方法
在Linux上保護SSH服務器連接的8種方法
Linux上建立SSH安全連接的10種方法
輕量服務器怎么搭建ssh?
深入解析SSH協(xié)議,輕松實現(xiàn)安全高效的服務器管理
如何配置Linux防火墻和Web服務器
SSH 遠程連接內(nèi)網(wǎng) Linux 服務器
詳解SSH服務器的安全配置方法
評論