国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

SSH安全加固與免密登錄實戰指南

馬哥Linux運維 ? 來源:馬哥Linux運維 ? 2026-02-09 15:17 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

SSH安全加固與免密登錄

一、概述

1.1 背景介紹

線上服務器被暴力破解SSH密碼的事每個月都在發生。我們團隊去年處理過一起安全事件,一臺測試機用了默認22端口加弱密碼,48小時內被植入挖礦程序,CPU跑滿導致同網段業務受影響。事后復盤發現/var/log/secure里有超過20萬次失敗登錄記錄,全是字典攻擊。

SSH是Linux服務器遠程管理的核心通道,OpenSSH默認配置偏向兼容性而非安全性——允許root登錄、允許密碼認證、監聽22端口。這些默認值在公網環境下等于敞開大門。生產環境必須做SSH加固,這不是可選項,是基線要求。

本篇覆蓋端口修改、認證方式切換、密鑰管理、fail2ban防護、證書認證等完整加固鏈路,所有配置均在CentOS 7/8/9和Ubuntu 20.04/22.04上線上驗證過。

1.2 技術特點

基于非對稱加密的身份認證:SSH密鑰登錄使用公私鑰對,私鑰不離開客戶端,服務端只存公鑰。即使服務端被入侵,攻擊者拿到的公鑰無法反推私鑰。ed25519算法密鑰長度僅68字節,比RSA-4096的800+字節短得多,簽名驗證速度快約30%。

支持多種認證方式靈活組合:密碼認證、公鑰認證、證書認證、GSSAPI認證、鍵盤交互認證,可以通過AuthenticationMethods指令組合使用。比如要求"公鑰+密碼"雙因素,配置為AuthenticationMethods publickey,password。

細粒度訪問控制:通過AllowUsers、AllowGroups、DenyUsers、DenyGroups四個指令控制誰能登錄,配合Match塊可以針對特定用戶、IP、端口設置不同策略。比如允許運維組從跳板機登錄,禁止其他所有來源。

1.3 適用場景

場景一:公網服務器加固。云主機直接暴露在公網,每天承受大量掃描和暴力破解。實測一臺新開的阿里云ECS,開機2小時內就有來自全球的SSH登錄嘗試。必須改端口+禁密碼+上fail2ban三件套。

場景二:多人運維團隊密鑰管理。團隊10+人需要登錄上百臺服務器,用密碼管理不現實。通過SSH密鑰+跳板機+ProxyJump實現統一入口管理,人員離職時只需在跳板機刪除公鑰。

場景三:自動化運維免密通道。Ansible、SaltStack等自動化工具依賴SSH免密登錄批量執行命令。CI/CD流水線部署也需要SSH免密推送代碼到目標機器。密鑰認證是自動化的基礎。

1.4 環境要求

組件 版本要求 說明
操作系統 CentOS 7+/Ubuntu 20.04+ RHEL系和Debian系均適用,配置路徑一致
OpenSSH 7.4+ 7.4開始支持ed25519密鑰,8.0+支持證書認證增強
fail2ban 0.10+ 用于防暴力破解,EPEL源或apt直接安裝
firewalld/iptables 系統自帶 用于限制SSH訪問來源IP
Python 3.6+ fail2ban依賴,CentOS 7需手動安裝python3

二、詳細步驟

2.1 準備工作

2.1.1 系統檢查

# 檢查系統版本
cat /etc/os-release

# 檢查當前SSH版本,低于7.4的建議升級
ssh -V

# 檢查SSH服務狀態
systemctl status sshd

# 檢查當前SSH監聽端口和連接數
ss -tlnp | grep ssh

# 檢查當前登錄的SSH會話,確認自己的連接信息
who -u

# 查看最近的SSH登錄失敗記錄,評估當前風險
# CentOS/RHEL
grep"Failed password"/var/log/secure | tail -20

# Ubuntu/Debian
grep"Failed password"/var/log/auth.log | tail -20

重要提醒:修改SSH配置前,務必保持當前SSH會話不斷開,同時開一個新終端測試。配置改錯了當前會話還能用來恢復,斷開就只能去機房或用VNC了。我們團隊的規矩是改SSH配置必須兩人操作,一人改一人保持連接。

2.1.2 安裝依賴

# CentOS/RHEL 安裝
sudo yum install -y epel-release
sudo yum install -y fail2ban fail2ban-systemd openssh-server openssh-clients

# Ubuntu/Debian 安裝
sudo apt update
sudo apt install -y fail2ban openssh-server openssh-client

# 確認fail2ban版本
fail2ban-client --version

2.1.3 備份原始配置

# 備份SSH配置,帶日期方便回溯
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d)

# 備份PAM相關SSH配置
sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.bak.$(date +%Y%m%d)

# 驗證備份
ls -la /etc/ssh/sshd_config.bak.*

2.2 核心配置

2.2.1 修改SSH監聽端口

默認22端口是所有掃描器的第一目標。改成高位端口不能防住定向攻擊,但能過濾掉99%的自動化掃描。實測改端口后,/var/log/secure里的失敗登錄記錄從每天幾萬條降到個位數。

# 編輯SSH配置文件
sudo vim /etc/ssh/sshd_config

# 找到#Port22,改為:
Port 52222

SELinux環境額外操作(CentOS/RHEL默認開啟SELinux):

# 檢查SELinux狀態
getenforce

# 如果是Enforcing,需要添加端口到SELinux策略
sudo semanage port -a -t ssh_port_t -p tcp 52222

# 驗證端口已添加
sudo semanage port -l | grep ssh
# 輸出應包含:ssh_port_t  tcp  52222, 22

防火墻放行新端口

# firewalld(CentOS 7+)
sudo firewall-cmd --permanent --add-port=52222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

# 或者iptables(舊系統)
sudo iptables -A INPUT -p tcp --dport 52222 -j ACCEPT
sudo iptables -D INPUT -p tcp --dport 22 -j ACCEPT
sudo service iptables save

# Ubuntu UFW
sudo ufw allow 52222/tcp
sudo ufw status

這個地方有個坑:先放行新端口再改配置重啟sshd,順序反了會把自己鎖在外面。

2.2.2 禁用Root直接登錄

root賬戶是暴力破解的首要目標,因為攻擊者知道每臺Linux都有root用戶,只需要猜密碼。禁用root登錄后,攻擊者還得猜用戶名,難度指數級上升。

# /etc/ssh/sshd_config 中修改
PermitRootLogin no

配套操作:確保有一個sudo權限的普通用戶可用。

# 創建運維用戶
sudo useradd -m -s /bin/bash opsadmin
sudo passwd opsadmin

# 加入wheel組(CentOS)或sudo組(Ubuntu)
# CentOS
sudo usermod -aG wheel opsadmin

# Ubuntu
sudo usermod -aG sudo opsadmin

# 驗證sudo權限
su - opsadmin
sudo whoami
# 輸出應為 root

2.2.3 禁用密碼認證,僅允許密鑰登錄

密碼認證的問題:再復雜的密碼也可能被社工、釣魚、撞庫搞到。密鑰認證從原理上杜絕了暴力破解——私鑰文件不在網絡上傳輸,服務端只做簽名驗證。

# /etc/ssh/sshd_config 中修改
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
PubkeyAuthentication yes

這個參數改錯了會導致所有用密碼登錄的人立刻無法連接,改之前確認密鑰登錄已經配好并測試通過。我見過不止一次有人先禁密碼后配密鑰,結果把自己鎖在外面。

2.2.4 配置訪問白名單

# /etc/ssh/sshd_config 中添加
# 只允許特定用戶登錄
AllowUsers opsadmin deployer monitor

# 或者只允許特定組登錄(二選一,不要同時配)
# AllowGroups sshusers ops-team

說明:AllowUsers和AllowGroups是白名單機制,配置后不在名單里的用戶全部拒絕。如果用AllowUsers,新增運維人員時記得加到這個列表里,否則加了賬號也登不上。我們團隊的做法是用AllowGroups sshusers,新人加入sshusers組就行,不用每次改sshd_config。

# 創建SSH用戶組
sudo groupadd sshusers

# 將允許登錄的用戶加入組
sudo usermod -aG sshusers opsadmin
sudo usermod -aG sshusers deployer

2.2.5 設置登錄超時和重試限制

# /etc/ssh/sshd_config 中修改
LoginGraceTime 30
MaxAuthTries 3
MaxSessions 5
MaxStartups 1060
ClientAliveInterval 300
ClientAliveCountMax 3

參數說明

LoginGraceTime 30:用戶30秒內必須完成認證,否則斷開。默認120秒太長了。

MaxAuthTries 3:單次連接最多嘗試3次認證。超過后斷開連接,配合fail2ban效果更好。

MaxSessions 5:單個連接最多5個會話復用。

MaxStartups 1060:當未認證連接數達到10個時,以30%概率拒絕新連接;達到60個時100%拒絕。防止連接洪水攻擊。

ClientAliveInterval 300:每300秒(5分鐘)發一次心跳探測。

ClientAliveCountMax 3:連續3次心跳無響應則斷開,即15分鐘無響應自動斷開。

2.2.6 SSH密鑰對生成

# 推薦使用ed25519算法
# ed25519比RSA-4096更安全,密鑰更短,簽名更快
ssh-keygen -t ed25519 -C"opsadmin@company.com"-f ~/.ssh/id_ed25519

# 如果目標系統OpenSSH版本低于6.5,不支持ed25519,退而求其次用RSA-4096
ssh-keygen -t rsa -b 4096 -C"opsadmin@company.com"-f ~/.ssh/id_rsa

# 查看生成的密鑰
ls -la ~/.ssh/
# id_ed25519   私鑰文件,權限必須是600
# id_ed25519.pub 公鑰文件,權限644即可

關于密鑰密碼(passphrase)

生產環境的個人密鑰建議設置passphrase,防止私鑰文件泄露后被直接使用

自動化場景(Ansible、CI/CD)的密鑰不設passphrase,否則每次執行都要輸密碼

設了passphrase的密鑰可以用ssh-agent緩存,避免反復輸入

# 啟動ssh-agent并添加密鑰
eval$(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519
# 輸入passphrase后,當前會話內不再需要重復輸入

# 查看已加載的密鑰
ssh-add -l

2.2.7 免密登錄配置

# 方法一:ssh-copy-id(推薦,自動處理權限)
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 52222 opsadmin@192.168.1.100

# 方法二:手動復制(ssh-copy-id不可用時)
cat ~/.ssh/id_ed25519.pub | ssh -p 52222 opsadmin@192.168.1.100"mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# 測試免密登錄
ssh -p 52222 opsadmin@192.168.1.100

# 如果登錄失敗,用verbose模式排查
ssh -vvv -p 52222 opsadmin@192.168.1.100

權限要求(這個是最常見的坑):

# 服務端權限必須嚴格設置,多一個權限都不行
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

# 家目錄權限不能大于755
chmod 755 ~

# 檢查文件屬主
ls -la ~/.ssh/
# 所有文件的owner必須是當前用戶,不能是root

StrictModes yes(默認開啟)會檢查這些權限,權限不對直接拒絕密鑰認證,而且日志里只寫Authentication refused: bad ownership or modes,不告訴你具體哪個文件有問題。

2.2.8 SSH Config配置多主機管理

管理幾十上百臺服務器時,記IP和端口不現實。SSH Config文件可以給每臺機器起別名,配置不同的連接參數。

# 編輯客戶端配置文件
vim ~/.ssh/config
# 全局默認配置
Host *
  ServerAliveInterval 60
  ServerAliveCountMax 3
  AddKeysToAgent yes
  IdentitiesOnly yes
  Compression yes

# 跳板機
Host jump
  HostName 203.0.113.10
  Port 52222
  User opsadmin
  IdentityFile ~/.ssh/id_ed25519

# 通過跳板機訪問內網Web服務器
Host web-prod-01
  HostName 10.0.1.11
  Port 22
  User deployer
  IdentityFile ~/.ssh/id_ed25519
  ProxyJump jump

Host web-prod-02
  HostName 10.0.1.12
  Port 22
  User deployer
  IdentityFile ~/.ssh/id_ed25519
  ProxyJump jump

# 數據庫服務器,限制只用特定密鑰
Host db-prod-*
  Port 22
  User dbadmin
  IdentityFile ~/.ssh/id_ed25519_db
  ProxyJump jump

Host db-prod-01
  HostName 10.0.2.21

Host db-prod-02
  HostName 10.0.2.22

# 測試環境,直連
Hosttest-*
  Port 52222
  User opsadmin
  IdentityFile ~/.ssh/id_ed25519

Hosttest-web-01
  HostName 192.168.100.11

Hosttest-db-01
  HostName 192.168.100.21
# 配置好后直接用別名連接
ssh web-prod-01
ssh db-prod-01

# scp也能用別名
scp app.jar web-prod-01:/opt/app/

# rsync同樣支持
rsync -avz ./dist/ web-prod-01:/var/www/html/

說明:IdentitiesOnly yes這個參數很關鍵。不加的話ssh會把~/.ssh/下所有密鑰都試一遍,如果密鑰多了,試到第3個還沒成功就會被MaxAuthTries 3攔住,報Too many authentication failures。加了這個參數后只用指定的密鑰文件。

2.2.9 配置fail2ban防暴力破解

fail2ban監控SSH日志,發現短時間內多次登錄失敗就自動封禁IP。實測效果:部署后暴力破解嘗試從每天5萬+降到0(因為攻擊IP在第5次嘗試后就被ban了)。

# 創建SSH專用的fail2ban配置
sudo vim /etc/fail2ban/jail.local
[DEFAULT]
# 封禁時間3600秒(1小時),慣犯會遞增
bantime = 3600
# 在600秒(10分鐘)內
findtime = 600
# 失敗5次就封禁
maxretry = 5
# 封禁動作:firewalld或iptables
banaction = firewallcmd-ipset
# 如果用iptables,改為:
# banaction = iptables-multiport

# 忽略的IP(運維跳板機IP,防止把自己封了)
ignoreip = 127.0.0.1/8 10.0.0.0/8 192.168.1.0/24

[sshd]
enabled = true
port = 52222
filter = sshd
logpath = /var/log/secure
# Ubuntu用這個路徑:
# logpath = /var/log/auth.log
maxretry = 3
bantime = 7200
findtime = 300
# 啟動fail2ban
sudo systemctl start fail2ban
sudo systemctlenablefail2ban

# 查看SSH jail狀態
sudo fail2ban-client status sshd

# 輸出示例:
# Status for the jail: sshd
# |- Filter
# | |- Currently failed: 2
# | |- Total failed:   156
# | `- File list:    /var/log/secure
# `- Actions
#  |- Currently banned: 3
#  |- Total banned:   47
#  `- Banned IP list:  185.234.xx.xx 103.145.xx.xx 45.148.xx.xx

# 手動解封某個IP(比如同事輸錯密碼被封了)
sudo fail2ban-clientsetsshd unbanip 192.168.1.50

# 手動封禁某個IP
sudo fail2ban-clientsetsshd banip 1.2.3.4

2.2.10 SSH證書認證(CA簽發方式)

密鑰認證的問題:每臺服務器的authorized_keys都要維護,100臺服務器就是100份。人員變動時要逐臺刪除。SSH證書認證用CA統一簽發,服務端只信任CA,不需要維護每臺機器的authorized_keys。

# 1. 生成CA密鑰對(在CA服務器上操作,通常是跳板機)
ssh-keygen -t ed25519 -f /etc/ssh/ca_user_key -C"SSH User CA"

# 2. 將CA公鑰分發到所有服務器
# 在每臺服務器的 /etc/ssh/sshd_config 中添加:
TrustedUserCAKeys /etc/ssh/ca_user_key.pub

# 3. 把CA公鑰復制到服務器
sudo scp /etc/ssh/ca_user_key.pub target-server:/etc/ssh/ca_user_key.pub

# 4. 為用戶簽發證書
# -s 簽發者標識
# -I 證書ID(用于審計日志)
# -n 允許登錄的用戶名列表
# -V 有效期(+52w表示52周)
ssh-keygen -s /etc/ssh/ca_user_key 
  -I"opsadmin-cert-20250101"
  -n opsadmin,deployer 
  -V +52w 
  /home/opsadmin/.ssh/id_ed25519.pub

# 生成的證書文件:/home/opsadmin/.ssh/id_ed25519-cert.pub

# 5. 查看證書信息
ssh-keygen -L -f /home/opsadmin/.ssh/id_ed25519-cert.pub

# 6. 用戶使用證書登錄(自動識別,無需額外配置)
ssh -p 52222 opsadmin@192.168.1.100

證書吊銷

# 生成吊銷列表
ssh-keygen -k -f /etc/ssh/revoked_keys -s /etc/ssh/ca_user_key /path/to/revoked_cert.pub

# 在sshd_config中配置吊銷列表
RevokedKeys /etc/ssh/revoked_keys

# 重載配置
sudo systemctl reload sshd

2.3 啟動和驗證

2.3.1 配置檢查和重載

# 檢查配置文件語法(改完必做,語法錯誤會導致sshd無法啟動)
sudo sshd -t
# 沒有輸出表示語法正確,有錯誤會顯示具體行號

# 用調試模式檢查配置
sudo sshd -T | head -50

# 重載配置(不斷開現有連接)
sudo systemctl reload sshd

# 如果reload不生效,再restart(會斷開所有連接)
# sudo systemctl restart sshd

# 確認服務狀態
sudo systemctl status sshd

2.3.2 功能驗證

# 1. 驗證端口變更(新開終端測試,不要斷開當前連接)
ssh -p 52222 opsadmin@服務器IP

# 2. 驗證root登錄已禁用
ssh -p 52222 root@服務器IP
# 預期輸出:Permission denied (publickey).

# 3. 驗證密碼登錄已禁用
ssh -p 52222 -o PubkeyAuthentication=no opsadmin@服務器IP
# 預期輸出:Permission denied (publickey).

# 4. 驗證密鑰登錄正常
ssh -p 52222 -i ~/.ssh/id_ed25519 opsadmin@服務器IP
# 預期:直接登錄成功

# 5. 驗證fail2ban工作
# 故意用錯誤密碼嘗試幾次(在測試環境操作)
sudo fail2ban-client status sshd

# 6. 驗證端口監聽
ss -tlnp | grep 52222
# 預期輸出:LISTEN 0 128 *:52222 *:* users:(("sshd",pid=xxxx,fd=3))

2.3.3 回滾方案

如果加固后出現問題,按以下步驟回滾:

# 恢復備份的配置
sudo cp /etc/ssh/sshd_config.bak.$(date +%Y%m%d) /etc/ssh/sshd_config

# 重啟SSH服務
sudo systemctl restart sshd

# 如果SSH完全無法連接,通過以下方式恢復:
# 1. 云服務器:通過控制臺VNC登錄
# 2. 物理機:接顯示器鍵盤直接操作
# 3. 如果有IPMI/iLO/iDRAC遠程管理卡,通過帶外管理登錄

三、示例代碼和配置

3.1 完整配置示例

3.1.1 生產級sshd_config完整配置

這份配置在我們團隊管理的300+臺CentOS 7/8和Ubuntu 20.04/22.04服務器上跑了兩年多,沒出過認證相關的事故。每一行都有注釋說明為什么這么配。

# 文件路徑:/etc/ssh/sshd_config
# 最后修改:2025-01-15
# 說明:生產環境SSH加固配置

# ============================================
# 網絡和協議
# ============================================
# 監聽端口,改掉默認22
Port 52222

# 只監聽IPv4,如果不用IPv6就關掉,減少攻擊面
AddressFamily inet

# 綁定特定IP(多網卡服務器建議綁內網IP)
# 如果只允許從內網跳板機連接:
# ListenAddress 10.0.0.100
# 如果需要公網訪問:
ListenAddress 0.0.0.0

# 協議版本,只用2(OpenSSH 7.4+已經默認只支持2)
Protocol 2

# ============================================
# 主機密鑰
# ============================================
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# 不用DSA和ECDSA
# HostKey /etc/ssh/ssh_host_dsa_key
# HostKey /etc/ssh/ssh_host_ecdsa_key

# ============================================
# 加密算法(只保留安全的算法)
# ============================================
# 密鑰交換算法
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512

# 對稱加密算法
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

# MAC算法
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com

# ============================================
# 認證配置
# ============================================
# 禁止root登錄
PermitRootLogin no

# 啟用公鑰認證
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

# 禁用密碼認證
PasswordAuthentication no
PermitEmptyPasswords no

# 禁用質詢響應認證
ChallengeResponseAuthentication no

# 禁用基于主機的認證
HostbasedAuthentication no
IgnoreRhosts yes

# 禁用GSSAPI(不用Kerberos就關掉,開著會導致連接慢)
GSSAPIAuthentication no
GSSAPICleanupCredentials no

# 禁用X11轉發(服務器不需要圖形界面)
X11Forwarding no

# 禁用TCP轉發(如果不需要SSH隧道)
# AllowTcpForwarding no
# 如果需要SSH隧道做端口轉發,保持默認yes
AllowTcpForwarding yes

# 禁用Agent轉發(除非明確需要)
AllowAgentForwarding no

# 關閉DNS反向解析(開著會導致連接慢2-5秒)
UseDNS no

# 使用PAM
UsePAM yes

# ============================================
# 訪問控制
# ============================================
# 只允許sshusers組的用戶登錄
AllowGroups sshusers

# 或者指定用戶白名單(和AllowGroups二選一)
# AllowUsers opsadmin deployer monitor

# ============================================
# 會話控制
# ============================================
# 認證超時30秒
LoginGraceTime 30

# 最大認證嘗試次數
MaxAuthTries 3

# 最大會話數
MaxSessions 5

# 未認證連接限制
MaxStartups 1060

# 客戶端存活檢測
ClientAliveInterval 300
ClientAliveCountMax 3

# ============================================
# 日志
# ============================================
SyslogFacility AUTH
LogLevel VERBOSE

# ============================================
# 登錄Banner
# ============================================
Banner /etc/ssh/banner.txt
PrintMotd no
PrintLastLog yes

# ============================================
# SFTP配置
# ============================================
Subsystem sftp /usr/libexec/openssh/sftp-server -l INFO -f AUTH

# ============================================
# 證書認證(可選)
# ============================================
# TrustedUserCAKeys /etc/ssh/ca_user_key.pub
# RevokedKeys /etc/ssh/revoked_keys

# ============================================
# Match塊:針對特定用戶/組的特殊配置
# ============================================
# SFTP專用用戶,限制在家目錄
Match Group sftponly
  ChrootDirectory /data/sftp/%u
  ForceCommand internal-sftp
  AllowTcpForwarding no
  X11Forwarding no
  PermitTunnel no

# 部署用戶,只允許從CI/CD服務器連接
Match User deployer Address 10.0.0.50
  AllowTcpForwarding no
  PermitOpen none

登錄Banner文件

# 文件路徑:/etc/ssh/banner.txt
cat > /etc/ssh/banner.txt <

3.1.2 批量分發SSH密鑰腳本

管理幾十臺服務器時,手動一臺臺ssh-copy-id太慢。這個腳本批量分發公鑰,支持密碼認證(首次部署時用)和已有密鑰認證兩種模式。

#!/bin/bash
# 文件名:distribute_ssh_keys.sh
# 功能:批量分發SSH公鑰到多臺服務器
# 依賴:sshpass(首次用密碼分發時需要)
# 用法:./distribute_ssh_keys.sh hosts.txt

set-euo pipefail

# ========== 配置區 ==========
SSH_PORT=52222
SSH_USER="opsadmin"
PUB_KEY_FILE="$HOME/.ssh/id_ed25519.pub"
LOG_FILE="/tmp/ssh_key_distribute_$(date +%Y%m%d_%H%M%S).log"
TIMEOUT=10
# =============================

# 顏色輸出
RED='?33[0;31m'
GREEN='?33[0;32m'
YELLOW='?33[1;33m'
NC='?33[0m'

log() {
 locallevel=$1
 shift
 localmsg="[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*"
 echo-e"$msg"| tee -a"$LOG_FILE"
}

usage() {
 echo"用法:$0<主機列表文件>"
 echo""
 echo"主機列表文件格式(每行一個IP):"
 echo"192.168.1.101"
 echo"192.168.1.102"
 echo"10.0.1.11"
 exit1
}

# 參數檢查
if[[$#-ne 1 ]];then
  usage
fi

HOST_FILE=$1

if[[ ! -f"$HOST_FILE"]];then
 log"ERROR""主機列表文件不存在:$HOST_FILE"
 exit1
fi

if[[ ! -f"$PUB_KEY_FILE"]];then
 log"ERROR""公鑰文件不存在:$PUB_KEY_FILE"
 log"INFO""請先生成密鑰: ssh-keygen -t ed25519"
 exit1
fi

# 檢查sshpass是否安裝
USE_PASSWORD=false
ifcommand-v sshpass &>/dev/null;then
 read-sp"輸入SSH密碼(如果目標機器已配置密鑰登錄,直接回車跳過): "SSH_PASS
 echo
 if[[ -n"$SSH_PASS"]];then
    USE_PASSWORD=true
 fi
fi

# 統計
TOTAL=0
SUCCESS=0
FAILED=0

log"INFO""開始分發SSH公鑰"
log"INFO""公鑰文件:$PUB_KEY_FILE"
log"INFO""目標用戶:$SSH_USER"
log"INFO""SSH端口:$SSH_PORT"

whileIFS=read-r host;do
 # 跳過空行和注釋
  [[ -z"$host"||"$host"=~ ^# ]] && continue

  TOTAL=$((TOTAL + 1))
 log"INFO""[$TOTAL] 正在處理:$host"

 if$USE_PASSWORD;then
   # 使用密碼分發
   ifsshpass -p"$SSH_PASS"ssh-copy-id 
      -i"$PUB_KEY_FILE"
      -p"$SSH_PORT"
      -o StrictHostKeyChecking=no 
      -o ConnectTimeout=$TIMEOUT
     "${SSH_USER}@${host}"2>>"$LOG_FILE";then
     log"INFO""${GREEN}成功${NC}:$host"
      SUCCESS=$((SUCCESS + 1))
   else
     log"ERROR""${RED}失敗${NC}:$host"
      FAILED=$((FAILED + 1))
   fi
 else
   # 使用已有密鑰分發新密鑰
   ifssh-copy-id 
      -i"$PUB_KEY_FILE"
      -p"$SSH_PORT"
      -o StrictHostKeyChecking=no 
      -o ConnectTimeout=$TIMEOUT
     "${SSH_USER}@${host}"2>>"$LOG_FILE";then
     log"INFO""${GREEN}成功${NC}:$host"
      SUCCESS=$((SUCCESS + 1))
   else
     log"ERROR""${RED}失敗${NC}:$host"
      FAILED=$((FAILED + 1))
   fi
 fi
done
# 使用方法
chmod +x distribute_ssh_keys.sh

# 準備主機列表
cat > hosts.txt <

3.2 實際應用案例

案例一:基于跳板機的SSH ProxyJump多層跳轉

場景描述:生產環境網絡架構分三層——公網跳板機、DMZ區應用服務器、內網數據庫服務器。運維人員從辦公網絡連接跳板機,再跳轉到內網服務器。數據庫服務器只允許從應用服務器網段訪問。

網絡拓撲

辦公網絡(172.16.0.0/16)
  |
  v
跳板機(公網: 203.0.113.10, 內網: 10.0.0.1)
  |
  v
應用服務器(10.0.1.0/24)
  |
  v
數據庫服務器(10.0.2.0/24)

SSH Config配置

# ~/.ssh/config

# 跳板機(一跳)
Host jump
  HostName 203.0.113.10
  Port 52222
  User opsadmin
  IdentityFile ~/.ssh/id_ed25519
 # 跳板機上開啟Agent轉發,用于二次跳轉
  ForwardAgent yes

# 應用服務器(二跳,通過跳板機)
Host app-01
  HostName 10.0.1.11
  User deployer
  IdentityFile ~/.ssh/id_ed25519
  ProxyJump jump

Host app-02
  HostName 10.0.1.12
  User deployer
  IdentityFile ~/.ssh/id_ed25519
  ProxyJump jump

# 數據庫服務器(三跳,通過應用服務器)
Host db-master
  HostName 10.0.2.21
  User dbadmin
  IdentityFile ~/.ssh/id_ed25519_db
  ProxyJump app-01

Host db-slave
  HostName 10.0.2.22
  User dbadmin
  IdentityFile ~/.ssh/id_ed25519_db
  ProxyJump app-01

使用效果

# 直接連接數據庫服務器,SSH自動完成兩次跳轉
ssh db-master
# 實際路徑:本機 -> jump(203.0.113.10) -> app-01(10.0.1.11) -> db-master(10.0.2.21)

# 通過跳板機做端口轉發,本地訪問遠程數據庫
ssh -L 33073306 app-01
# 然后本地用 mysql -h 127.0.0.1 -P 3307 連接

# 通過跳板機傳文件到內網服務器
scp backup.sql db-master:/tmp/

案例二:多環境SSH Config管理與自動切換

場景描述:團隊管理開發、測試、預發布、生產四套環境,共200+臺服務器。不同環境用不同的密鑰和用戶,需要一套清晰的管理方案。

目錄結構

~/.ssh/
├── config         # 主配置文件,include其他配置
├── config.d/
│  ├── 00-defaults.conf  # 全局默認配置
│  ├── 10-dev.conf    # 開發環境
│  ├── 20-test.conf    # 測試環境
│  ├── 30-staging.conf  # 預發布環境
│  └── 40-prod.conf    # 生產環境
├── id_ed25519       # 默認密鑰
├── id_ed25519_prod    # 生產環境專用密鑰
├── id_ed25519_db     # 數據庫專用密鑰
└── known_hosts

主配置文件

# ~/.ssh/config
# 使用Include指令加載分環境配置(OpenSSH 7.3+支持)
Include config.d/*.conf

全局默認配置

# ~/.ssh/config.d/00-defaults.conf
Host *
  ServerAliveInterval 60
  ServerAliveCountMax 3
  AddKeysToAgent yes
  IdentitiesOnly yes
  Compression yes
 # 連接復用,同一臺服務器的多個SSH會話共用一個TCP連接
  ControlMaster auto
  ControlPath ~/.ssh/sockets/%r@%h-%p
  ControlPersist 600
 # 首次連接自動接受主機密鑰(僅限內網環境,公網建議去掉)
 # StrictHostKeyChecking accept-new

生產環境配置

# ~/.ssh/config.d/40-prod.conf
# 生產環境 - 通過跳板機訪問
Host prod-jump
  HostName 203.0.113.10
  Port 52222
  User opsadmin
  IdentityFile ~/.ssh/id_ed25519_prod

Host prod-web-*
  User deployer
  IdentityFile ~/.ssh/id_ed25519_prod
  ProxyJump prod-jump

Host prod-web-01
  HostName 10.0.1.11
Host prod-web-02
  HostName 10.0.1.12
Host prod-web-03
  HostName 10.0.1.13

Host prod-db-*
  User dbadmin
  IdentityFile ~/.ssh/id_ed25519_db
  ProxyJump prod-jump

Host prod-db-master
  HostName 10.0.2.21
Host prod-db-slave-01
  HostName 10.0.2.22
Host prod-db-slave-02
  HostName 10.0.2.23
# 創建socket目錄(連接復用需要)
mkdir -p ~/.ssh/sockets

# 使用效果
ssh prod-web-01   # 連接生產Web服務器
ssh prod-db-master # 連接生產數據庫主庫

# 查看當前活躍的連接復用
ls ~/.ssh/sockets/

# 手動關閉某個復用連接
ssh -Oexitprod-web-01

案例三:SSH密鑰自動輪換腳本

場景描述:安全合規要求SSH密鑰每90天輪換一次。手動操作容易遺漏,寫個腳本自動化處理。

#!/bin/bash
# 文件名:rotate_ssh_keys.sh
# 功能:自動輪換SSH密鑰并分發到目標服務器
# 建議配合crontab每季度執行一次

set-euo pipefail

KEY_DIR="$HOME/.ssh"
KEY_TYPE="ed25519"
KEY_COMMENT="$(whoami)@$(hostname)-$(date +%Y%m%d)"
BACKUP_DIR="$KEY_DIR/archived_keys"
HOST_FILE="$HOME/.ssh/managed_hosts.txt"
LOG_FILE="/var/log/ssh_key_rotation_$(date +%Y%m%d).log"

log() {
 echo"[$(date '+%Y-%m-%d %H:%M:%S')] $*"| tee -a"$LOG_FILE"
}

# 創建備份目錄
mkdir -p"$BACKUP_DIR"

# 1. 備份舊密鑰
if[[ -f"$KEY_DIR/id_${KEY_TYPE}"]];then
  BACKUP_NAME="id_${KEY_TYPE}_$(date +%Y%m%d_%H%M%S)"
  cp"$KEY_DIR/id_${KEY_TYPE}""$BACKUP_DIR/$BACKUP_NAME"
  cp"$KEY_DIR/id_${KEY_TYPE}.pub""$BACKUP_DIR/${BACKUP_NAME}.pub"
 log"舊密鑰已備份到:$BACKUP_DIR/$BACKUP_NAME"
fi

# 2. 生成新密鑰(不設passphrase,自動化場景用)
ssh-keygen -t"$KEY_TYPE"-C"$KEY_COMMENT"-f"$KEY_DIR/id_${KEY_TYPE}"-N""-q
log"新密鑰已生成:$KEY_DIR/id_${KEY_TYPE}"

# 3. 分發新公鑰到所有服務器(用舊密鑰認證)
if[[ -f"$HOST_FILE"]];then
 whileIFS=:read-r host port user;do
    port=${port:-52222}
    user=${user:-opsadmin}
   log"分發到:${user}@${host}:${port}"
   ifssh-copy-id -i"$KEY_DIR/id_${KEY_TYPE}.pub"
      -p"$port"
      -o ConnectTimeout=10 
      -o IdentityFile="$BACKUP_DIR/$(ls -t $BACKUP_DIR/id_${KEY_TYPE}_* 2>/dev/null | head -1)"
     "${user}@${host}"2>>"$LOG_FILE";then
     log"成功:${host}"
   else
     log"失敗:${host}- 需要手動處理"
   fi
 done/dev/null;then
     log"驗證通過:${host}"
   else
     log"驗證失敗:${host}- 緊急!請檢查"
   fi
 done
# managed_hosts.txt 格式:主機:端口:用戶
cat > ~/.ssh/managed_hosts.txt <

四、最佳實踐和注意事項

4.1 最佳實踐

4.1.1 性能優化

使用ed25519替代RSA密鑰:ed25519密鑰長度只有68字節,RSA-4096是800+字節。實測簽名速度ed25519比RSA-4096快約30%,在批量SSH操作(Ansible管理500臺機器)時差異明顯。Ansible playbook跑完全量主機,ed25519密鑰比RSA-4096快了約12秒(總耗時從98秒降到86秒)。

# 生成ed25519密鑰
ssh-keygen -t ed25519 -C"ops@company.com"

# 如果已有RSA密鑰,生成新的ed25519密鑰后逐步替換
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C"ops@company.com"

開啟連接復用(ControlMaster):同一臺服務器的多個SSH會話共用一個TCP連接,省去重復的TCP握手和密鑰交換。實測第二次連接耗時從1.2秒降到0.1秒。對于頻繁ssh/scp操作的場景提升巨大。

# ~/.ssh/config 中配置
Host *
  ControlMaster auto
  ControlPath ~/.ssh/sockets/%r@%h-%p
  ControlPersist 600

# 創建socket目錄
mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/sockets

關閉DNS反向解析和GSSAPI:sshd默認會對客戶端IP做DNS反向解析,如果DNS服務器響應慢或不可達,每次連接會卡5-30秒。GSSAPI認證同理,不用Kerberos就關掉。

# 服務端 /etc/ssh/sshd_config
UseDNS no
GSSAPIAuthentication no

# 客戶端 ~/.ssh/config(雙向都關)
Host *
  GSSAPIAuthentication no

啟用壓縮傳輸:在帶寬有限的網絡環境下(比如跨地域機房),開啟壓縮可以減少傳輸數據量。實測傳輸日志文件(文本類數據壓縮率高)速度提升40-60%。但在局域網高帶寬環境下,壓縮反而增加CPU開銷,建議關閉。

# 低帶寬環境開啟
Host slow-network-*
  Compression yes

# 局域網環境關閉
Host lan-*
  Compression no

4.1.2 安全加固

限制SSH訪問來源IP:即使改了端口、禁了密碼,也建議在防火墻層面限制只允許特定IP段訪問SSH端口。縱深防御,多一層保護。

# firewalld:只允許辦公網絡和跳板機IP訪問SSH
sudo firewall-cmd --permanent --zone=public --remove-service=ssh
sudo firewall-cmd --permanent --new-zone=ssh-restricted 2>/dev/null ||true
sudo firewall-cmd --permanent --zone=ssh-restricted --add-source=172.16.0.0/16
sudo firewall-cmd --permanent --zone=ssh-restricted --add-source=203.0.113.10/32
sudo firewall-cmd --permanent --zone=ssh-restricted --add-port=52222/tcp
sudo firewall-cmd --reload

# iptables方式
sudo iptables -A INPUT -p tcp --dport 52222 -s 172.16.0.0/16 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 52222 -s 203.0.113.10/32 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 52222 -j DROP
sudo service iptables save

定期審計SSH登錄日志:每周檢查一次異常登錄記錄,關注非工作時間登錄、陌生IP登錄、頻繁失敗嘗試。

# 查看成功登錄記錄
grep"Accepted"/var/log/secure | awk'{print $1,$2,$3,$9,$11}'| sort | uniq -c | sort -rn | head -20

# 查看失敗登錄統計(按IP排序)
grep"Failed password"/var/log/secure | awk'{print $(NF-3)}'| sort | uniq -c | sort -rn | head -20

# 查看非工作時間(2200)的登錄
grep"Accepted"/var/log/secure | awk'{split($3,t,":"); if(t[1]>=22 || t[1]<8) print}'

SSH密鑰指紋驗證:首次連接新服務器時,SSH會提示確認主機指紋。生產環境不要無腦yes,應該提前通過安全渠道獲取服務器指紋并核對。

# 在服務器上查看主機密鑰指紋
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

# 客戶端連接時核對指紋
# The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established.
# ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
# 核對一致后輸入yes

禁用弱加密算法:默認配置包含一些老舊的加密算法(如arcfour、3des-cbc),存在已知漏洞。只保留安全的算法。

# /etc/ssh/sshd_config
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com

# 驗證當前使用的算法
ssh -vv -p 52222 opsadmin@192.168.1.100 2>&1 | grep"kex:"

4.1.3 高可用配置

跳板機高可用:跳板機是單點,掛了所有人都連不上內網服務器。生產環境至少部署兩臺跳板機,用DNS輪詢或keepalived做VIP漂移。

# SSH Config中配置備用跳板機
Host jump
  HostName jump-vip.company.com
  Port 52222
  User opsadmin
  IdentityFile ~/.ssh/id_ed25519
 # 連接超時后自動嘗試備用
  ConnectTimeout 5

# 或者用Match塊配置fallback
# 主跳板機
Host jump-primary
  HostName 203.0.113.10
  Port 52222

# 備用跳板機
Host jump-backup
  HostName 203.0.113.11
  Port 52222

SSH服務端口探活:用監控系統定期檢測SSH端口是否可達,sshd進程是否存活。

# 簡單的SSH端口探活腳本
nc -z -w 3 192.168.1.100 52222 &&echo"SSH OK"||echo"SSH DOWN"

# 或者用ssh命令探活(更準確,驗證到協議層)
ssh -o ConnectTimeout=3 -o BatchMode=yes -p 52222 opsadmin@192.168.1.100"echo ok"2>/dev/null

備份策略:SSH配置文件和密鑰是關鍵資產,必須納入備份。

/etc/ssh/sshd_config和/etc/ssh/ssh_host_*主機密鑰:納入系統配置備份

用戶~/.ssh/目錄:納入用戶數據備份

CA密鑰(如果用證書認證):離線備份,存放在保險柜級別的安全位置

4.2 注意事項

4.2.1 配置注意事項

改SSH配置前必須保持一個活躍會話不斷開。這是鐵律,違反一次就可能要跑機房。我親眼見過同事改錯sshd_config后restart,所有SSH連接斷開,最后開車去機房用顯示器鍵盤恢復的。

修改sshd_config后先用sshd -t檢查語法,再reload而不是restart

改端口時先在防火墻放行新端口,再改配置重啟,順序不能反

禁用密碼認證前,必須確認密鑰登錄已經配好并測試通過

AllowUsers和AllowGroups是白名單,配了之后不在名單里的用戶全部被拒絕,包括root

Match塊必須放在sshd_config文件末尾,Match塊之后的配置都屬于這個Match塊的作用域

4.2.2 常見錯誤

錯誤現象 原因分析 解決方案
Permission denied (publickey) 公鑰未添加到authorized_keys,或文件權限不對 檢查~/.ssh/目錄700、authorized_keys文件600、家目錄不超過755
Connection refused sshd未啟動或端口不對 systemctl status sshd 檢查服務狀態,ss -tlnp檢查端口
Connection timed out 防火墻未放行端口或網絡不通 telnet IP PORT 測試端口連通性,檢查firewalld/iptables規則
Too many authentication failures 客戶端嘗試了太多密鑰,超過MaxAuthTries 在~/.ssh/config中加IdentitiesOnly yes指定密鑰
SSH連接后卡住5-10秒 DNS反向解析超時或GSSAPI認證超時 服務端設UseDNS no,客戶端設GSSAPIAuthentication no
Host key verification failed 服務器重裝后主機密鑰變了 ssh-keygen -R 主機IP 刪除舊指紋,重新確認
Bad owner or modes .ssh目錄或文件權限過大 chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys

4.2.3 兼容性問題

版本兼容:ed25519密鑰需要OpenSSH 6.5+,ProxyJump指令需要7.3+,Include指令需要7.3+。CentOS 6自帶的OpenSSH 5.3不支持這些特性,需要升級或用ProxyCommand替代ProxyJump。

# CentOS 6上用ProxyCommand替代ProxyJump
Host internal-server
  HostName 10.0.1.11
  ProxyCommand ssh -W %h:%p jump

平臺兼容:macOS自帶的OpenSSH版本通常較新(Ventura自帶8.6),但ssh-copy-id需要額外安裝(brew install ssh-copy-id)。Windows 10/11自帶OpenSSH客戶端,但版本可能較舊,建議用Git Bash或WSL。

組件依賴:fail2ban在CentOS 7上依賴EPEL源;CentOS 8/9的fail2ban需要python3-systemd包;Ubuntu直接apt安裝即可。semanage命令需要安裝policycoreutils-python-utils包。

五、故障排查和監控

5.1 故障排查

5.1.1 日志查看

# CentOS/RHEL 查看SSH認證日志
sudo tail -f /var/log/secure

# Ubuntu/Debian 查看SSH認證日志
sudo tail -f /var/log/auth.log

# 用journalctl查看sshd日志(systemd系統通用)
sudo journalctl -u sshd -f

# 只看最近1小時的SSH日志
sudo journalctl -u sshd --since"1 hour ago"

# 過濾失敗登錄
sudo journalctl -u sshd | grep -i"failed|error|denied"

# 查看fail2ban日志
sudo tail -f /var/log/fail2ban.log

日志級別調整:排查問題時臨時調高日志級別,排查完改回來。

# /etc/ssh/sshd_config
# 正常運行用VERBOSE,排查問題臨時改為DEBUG3
LogLevel VERBOSE
# LogLevel DEBUG3

# 改完reload
sudo systemctl reload sshd

DEBUG3級別會記錄每一步認證細節,包括嘗試了哪些密鑰、為什么拒絕等。日志量很大,排查完務必改回VERBOSE,否則磁盤會被撐滿。

5.1.2 常見問題排查

問題一:Permission denied (publickey) —— 密鑰認證失敗

這是最常見的SSH問題,原因有很多種,按排查優先級列出:

# 1. 客戶端用verbose模式連接,看具體卡在哪一步
ssh -vvv -p 52222 -i ~/.ssh/id_ed25519 opsadmin@192.168.1.100

# 關注這些關鍵行:
# "Offering public key: /home/user/.ssh/id_ed25519 ED25519" -> 客戶端發送了密鑰
# "Server accepts key: /home/user/.ssh/id_ed25519 ED25519" -> 服務端接受了密鑰
# "Authentication succeeded (publickey)" -> 認證成功

# 如果看到 "No more authentication methods to try" 說明服務端拒絕了所有密鑰
# 2. 檢查服務端權限(最常見的原因)
ls -la ~/
# 家目錄權限不能大于755,如果是777就會被拒絕
ls -la ~/.ssh/
# .ssh目錄必須是700
ls -la ~/.ssh/authorized_keys
# authorized_keys必須是600

# 修復權限
chmod 755 ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

# 3. 檢查authorized_keys內容
cat ~/.ssh/authorized_keys
# 確認公鑰完整,沒有換行符截斷
# 每個公鑰必須是一行,不能有折行

# 4. 檢查文件屬主
ls -la ~/.ssh/authorized_keys
# owner必須是當前用戶,不能是root
chown $(whoami):$(whoami) ~/.ssh/authorized_keys

# 5. 檢查SELinux上下文(CentOS/RHEL)
ls -Z ~/.ssh/authorized_keys
# 應該是 unconfined_ussh_home_t:s0
# 如果不對,恢復上下文:
restorecon -Rv ~/.ssh/

問題二:SSH連接慢,登錄要等5-30秒

# 原因1:DNS反向解析(最常見)
# 服務端對客戶端IP做反向DNS查詢,DNS服務器不可達時會等到超時
# 解決:
sudo grep"UseDNS"/etc/ssh/sshd_config
# 如果是yes或者沒配(默認yes),改為no
# UseDNS no

# 原因2:GSSAPI認證超時
# 客戶端嘗試GSSAPI認證,沒有Kerberos環境時會超時
# 解決(客戶端):
ssh -o GSSAPIAuthentication=no -p 52222 opsadmin@192.168.1.100
# 或者在~/.ssh/config中全局關閉
# Host *
#   GSSAPIAuthentication no

# 原因3:systemd-logind響應慢
# CentOS 7上偶發,dbus通信超時
# 診斷:
sudo journalctl -u systemd-logind --since"10 minutes ago"
# 解決:
sudo systemctl restart systemd-logind

# 用time命令量化連接耗時
time ssh -p 52222 opsadmin@192.168.1.100"exit"
# 正常應該在1秒以內

問題三:Connection refused —— 連接被拒絕

# 1. 檢查sshd是否在運行
sudo systemctl status sshd
# 如果是dead/failed狀態,查看原因
sudo journalctl -u sshd --no-pager | tail -30

# 2. 檢查監聽端口
ss -tlnp | grep sshd
# 確認sshd在監聽正確的端口

# 3. 檢查配置文件語法
sudo sshd -t
# 如果有語法錯誤,sshd可能啟動失敗

# 4. 檢查防火墻
sudo firewall-cmd --list-all
# 或
sudo iptables -L -n | grep 52222

# 5. 檢查SELinux是否阻止了非標準端口
sudo semanage port -l | grep ssh
# 如果新端口不在列表里:
sudo semanage port -a -t ssh_port_t -p tcp 52222

# 6. 檢查TCP Wrappers(/etc/hosts.allow 和 /etc/hosts.deny)
cat /etc/hosts.deny
# 如果有 sshd: ALL 會拒絕所有SSH連接

問題四:fail2ban誤封了合法IP

# 查看當前被封禁的IP列表
sudo fail2ban-client status sshd

# 解封特定IP
sudo fail2ban-clientsetsshd unbanip 172.16.1.50

# 查看封禁原因(在fail2ban日志中搜索)
sudo grep"172.16.1.50"/var/log/fail2ban.log

# 將合法IP加入白名單(永久生效)
# 編輯 /etc/fail2ban/jail.local
# ignoreip = 127.0.0.1/8 10.0.0.0/8 172.16.0.0/16

# 重啟fail2ban使白名單生效
sudo systemctl restart fail2ban

5.1.3 調試模式

# 在前臺以調試模式啟動sshd(不影響正在運行的sshd)
# 監聽在不同端口避免沖突
sudo /usr/sbin/sshd -d -p 52223

# 客戶端連接調試端口
ssh -vvv -p 52223 opsadmin@192.168.1.100

# 兩邊的輸出對照看,能精確定位認證失敗的原因

# 檢查sshd加載的完整配置(排查配置覆蓋問題)
sudo sshd -T

# 檢查特定用戶從特定IP連接時的有效配置(Match塊生效情況)
sudo sshd -T -C user=deployer,host=10.0.0.50,addr=10.0.0.50

5.2 性能監控

5.2.1 關鍵指標監控

# SSH連接數監控
ss -tnp | grep":52222"| wc -l

# 當前活躍SSH會話數
who | wc -l

# sshd進程資源占用
ps aux | grep sshd | grep -v grep

# SSH認證失敗頻率(最近1小時)
sudo journalctl -u sshd --since"1 hour ago"| grep -c"Failed"

# fail2ban封禁統計
sudo fail2ban-client status sshd | grep"Currently banned"

# SSH端口連接狀態分布
ss -tn | grep":52222"| awk'{print $1}'| sort | uniq -c

5.2.2 監控指標說明

指標名稱 正常范圍 告警閾值 說明
SSH活躍連接數 0-50 >100 超過100可能是暴力破解或連接泄漏
認證失敗次數/小時 0-10 >50 大量失敗說明有暴力破解行為
fail2ban封禁IP數 0-5 >20 大量封禁說明正在遭受攻擊
SSH連接延遲 <1s >5s 延遲高需要排查DNS/GSSAPI/網絡問題
sshd進程CPU使用率 <5% >30% CPU高可能是密鑰交換風暴或DDoS
sshd進程內存使用 <50MB >200MB 內存異常增長需要排查連接泄漏

5.2.3 Prometheus監控規則

# prometheus_ssh_rules.yml
# 文件路徑:/etc/prometheus/rules/ssh_rules.yml

groups:
-name:ssh_security
 interval:30s
 rules:
  # SSH認證失敗率告警
  -alert:SSHAuthFailureHigh
   expr:rate(ssh_auth_failures_total[5m])>10
   for:5m
   labels:
    severity:warning
   annotations:
    summary:"SSH認證失敗率過高 ({{ $labels.instance }})"
    description:"5分鐘內SSH認證失敗率超過10次/秒,可能遭受暴力破解"

  # SSH活躍連接數告警
  -alert:SSHConnectionsHigh
   expr:ssh_active_connections>100
   for:2m
   labels:
    severity:warning
   annotations:
    summary:"SSH連接數過高 ({{ $labels.instance }})"
    description:"SSH活躍連接數{{ $value }},超過閾值100"

  # fail2ban封禁數告警
  -alert:Fail2banBannedIPsHigh
   expr:fail2ban_banned_ips{jail="sshd"}>20
   for:5m
   labels:
    severity:critical
   annotations:
    summary:"fail2ban封禁IP數過多 ({{ $labels.instance }})"
    description:"SSH jail當前封禁{{ $value }}個IP,可能正在遭受大規模攻擊"

  # sshd進程存活檢測
  -alert:SSHDProcessDown
   expr:node_systemd_unit_state{name="sshd.service",state="active"}!=1
   for:1m
   labels:
    severity:critical
   annotations:
    summary:"sshd服務異常 ({{ $labels.instance }})"
    description:"sshd服務未在運行狀態,遠程管理通道中斷"

配合node_exporter的textfile collector采集SSH指標

#!/bin/bash
# 文件名:ssh_metrics.sh
# 功能:采集SSH相關指標,輸出為Prometheus格式
# 配合crontab每分鐘執行:* * * * * /opt/scripts/ssh_metrics.sh

METRICS_DIR="/var/lib/node_exporter/textfile_collector"
METRICS_FILE="$METRICS_DIR/ssh_metrics.prom"

mkdir -p"$METRICS_DIR"

# 活躍SSH連接數
ACTIVE_CONN=$(ss -tnp | grep -c":52222"2>/dev/null ||echo0)

# 當前登錄用戶數
LOGGED_USERS=$(who | wc -l)

# 最近5分鐘認證失敗次數
FAIL_COUNT=$(sudo journalctl -u sshd --since"5 minutes ago"2>/dev/null | grep -c"Failed"||echo0)

# fail2ban封禁IP數
BANNED_IPS=$(sudo fail2ban-client status sshd 2>/dev/null | grep"Currently banned"| awk'{print $NF}'||echo0)

cat >"$METRICS_FILE.tmp"<< EOF
# HELP ssh_active_connections Current number of SSH connections
# TYPE ssh_active_connections gauge
ssh_active_connections?$ACTIVE_CONN
# HELP ssh_logged_users Current number of logged in users
# TYPE ssh_logged_users gauge
ssh_logged_users?$LOGGED_USERS
# HELP ssh_auth_failures_5m SSH authentication failures in last 5 minutes
# TYPE ssh_auth_failures_5m gauge
ssh_auth_failures_5m?$FAIL_COUNT
# HELP fail2ban_banned_ips Number of IPs banned by fail2ban
# TYPE fail2ban_banned_ips gauge
fail2ban_banned_ips{jail="sshd"}?$BANNED_IPS
EOF

mv?"$METRICS_FILE.tmp""$METRICS_FILE"

5.3 備份與恢復

5.3.1 備份策略

#!/bin/bash
# 文件名:backup_ssh_config.sh
# 功能:備份SSH服務端和客戶端配置
# 建議每周執行一次,保留最近12周的備份

BACKUP_BASE="/data/backup/ssh"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_BASE/$DATE"
KEEP_WEEKS=12

mkdir -p"$BACKUP_DIR"

# 備份服務端配置
sudo cp -a /etc/ssh/sshd_config"$BACKUP_DIR/"
sudo cp -a /etc/ssh/ssh_config"$BACKUP_DIR/"2>/dev/null
sudo cp -a /etc/ssh/banner.txt"$BACKUP_DIR/"2>/dev/null

# 備份主機密鑰(恢復時需要,否則所有客戶端會報host key changed)
sudo cp -a /etc/ssh/ssh_host_*"$BACKUP_DIR/"

# 備份fail2ban配置
sudo cp -a /etc/fail2ban/jail.local"$BACKUP_DIR/"2>/dev/null

# 備份CA密鑰(如果有)
sudo cp -a /etc/ssh/ca_user_key*"$BACKUP_DIR/"2>/dev/null
sudo cp -a /etc/ssh/revoked_keys"$BACKUP_DIR/"2>/dev/null

# 設置備份文件權限
sudo chmod 600"$BACKUP_DIR"/ssh_host_*
sudo chmod 600"$BACKUP_DIR"/ca_user_key 2>/dev/null

# 清理過期備份
find"$BACKUP_BASE"-maxdepth 1 -typed -mtime +$((KEEP_WEEKS * 7)) -execrm -rf {} ;

echo"SSH配置備份完成:$BACKUP_DIR"
ls -la"$BACKUP_DIR/"

5.3.2 恢復流程

停止服務(如果sshd還在運行):

# 不要直接stop,先確認有其他方式訪問服務器(VNC/IPMI/控制臺)
sudo systemctl stop sshd

恢復配置文件

# 找到最近的備份
ls -lt /data/backup/ssh/ | head -5

# 恢復配置
RESTORE_DIR="/data/backup/ssh/20250115_020000"
sudo cp"$RESTORE_DIR/sshd_config"/etc/ssh/sshd_config
sudo cp"$RESTORE_DIR"/ssh_host_* /etc/ssh/

# 恢復權限
sudo chmod 600 /etc/ssh/ssh_host_*_key
sudo chmod 644 /etc/ssh/ssh_host_*_key.pub
sudo chmod 644 /etc/ssh/sshd_config

驗證配置

sudo sshd -t

重啟服務

sudo systemctl start sshd
sudo systemctl status sshd
ss -tlnp | grep sshd

六、總結

6.1 技術要點回顧

端口+認證雙重加固:改默認端口過濾自動化掃描,禁密碼認證杜絕暴力破解。實測改端口后掃描日志從每天數萬條降到個位數,禁密碼后暴力破解徹底歸零。

ed25519是當前最優密鑰算法:比RSA-4096更安全、密鑰更短(68字節 vs 800+字節)、簽名驗證更快(約30%)。除非目標系統OpenSSH低于6.5,否則一律用ed25519。

fail2ban是必備防護組件:配合MaxAuthTries形成兩層防線——MaxAuthTries限制單次連接嘗試次數,fail2ban在多次連接失敗后封禁IP。兩者配合效果遠大于單獨使用。

SSH Config + ProxyJump實現高效多主機管理:用別名替代IP+端口,用ProxyJump實現透明跳轉,用ControlMaster實現連接復用。管理200+臺服務器和管理2臺一樣方便。

證書認證是大規模環境的終極方案:超過50臺服務器時,逐臺維護authorized_keys不現實。CA簽發證書后服務端只需信任CA公鑰,人員變動只需吊銷證書,不用逐臺操作。

配置變更必須有回滾方案:改SSH配置前備份、保持活躍會話、先放行新端口再改配置、用sshd -t檢查語法。這些流程每一步都不能省。

6.2 進階學習方向

SSH證書認證與HashiCorp Vault集成

Vault可以作為SSH CA,動態簽發短期證書(比如有效期8小時),實現"用完即廢"的零信任模式

學習資源:HashiCorp Vault官方文檔 SSH Secrets Engine章節

實踐建議:先在測試環境搭建Vault,配置SSH Secrets Engine,體驗動態證書簽發流程

基于FIDO2/U2F硬件密鑰的SSH認證

OpenSSH 8.2+支持FIDO2安全密鑰(如YubiKey),私鑰存儲在硬件中無法導出,比軟件密鑰更安全

學習資源:OpenSSH 8.2 Release Notes,Yubico官方SSH配置指南

實踐建議:購買一個YubiKey 5系列,配置ssh-keygen -t ed25519-sk生成硬件綁定密鑰

Teleport/Boundary等零信任SSH網關

替代傳統跳板機,提供會話錄制、RBAC權限控制、審計日志、MFA集成等企業級功能

學習資源:Teleport官方文檔,Gravitational GitHub倉庫

實踐建議:用Docker快速部署Teleport試用版,體驗Web Terminal和會話回放功能

6.3 參考資料

OpenSSH官方文檔- sshd_config所有參數的權威說明

Mozilla SSH安全指南- Mozilla內部SSH加固標準,推薦的加密算法列表

fail2ban官方Wiki- fail2ban配置詳解和自定義filter編寫

SSH Mastery (Michael W Lucas)- SSH進階書籍,覆蓋證書認證、端口轉發等高級主題

CIS Benchmark for Linux- CIS安全基線中SSH加固章節

附錄

A. 命令速查表

# ===== 密鑰管理 =====
ssh-keygen -t ed25519 -C"comment"      # 生成ed25519密鑰
ssh-keygen -t rsa -b 4096 -C"comment"     # 生成RSA-4096密鑰
ssh-keygen -lf ~/.ssh/id_ed25519.pub       # 查看密鑰指紋
ssh-keygen -R 192.168.1.100           # 刪除known_hosts中的主機記錄
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 52222 user@host # 分發公鑰

# ===== 連接和調試 =====
ssh -p 52222 user@host              # 指定端口連接
ssh -vvv user@host                # 詳細調試模式
ssh -J jump user@internal-host          # 通過跳板機連接
ssh -L 33073306 user@jump        # 本地端口轉發
ssh -D 1080 user@host              # SOCKS代理

# ===== 服務管理 =====
sudo sshd -t                   # 檢查配置語法
sudo sshd -T                   # 顯示完整有效配置
sudo systemctl reload sshd            # 重載配置(不斷連接)
sudo systemctl restart sshd           # 重啟服務(斷開所有連接)

# ===== fail2ban =====
sudo fail2ban-client status sshd         # 查看SSH jail狀態
sudo fail2ban-clientsetsshd unbanip 1.2.3.4  # 解封IP
sudo fail2ban-clientsetsshd banip 1.2.3.4   # 封禁IP

# ===== 證書認證 =====
ssh-keygen -s ca_key -I cert_id -n user -V +52w user.pub # 簽發證書
ssh-keygen -L -f cert.pub            # 查看證書信息

# ===== 權限設置 =====
chmod 700 ~/.ssh                 # .ssh目錄權限
chmod 600 ~/.ssh/authorized_keys         # authorized_keys權限
chmod 600 ~/.ssh/id_ed25519           # 私鑰權限
chmod 644 ~/.ssh/id_ed25519.pub         # 公鑰權限
chmod 755 ~                   # 家目錄權限上限

B. 配置參數詳解

sshd_config 關鍵參數速查

參數 默認值 推薦值 說明
Port 22 52222 SSH監聽端口
PermitRootLogin yes no 是否允許root登錄
PasswordAuthentication yes no 是否允許密碼認證
PubkeyAuthentication yes yes 是否允許公鑰認證
MaxAuthTries 6 3 單次連接最大認證嘗試次數
LoginGraceTime 120 30 認證超時時間(秒)
MaxSessions 10 5 單連接最大會話數
MaxStartups 10100 1060 未認證連接限制
ClientAliveInterval 0 300 心跳探測間隔(秒)
ClientAliveCountMax 3 3 心跳失敗斷開閾值
UseDNS yes no 是否做DNS反向解析
GSSAPIAuthentication yes no 是否啟用GSSAPI認證
X11Forwarding yes no 是否允許X11轉發
AllowAgentForwarding yes no 是否允許Agent轉發
LogLevel INFO VERBOSE 日志級別
Banner none /etc/ssh/banner.txt 登錄前顯示的警告信息
StrictModes yes yes 是否檢查文件權限

客戶端 ~/.ssh/config 常用參數

參數 說明 示例
HostName 實際主機地址 192.168.1.100
Port SSH端口 52222
User 登錄用戶名 opsadmin
IdentityFile 私鑰文件路徑 ~/.ssh/id_ed25519
IdentitiesOnly 只用指定密鑰 yes
ProxyJump 跳板機 jump
ServerAliveInterval 心跳間隔(秒) 60
ControlMaster 連接復用 auto
ControlPath 復用socket路徑 ~/.ssh/sockets/%r@%h-%p
ControlPersist 復用保持時間(秒) 600
Compression 壓縮傳輸 yes
ForwardAgent Agent轉發 no

C. 術語表

術語 英文 解釋
非對稱加密 Asymmetric Encryption 使用公鑰加密、私鑰解密的加密方式,SSH密鑰認證的基礎
公鑰 Public Key 可以公開分發的密鑰,放在服務端的authorized_keys中
私鑰 Private Key 必須嚴格保密的密鑰,存放在客戶端,權限必須是600
密鑰指紋 Key Fingerprint 密鑰的哈希摘要,用于快速識別和驗證密鑰身份
CA Certificate Authority 證書頒發機構,SSH證書認證中負責簽發和吊銷用戶證書
跳板機 Jump Host / Bastion Host 作為SSH中轉的服務器,內網服務器只允許從跳板機訪問
端口轉發 Port Forwarding 通過SSH隧道將本地端口映射到遠程端口,或反向映射
Agent轉發 Agent Forwarding 將本地ssh-agent轉發到遠程服務器,實現多跳免密
連接復用 Connection Multiplexing 多個SSH會話共用一個TCP連接,減少握手開銷
fail2ban fail2ban 入侵防御工具,監控日志并自動封禁惡意IP
GSSAPI Generic Security Services API 通用安全服務接口,用于Kerberos認證集成
SELinux Security-Enhanced Linux 安全增強Linux,強制訪問控制機制,影響SSH端口和文件訪問

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 服務器
    +關注

    關注

    14

    文章

    10250

    瀏覽量

    91476
  • SSH
    SSH
    +關注

    關注

    0

    文章

    200

    瀏覽量

    17717

原文標題:SSH安全加固與免密登錄:企業級SSH管理方案

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    ssh登錄過慢和登錄怎么設置

    ssh登錄過慢和登錄
    發表于 06-08 10:55

    對目前流行的ssh密碼暴力破解工具進行實戰研究、分析和總結

    Group)所制定;SSH 為建立在應用層基礎上的安全協議。SSH 是目前較可靠,專為遠程登錄會話和其他網絡服務提供安全性的協議。
    的頭像 發表于 01-29 15:10 ?5.6w次閱讀
    對目前流行的<b class='flag-5'>ssh</b>密碼暴力破解工具進行<b class='flag-5'>實戰</b>研究、分析和總結

    Linux上建立SSH安全連接的10種方法

    建立 SSH 安全連接的方法是通過 SSH (Secure Shell) 協議建立的加密通道,用于在服務器和客戶機之間的安全通信。SSH
    的頭像 發表于 05-29 10:29 ?6969次閱讀

    SSH命令詳解

    ssh是一種安全的遠程登錄及傳輸協議。ssh可用于遠程登錄、遠程文件傳輸等。ssh
    的頭像 發表于 06-02 10:00 ?2w次閱讀
    <b class='flag-5'>SSH</b>命令詳解

    虹科干貨 | 工業樹莓派開發工具指南SSH登錄工具篇

    虹科IIoT工業樹莓派開發工具指南SSH登錄工具篇前言SSH是指安全外殼協議(SecureShell),是一種加密的網絡傳輸協議,使用
    的頭像 發表于 06-09 09:52 ?1455次閱讀
    虹科干貨 | 工業樹莓派開發工具<b class='flag-5'>指南</b>之<b class='flag-5'>SSH</b><b class='flag-5'>登錄</b>工具篇

    虹科干貨 | 工業樹莓派開發工具指南SSH登錄工具篇

    獲取更多IIoT干貨點擊藍字關注我們虹科IIoT工業樹莓派開發工具指南SSH登錄工具篇前言SSH是指安全外殼協議(SecureShell),
    的頭像 發表于 06-14 10:05 ?1732次閱讀
    虹科干貨 | 工業樹莓派開發工具<b class='flag-5'>指南</b>之<b class='flag-5'>SSH</b><b class='flag-5'>登錄</b>工具篇

    如何配置交換機SSH遠程登錄

    如何配置交換機SSH遠程登錄,本期我們就來了解下ssh遠程登陸的方式,以銳捷交換機為例。
    的頭像 發表于 08-02 09:35 ?5939次閱讀
    如何配置交換機<b class='flag-5'>SSH</b>遠程<b class='flag-5'>登錄</b>?

    SSH端口號是什么?SSH是如何工作的?

    SSH(Secure Shell,安全外殼)是一種網絡安全協議,通過加密和認證機制實現安全的訪問和文件傳輸等業務。傳統遠程登錄或文件傳輸方式
    的頭像 發表于 11-10 10:06 ?4443次閱讀
    <b class='flag-5'>SSH</b>端口號是什么?<b class='flag-5'>SSH</b>是如何工作的?

    Ubuntu修改SSH默認端口指南

    修改SSH(Secure Shell)默認端口是一種增加系統安全性的方法,因為大多數攻擊都是針對默認端口22進行的。以下是在Ubuntu系統上修改SSH默認端口的指南: 1、
    的頭像 發表于 12-21 17:27 ?2965次閱讀

    NAS教程:鐵威馬如何登錄 SSH終端?

    適用型號: 所有TNAS 型號 如您有特殊操作需要通過 SSH 終端登錄 TNAS,請參照以下指引: (注意: 關于以下操作步驟中的"cd /"的指令,其作用是使當前 SSH/Telnet 連接
    的頭像 發表于 06-26 14:30 ?1275次閱讀
    NAS教程:鐵威馬如何<b class='flag-5'>登錄</b> <b class='flag-5'>SSH</b>終端?

    交換機如何配置SSH遠程登錄

    從事網絡運維工作的小伙伴們都知道,在交換機正式上線時,必須完成配置SSH遠程登錄,這樣做目的是為了日后,維護方便,不需要每次登錄設備都要跑到機房,這樣既不現實,又費事。
    的頭像 發表于 10-10 14:33 ?3892次閱讀
    交換機如何配置<b class='flag-5'>SSH</b>遠程<b class='flag-5'>登錄</b>

    禁止使用root用戶通過ssh遠程登錄Linux

    1、背景描述 出于安全考慮,需要禁止使用root用戶通過ssh遠程登錄Linux 禁用root用戶遠程登錄后,需要提供一個權限用戶用于ssh
    的頭像 發表于 12-21 16:25 ?2757次閱讀
    禁止使用root用戶通過<b class='flag-5'>ssh</b>遠程<b class='flag-5'>登錄</b>Linux

    rsync 的傳輸(同步)文件

    要實現 rsync 的傳輸(同步)文件,你需要設置 SSH 登錄。這樣,rsync 就可
    的頭像 發表于 12-23 16:26 ?2472次閱讀

    信息安全管理必備!Linux系統使用SSH登錄root賬號的方法

    Linux遠程管理信息安全必備!本文介紹各類Linux開發板/主板使用SSH登錄root賬號的方法,使用觸覺智能RK3562開發板演示,關注觸覺智能,持續為大家帶來更多使用技巧!
    的頭像 發表于 02-12 15:46 ?1294次閱讀
    信息<b class='flag-5'>安全</b>管理必備!Linux系統使用<b class='flag-5'>SSH</b><b class='flag-5'>登錄</b>root賬號的方法

    SSH遠程登錄與控制教程

    SSH(Secure Shell)是一種安全通道協議,主要用來實現字符界面的遠程登錄、遠程 復制等功能。SSH 協議對通信雙方的數據傳輸進行了加密處理,其中包括用戶
    的頭像 發表于 04-09 13:43 ?4289次閱讀
    <b class='flag-5'>SSH</b>遠程<b class='flag-5'>登錄</b>與控制教程