Linux VPS上的SSH安全加固:sshd_config完整配置指南

3 分钟阅读·Matthieu|

在Debian 12或Ubuntu 24.04 VPS上锁定SSH。Ed25519密钥生成、sshd_config加固、ProxyJump跳板机配置、加密算法优化、ssh-audit验证。每一步都有验证环节。

SSH是服务器的大门。VPS上线几分钟内,自动化机器人就会开始扫描22端口。本指南将逐步讲解在Debian 12(OpenSSH 9.2)和Ubuntu 24.04(OpenSSH 9.6)上加固sshd_config所需的每一项配置,每次修改后都有验证步骤,确保配置生效。

前提条件

你需要:

  • 一台运行Debian 12或Ubuntu 24.04的VPS(全新或已有均可)
  • 一个拥有sudo权限的非root用户
  • 一个已打开的第二终端或SSH会话(修改配置时需要用它来测试,避免把自己锁在外面)

本指南是Linux VPS安全:威胁、层级与加固指南系列的一部分。完成SSH加固后,接下来配置自动暴力破解防护 。

如何为VPS生成安全的SSH密钥?

本地机器(笔记本电脑或工作站,不是服务器)上生成Ed25519密钥。Ed25519生成256位密钥,提供128位安全强度,等同于RSA-3072,同时生成和验证速度更快。签名是确定性的(deterministic),不依赖签名时的随机数生成器。这消除了影响RSA的一整类实现攻击。

ssh-keygen -t ed25519 -C "yourname@yourmachine"

你会看到类似这样的输出:

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/yourname/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/yourname/.ssh/id_ed25519
Your public key has been saved in /home/yourname/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:xR5xGk3TOs4mEfW8sBv7g7LkE2PLxYae2TqfGxpfM3Q yourname@yourmachine

设置一个密码短语(passphrase)。如果有人窃取了你的私钥文件,密码短语是他们和你的服务器之间唯一的屏障。

Ed25519与RSA:应该用哪种密钥?

Ed25519 RSA-4096
密钥长度 256位 4096位
安全强度 约128位 约140位
密钥生成 瞬间完成 1-5秒
签名验证 更快 更慢
私钥文件大小 464字节 约3.3 KB
签名时依赖随机数 否(确定性)
兼容性 OpenSSH 6.5+(2014年) 通用

除非你需要连接运行OpenSSH 6.5以下版本的系统(2026年已非常罕见),否则使用Ed25519。

将公钥复制到服务器

从本地机器执行:

ssh-copy-id -i ~/.ssh/id_ed25519.pub youruser@your-server-ip

如果ssh-copy-id不可用(某些macOS环境),手动复制:

cat ~/.ssh/id_ed25519.pub | ssh youruser@your-server-ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

**验证:**从新终端使用密钥认证登录:

ssh -i ~/.ssh/id_ed25519 youruser@your-server-ip

如果你无需输入服务器密码(只需输入密钥的密码短语)就获得了shell,说明密钥认证已生效。

理解Include指令

编辑sshd_config之前,你需要知道:Debian 12和Ubuntu 24.04都在/etc/ssh/sshd_config顶部包含了Include /etc/ssh/sshd_config.d/*.conf。OpenSSH对大多数指令使用它找到的第一个值。sshd_config.d/中的.conf文件优先于主配置文件中的设置。

检查已有配置:

ls -la /etc/ssh/sshd_config.d/

在Ubuntu 24.04上,如果cloud-init处于活跃状态,通常会看到50-cloud-init.conf。修改前先查看已有文件:

cat /etc/ssh/sshd_config.d/*.conf 2>/dev/null

我们将所有加固配置放在一个最先加载的文件中:

sudo touch /etc/ssh/sshd_config.d/00-hardening.conf
sudo chmod 600 /etc/ssh/sshd_config.d/00-hardening.conf

00-前缀确保我们的文件在其他配置片段之前被读取。chmod 600将读取权限限制为仅root,因为该文件控制着谁可以登录。

本指南中所有sshd_config修改都放入/etc/ssh/sshd_config.d/00-hardening.conf,除非另有说明。

如何禁用SSH密码认证?

禁用密码认证后,只允许密钥登录。暴力破解攻击变得毫无意义,因为没有密码可猜。

打开加固配置文件:

sudo nano /etc/ssh/sshd_config.d/00-hardening.conf

添加:

PasswordAuthentication no
KbdInteractiveAuthentication no

KbdInteractiveAuthentication替代了OpenSSH 9.x中已弃用的ChallengeResponseAuthentication。两者都禁用,以关闭所有基于密码的登录路径。

重启sshd之前,务必验证配置并保持当前会话不关闭。

sudo sshd -t

如果没有输出,说明配置有效。任何错误会打印到终端。

现在重启sshd:

sudo systemctl restart sshd

从第二个终端验证(不要关闭当前会话):

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no youruser@your-server-ip

你应该看到:

youruser@your-server-ip: Permission denied (publickey).

这确认密码认证已关闭。注意输出中显示(publickey)作为唯一允许的方法。这正是我们要的结果。

现在从同一个第二终端确认密钥登录仍然有效:

ssh youruser@your-server-ip

如果两项测试都通过,密码认证已禁用且密钥登录正常。如果密钥登录失败,回到仍然打开的第一个会话修复配置,以免被锁在外面。

如何在Ubuntu和Debian上禁用SSH root登录?

应该关闭通过SSH直接以root身份登录。即使只允许密钥认证,被泄露的root密钥会直接获得完整系统权限,且没有登录者的审计记录。改用普通用户加sudo。

/etc/ssh/sshd_config.d/00-hardening.conf中添加:

PermitRootLogin no

验证并重启:

sudo sshd -t && sudo systemctl restart sshd

从第二个终端验证:

ssh root@your-server-ip

预期输出:

root@your-server-ip: Permission denied (publickey).

用sshd -T验证设置是否生效(大写T输出运行中的配置):

sudo sshd -T | grep -i permitrootlogin
permitrootlogin no

如何限制SSH访问特定用户和组?

AllowUsers和AllowGroups将SSH登录限制在明确的列表内。不在列表中的人会被拒绝,即使他们有有效的密钥。这是防止意外密钥部署或软件包创建新用户的安全网。

/etc/ssh/sshd_config.d/00-hardening.conf中添加:

AllowUsers youruser

youruser替换为你的实际用户名。允许多个用户:

AllowUsers youruser deployer

也可以使用基于组的访问控制(更适合团队):

sudo groupadd sshusers
sudo usermod -aG sshusers youruser

然后在配置中:

AllowGroups sshusers

处理顺序

OpenSSH按以下顺序评估访问权限:DenyUsers、AllowUsers、DenyGroups、AllowGroups。任何阶段的deny都会阻止该用户。如果使用AllowUsers,只有列出的用户可以登录。如果使用AllowGroups,只有列出的组的成员可以登录。可以组合使用,但AllowUsers先被检查。

验证并重启:

sudo sshd -t && sudo systemctl restart sshd

从第二个终端验证:

ssh youruser@your-server-ip

确认你的用户仍然可以登录。然后验证非列表用户会被拒绝:

sudo sshd -T | grep -i allowusers
allowusers youruser

应该设置哪些SSH会话限制?

这些指令限制认证尝试次数、连接超时和未认证连接数。它们减缓暴力破解攻击并清理僵死会话。

/etc/ssh/sshd_config.d/00-hardening.conf中添加:

MaxAuthTries 3
LoginGraceTime 20
MaxStartups 10:30:60
MaxSessions 3
ClientAliveInterval 300
ClientAliveCountMax 2

各项设置的含义:

指令 效果
MaxAuthTries 3 每次连接3次认证失败后断开
LoginGraceTime 20 给予20秒时间完成认证,超时断开
MaxStartups 10:30:60 10个未认证连接后,随机丢弃30%的新连接。到60个时丢弃所有新连接。
MaxSessions 3 每个连接最多3个多路复用会话
ClientAliveInterval 300 每300秒(5分钟)发送一次保活包
ClientAliveCountMax 2 2次保活无响应后断开

**ClientAliveInterval计算:**实际空闲超时时间为ClientAliveInterval x ClientAliveCountMax。按当前配置:300 x 2 = 600秒 = 10分钟。空闲会话在10分钟无响应后断开。

验证并重启:

sudo sshd -t && sudo systemctl restart sshd

验证:

sudo sshd -T | grep -E "maxauthtries|logingracetime|maxstartups|maxsessions|clientaliveinterval|clientalivecountmax"
maxauthtries 3
logingracetime 20
maxstartups 10:30:60
maxsessions 3
clientaliveinterval 300
clientalivecountmax 2

禁用不必要的转发功能

转发功能扩大了SSH的攻击面。禁用所有你没有在用的功能。

/etc/ssh/sshd_config.d/00-hardening.conf中添加:

AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no

验证并重启:

sudo sshd -t && sudo systemctl restart sshd

验证:

sudo sshd -T | grep -E "allowagentforwarding|allowtcpforwarding|x11forwarding|permittunnel"
allowagentforwarding no
allowtcpforwarding no
x11forwarding no
permittunnel no

为什么应该禁用SSH Agent Forwarding?

Agent Forwarding(代理转发)允许远程服务器使用你本地的SSH密钥来认证到其他服务器。听起来方便,但问题在于:在该远程服务器上拥有root权限的任何人都可以劫持你的agent socket(代理套接字)并使用你的密钥。

攻击场景:

  1. 你启用Agent Forwarding并SSH到服务器A。
  2. OpenSSH在服务器A上创建一个socket,位于/tmp/ssh-XXXX/agent.YYYY
  3. 在服务器A上拥有root权限的攻击者读取你会话中的SSH_AUTH_SOCK环境变量。
  4. 攻击者连接到该socket:SSH_AUTH_SOCK=/tmp/ssh-XXXX/agent.YYYY ssh user@server-b
  5. 服务器B看到一个使用你的密钥的有效认证。攻击者成功进入。

攻击者从未接触你的私钥。他们只需要在你的会话活跃期间拥有中间服务器的root权限。

改用ProxyJump(下一节)。它提供同样的多跳访问,但不会将你的agent socket暴露给任何中间服务器。

如何配置SSH ProxyJump实现跳板机访问?

ProxyJump通过跳板机(bastion)路由你的SSH连接,无需Agent Forwarding。你的密钥始终留在本地机器上。连接是端到端加密的:跳板机只能看到经过加密的流量通过。

命令行用法

ssh -J jumpuser@bastion.example.com targetuser@10.0.1.50

-J参数告诉SSH先连接到跳板机,然后通过隧道到达目标。可以用逗号链接多个跳转:

ssh -J jump1@bastion1,jump2@bastion2 targetuser@10.0.1.50

SSH配置文件设置

日常使用时,在本地机器~/.ssh/config中添加条目:

Host bastion
    HostName bastion.example.com
    User jumpuser
    IdentityFile ~/.ssh/id_ed25519

Host internal-app
    HostName 10.0.1.50
    User appuser
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519

Host internal-db
    HostName 10.0.2.100
    User dbadmin
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519

现在可以直接连接内部服务器:

ssh internal-app

SSH自动处理跳板机中转。

加固跳板机

在跳板机上限制jump用户的操作。在跳板机的sshd_config中添加:

Match User jumpuser
    PermitTTY no
    X11Forwarding no
    PermitTunnel no
    ForceCommand /usr/sbin/nologin
    AllowTcpForwarding yes

这允许TCP转发(ProxyJump需要),但阻止jump用户获取shell、执行命令或使用X11。如果跳板机被攻破,攻击者得到的只是一个没有shell权限的纯转发账户。

哪些SSH加密算法和密钥交换算法是安全的?

OpenSSH默认的加密算法列表包含为向后兼容而保留的算法。移除弱算法可以缩小攻击面。以下建议针对OpenSSH 9.2+(Debian 12)和9.6+(Ubuntu 24.04)。

首先,仅使用Ed25519重新生成主机密钥,并移除所有DSA或ECDSA密钥:

sudo rm -f /etc/ssh/ssh_host_*key*
sudo ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
sudo ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""

我们保留一个RSA主机密钥,用于不支持Ed25519的客户端(很少见,但可以避免锁定)。

接下来,移除弱Diffie-Hellman模数(moduli)(小于3072位的组):

sudo awk '$5 >= 3071' /etc/ssh/moduli > /tmp/moduli.safe
sudo mv /tmp/moduli.safe /etc/ssh/moduli
sudo chown root:root /etc/ssh/moduli
sudo chmod 644 /etc/ssh/moduli

/etc/ssh/sshd_config.d/00-hardening.conf中添加:

HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256
KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
类别 算法 说明
密钥交换 sntrup761x25519、curve25519、DH group16/18 sntrup761是后量子混合算法。curve25519是当前标准。
加密算法 ChaCha20-Poly1305、AES-256-GCM、AES-128-GCM、AES-CTR ChaCha20优先:在没有AES-NI的软件环境中更快。GCM是认证加密。
MAC HMAC-SHA2 ETM、UMAC-128 ETM 仅使用ETM(Encrypt-then-MAC,先加密后MAC)模式。非ETM模式更弱。
主机密钥 Ed25519、RSA(SHA-2) 不用DSA(已被破解)。不用ECDSA(NIST曲线信任问题)。

验证并重启:

sudo sshd -t && sudo systemctl restart sshd

**从第二个终端验证你仍然可以连接。**如果你的SSH客户端不支持这些算法中的任何一个(客户端非常旧),你会收到"no matching cipher"错误。此时,更新客户端或临时添加回所需的算法。

配置登录横幅

隐藏SSH版本信息并显示法律警告横幅:

sudo nano /etc/ssh/banner.txt
Authorized access only. All activity is monitored and logged.

保持简短。包含系统信息的长横幅会帮助攻击者识别你的操作系统。

/etc/ssh/sshd_config.d/00-hardening.conf中添加:

Banner /etc/ssh/banner.txt
DebianBanner no

DebianBanner no从SSH协议横幅中移除Debian/Ubuntu版本字符串。版本泄露帮助攻击者针对你特定OpenSSH版本的已知漏洞发起攻击。

验证并重启:

sudo sshd -t && sudo systemctl restart sshd

从本地机器验证:

ssh -v youruser@your-server-ip 2>&1 | grep "banner"

完整的加固sshd_config参考

以下是本指南中所有设置的完整/etc/ssh/sshd_config.d/00-hardening.conf

# Authentication
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
AuthenticationMethods publickey

# Access control
AllowUsers youruser

# Session limits
MaxAuthTries 3
LoginGraceTime 20
MaxStartups 10:30:60
MaxSessions 3
ClientAliveInterval 300
ClientAliveCountMax 2

# Forwarding restrictions
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no

# Cryptography
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256
KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com

# Banner
Banner /etc/ssh/banner.txt
DebianBanner no

# Logging
LogLevel VERBOSE

LogLevel VERBOSE记录额外的详细信息,包括用于认证的密钥指纹。对于审计谁用哪个密钥登录非常有用。

写入此文件后,重启前务必验证:

sudo sshd -t && sudo systemctl restart sshd

查看完整的生效配置:

sudo sshd -T

这会输出每个活跃设置,包括默认值。通过grep管道检查特定值:

sudo sshd -T | grep -E "permitrootlogin|passwordauthentication|allowusers"
permitrootlogin no
passwordauthentication no
allowusers youruser

如何使用ssh-audit验证SSH加固效果?

ssh-audit扫描你的服务器,将每个算法评级为good、warning或fail。加固完成后运行它,确认所有项都通过。

本地机器或另一台服务器上安装(不要装在目标服务器上):

pip3 install ssh-audit

或者在Debian/Ubuntu上用apt安装:

sudo apt update && sudo apt install -y ssh-audit

扫描你的服务器:

ssh-audit your-server-ip

按照本指南的加固配置,你应该看不到任何[fail]条目。输出从检测到的OpenSSH版本开始,然后列出各算法类别:

# general
(gen) banner: SSH-2.0-OpenSSH_9.6
(gen) software: OpenSSH 9.6
(gen) compression: enabled (zlib@openssh.com)

# key exchange algorithms
(kex) sntrup761x25519-sha512@openssh.com  -- [info] available since OpenSSH 8.5
(kex) curve25519-sha256                   -- [info] available since OpenSSH 7.4
...

# encryption algorithms (ciphers)
(enc) chacha20-poly1305@openssh.com       -- [info] available since OpenSSH 6.5
(enc) aes256-gcm@openssh.com              -- [info] available since OpenSSH 6.2
...

如果看到任何[fail]条目,检查你的00-hardening.conf是否被加载(注意Include顺序),以及sshd_config.d/中是否有其他文件覆盖了你的设置。

ssh-audit还内置了加固指南:

ssh-audit --list-hardening-guides

故障排除

被锁在外面了

如果配置修改后无法SSH登录:

  1. 使用VPS提供商的Web控制台(KVM/VNC)直接登录。
  2. 修复/etc/ssh/sshd_config.d/00-hardening.conf
  3. 运行sshd -t验证。
  4. 重启:systemctl restart sshd

这就是为什么我们说:测试完毕前绝不关闭你的当前会话。

配置修改后sshd无法启动

sudo sshd -t

这会打印出错误所在的确切行和文件。常见问题:

  • 算法名称拼写错误(逗号分隔的列表中不允许有空格)
  • 多个文件中存在重复指令(检查sshd_config.d/和主sshd_config
  • AllowUsers中指定了不存在的用户名(sshd可以启动,但没人能登录)

加密算法加固后连接被拒绝

你本地的SSH客户端可能不支持你配置的加密算法。检查客户端支持哪些算法:

ssh -Q cipher

与服务器的列表对比。添加回客户端需要的算法,或更新你的客户端。

查看SSH日志

sudo journalctl -u sshd -f

在从另一个终端尝试连接的同时实时查看日志。认证失败、配置错误和连接中断都会显示在这里。

验证哪个配置文件设置了某个指令

sudo sshd -T | grep passwordauthentication

如果值与你设置的不一致,说明sshd_config.d/中有其他文件覆盖了你的设置。文件按字母顺序加载。我们的00-hardening.conf最先加载,所以对大多数指令它的设置优先。但要检查cloud-init或其他管理工具是否写入了自己的配置。

验证清单

完成所有加固步骤后逐项检查:

  1. 密码认证已禁用:ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no youruser@server返回"Permission denied"
  2. Root登录已禁用:ssh root@server返回"Permission denied"
  3. 密钥认证正常:ssh youruser@server获得shell
  4. AllowUsers生效:sudo sshd -T | grep allowusers显示你的用户
  5. 会话限制已设置:sudo sshd -T | grep maxauthtries显示3
  6. 转发已禁用:sudo sshd -T | grep allowagentforwarding显示no
  7. 仅使用强加密算法:ssh-audit server-ip没有[fail]条目
  8. 日志正常:sudo journalctl -u sshd -n 20显示最近的认证条目

SSH加固完成后,配置 自动封禁认证失败的IP。关于网络层面的SSH访问控制,参见 。


Copyright 2026 Virtua.Cloud. All rights reserved.

准备好亲自尝试了吗?

几秒内部署您自己的服务器。支持 Linux、Windows 或 FreeBSD。

查看 VPS 方案