跳转至

5. SSH 安全配置

本章介绍 RHEL 9 上 OpenSSH 服务的完整安全配置:服务启动与验证、端口变更(含 SELinux 联动)、安全参数加固、ed25519 密钥认证配置,以及禁用密码认证的完整验证流程。本章完成后,所有后续章节统一通过 SecureCRT 以端口 2222、密钥认证方式连接 linuxdc

配置原则

SSH 安全配置的核心原则:禁用密码认证,强制密钥认证;禁止 root 直接登录;最小化允许登录的账户范围。本章按此原则逐步配置,达到企业级 SSH 安全基线。


5.1 前提条件

  • RHEL 9 已完成安装(第 1 章)、网络配置(第 3 章)与用户权限配置(第 4 章)。
  • ops 用户存在,具有 sudo 权限(第 4 章)。
  • 通过控制台或 SecureCRT(SSH 端口 22)以 root 身份登录 192.168.1.100

重要警告:配置过程中勿断开当前会话

修改 SSH 配置并重启服务之前,务必保持当前 SSH 会话不断开。另开一个新会话测试新配置,确认可以连接后再关闭旧会话。若配置出错导致新会话无法连接,可通过当前会话回滚,避免永久失去远程访问。


5.2 确认 OpenSSH 服务状态

# 确认 openssh-server 已安装
rpm -q openssh-server

# 若未安装
dnf install -y openssh-server

# 启用并立即启动
systemctl enable --now sshd

# 验证状态
systemctl status sshd
ss -tuln | grep :22

检查点

systemctl is-active sshd 返回 activess -tuln | grep :22 显示端口监听。


5.3 备份原始配置文件

cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig

后续如需回滚:

cp /etc/ssh/sshd_config.orig /etc/ssh/sshd_config
systemctl restart sshd

5.4 修改 SSH 监听端口

将 SSH 从默认端口 22 改为 2222,可降低自动化扫描攻击的干扰。修改端口需要同步更新 SELinux 策略firewalld 规则,三步缺一不可。

5.4.1 编辑 sshd_config

vim /etc/ssh/sshd_config

找到 Port 行,修改为:

Port 2222

5.4.2 更新 SELinux 端口上下文

关键步骤:不可省略

RHEL 9 默认启用 SELinux(Enforcing 模式)。未更新 SELinux 策略时,sshd 无法监听非标准端口,服务会启动失败。

# 安装 SELinux 管理工具
dnf install -y policycoreutils-python-utils

# 查看当前 SSH 允许的端口
semanage port -l | grep ssh

# 为端口 2222 添加 ssh_port_t 类型
semanage port -a -t ssh_port_t -p tcp 2222

# 验证添加成功
semanage port -l | grep ssh

检查点

输出中应包含 ssh_port_t tcp 2222, 22

5.4.3 更新 firewalld 规则

# 开放新端口
firewall-cmd --permanent --add-port=2222/tcp

# 重载规则
firewall-cmd --reload

# 验证
firewall-cmd --list-ports

5.4.4 验证配置语法并重启服务

# 重启前先验证语法(有错误时会输出错误行,配置不会生效)
sshd -t

# 语法正确后重启
systemctl restart sshd

# 确认新端口监听
ss -tuln | grep :2222

检查点

ss -tuln | grep :2222 显示端口处于监听状态。

5.4.5 测试新端口连接

保持当前 22 端口会话不断开,在 SecureCRT 中新建会话,使用端口 2222 连接 192.168.1.100

ssh -p 2222 root@192.168.1.100

检查点

新会话通过端口 2222 成功登录后,再关闭旧的 22 端口会话。


5.5 完整安全参数配置

端口变更验证通过后,配置完整的 SSH 安全参数:

vim /etc/ssh/sshd_config

安全配置参考(完整关键参数):

# 端口与协议
Port 2222
AddressFamily inet

# 认证方式
PermitRootLogin no
PasswordAuthentication yes       # 稍后配置密钥后改为 no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

# 访问控制
AllowUsers ops

# 会话安全
LoginGraceTime 30
MaxAuthTries 3
MaxSessions 10
ClientAliveInterval 300
ClientAliveCountMax 2

# 功能限制
X11Forwarding no
AllowTcpForwarding no
PermitEmptyPasswords no
UseDNS no

# 登录警告横幅
Banner /etc/ssh/banner.txt

创建登录警告横幅(合规要求):

cat > /etc/ssh/banner.txt << 'EOF'
*******************************************************************************
                          AUTHORIZED ACCESS ONLY
  This system is restricted to authorized users for legitimate business purposes.
  All activities on this system are monitored and recorded.
  Unauthorized access is prohibited and subject to criminal prosecution.
*******************************************************************************
EOF

验证语法并重启:

sshd -t && systemctl restart sshd

AllowUsers 生效说明

配置 AllowUsers ops 后,只有 ops 用户可通过 SSH 登录。确保 ops 用户存在且密码已设置(见第 4 章),否则重启服务后将无法远程登录。


5.6 配置 ed25519 密钥认证

密钥认证比密码认证安全数个量级,是企业环境的强制要求。

5.6.1 在客户端生成密钥对

Linux / macOS 客户端:

# 推荐 ed25519 算法(安全性高,密钥短,性能好)
ssh-keygen -t ed25519 -C "ops@linuxdc"

# 建议设置 passphrase 保护私钥(私钥加密存储)
# 生成后:
# ~/.ssh/id_ed25519      私钥(权限必须为 600)
# ~/.ssh/id_ed25519.pub  公钥

Windows 客户端(PowerShell / Windows 10+):

ssh-keygen -t ed25519 -C "ops@linuxdc"
# 密钥存放于 C:\Users\<username>\.ssh\

5.6.2 将公钥上传至服务器

Linux / macOS 客户端(推荐方式):

ssh-copy-id -p 2222 ops@192.168.1.100

手动方式(Windows 客户端 / 通用):

在服务器上切换至 ops 用户执行:

# 切换为 ops 用户
su - ops

# 创建 .ssh 目录
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# 追加公钥内容(将客户端 id_ed25519.pub 的内容粘贴至此)
cat >> ~/.ssh/authorized_keys << 'EOF'
ssh-ed25519 AAAA...(此处替换为完整公钥内容)... ops@client
EOF

# 设置文件权限
chmod 600 ~/.ssh/authorized_keys
chown ops:ops ~/.ssh ~/.ssh/authorized_keys

# 修复 SELinux 安全上下文
restorecon -Rv ~/.ssh

权限要求(必须严格遵守)

路径 权限 所有者
~/.ssh/ 700 ops
~/.ssh/authorized_keys 600 ops

权限过宽(如 755、644)会导致 sshd 拒绝使用该公钥,认证失败。

5.6.3 测试密钥登录

ssh -p 2222 -i ~/.ssh/id_ed25519 ops@192.168.1.100

检查点

无需输入密码(设置了 passphrase 则输入 passphrase 解密私钥)即可成功登录。

5.6.4 验证密码认证仍然有效

密钥认证测试通过后,在禁用密码认证之前,先显式确认密码认证当前仍可正常工作

# 在客户端执行:强制禁用公钥认证,仅使用密码认证测试
ssh -p 2222 -o PubkeyAuthentication=no ops@192.168.1.100

输入 ops 账户密码后应成功登录。

检查点

使用 -o PubkeyAuthentication=no 参数,仅凭密码可成功登录,说明 PasswordAuthentication yes 当前生效。确认无误后执行 5.7 节关闭密码认证。

为什么要做这一步

先验证密码认证有效,意味着:若后续密钥认证出现问题,仍有密码作为应急登录手段。在彻底关闭密码认证之前务必完成此确认,避免两种认证方式同时失效。


5.7 禁用密码认证

确认密钥认证正常工作(5.6.3 节)且密码认证当前有效(5.6.4 节)后,再禁用密码认证:

vim /etc/ssh/sshd_config

修改为:

PasswordAuthentication no

验证并重启:

sshd -t && systemctl restart sshd

5.7.1 验证密码认证已被禁用

重启服务后,立即验证密码认证已无法使用:

# 在客户端执行:强制使用密码认证,应当被拒绝
ssh -p 2222 -o PubkeyAuthentication=no ops@192.168.1.100

检查点

服务器应返回 Permission denied (publickey) 或直接拒绝连接,不再出现密码输入提示。这表示密码认证已成功禁用,仅允许密钥认证。

操作顺序

必须严格按照以下顺序执行,任一步骤跳过都可能导致账户被锁: 1. 配置并测试密钥认证成功(5.6.3 节) 2. 验证密码认证当前有效(5.6.4 节) 3. 禁用密码认证(5.7 节) 4. 验证密码认证已失效(5.7.1 节)


5.8 配置 SSH 客户端(可选但推荐)

在客户端创建 ~/.ssh/config,简化后续连接命令:

Host linuxdc
    HostName 192.168.1.100
    Port 2222
    User ops
    IdentityFile ~/.ssh/id_ed25519
    ServerAliveInterval 60
    ServerAliveCountMax 3

配置后直接使用:

ssh linuxdc

5.9 常见问题与排查

问题现象 排查步骤
sshd 启动失败 journalctl -u sshd 查看日志;sshd -t 检查语法;检查 SELinux:semanage port -l | grep ssh
端口修改后无法连接 确认 SELinux 已放行:semanage port -l | grep ssh;确认防火墙已开放:firewall-cmd --list-ports
密钥认证失败 检查 ~/.ssh/ 权限(700)和 authorized_keys 权限(600);执行 restorecon -Rv ~/.ssh
密码认证已禁用但密钥仍无法登录 通过 VMware 控制台本地登录,临时恢复 PasswordAuthentication yes,重新检查密钥配置
连接非常慢 sshd_config 中设置 UseDNS no;确认 GSSAPIAuthentication no
# 服务端实时查看认证日志
journalctl -u sshd -f

# 客户端调试模式(显示详细协商过程)
ssh -vvv -p 2222 ops@192.168.1.100

5.10 实践任务

  1. 备份 /etc/ssh/sshd_config.orig
  2. 修改端口为 2222,完成 SELinux 放行、firewalld 规则更新,验证语法后重启。
  3. 保持 22 端口旧会话,用新会话测试端口 2222 连接成功后关闭旧会话。
  4. 完成 5.5 节安全参数配置(PermitRootLogin noAllowUsers ops 等)。
  5. 在客户端生成 ed25519 密钥对,将公钥上传至服务器,测试密钥登录(5.6.3 节)。
  6. 使用 -o PubkeyAuthentication=no 验证密码认证仍然有效(5.6.4 节)。
  7. PasswordAuthentication 改为 no 并重启,验证密码认证已失效(5.7.1 节)。
  8. 在 VMware 中创建快照 RHEL9-SSH-Secured

完成标志

从此以后,所有后续章节均通过 SecureCRT 以端口 2222ops 用户ed25519 密钥连接 192.168.1.100。登录后执行 sudo -i 切换至 root 环境执行特权命令。


5.11 速查表

命令 / 参数 用途
sshd -t 验证配置文件语法
systemctl restart sshd 重启 SSH 服务
semanage port -a -t ssh_port_t -p tcp 2222 SELinux 放行端口 2222
restorecon -Rv ~/.ssh 修复 .ssh 目录 SELinux 上下文
ssh-keygen -t ed25519 生成 ed25519 密钥对
ssh-copy-id -p 2222 ops@192.168.1.100 上传公钥(Linux 客户端)
ssh -p 2222 ops@192.168.1.100 指定端口连接
ssh -p 2222 -o PubkeyAuthentication=no ops@192.168.1.100 强制密码认证测试
journalctl -u sshd -f 实时查看 SSH 日志
ss -tuln \| grep :2222 确认端口监听

5.12 自测问题

Q1:修改 SSH 端口时,为什么必须先更新 SELinux 策略?

RHEL 9 默认以 Enforcing 模式运行 SELinux,sshd 进程只被允许监听 ssh_port_t 类型标记的端口。未添加 SELinux 规则时,sshd 尝试绑定 2222 端口会被 SELinux 阻止,服务启动失败。semanage port -a -t ssh_port_t -p tcp 2222 将 2222 标记为 SSH 允许端口。

Q2:为什么在禁用密码认证之前要先用 -o PubkeyAuthentication=no 测试密码登录?

这一步确认两件事:密码认证目前可用(说明 PasswordAuthentication yes 已生效),以及 ops 用户密码正确可用。若此时密码认证就已失败,说明存在配置问题,可在密钥认证正常的情况下安全排查,而不是在彻底关闭密码认证后才发现问题。

Q3:密钥认证失败但权限已设置正确,还有什么原因?

常见原因:SELinux 安全上下文不正确(执行 restorecon -Rv ~/.ssh 修复);authorized_keys 文件内容格式错误(公钥必须是完整的单行内容);sshd_configPubkeyAuthentication 未设置为 yes

Q4:为什么要在客户端配置 ~/.ssh/config

避免每次连接输入冗长的 -p 2222 -i ~/.ssh/id_ed25519 ops@192.168.1.100;集中管理多台服务器的连接参数;配置 ServerAliveInterval 防止空闲会话被网络设备断开。


5.13 章节总结

本章完成了 RHEL 9 SSH 服务的企业级安全配置:端口变更(SELinux + firewalld 三步联动)、安全参数加固(禁止 root 登录、访问控制、会话保护)、ed25519 密钥认证部署,以及密码认证的有序关闭(含关闭前后的双重验证)。

至此,第一阶段基础环境部署与配置全部完成。系统具备了安全、稳定的远程管理基础,后续章节(订阅、仓库、时间同步等)均通过端口 2222 以密钥认证方式远程操作。