SSH 安全登录终极配置:从密钥生成到 fail2ban
目录
VPS 暴露在公网,第一道防线就是 SSH。默认配置(22 端口 + 密码登录)等于把家门钥匙挂在门把手上——你不去看 /var/log/auth.log,永远不知道每天有几千次自动化爆破在尝试你的 root 密码。
这篇把 SSH 安全登录的完整流程从头讲到尾:密钥生成 → 公钥上传 → 服务端配置 → 防火墙 → fail2ban,每一步都说清楚为什么这么做。
一、最终目标
四道关卡叠加,攻击成本指数级上升。
二、第一步:本地生成密钥对
在你自己的电脑上(不是 VPS):
2.1 PowerShell / Bash / Zsh 都一样
ssh-keygen -t ed25519 -C "my-vps-key" -f ~/.ssh/my-vps-key
| 参数 | 含义 |
|---|---|
-t ed25519 |
算法(ed25519 比 RSA 更短更安全) |
-C "..." |
注释,方便区分多个密钥 |
-f path |
私钥文件名 |
提示输入 passphrase(密钥保护密码):
- 本地开发机:可设可不设,设了每次用都要输
- 服务器中转 / 自动化场景:直接回车不设
2.2 生成结果
会得到两个文件:
| 文件 | 用途 |
|---|---|
~/.ssh/my-vps-key |
私钥,绝不能泄露,绝不上传 |
~/.ssh/my-vps-key.pub |
公钥,传到所有要登录的服务器 |
2.3 查看公钥内容
cat ~/.ssh/my-vps-key.pub
输出类似:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...........xxxxxxxx my-vps-key
整行复制下来。
三、第二步:把公钥放到 VPS
3.1 方式一:ssh-copy-id(最简单)
ssh-copy-id -i ~/.ssh/my-vps-key.pub root@<VPS_IP>
# 输入一次密码,自动放到 ~/.ssh/authorized_keys
3.2 方式二:手动 echo(万能)
如果商家不支持 ssh-copy-id 或 Windows 没装:
# 先用密码 SSH 进去
ssh root@<VPS_IP>
# 在 VPS 上跑
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# 把整行公钥追加到 authorized_keys
echo "ssh-ed25519 AAAAC3...... my-vps-key" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# 验证权限
ls -la ~/.ssh/
权限必须是:
drwx------ 2 root root . (.ssh 700)
-rw------- 1 root root authorized_keys (600)
🪤 90% 的“密钥登录失败”都是权限错。权限太宽 sshd 会拒绝读密钥,就一直要密码。
3.3 验证密钥登录可用
开一个新终端(旧的别关,万一密钥配错可以救):
ssh -i ~/.ssh/my-vps-key root@<VPS_IP>
不让你输密码、直接进去——成功。
四、第三步:配置 sshd
4.1 备份原配置
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
4.2 修改 /etc/ssh/sshd_config
sudo vim /etc/ssh/sshd_config
找到以下行(如果前面有 # 要去掉):
# 改端口(建议 1024-65535 之间随机选一个)
Port 22000
# 开启密钥登录
PubkeyAuthentication yes
# 指定授权文件位置
AuthorizedKeysFile .ssh/authorized_keys
# 关闭密码登录
PasswordAuthentication no
# 关闭空密码
PermitEmptyPasswords no
# 关闭挑战应答(PAM 那套)
ChallengeResponseAuthentication no
# root 只能密钥登录(保留 root 但禁密码)
PermitRootLogin prohibit-password
# 限制登录尝试次数
MaxAuthTries 3
| 配置项 | 改前 | 改后 | 作用 |
|---|---|---|---|
Port |
22 |
22000 |
避开自动化扫描 |
PubkeyAuthentication |
yes/no |
yes |
启用密钥 |
PasswordAuthentication |
yes |
no |
关闭密码登录 |
PermitEmptyPasswords |
no/yes |
no |
禁止空密码 |
PermitRootLogin |
yes |
prohibit-password |
root 只允许密钥 |
MaxAuthTries |
6 |
3 |
限制单次连接的尝试次数 |
4.3 检查配置语法(关键!)
sudo sshd -t
没有输出 = 配置正确。如果有 Bad configuration option 之类的错误,绝对不要重启 sshd——重启会导致 sshd 起不来,你就被锁外面了。
4.4 防火墙先开新端口
sudo ufw allow 22000/tcp
sudo ufw status
4.5 重启 sshd
sudo systemctl restart sshd
sudo systemctl status sshd
确认状态 active (running)。
4.6 确认监听端口
sudo ss -tlnp | grep ssh
# 应该显示
# LISTEN 0 128 0.0.0.0:22000 0.0.0.0:* users:(("sshd",pid=xxx,fd=3))
4.7 新终端验证新端口
别关旧终端,新开:
ssh -p 22000 -i ~/.ssh/my-vps-key root@<VPS_IP>
进得去——再删 22 端口的防火墙规则:
sudo ufw delete allow 22
五、第四步:fail2ban 兜底
即使密钥登录、改了端口,攻击者还是可能扫到你的端口疯狂尝试。fail2ban 会监控日志,N 次失败自动封 IP M 分钟。
5.1 装 + 配置
sudo apt install -y fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo vim /etc/fail2ban/jail.local
把 [sshd] 段改成:
[sshd]
enabled = true
port = 22000
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
backend = auto
# 自己的家庭/办公 IP 加白名单,避免自封
ignoreip = 127.0.0.1/8 ::1 <你的家庭 IP>
5.2 启动
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
5.3 常用命令
# 总览
sudo fail2ban-client status
# 看 sshd jail(含被封 IP 列表)
sudo fail2ban-client status sshd
# 手动封 / 解封
sudo fail2ban-client set sshd banip 1.2.3.4
sudo fail2ban-client set sshd unbanip 1.2.3.4
六、本地 SSH config(开发体验飞升)
每次 ssh -p 22000 -i ~/.ssh/my-vps-key root@<IP> 太累。
编辑 ~/.ssh/config:
Host myvps
HostName 1.2.3.4
Port 22000
User root
IdentityFile ~/.ssh/my-vps-key
ServerAliveInterval 60
ServerAliveCountMax 3
之后只用:
ssh myvps
| 配置项 | 含义 |
|---|---|
Host |
别名 |
HostName |
真实 IP/域名 |
Port |
端口 |
User |
默认用户 |
IdentityFile |
私钥路径 |
ServerAliveInterval |
多少秒发一次心跳(防止 NAT 断开) |
ServerAliveCountMax |
心跳几次没回应才认定断了 |
七、Termius / Tabby / 其它 GUI 客户端
这类工具的“添加密钥”功能:
- 生成密钥:在客户端里
Keys → Generate Key - 导入私钥:把本地生成的私钥整个文件内容粘贴进去(不要只贴公钥)
- 绑定到主机:在主机配置里选这个 key
不同客户端 UI 不一样,原理都是一样:私钥放在客户端 / 本地,公钥放在 VPS 的 ~/.ssh/authorized_keys。
八、所有关键文件位置
| 文件 | 作用 | 权限 |
|---|---|---|
本地 ~/.ssh/private_key |
私钥 | 600 |
本地 ~/.ssh/public_key.pub |
公钥 | 644 |
本地 ~/.ssh/config |
客户端配置 | 600 |
VPS /etc/ssh/sshd_config |
服务端配置 | 644 |
VPS ~/.ssh/authorized_keys |
已授权公钥列表 | 600 |
VPS /var/log/auth.log |
SSH 登录日志 | - |
VPS /etc/fail2ban/jail.local |
fail2ban 配置 | - |
九、踩坑清单
| 现象 | 原因 | 解决 |
|---|---|---|
| 密钥配了还是要密码 | ~/.ssh 或 authorized_keys 权限不对 |
chmod 700 ~/.ssh; chmod 600 authorized_keys |
| 改端口连不上 | 防火墙没放新端口 | VNC 进去 ufw allow 新端口 |
| sshd restart 后服务起不来 | 配置语法错 | 用 sshd -t 提前检查 |
| 改了配置没生效 | 没 restart sshd | systemctl restart sshd |
| 改端口没生效(仍 22) | 云厂商平台代理 SSH | ss -lntp grep :22 看监听的是 sshd 还是 init |
| fail2ban 把自己封了 | 没加 ignoreip | VNC 进去 fail2ban-client set sshd unbanip 你的IP |
| 部分商家轻量服务器没法改端口 | 平台层硬编码 22 | 去厂商控制台改 |
十、几条实用经验
- 不要用 RSA,用 ed25519。短、快、安全。
- 公钥可以放多份,
authorized_keys一行一个,多设备共用同一 VPS 很方便。 - 私钥分机器:每台开发机生成自己的密钥,VPS 上
authorized_keys加多行,任何一台机器丢失只需要删那行。 - 改完 sshd 一定先
sshd -t再 restart——这一条能救命。 - fail2ban 不是万能:它防 SSH 爆破有用,对零日漏洞无能为力。保持系统更新才是根本。
- 永远不要图省事用密码登录——爆破一旦被打穿,整台机器没了。
完成这一套,你的 SSH 已经能扛住绝大多数自动化攻击。剩下的就是养成“系统勤更新、关注 CVE”的习惯。