SSH 安全加固:给你的服务器上把锁
2026-06-21
只要服务器有公网 IP,SSH 端口就会不断被扫描和爆破。几个简单的措施可以大幅降低风险。
先看看自己正在被扫描
新买的服务器,过不了多久日志里就会出现大量登录失败记录。在 Debian 或 Ubuntu 上可以这样查看:
sudo journalctl -u ssh --no-pager -n 50 sudo grep "Failed password" /var/log/auth.log | tail
注意有的系统服务名是 ssh,有的是 sshd;较新的 Debian 默认可能没有 auth.log,用 journalctl 即可。这些记录大多来自自动化脚本,并不是针对你个人,但弱密码确实会被撞开,所以加固很有必要。
动手前的安全守则
SSH 加固里有几步一旦做错,就会把自己锁在服务器外面。我自己遵守这几条:
- 永远保留一个已登录的会话,不要关闭,直到新的登录方式在另一个窗口测试通过。
- 改配置前先备份:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak。 - 改完先检查语法再重载,不要直接重启。
- 确认云厂商提供控制台(VNC 或救援模式)作为最后的后路。
1. 使用密钥登录
ssh-keygen -t ed25519 ssh-copy-id -p 22 user@your-server
私钥务必设置口令并妥善保管,不要发给别人。
如果没有 ssh-copy-id,也可以手动把公钥追加到服务器上的 ~/.ssh/authorized_keys,并保证权限正确:
mkdir -p ~/.ssh chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
权限过宽是密钥登录失败最常见的原因之一,sshd 会因为目录或文件权限不安全而拒绝使用密钥。用 ssh-keygen 生成的文件里,没有 .pub 后缀的是私钥,只能留在自己电脑上,只有 .pub 文件才可以上传。
2. 关闭密码登录和 root 登录
确认密钥能登录之后,编辑 /etc/ssh/sshd_config:
PasswordAuthentication no PermitRootLogin no
然后重载 SSH 服务。修改前请保持当前会话不要断开,避免把自己锁在门外。
警告:关闭 root 登录之前,必须确认已有一个能用密钥登录、并且拥有 sudo 权限的普通用户(创建方法见 VPS 入门)。否则关掉之后你将没有任何入口。操作流程建议如下:
- 保持原会话不关闭。
- 修改配置文件,保存。
- 检查语法:
sudo sshd -t,没有输出表示没问题。 - 重载服务:
sudo systemctl reload ssh(部分系统服务名为 sshd)。 - 新开一个本地终端,用密钥登录测试,同时测试
sudo whoami。 - 测试通过后,才能关闭旧会话。
还有一个坑:Debian 和 Ubuntu 的 /etc/ssh/sshd_config.d/ 目录下可能有额外的配置文件,会覆盖主文件的设置。如果改完发现密码登录仍然可用,可以用 sudo sshd -T | grep -i passwordauthentication 查看实际生效的值,再检查那个目录。
3. 修改端口并配合防火墙
改端口只能减少无意义的扫描,不是真正的安全手段,最好配合防火墙只允许必要的来源。
如果决定修改端口,顺序很关键:先放行新端口,再改配置,测试通过后才去掉旧端口。以 ufw 为例,假设新端口为 2222:
sudo ufw allow 2222/tcp # 在 sshd_config 中加入 Port 2222,并先保留 Port 22 sudo sshd -t sudo systemctl reload ssh # 新终端测试:ssh -p 2222 user@203.0.113.10 # 确认可用后,再删除旧端口规则和 Port 22 sudo ufw delete allow 22/tcp
请不要在没有放行 SSH 端口的情况下执行 ufw enable。同时别忘了云厂商的安全组也要放行新端口。较新的 Ubuntu 可能使用 systemd 的 socket 激活来监听 SSH,此时改端口可能还要调整 ssh.socket,如果改完发现端口没变,请查阅所用版本的文档。防火墙的更多内容见 防火墙。
4. 装 fail2ban
fail2ban 会根据登录失败日志自动封禁可疑 IP。
sudo apt install -y fail2ban sudo systemctl enable --now fail2ban
不要直接改 jail.conf,而是新建 /etc/fail2ban/jail.local:
[sshd] enabled = true maxretry = 5 findtime = 10m bantime = 1h ignoreip = 127.0.0.1/8 203.0.113.5
ignoreip 里可以写你自己固定的 IP(这里 203.0.113.5 为示例),避免自己输错密码被封。若你改了 SSH 端口,要在 [sshd] 里加上 port = 2222。修改后重启并查看状态:
sudo systemctl restart fail2ban sudo fail2ban-client status sshd
如果不小心把自己封了,可以通过云厂商控制台登录,执行 sudo fail2ban-client set sshd unbanip 你的IP 解封。
5. 用完要清理
临时添加的公钥,用完后记得从 ~/.ssh/authorized_keys 中删除。
给每把公钥的末尾写上注释(比如“笔记本-2026”),以后清理时才知道哪一行属于哪台设备。换电脑、离职交接、怀疑私钥泄露时,都应该及时清点这个文件。
日常使用小技巧
在自己电脑的 ~/.ssh/config 里写一段配置,就不用每次输入长命令:
Host myvps
HostName 203.0.113.10
User deploy
Port 22
IdentityFile ~/.ssh/id_ed25519
之后直接 ssh myvps 即可。需要从本地访问服务器内网服务时,可以用端口转发,比如 ssh -L 8080:127.0.0.1:80 myvps,比直接把服务暴露到公网更安全。
常见问题与排查
- Permission denied (publickey):多半是公钥没装对、权限不对,或是用了错误的用户名和私钥。用
ssh -v看客户端尝试了哪些密钥。 - Connection refused:服务没有监听该端口,或者端口没放行,用
sudo ss -tlnp | grep ssh检查。 - Connection timed out:通常是防火墙或安全组拦截,或者 IP 填错。
- WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED:服务器重装后指纹变了。确认确实是自己重装的,再用
ssh-keygen -R 203.0.113.10删除旧记录。如果你没有重装,就要警惕中间人风险。 - 已经把自己锁在外面:用服务商的 VNC 控制台或救援模式登录,恢复备份的 sshd_config。
其他值得做的事
除了上述几条,还可以定期执行系统更新,保持 OpenSSH 版本较新;只开放需要的服务端口;用 AllowUsers deploy 限制允许登录的用户;为重要机器启用二步验证。每一项都不复杂,但叠起来就是好几层防护,对应的 Web 服务加密部分见 HTTPS 与证书,域名访问见 DNS 是什么。
密钥管理的几点建议
私钥是身份凭证,丢了就等于钥匙丢了。我的做法是:每台常用设备各生成一把密钥,而不是复制同一把到处用;这样某台设备丢失时,只需要从服务器上删掉对应的那一行公钥。私钥设置口令后,可以配合 ssh-agent 在一次会话中只输入一次口令:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519
备份私钥时要放在加密的存储里,不要放进网盘、聊天记录或公开代码仓库。如果怀疑私钥已经泄露,应立刻在服务器上移除对应公钥,并生成新密钥。
检查当前登录情况
除了加固,也要定期看看有没有异常的登录:
last -n 10 who sudo lastb | head
其中 last 显示最近成功登录记录,lastb 显示失败尝试(需要 root 权限,部分系统可能没有记录)。如果发现陌生的 IP 成功登录,应立即排查:修改密码、检查 authorized_keys、查看异常进程,必要时重装系统。
总结
SSH 加固的核心顺序是:先配好密钥登录并测试,再关闭密码和 root 登录,端口和防火墙调整要先放行再生效,最后用 fail2ban 做自动封禁。每一步都留一个备用会话,改完用 sshd -t 检查,测试通过再收尾。这些做法不花钱,却能挡掉绝大多数无差别的扫描和爆破。