服务器 SSH 安全加固:从改端口到免密登录的完整配置
SSH 是管理 Linux 服务器最主要的入口,默认配置下暴露 22 端口、允许 root 密码登录,很容易被扫描和暴力破解。
本文按照“先备份、再改配置、逐项验证”的顺序,讲清楚服务器 SSH 安全加固的完整流程。
操作前请确保你有一台可以正常 SSH 登录的服务器,并且拥有 root 或 sudo 权限。
动手前先做两件事:备份和留后路
加固过程中如果配置写错,可能导致自己也无法登录。
建议先做以下准备:
- 备份原始配置文件:
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak - 确认当前登录方式正常,并保持一个已登录的 SSH 窗口不要关闭,方便出错时回滚。
- 如果使用云服务器,提前在控制台确认 VNC 或救援模式可用,万一 SSH 断开可以通过网页终端恢复。
修改任何配置后,不要直接重启 SSH 服务,先用 sshd -t 检查语法:
sshd -t
如果没有输出,说明配置语法正确;
有报错则根据提示行号修改。
修改默认端口并限制登录来源
SSH 默认使用 22 端口,自动化扫描器会优先尝试这个端口。
改为一个非标准端口能减少大量无效扫描,但并不能替代密钥认证。
编辑配置文件:
vi /etc/ssh/sshd_config
找到 #Port 22,去掉注释并改成自定义端口,例如:
Port 22222
如果服务器有固定管理 IP,可以进一步限制监听地址:
ListenAddress 192.0.2.10
保存后先检查语法,再重启服务:
sshd -t
systemctl restart sshd
验证新端口是否生效:
ss -tlnp | grep 22222
看到 LISTEN 状态说明端口已监听。
此时不要关闭当前 SSH 窗口,另开一个终端用新端口登录测试:
ssh -p 22222 用户名@服务器IP
登录成功后再关闭旧窗口。
禁用 root 密码登录,改用密钥认证
密码可以被暴力猜解,密钥认证则几乎无法被穷举。
加固的核心是关闭密码登录,只允许密钥。
生成密钥对
在本地电脑执行:
ssh-keygen -t ed25519 -C "your_email@example.com"
按提示保存密钥,建议设置一个私钥密码。
生成的公钥默认在 ~/.ssh/id_ed25519.pub。
上传公钥到服务器
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 22222 用户名@服务器IP
如果没有 ssh-copy-id,可以手动把公钥内容追加到服务器对应用户的 ~/.ssh/authorized_keys 文件。
关闭密码登录和 root 远程登录
再次编辑 /etc/ssh/sshd_config,修改以下参数:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
注意:PermitRootLogin no 表示不允许 root 用户直接 SSH 登录,请确保你已经有一个普通用户可以通过密钥登录,并且该用户能使用 sudo。
重启 SSH 前先测试语法并确认密钥登录正常:
sshd -t
systemctl restart sshd
新开终端测试密钥登录,成功后再关闭旧会话。
限制可登录用户和失败尝试
即使关闭了密码登录,仍然建议限制哪些用户能通过 SSH 访问。
在 sshd_config 末尾添加:
AllowUsers deploy admin
只允许 deploy 和 admin 两个用户登录,其他用户即使有密钥也会被拒绝。
同时可以设置登录尝试次数和超时时间:
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
这些参数能减少暴力尝试窗口,并在空闲连接上自动断开。
如果希望自动封禁多次失败的 IP,可以安装 Fail2ban:
apt update && apt install fail2ban -y
复制默认配置并启用 SSH 规则:
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
在 jail.local 的 [sshd] 段落中设置:
enabled = true
port = 22222
maxretry = 3
bantime = 3600
启动并设置开机自启:
systemctl enable fail2ban
systemctl start fail2ban
查看封禁状态:
fail2ban-client status sshd
防火墙放行新端口
修改 SSH 端口后,防火墙必须同步放行,否则新连接会被拒绝。
以 ufw 为例:
ufw allow 22222/tcp
ufw delete allow 22/tcp
ufw enable
ufw status
如果使用 firewalld,对应命令为:
firewall-cmd --permanent --add-port=22222/tcp
firewall-cmd --permanent --remove-port=22/tcp
firewall-cmd --reload
firewall-cmd --list-ports
云服务器还需要在控制台的安全组中放行新端口,并移除 22 端口的公网规则。
常见报错和避坑提醒
配置改完无法登录:先检查 sshd -t 是否通过,再确认防火墙和云安全组是否放行新端口。
如果仍然无法登录,通过 VNC 恢复备份文件:cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config,重启 SSH 服务。
密钥登录仍然提示输入密码:检查服务器上 ~/.ssh 目录权限应为 700,authorized_keys 权限应为 600,属主必须是登录用户。
SELinux 导致端口无法监听:
在 CentOS 或 RHEL 上,
如果修改端口后服务起不来,
可能需要执行 semanage port -a -t ssh_port_t -p tcp 22222 放行新端口。
不要同时关闭密码和密钥:PasswordAuthentication no 和 PubkeyAuthentication yes 必须搭配使用,确保至少有一种可用的登录方式。
加固完成后的检查清单
逐项确认以下内容,全部通过才算完成:
- 新端口可以正常 SSH 登录,旧端口已关闭或被防火墙拒绝;
- root 用户无法直接远程登录;
- 密码登录已关闭,只能使用密钥;
AllowUsers只放行了必要账号;- Fail2ban 正在运行,
fail2ban-client status sshd能看到当前封禁情况; - 云安全组和系统防火墙都已同步放行新端口。
服务器 SSH 安全加固不是一次性任务,后续新增用户、更换端口或调整防火墙时,都要同步更新 SSH 配置和放行规则,避免把自己锁在门外。
关于密钥和密码的常见疑问
私钥需要设置密码吗? 建议设置。
私钥密码用于保护本地私钥文件,即使私钥泄露,攻击者也需要破解密码才能使用。
改了端口是不是就不用密钥了? 不是。
改端口只能减少扫描噪声,不能阻止针对性攻击,密钥认证仍是核心防线。
Fail2ban 会不会误封自己? 如果多次输错密钥或密码,可能触发封禁。
可以在 jail.local 中把自己的管理 IP 加入 ignoreip。