前言

新机器到手,控制台给的往往是 root + 22 端口 + 初始密码。公网上默认 SSH 扫库非常猛,不加固就等于把登录面敞着。

本文按 Debian 2系统流程整理「拿到 VPS 建议先做完」的基础清单,密钥登录单独成文,本文默认你已经做完并测通。

前置: 已完成 SSH 密钥登录,本机可用私钥登录。尚未完成密钥就不要关密码。

本文参数:

取值
系统 Debian12
管理用户 root
SSH 端口 39217(文中示例端口,请换成自己的;勿用 22/2222 等过常见端口)
登录方式 仅密钥(关闭密码)
Fail2ban 监控 sshd,端口与 SSH 一致

日常登录(全部完成后):

1
ssh -i $env:USERPROFILE\.ssh\id_finalshell_rsa -p 39217 root@你的服务器IP

总顺序

1
2
3
4
5
6
7
8
9
① 系统更新 + 时区
② 终端修改 root 密码(可选:商家后台)
③ 确认密钥登录已测通 ← 上篇
④ 修改 SSH 端口(新窗口测通)
⑤ 关闭密码登录(新窗口测通) ← 注意 cloud-init
⑥ 安装并配置 Fail2ban
⑦(推荐)原版 BBR
⑧(推荐)添加 Swap
⑨ 收尾自检

铁律:

  1. 改 SSH 时 始终留一条已登录会话,用 新窗口 验证成功后再关旧会话。
  2. 顺序只能是:密钥通 → 端口通 → 再关密码。反了容易把自己锁在门外。
  3. 商家控制台是否有 VNC / 网页终端 / 救援模式,先确认,作最后退路。
  4. 有「安全组 / 云防火墙」时,改端口前先放行新端口 TCP,否则新会话进不来。

系统更新 + 时区 + 基础工具

以 root 登录后执行:

1
2
3
4
5
6
7
8
9
10
11
12
export DEBIAN_FRONTEND=noninteractive

apt-get update
apt-get -y upgrade
apt-get -y install \
curl wget ca-certificates gnupg lsb-release \
vim htop net-tools sudo

timedatectl set-timezone Asia/Shanghai

date
timedatectl

期望: 时区为 Asia/Shanghaidate 显示 CST。

修改root密码

SSH终端里改

已用密码或密钥进到服务器后,执行:

1
2
# 交互式:按提示输入两遍新密码(输入时不回显,属正常)
passwd

也可用一条命令非交互写入(shell 历史里会留下明文,日常更推荐上面的 passwd):

1
2
# 将 NewStrongPass_ 换成你的强密码
echo 'root:NewStrongPass_' | chpasswd

期望: passwd 提示 password updated successfully(或 chpasswd 无报错即成功)。

商家后台改密码

部分商家面板提供「重置 root 密码 / 发送新密码邮件」。这只作备用,例如:

  • 当前进不了系统,只能走面板重置;
  • 或你更习惯先在后台点一次再 SSH。

确认密钥登录已就绪

若还没配密钥,先完成上篇再继续。本机应已能类似这样进入 shell:

1
ssh -i $env:USERPROFILE\.ssh\id_finalshell_rsa -o IdentitiesOnly=yes root@你的服务器IP

(端口若仍是 22,可不写 -p。)

能进 root shell 才往下改端口、关密码。 旧会话先不要关。

修改 SSH 端口

改配置并重启 sshd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.port

# 有 Port 行则改,没有则追加(端口请改成你自己的)
if grep -qE '^[#[:space:]]*Port[[:space:]]+' /etc/ssh/sshd_config; then
sed -i -E 's/^[#[:space:]]*Port[[:space:]].*/Port 39217/' /etc/ssh/sshd_config
else
echo 'Port 39217' >> /etc/ssh/sshd_config
fi

sshd -t && systemctl restart ssh

# 验证
ss -lntp | grep sshd
sshd -T | grep -E '^port '

本机新窗口测通

FinalShell / OpenSSH 都把端口改成 39217新开连接测试:

1
ssh -i $env:USERPROFILE\.ssh\id_finalshell_rsa -p 39217 -o IdentitiesOnly=yes root@你的服务器IP

必须新端口密钥登录成功后,再关旧会话、再做下一步。


禁止 SSH 密码登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 覆盖 cloud-init 下发的密码登录开关
echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/50-cloud-init.conf

# 降低之后 cloud-init 再改回 yes 的概率
mkdir -p /etc/cloud/cloud.cfg.d
cat > /etc/cloud/cloud.cfg.d/99-disable-ssh-pwauth.cfg <<'EOF'
ssh_pwauth: false
EOF

# 加固片段(文件名靠后,语义清晰;与上面形成双保险)
cat > /etc/ssh/sshd_config.d/zz-hardening.conf <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
EOF

# 主配置一并规范
sed -i -E 's/^[#[:space:]]*PasswordAuthentication[[:space:]].*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i -E 's/^[#[:space:]]*KbdInteractiveAuthentication[[:space:]].*/KbdInteractiveAuthentication no/' /etc/ssh/sshd_config
sed -i -E 's/^[#[:space:]]*PubkeyAuthentication[[:space:]].*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i -E 's/^[#[:space:]]*PermitRootLogin[[:space:]].*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config

sshd -t && systemctl restart ssh

# 看生效值(以 sshd -T 为准,不要只看配置文件)
sshd -T | egrep 'passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|permitrootlogin|port '

期望类似:

1
2
3
4
5
port 39217
passwordauthentication no
pubkeyauthentication yes
permitrootlogin without-password
kbdinteractiveauthentication no

说明:

指令 含义
PasswordAuthentication no 关闭密码登录
KbdInteractiveAuthentication no 关掉键盘交互类认证,避免绕过
PubkeyAuthentication yes 明确允许公钥
PermitRootLogin prohibit-password 允许 root,但只能密钥sshd -T 里常显示为 without-password

本机验证

1
2
3
4
5
# 应成功
ssh -i $env:USERPROFILE\.ssh\id_finalshell_rsa -p 39217 -o IdentitiesOnly=yes root@你的服务器IP

# 应失败:Permission denied(强制只走密码)
ssh -p 39217 -o PubkeyAuthentication=no -o PreferredAuthentications=password -o NumberOfPasswordPrompts=1 root@你的服务器IP

密钥能进、纯密码进不去,这一步才算完成。

sshd -T 仍是 passwordauthentication yes:再写一次 50-cloud-init.confnosystemctl restart ssh,用 sshd -T 复查。

安装 Fail2ban

改端口 + 仅密钥后,扫库大多直接失败;Fail2ban 负责在短时间多次失败后 封禁源IP,减轻噪音与偶发撞库。

安装

1
2
3
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get -y install fail2ban python3-systemd iptables

配置(端口必须与 SSH 一致)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
banaction = iptables-multiport
allowipv6 = auto
EOF

# jail.d 里只写 [sshd],不要再塞一整段 [DEFAULT] 造成混乱
cat > /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled = true
port = 39217
filter = sshd
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
EOF

# 消除 allowipv6 相关提示(可选)
cat > /etc/fail2ban/fail2ban.local <<'EOF'
[Definition]
allowipv6 = auto
EOF

fail2ban-client -t
rm -f /run/fail2ban/fail2ban.sock /var/run/fail2ban/fail2ban.sock
systemctl enable --now fail2ban
systemctl restart fail2ban
sleep 2

systemctl is-active fail2ban
fail2ban-client status
fail2ban-client status sshd

期望:

  • fail2banactive
  • Jail 列表含 sshd
  • port 与当前 SSH 端口一致(此处为 39217

查看 SSH 近期日志(Debian 12):

1
journalctl -u ssh -n 20 --no-pager

若以后又改了 SSH 端口,记得同步改 /etc/fail2ban/jail.d/sshd.local 里的 portsystemctl restart fail2ban

开启原版 BBR

小带宽 VPS 上,内核自带 BBR + fq 通常比默认拥塞控制更稳一些,不必上第三方「暴力 TCP」脚本。

1
2
3
4
5
6
7
8
9
10
11
12
cat > /etc/sysctl.d/99-bbr.conf <<'EOF'
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
EOF

sysctl --system >/dev/null
sysctl -p /etc/sysctl.d/99-bbr.conf

sysctl net.ipv4.tcp_congestion_control
sysctl net.core.default_qdisc
sysctl net.ipv4.tcp_available_congestion_control
lsmod | grep bbr

期望:

1
2
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

available 中含 bbrlsmod 可见 tcp_bbr(少数内建编译场景列表为空,以 sysctl 为准)。


添加 Swap

内存不大的机器,给一点 Swap 作 OOM 缓冲。服务器一般不休眠,不必按「2 倍内存」算;6G 内存常见用 2~4G,这里取 4G

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
swapon --show
free -h

fallocate -l 4G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progress
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

grep -q '^/swapfile' /etc/fstab || echo '/swapfile none swap sw 0 0' >> /etc/fstab

echo 'vm.swappiness=10' > /etc/sysctl.d/99-swappiness.conf
sysctl -p /etc/sysctl.d/99-swappiness.conf

free -h
swapon --show
sysctl vm.swappiness
grep swap /etc/fstab

期望: Swap 约 4G 已挂载,vm.swappiness = 10/etc/fstab 已持久化。若机器上已有 Swap,先 swapon --show 确认,避免重复创建。

收尾自检

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
echo "===== 系统 ====="
date; timedatectl | head -n 6
uname -a

echo "===== SSH ====="
sshd -T | egrep 'port|passwordauthentication|pubkeyauthentication|permitrootlogin'
ss -lntp | grep sshd

echo "===== Fail2ban ====="
systemctl is-active fail2ban
fail2ban-client status sshd | head -n 20

echo "===== BBR ====="
sysctl net.ipv4.tcp_congestion_control net.core.default_qdisc

echo "===== 内存/Swap ====="
free -h
swapon --show

echo "===== 磁盘 ====="
df -h /

本机最终登录:

1
ssh -i $env:USERPROFILE\.ssh\id_finalshell_rsa -p 39217 root@你的服务器IP

小结

拿到 Debian VPS,SSH 相关建议按这条线做完:

1
2
3
4
5
更新系统 → 改 root 密码 → 密钥登录(上篇)
→ 改 SSH 端口并测通
→ 关密码登录并测通(盯住 cloud-init)
→ Fail2ban
→ BBR + Swap(推荐)