系统与运维

生产级 Linux SSH 安全加固规范:ED25519 密钥认证、端口隐藏与 Fail2ban 防爆破

VPSMap 编辑整理 · 内容更新 2026-09-26 · 27 分钟阅读 · 纯文本版本

公网虚拟专用服务器(VPS)在分配独立 IPv4/IPv6 地址并启动实例的数分钟内,便会暴露在全球自动化僵尸网络(Botnet)的高频探测之下。成千上万的分布式扫描节点通过全网端口扫描工具不间断遍历常见端口,利用弱口令词表执行高密度的暴力破解(Brute-Force Attack)。一旦攻击者撞库成功,主机通常会在短时间内被注入矿机木马、配置后门账户或充当下一轮 DDoS 攻击的发起节点。

构建高标准的 Linux 运维基线,关键在于彻底消除密码暴露面、规范非对称加密体系、重整端口暴露策略并引入动态防御机制。本文系统性阐述从本地现代密钥对生成、服务端守护进程(sshd)安全硬化、最小权限账户管理,到 Fail2ban 动态封锁与失联应急救援的完整作业规范。


一、 公网威胁模型与主流服务商初始策略解析#

在深入配置之前,需要理解不同服务商在实例交付初期的网络与鉴权架构差异:

  • DMIT 的“默认密钥”驱动模型: DMIT 在交付云服务器实例时,安全策略倾向于严苛的无密码环境。系统镜像在初始化过程中默认关闭远程 root 密码登录,强烈要求用户在开通实例时绑定 SSH 公钥。这种机制从源头规避了初始默认密码泄露与密码字典撞库的风险。
  • BandwagonHost(搬瓦工)的“随机高位端口”模型: 搬瓦工(BandwagonHost)在 KiwiVM 架构下初始化操作系统时,虽然会生成随机的 root 初始密码,但其机制会默认分配一个五位数的非常规 SSH 端口(如 2xxxx~3xxxx),而非开放默认的 22 端口。这种策略能够在第一时间过滤掉全网绝大多数盲扫 22 端口的低级扫描脚本。

无论服务商初始策略如何,将服务器投入生产运行前,均须按照统一的生产级安全标准重构 SSH 链路。


二、 现代加密基准:为什么弃用 RSA,全面转向 ED25519?#

长期以来,基于大数分解难题的 RSA 算法被广泛用于 SSH 鉴权。然而在当前的算力与安全架构下,RSA 逐渐显露劣势:

  1. 安全性与密钥体积失衡:要达到足够的安全强度,RSA 必须采用 3072 位或 4096 位密钥,导致传输握手开销增大,字符串极度冗长。
  2. 侧信道攻击风险:传统的 RSA 软件实现容易受到微架构计时攻击(Timing Attacks)和旁路缓存攻击。

ED25519 是基于 EdDSA(Edwards-curve Digital Signature Algorithm)高性能椭圆曲线签名方案(Curve25519):

  • 等效高强度:长度仅为 256 位(公钥约 68 个字符),其提供的安全防护等级等效于约 3000 位以上的经典 RSA 密钥。
  • 抗侧信道攻击:算法设计在底层运算中完全保持常数时间执行(Constant-Time Execution),天然免疫计时侧信道攻击。
  • 极速性能:签名生成与验证速度大幅领先,内存占用极低,在弱网或突发大量并发连接时握手表现更优。

1. 在本地工作站生成 ED25519 密钥对#

密钥生成应始终在受信任的本地工作站(Linux、macOS 或配置了 OpenSSH 的 Windows Terminal)中执行,严禁在公网 VPS 服务端生成后再下载私钥。

在本地终端执行以下命令:

bash
ssh-keygen -t ed25519 -a 100 -C "admin-ops-2026@vpsmap"

参数技术剖析:

  • -t ed25519:指定生成 ED25519 签名算法密钥。
  • -a 100:指定密钥派生函数(KDF)执行 100 轮 bcrypt 强化哈希。这显著拉长了利用 GPU/ASIC 离线暴力穷举私钥密码的耗时。
  • -C "...":为公钥末尾附加注释标识,便于多设备协同管理时识别密钥用途与所属主机。
text
Enter file in which to save the key (/home/username/.ssh/id_ed25519): [直接回车使用默认路径,或指定独立名称]
Enter passphrase (empty for no passphrase): [务必设置强私钥密码短语]
Enter same passphrase again: [再次输入确认]

[!IMPORTANT] 私钥短语(Passphrase)是防范本地资产失窃的最后防线。即使本地工作站被物理失窃或拷贝了 id_ed25519 私钥文件,缺乏短语的攻击者也无法解开私钥并发起远程连接。

命令执行完毕后,本地 ~/.ssh/ 目录下将生成两个核心文件:

  • id_ed25519:私钥文件。权限必须为 600,绝不可上传、复制或共享。
  • id_ed25519.pub:公钥文件。公开字符串,用于分发至目标云服务器。

三、 公钥部署与 Linux 文件系统严格权限规范#

方案 A:使用 ssh-copy-id 自动化投递(适用于当前允许密码登录的主机)#

如果新购实例初始状态支持密码登录(例如搬瓦工初始安装环境),可在本地运行:

bash
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p [当前实际SSH端口] root@[服务器公网IP]

方案 B:手动配置与控制台接入(适用于 DMIT 等纯密钥环境)#

若服务商初始镜像直接禁用了密码认证,或需要更新现有密钥:

  1. 控制台或服务商面板注入: 在 DMIT 控制面板的实例详情页中,导航至 Access(访问控制) 页面,可直接调出 SSH Keys(密钥库)。在控制台添加本地生成的 id_ed25519.pub 公钥内容。

    [!WARNING] 根据 DMIT 官方技术文档说明,通过面板 Access 更换或追加 SSH Key 后,必须在控制面板中对实例执行重启(Restart)操作,底层的元数据服务(Cloud-Init)才会将新的公钥正确渲染至系统的 authorized_keys 中。

  2. 手工登入系统写入: 如果通过临时密码或带外控制台(Console)登入系统,可手动创建并追加:
bash
# 1. 确保用户主目录下的 .ssh 目录存在
mkdir -p ~/.ssh

# 2. 将本地 id_ed25519.pub 内容以追加模式写入目标文件
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... admin-ops-2026@vpsmap" >> ~/.ssh/authorized_keys

Linux 文件系统权限铁律#

OpenSSH 的守护进程内部集成了严格的权限检查机制(StrictModes)。如果父级目录或密钥文件拥有过宽的组写入权限(Group-Writable)或全局权限,sshd 会判定当前环境可能被同机恶意进程纂改,进而拒绝加载公钥认证,导致连接失败。

必须在服务器端执行权限校准:

bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $(whoami):$(whoami) ~/.ssh

四、 SSH 守护进程(sshd)生产级深度硬化#

服务器能够正常通过密钥连接后,必须对 SSH 守护进程的主配置文件进行深度加固,关闭密码认证通道,并将端口从通用扫描范围中隐匿。

以 root 身份编辑配置文件:

bash
nano /etc/ssh/sshd_config

(注意:在较新的 Debian 12 / Ubuntu 22.04+ 系统中,建议检查 /etc/ssh/sshd_config.d/ 目录下是否存在 .conf 覆盖文件,确保加固指令未被子配置文件覆盖)。

生产级配置指令集#

在配置文件中检索并修改以下核心参数(若不存在则在文件末尾追加):

text
# -------------------------------------------------------------
# 1. 网络与端口绑定
# 避开众所周知的 22 端口,选择 1024~65535 范围内未被占用的高位端口
# -------------------------------------------------------------
Port 49222
AddressFamily any
ListenAddress 0.0.0.0
ListenAddress ::

# -------------------------------------------------------------
# 2. 身份验证核心策略
# -------------------------------------------------------------
# 开启公钥认证
PubkeyAuthentication yes

# 彻底禁用所有交互式密码验证形式,从根源粉碎字典暴破
PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no

# 禁用空密码账户
PermitEmptyPasswords no

# -------------------------------------------------------------
# 3. 根用户与认证尝试限制
# -------------------------------------------------------------
# 允许 root 仅通过密钥登录;后续若建立专属运维账户,可进一步改为 no
PermitRootLogin prohibit-password

# 限制单次连接最大鉴权尝试次数(若客户端尝试超过 3 次未命中则断开)
MaxAuthTries 3

# 限制未认证会话的超时断开时间(降低慢速拒绝服务攻击影响)
LoginGraceTime 30

# -------------------------------------------------------------
# 4. 连接保活与防伪造
# -------------------------------------------------------------
# 每 60 秒向客户端发送探活包,避免 SSH 长时间空闲被中间路由 NAT 丢弃
ClientAliveInterval 60
ClientAliveCountMax 3

# 严格模式核查文件属主与权限
StrictModes yes

# 禁用老旧或容易引入安全隐患的特性
X11Forwarding no
AllowAgentForwarding yes
AllowTcpForwarding yes

校验配置文件语法(绝不能跳过的验证步骤)#

在重启 sshd 之前,必须执行语法静态扫描:

bash
sshd -t

如果命令没有任何输出返回,说明配置文件语法无误;如果有任何高亮报错(例如指令书写错误或废弃参数),必须立即修正,否则会导致重启守护进程时服务崩溃。


五、 防火墙协同放行与防失联作业闭环#

修改默认端口是许多运维人员遭遇“服务器失联”的高发阶段。核心原因往往在于:SSH 端口已经迁移,但底层防火墙尚未放行新端口,直接断开终端导致彻底断联。

1. 动态放行防火墙端口#

根据系统采用的防火墙方案执行对应规则:

  • 如果使用 UFW(Ubuntu / Debian 常见):
bash
# 优先允许新端口通过(以 49222 为例)
ufw allow 49222/tcp comment 'Custom-SSH'

# 检查防火墙状态确保规则生效
ufw status verbose
  • 如果使用 Firewalld(AlmaLinux / Rocky / CentOS 常见):
bash
firewall-cmd --permanent --add-port=49222/tcp
firewall-cmd --reload
  • 如果使用原生 Iptables / NFTables: 确保在 INPUT 链的默认 DROP 规则前插入允许新端口 TCP 入站的 ACCEPT 规则。

2. 重启 SSH 守护进程#

bash
systemctl restart sshd || systemctl restart ssh

3. “先验证、后断开”防失联黄金铁律#

text
+-----------------------------------------------------------+
|               生产防失联操作 SOP 流程图                    |
+-----------------------------------------------------------+
  [终端 A: 维持现有活跃连接]
            |
            v
  修改端口与加固项 -> 执行 sshd -t -> 防火墙放行新端口 -> 重启 sshd
            |
            v
  [保持终端 A 绝对不要关闭/退出!]
            |
            v
  [新开本地终端 B] 发起测试连接:
  ssh -p 49222 -i ~/.ssh/id_ed25519 root@[服务器IP]
            |
            +--> [连接成功,密钥秒级登录] -> 确认无误 -> 放心关闭终端 A
            |
            +--> [连接超时或拒绝] --------> 立即切回终端 A 排查防火墙与配置

在本地工作站开启全新的终端会话测试连接:

bash
ssh -p 49222 -i ~/.ssh/id_ed25519 -vvv root@[服务器IP]

如果发生连接挂起或错误,利用未关闭的原终端窗口检查 journalctl -u sshd -e 排查错误,或者重新放行防火墙端口。


六、 最小权限原则:配置专属 Sudo 运维账户#

在生产环境中,长期直接以 root 超级用户登录执行常规维护,存在严重的越权与误操作风险。标准的企业级方案应创建日常操作账户,并将其纳入 sudo 授权链条。

1. 创建专用运维用户#

bash
# 创建普通系统账户(以 opsadmin 为例)
adduser opsadmin

按照提示设置该用户的初始密码。

2. 赋予提权管理能力#

  • Debian / Ubuntu 系:
    bash
    usermod -aG sudo opsadmin
  • RHEL / Rocky / AlmaLinux 系:
    bash
    usermod -aG wheel opsadmin

3. 同步 ED25519 鉴权密钥到普通用户#

为新建账户配置公钥免密登录能力,并严密设置权限:

bash
# 建立用户目录下的 .ssh 文件夹
mkdir -p /home/opsadmin/.ssh

# 将 root 的 authorized_keys 复制过去,或写入专门分配给该运维的公钥
cp ~/.ssh/authorized_keys /home/opsadmin/.ssh/authorized_keys

# 更改目录和文件属主为 opsadmin 用户及其主用户组
chown -R opsadmin:opsadmin /home/opsadmin/.ssh

# 强制修正权限为安全规范
chmod 700 /home/opsadmin/.ssh
chmod 600 /home/opsadmin/.ssh/authorized_keys

4. (可选)进一步收紧 Root 登录权限#

在本地终端成功以 opsadmin 用户登录并验证 sudo -i 提权成功后,可再次编辑 /etc/ssh/sshd_config:

text
# 彻底禁止 root 用户从外部任何途径登录,仅允许普通用户提权
PermitRootLogin no

执行 sshd -t 并重启服务。此时任何外部探测将无法命中 root 账户名。


七、 自动化入侵防御:部署 Fail2ban 动态封锁#

即使修改了非标准端口并关闭了密码验证,公网上的恶意扫描依然会不间断尝试连接,持续占用服务器的连接通道并污染系统日志。

Fail2ban 是一款轻量级主动入侵防御工具,能够实时监听系统认证日志。当检测到特定 IP 在一定周期内连续触发认证失败时,Fail2ban 会动态调用系统底层防火墙(Iptables、NFTables 或 UFW)对该源 IP 进行 DROP 封禁。

1. 安装 Fail2ban#

  • Ubuntu / Debian:
    bash
    apt update && apt install -y fail2ban
  • Rocky / AlmaLinux:
    bash
    dnf install -y epel-release && dnf install -y fail2ban

2. 配置针对自定端口的防护 Jail#

Fail2ban 默认提供 /etc/fail2ban/jail.conf 作为模板,但升级软件包时可能覆盖该文件。生产规范必须新建本地覆盖文件 jail.local:

bash
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
nano /etc/fail2ban/jail.local

修改或在文件末尾定义 [sshd] 规则块:

ini
[DEFAULT]
# 忽略的白名单 IP(例如公司出口固定 IP、本地宽带公网 IP,以空格分隔)
ignoreip = 127.0.0.1/8 ::1

# 封禁动作:使用 iptables 丢弃恶意数据包
banaction = iptables-multiport

[sshd]
enabled = true
# 务必修改为当前服务器实际配置的高位 SSH 端口!
port = 49222
filter = sshd
# 统计时间窗口(秒):600 秒(10分钟)内
findtime = 600
# 触发拉黑的失败最大尝试次数:尝试 3 次失败即封禁
maxretry = 3
# 惩罚封禁时长(秒):86400 秒(24小时);设为 -1 为永久封禁
bantime = 86400

# 针对较新的 Debian 12 / Ubuntu 22.04+ 系统,OpenSSH 日志由 systemd-journald 托管:
# 推荐显式指定后端为 systemd,避免因找不到 /var/log/auth.log 导致规则不生效
backend = systemd

3. 启用服务与常态化运行监控#

启动 Fail2ban 并将其设置为随系统引导自启:

bash
systemctl enable --now fail2ban
systemctl restart fail2ban

日常运维与黑名单管理实用命令#

  • 查看 SSH 监控牢笼(Jail)状态与实时封禁 IP 列表:

    bash
    fail2ban-client status sshd

    输出示例:

    text
    Status for the jail: sshd
    |- Filter
    |  |- Currently failed: 1
    |  |- Total failed:     28
    |  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
    `- Actions
       |- Currently banned: 3
       |- Total banned:     3
       `- Banned IP list:   198.51.100.24 203.0.113.88 192.0.2.14
  • 将误封禁的合法 IP 手动移出黑名单:

    bash
    fail2ban-client set sshd unbanip [被误封的IP地址]
  • 手动拉黑某个恶意 IP:

    bash
    fail2ban-client set sshd banip [恶意IP地址]

八、 失联应急响应与带外控制台(Console)救援规范#

在执行防火墙变更、SSH 配置更新或密钥替换时,如果操作失误导致 SSH 完全拒绝访问,切勿慌张尝试重装系统。主流优质服务商均提供了绕过公网网络层面的带外控制台(Out-of-band Console)。

1. 搬瓦工(BandwagonHost)KiwiVM 控制台救援#

当由于端口错误、防火墙封锁或配置笔误导致无法连接搬瓦工 VPS 时:

text
客户中心 -> 服务管理 -> 登入 KiwiVM 控制面板
  |
  +--> 凭据管理提示:
  |    KiwiVM 管理面板密码与客户中心登录密码、系统的 root 初始密码彼此独立。
  |    若忘记 KiwiVM 登录密码,可在用户中心直接请求重置。
  |
  +--> 应急恢复路径:
       1. 点击左侧导航栏的 "Interactive Console"(交互式控制台)或 "Root shell - basic"。
       2. 打开类似物理显示器的终端窗口(模拟真实键盘显示器直连)。
       3. 直接输入 root 账户与系统密码登录系统内部。
       4. 执行 "ufw disable" 暂时关闭防火墙,或编辑 "/etc/ssh/sshd_config" 纠正错误配置。
       5. 执行 "systemctl restart sshd" 恢复网络通信。

[!NOTE] 在遭遇重大不可逆系统毁损时,KiwiVM 提供了便捷的系统重装(Install new OS)功能;但请注意:根据官方条款规范,若实例 IP 被列入外部黑名单,其跨机房数据中心迁移(DC Migration)功能将受到限制。

2. DMIT 控制面板 Web Console 救援#

在 DMIT 实例中,如果因公钥误删或 sshd_config 解析失败被拒之门外:

  1. 登录 DMIT 客户中心,进入受影响的实例管理界面。
  2. 在顶部控制区域直接启动 Console(Web VNC 应急控制台)。
  3. 通过控制台接入可以在无 SSH 网络连接的状态下直接接管虚拟机控制权。
  4. 检查 ~/.ssh/authorized_keys 是否正确挂载,或查看 systemctl status sshd 确认报错行号。
  5. 如果公钥完全丢失,可在面板 Access 选项卡下重新选择绑定的公钥,随后通过面板发起的重启重新触发公钥加载。

九、 生产加固清单快速校验表#

完成全套流程后,使用以下清单核验主机的最终加固状态:

校验维度生产标准要求校验命令 / 验证方式
密钥算法严格采用 ED25519 规范ssh-keygen -l -f ~/.ssh/authorized_keys 应当显示 ED25519
本地私钥必须设置强保护短语(Passphrase)每次在本地加载密钥时提示输入短语
文件权限~/.ssh 为 700,authorized_keys 为 600ls -la ~/.ssh 校验权限标志位与属主
密码鉴权彻底关闭密码认证与交互式认证ssh -o PreferredAuthentications=password 应直接被服务端拒载
端口策略迁移至 1024 以上非常规端口ss -tulpn | grep sshd 查看监听端口
自动化防御Fail2ban 正常拦截并处于自启状态systemctl is-active fail2ban 返回 active
带外通路掌握服务商 Console 紧急登入途径验证过 KiwiVM Interactive Console 或 DMIT Web Console 可用

遵循以上工程规范,Linux 服务器在公网暴露面上的非对称加密基准与防御纵深将达到行业生产级安全标准,极大压缩各类针对 SSH 服务端攻击的可利用空间。