FieryWing 的技术博客

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 加固里有几步一旦做错,就会把自己锁在服务器外面。我自己遵守这几条:

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 入门)。否则关掉之后你将没有任何入口。操作流程建议如下:

  1. 保持原会话不关闭。
  2. 修改配置文件,保存。
  3. 检查语法:sudo sshd -t,没有输出表示没问题。
  4. 重载服务:sudo systemctl reload ssh(部分系统服务名为 sshd)。
  5. 新开一个本地终端,用密钥登录测试,同时测试 sudo whoami。
  6. 测试通过后,才能关闭旧会话。

还有一个坑: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,比直接把服务暴露到公网更安全。

常见问题与排查

其他值得做的事

除了上述几条,还可以定期执行系统更新,保持 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 检查,测试通过再收尾。这些做法不花钱,却能挡掉绝大多数无差别的扫描和爆破。