菜单

Administrator
发布于 2026-10-10 / 1 阅读
0
0

Linux 进阶 L19:SSH 加固——把黑客挡在门外

Linux 进阶 L19:SSH 加固——把黑客挡在门外

你的服务器每时每刻都在被陌生人敲门。这不是危言耸听,下面这段日志就截自我自己的这台博客服务器(今天刚抓的):

$ journalctl -u ssh | grep "Failed password" | tail -3
Oct 10 11:58:23 ip-172-26-2-80 sshd-session[1006426]: Failed password for root from 195.178.110.227 port 56700 ssh2
Oct 10 11:59:48 ip-172-26-2-80 sshd-session[1006649]: Failed password for root from 195.178.110.227 port 59918 ssh2

看不懂没关系,关键信息就三个:有人(195.178.110.227)、在试 root 账号的密码、失败了。这种扫描全网的机器 24 小时不停,你的服务器上线第一天就会被光顾。密码再复杂,也架不住日夜不停的字典爆破。

好消息是:SSH 加固做完,爆破就彻底失效——因为服务器根本不再接受密码登录。这篇把 SSH 加固从头到尾做一遍,全是真机实操。

先看清现状:你的 SSH 现在什么配置

打开服务器上的 SSH 配置文件看看(Debian 13,OpenSSH 10.0):

$ sshd -V
OpenSSH_10.0p2 Debian-7+deb13u4, OpenSSL 3.5.7 9 Jun 2026

$ grep -vE "^\s*#|^\s*$" /etc/ssh/sshd_config
PermitRootLogin yes
PubkeyAuthentication yes
PasswordAuthentication yes
KbdInteractiveAuthentication no

解读一下这三行 yes:

  • PermitRootLogin yes —— 允许 root 直接登录。黑客最爱,因为用户名都不用猜,全世界的 Linux 都有 root。

  • PubkeyAuthentication yes —— 允许密钥登录。好东西,留着。

  • PasswordAuthentication yes —— 允许密码登录。这就是黑客正在利用的那扇门。

默认配置等于"大门敞开,欢迎试密码"。加固的目标就是:关掉密码这扇门,只留密钥这条小路。

密码登录和密钥登录,到底差在哪

打个比方:

  • 密码登录 = 你家门上有个密码键盘,任何人都能走过去试。试错了也没代价,换个密码继续试。

  • 密钥登录 = 你家门只能用一把特制的钥匙开。钥匙分两半:一半(公钥)放在门上,一半(私钥)揣你兜里。没钥匙的人连"试"的机会都没有——服务器直接拒绝,连密码输入框都不给你。

密钥有多难破解?我们用的是 ed25519 算法,256 位。暴力破解它需要的算力,比把全宇宙的原子都用上还不够。密码是"难猜",密钥是"猜不动",这是质的区别。

第一步:生成你的密钥对

在你自己的电脑(不是服务器)上运行:

$ ssh-keygen -t ed25519 -C "my-laptop"
Generating public/private ed25519 key pair.
Your identification has been saved in /tmp/demo_key
Your public key has been saved in /tmp/demo_key.pub
The key fingerprint is:
SHA256:7QHleGlij0LPrOhc6fK6r/sIBWruu24Zzbe9OwgYFJ8 demo@local
The key's randomart image is:
+--[ED25519 256]--+
| ..       .      |
| .. .    + .     |
|. .E  . = =      |
| o . . = O       |
|..= . . S +      |
|oo = o + . .     |
| .+ + B   .      |
|.o +.* o         |
|o=o OX=o+        |
+----[SHA256]-----+

(上面是在服务器上演示生成的,用完就删了,你在自己电脑上跑,路径会是 ~/.ssh/id_ed25519。)

逐句解读:

  • -t ed25519 —— 指定算法。ed25519 是目前最推荐的:又短又快又安全,比老式的 rsa-2048 强。

  • -C "my-laptop" —— 注释,随便写,方便以后认出"这是哪台电脑的钥匙"。

  • 运行后会问你存哪、要不要设密码(passphrase):直接回车用默认路径;passphrase 建议设一个,等于给钥匙再加一把锁,私钥丢了也不怕。

生成完得到两个文件,千万分清:

文件

名字

能不能给别人看

id_ed25519

私钥(你的那半钥匙)

绝对保密,谁拿到谁就能登录你的服务器

id_ed25519.pub

公钥(门上的那半)

随便给,贴博客上都没事

公钥长这样(一行):

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEJ1WNUPwAJHWi24DZWWBhFjBB0VrVtw4BiYFqdYI/u+ demo@local

第二步:把公钥送上服务器

最省事的方法,一条命令搞定(在你电脑上运行,把 your-server-ip 换成服务器 IP):

$ ssh-copy-id root@your-server-ip

它会让你输一次密码(最后一次输密码的机会,珍惜),然后自动把公钥追加到服务器的 ~/.ssh/authorized_keys 文件里。

手动党也可以自己来,分两步:

# 1. 在你电脑上:显示公钥,复制整行
$ cat ~/.ssh/id_ed25519.pub

# 2. 登录服务器:粘贴进去
$ mkdir -p ~/.ssh && chmod 700 ~/.ssh
$ nano ~/.ssh/authorized_keys    # 粘贴公钥,保存
$ chmod 600 ~/.ssh/authorized_keys

注意两个权限数字:~/.ssh 目录必须是 700,authorized_keys 必须是 600。权限不对,SSH 会直接无视你的公钥——这是很多人"密钥配好了却登不上"的头号原因。

第三步:验证密钥登录(重要,别跳过)

先别急着关密码! 新开一个终端窗口,用密钥试登录:

$ ssh -i ~/.ssh/id_ed25519 root@your-server-ip

如果直接进去了、没问你要密码,说明密钥通道通了。再确认一遍服务器认出了你的钥匙:

$ ssh root@your-server-ip "cat ~/.ssh/authorized_keys" | cut -c1-60
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEJ1WNUPwAJHWi24DZWWBhFjBB0VrVtw4...

两个窗口都保持登录状态——这是你的"安全绳"。万一后面改错了配置,还有个活着的会话能进去修。老手翻车,十有八九是把自己锁在门外还断了所有连接。

第四步:关闭密码登录(核心动作)

确认密钥能用之后,编辑服务器上的 SSH 配置:

$ sudo nano /etc/ssh/sshd_config

找到这一行,改成 no:

PasswordAuthentication no

保存后重启 SSH 服务让配置生效:

$ sudo systemctl restart ssh
$ sudo systemctl status ssh --no-pager | head -3
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; ...)
     Active: active (running) since ...

验证:从你电脑上故意用密码试一次(加 -o PreferredAuthentications=password 强制走密码):

$ ssh -o PreferredAuthentications=password root@your-server-ip
root@your-server-ip: Permission denied (publickey).

Permission denied (publickey) —— 服务器连密码输入框都不给了,只认密钥。爆破脚本从此对你这台机器彻底失业:它手里没有你的私钥,试一亿个密码也没用。

第五步:禁止 root 直接登录

root 是全网都知道的用户名,等于告诉黑客"用户名我已经告诉你了,你只管猜密码"。配合密钥登录,正确姿势是:用普通用户登录,再 sudo 提权。

# 在服务器上:先确保你有个带 sudo 权限的普通用户,并且它的 authorized_keys 里也有你的公钥
$ sudo useradd -m -s /bin/bash deploy
$ sudo usermod -aG sudo deploy
$ sudo mkdir -p /home/deploy/.ssh && sudo cp ~/.ssh/authorized_keys /home/deploy/.ssh/
$ sudo chown -R deploy:deploy /home/deploy/.ssh && sudo chmod 700 /home/deploy/.ssh && sudo chmod 600 /home/deploy/.ssh/authorized_keys

# 确认 deploy 能用密钥登录后,再改配置
$ sudo nano /etc/ssh/sshd_config

改成:

PermitRootLogin no

重启 ssh 后,ssh root@your-server-ip 会直接被拒绝,只能 ssh deploy@your-server-ip 再 sudo -i。攻击面又小一圈。

第六步:换个端口?(可选,聊聊真相)

很多人加固教程第一条就是"把 22 端口改掉"。说实话:换端口防不住定向攻击,只能挡住扫全网的脚本小子——但挡掉 99% 的噪音日志也是实实在在的好处,日志干净了,真有事你才看得见。

$ sudo nano /etc/ssh/sshd_config
# 把 #Port 22 改成(比如)
Port 2222

$ sudo systemctl restart ssh
# 记得防火墙放行新端口!不然自己都进不来
$ sudo ufw allow 2222/tcp

登录时加上 -p:

$ ssh -p 2222 deploy@your-server-ip

⚠️ 血泪提醒:改端口前,务必确认防火墙放行了新端口,云服务商的安全组也要放行。先开新端口测试能连,再考虑关 22。我见过太多人改完端口、防火墙没开,直接失联。

第七步:Fail2Ban 兜底(纵深防御)

关了密码登录之后,爆破已经不可能成功。但扫描器还是会不停敲门,写满你的日志。Fail2Ban 就是"看门大爷":谁短时间内失败太多次,直接拉黑 IP。

我这台服务器上它正在工作,看看它的"战绩":

$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed:    0
|  |- Total failed:    7
|  `- Journal matches:    _SYSTEMD_UNIT=ssh.service + _COMM=sshd
`- Actions
   |- Currently banned:    0
   |- Total banned:    1
   `- Banned IP list:

解读:累计拦截了 7 次失败登录,封过 1 个 IP。配合"只认密钥"的配置,现在这台服务器的状态是:密码试不进来(配置层面拒绝),乱试的 IP 还会被封(Fail2Ban 层面拉黑)。双保险。

Fail2Ban 的安装配置我之前专门写过一篇(《Fail2Ban 防护:自动封禁 SSH 爆破 IP》),这里不重复,记住它的定位就行:它是"减噪音"的,不是"防入侵"的。真正的防线是密钥登录,Fail2Ban 只是让日志清净、顺手挡掉低级扫描。

第八步(进阶):密钥 + 密码双因素

偏执狂专用:要求"既有钥匙,又要对上暗号"才放行。适合放了重要数据的机器。

$ sudo nano /etc/ssh/sshd_config
# 取消注释或添加:
AuthenticationMethods publickey,password
PasswordAuthentication yes    # 注意:这里要重新打开,但只在"已有密钥"之后才问密码

重启后登录流程变成:先验证密钥 → 再问密码。两道都过才进门。缺点是自动化脚本(比如 rsync 定时备份)会变麻烦,按需使用。

急救包:万一把自己锁门外了怎么办

先别慌,按这个顺序自救:

  1. 检查是不是还有活着的 SSH 会话——没断开的那个窗口就是救命稻草,直接进去改配置。

  2. 云服务商的网页控制台:Lightsail / 各大云都有浏览器里的紧急 SSH(走的是独立通道,不走你改坏的那个 sshd 配置,大多数情况下还能进)。我这台 Lightsail 就留着这条后路。

  3. VNC / 救援模式:终极手段,挂载磁盘改文件,慢但是稳。

  4. 预防胜于治疗:每次改 sshd_config 之前,先 cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak 备个份;改完用 sshd -t 检查语法,通过了再重启:

$ sudo sshd -t && echo "语法 OK" && sudo systemctl restart ssh

sshd -t 不输出就是没毛病,有毛病它会直接告诉你第几行写错了。

小结

加固措施

防什么

难度

优先级

密钥登录 + 关闭密码登录

密码爆破(釜底抽薪)

⭐⭐

🔴 必做

禁止 root 直接登录

用户名已知的定向攻击

⭐

🔴 必做

普通用户 + sudo

误操作毁系统

⭐

🟡 推荐

Fail2Ban 自动封禁

扫描噪音、日志轰炸

⭐

🟡 推荐

更换 SSH 端口

全网扫描脚本

⭐

🟢 可选

密钥+密码双因素

私钥泄露的极端情况

⭐⭐⭐

🟢 按需

改前备份 + sshd -t 检查

把自己锁门外

⭐

🔴 必做

SSH 加固的本质就一句话:把"人人都能试"变成"没钥匙连试的资格都没有"。做完前两行(密钥登录、禁 root),你的服务器就已经比 95% 的公网机器安全了。剩下的,是让日志更干净、让偏执狂更安心。

下一篇预告:防火墙进阶——ufw 只是开胃菜,iptables/nftables 才是真正的包过滤,下期带你看透 Linux 防火墙的五条链。


评论