运维

AlmaLinux 服务器安全加固:从基础配置到双因素认证(2FA)完整实战

·17 分钟阅读·更新于 今天

包含 AI 内容

本文由 DeepSeek 总结,经过人工修改

在学习安全这方面的知识以前,我开一个VPS都是直接使用root账户+密码+默认22端口的形式登录SSH。虽然以前用滴滴云的时候,滴滴云强制要求用户使用普通账户登录SSH再通过命令使用root权限,但是当时只是感到麻烦更多罢了。其实使用一个普通账户登录SSH再用命令使用root权限会比直接登录root账户稍微安全一些,不过这只能算是基础的安全防御手段。

随着网络安全威胁日益复杂,仅靠静态密码已经难以抵御暴力破解、凭证泄露等攻击。为了达到真正的安全标准,我们需要引入多层次的防御机制。

本文操作主要在AlmaLinux 10环境下验证通过,理论上同样适用于RHEL、Rocky Linux等RHEL衍生发行版。

特别提醒

以下涉及大量SSH和PAM配置,修改不当可能导致无法登录。强烈建议通过VNC等带外控制台进行操作,以防配置错误无法恢复。

基础安全配置

1.1 添加普通用户

为了安全,平时我们应该以普通用户的身份操作VPS,而不是直接使用root。添加用户有两个命令,adduser和useradd,在不同系统中的定义以及用法上有区别,这里提供一个通用添加方法(Ubuntu/Debian/RHEL/RHEL衍生均可用):

bashbash
# 以添加用户名为 ec2-user 的普通用户为例子
useradd -m -s /bin/bash ec2-user

# 对该用户设置密码
passwd ec2-user

1.2 授予普通用户sudo权限

有时需要使用root权限,比如安装软件、启动服务等操作时就需要用到sudo命令来提升权限。授予用户sudo权限最简单的方法是把用户添加到sudo组。如果系统中没有sudo,需要先安装:

RHELbash
# 安装sudo(如已安装可跳过)
dnf install sudo -y

# 以添加 ec2-user 到 wheel 组为例
usermod -aG wheel ec2-user
Debianbash
# 安装sudo(如已安装可跳过)
apt install sudo -y

# 以添加 ec2-user 到 sudo 组为例
usermod -aG sudo ec2-user

1.3 配置SSH密钥登录

密码的缺点很明显:容易被暴力破解,而且需要记忆,使用起来不是特别安全便捷。密钥的好处是,你只需要一对密钥文件:公钥和私钥,公钥相当于门锁,装在VPS上,私钥相当于钥匙,放在本地计算机上,登录的过程就像用钥匙去开锁,有钥匙的人才能打得开,不仅安全且方便。

在服务器上操作(切换到新建的普通用户):

bashbash
# 切换到 ec2-user并创建 .ssh 目录并设置正确权限
su - ec2-user && mkdir -p ~/.ssh && chmod 700 ~/.ssh

在本地计算机上生成密钥对(以Windows为例):

bashbash
# 生成ED25519密钥对(推荐,安全性高且性能好)
ssh-keygen -t ed25519 -C "your_email@example.com"

依据命令提示输入密钥的生成路径以及密钥的通行短语(Passphrase)。如果设置了保密口令则必须牢记,否则无法找回或更改。

生成后,在生成路径找到公钥xxx.pub(这是一个纯文本文件),将其内容复制到服务器的~/.ssh/authorized_keys中:

bashbash
# 在服务器上,将公钥内容写入 authorized_keys
nano ~/.ssh/authorized_keys

# 设置文件正确权限
chmod 600 ~/.ssh/authorized_keys

1.4 禁用不安全的登录方式

前面的一系列操作都是铺垫,为禁止root账户登录和密码登录以及修改SSH端口做准备,这才是提升VPS安全性的主要目的。

打开/etc/ssh/sshd_config文件进行修改:

bashbash
sudo nano /etc/ssh/sshd_config

主要配置以下的项

配置项 推荐值 说明
Port 自定义端口(如6022) 避免默认22端口被扫描
LoginGraceTime 2m 登录认证超时时间
PermitRootLogin no 禁止root直接登录
PasswordAuthentication no 禁止密码登录
PubkeyAuthentication yes 启用密钥登录
ChallengeResponseAuthentication yes 为后续2FA做准备
UsePAM yes 启用PAM认证
KbdInteractiveAuthentication yes 启用键盘交互认证
AuthenticationMethods publickey,keyboard-interactive 强制双因素认证

修改完成后检查并重启SSH服务:

bashbash
sudo sshd -t
sudo systemctl restart sshd
注意

如果是通过SSH进行配置,请勿直接断开连接。应先打开一个新终端测试能否使用私钥登录普通用户,确认成功后再关闭旧会话。

SSH双因素认证(2FA)配置

即使我们禁用了密码登录,只允许使用公钥和私钥进行SSH连接,如果未经授权的用户窃取了你的密钥,他仍然可以借此访问系统。双因素认证(2FA)通过增加一层验证(如手机上的验证器应用生成的动态验证码),使仅凭密钥无法登录,极大提升了安全性。

AlmaLinux使用PAM(Pluggable Authentication Modules,可插拔认证模块)来集成OTP认证。Google Authenticator是其中最常用的方案。

2.1 安装Google Authenticator PAM模块

Google Authenticator PAM模块需要从EPEL仓库安装。qrencode用于在终端显示二维码,方便手机扫描:

bashbash
# 启用EPEL仓库
sudo dnf install -y epel-release
RHEL · Bashbash
# 安装google-authenticator和qrencode
sudo dnf install -y google-authenticator qrencode
#sudo apt update && sudo apt install -y libpam-google-authenticator
Debian · Bashbash
# 安装google-authenticator和qrencode
sudo dnf install -y google-authenticator qrencode
#sudo apt update && sudo apt install -y libpam-google-authenticator

关于AlmaLinux 10的特别说明: 目前AlmaLinux 10的官方仓库和EPEL 10尚未完全稳定,google-authenticator包可能暂时不可用。如果你在使用AlmaLinux 10时遇到此问题,可以考虑启用EPEL 10的测试仓库或改用OATH Toolkit方案

2.2 为用户生成OTP密钥

务必以目标用户身份(而非root)执行以下命令。本文以ec2-user为例:

bashbash
# 切换到目标用户
su - ec2-user

# 运行 google-authenticator
google-authenticator

执行后,终端会显示一个二维码,同时输出以下关键信息:

  • Secret key:密钥字符串(备用)
  • Verification code:当前验证码
  • Emergency scratch codes:5个紧急备用码
注意

**请务必将紧急备用码保存在安全的地方!**这些备用码是你在丢失OTP设备后唯一的恢复途径。

根据提示回答以下问题:

提示 建议选择 中文翻译
Do you want me to update your "~/.google_authenticator" file? y 您是否希望我更新“~/.google_authenticator”文件?
Do you want to disallow multiple uses of the same token? y 您是否希望禁止重复使用同一认证令牌?此设置会将登录间隔限制为大约每30秒一次,但能提高您发现甚至阻止中间人攻击的可能性
Do you want to increase the original time window? n 默认情况下,移动应用每 30 秒生成一个新令牌。为了弥补客户端与服务器之间可能存在的时间偏差,我们在当前时间的前后各允许一个额外的令牌。这使得认证服务器与客户端之间的时间偏差最多可达 30 秒。如果您遇到时间同步不佳的问题,可以将时间窗口从默认的 3 个有效代码(前一个代码、当前代码和下一个代码)扩展至 17 个有效代码(前 8 个代码、当前代码和后 8 个代码)。这样可以容忍客户端与服务器之间最多 4 分钟的时间偏差。您要这样做吗?
Do you want to enable rate-limiting? y 如果您要登录的计算机未针对暴力破解登录尝试进行强化防护,您可以为身份验证模块启用速率限制。默认情况下,此功能将限制攻击者每 30 秒最多只能进行 3 次登录尝试。您要启用速率限制吗?

2.3 配置PAM强制OTP认证

编辑SSH服务的PAM配置文件:

bashbash
sudo nano /etc/pam.d/sshd

修改要点:

  1. 在文件开头添加OTP认证行:
texttext
auth required pam_google_authenticator.so
  1. 注释掉原有的密码认证行(跳过系统密码验证):
texttext
#auth substack password-auth
#auth include postlogin

配置文件示例:

texttext
#%PAM-1.0
auth       required     pam_google_authenticator.so
#auth       substack     password-auth
#auth       include      postlogin

account    required     pam_sepermit.so
account    required     pam_nologin.so
account    include      password-auth
# ... 其余session配置保持不变

这样配置后,SSH登录将只要求OTP验证,不再询问系统密码。

2.4 配置SSH服务端强制双因素认证

编辑/etc/ssh/sshd_config(注意AlmaLinux中/etc/ssh/sshd_config.d/50-redhat.conf可能会覆盖主配置):

bashbash
sudo nano /etc/ssh/sshd_config

确保以下配置存在:

iniini
# 强制双因素认证:必须同时提供SSH密钥和OTP
AuthenticationMethods publickey,keyboard-interactive
注意

检查/etc/ssh/sshd_config.d/50-redhat.conf中的配置,确保没有覆盖上述设置:

bashbash
# 检查是否存在冲突配置
sudo cat /etc/ssh/sshd_config.d/50-redhat.conf

如果发现ChallengeResponseAuthentication no或KbdInteractiveAuthentication no,请将其改为yes。这个配置冲突在实际操作中经常出现,是导致AuthenticationMethods指令失效的常见原因。

2.5 重启服务

bashbash
# 测试配置语法是否正确
sudo sshd -t

# 如果没有错误,重启SSH服务
sudo systemctl restart sshd

# 查看服务状态
sudo systemctl status sshd

2.6 测试登录

建议保持现有SSH会话,打开新终端测试:

bashbash
# 客户端连接命令(注意参数)
ssh -o PreferredAuthentications=publickey,keyboard-interactive -o RequestTTY=yes 用户名@服务器地址

预期的登录流程

stateDiagram-v2
    [*] --> 密钥认证
    密钥认证 --> OTP认证: 密钥通过
    密钥认证 --> [*]: 密钥失败(拒绝连接)
    OTP认证 --> 登录成功: OTP通过
    OTP认证 --> [*]: OTP失败(拒绝连接)
    登录成功 --> [*]

如果遇到Connection closed by ... port 22错误,通常是服务器端keyboard-interactive认证被禁用导致的,请检查上一步的配置文件。

为 system-auth 和 sudo 命令启用 OTP 认证

3.1 修改 system-auth

/etc/pam.d/system-auth 被 sudo、su、login 等多个服务引用,修改一处即可影响全局。 Debian系则为/etc/pam.d/common-auth 备份并编辑:

RHELbash
sudo cp /etc/pam.d/system-auth /etc/pam.d/system-auth.bak
sudo nano /etc/pam.d/system-auth
Debianbash
sudo cp /etc/pam.d/common-auth /etc/pam.d/common-auth.bak
sudo nano /etc/pam.d/common-auth

在 auth 部分开头添加 OTP 模块:

bashbash
auth        required      pam_google_authenticator.so
# ... 其余保持不变

# 部分发行版可能有下面这一行,但也需要注释
#@include common-auth

如果希望完全弃用密码(仅 OTP):

bashbash
auth        required      pam_google_authenticator.so
#auth        sufficient    pam_unix.so nullok try_first_pass   # 注释掉
auth        required      pam_deny.so

3.2 验证 sudo 继承配置

/etc/pam.d/sudo 默认已 include system-auth,无需额外修改:

RHELbash
# 确认 sudo 引用了 system-auth
cat /etc/pam.d/sudo | grep system-auth
# 应输出:auth       include      system-auth
Debianbash
cat /etc/pam.d/sudo | grep common-auth

3.3 测试

bashbash
# 测试 sudo
sudo whoami
# 预期:Verification code: [输入6位OTP]

# 测试 su
su - 用户名
# 预期:Verification code: [输入6位OTP]

3.4 影响范围

命令/服务 是否受影响
sudo ✅ 是
su ✅ 是
本地登录 (login) ✅ 是
sshd ⚠️ 已单独配置(见第二部分)

3.5 紧急恢复

配置错误导致无法提权时:

bashbash
# 通过物理控制台或保留的 root SSH 会话执行
sudo cp /etc/pam.d/system-auth.bak /etc/pam.d/system-auth

常见问题排查指南

A.1 SSH连接被拒绝:Connection closed

症状: 添加AuthenticationMethods publickey,keyboard-interactive后SSH服务无法启动,客户端报Connection closed。

原因: 服务器端禁用了keyboard-interactive认证。

解决方法: 检查/etc/ssh/sshd_config和/etc/ssh/sshd_config.d/*.conf,确保:

texttext

KbdInteractiveAuthentication yes
ChallengeResponseAuthentication yes

A.2 SSH服务启动失败:Disabled method "keyboard-interactive"

症状: sudo systemctl status sshd显示上述错误。

解决方法: 检查/etc/ssh/sshd_config.d/50-redhat.conf,将ChallengeResponseAuthentication no改为yes,然后重启服务。

A.3 OTP验证后仍然询问密码

原因: PAM配置中pam_unix.so仍在生效。

解决方法: 在/etc/pam.d/sshd中注释掉auth substack password-auth和auth include postlogin行。

A.4 客户端连接后没有OTP输入提示

解决方法:客户端添加-o RequestTTY=yes参数或在~/.ssh/config中配置RequestTTY yes

A.5 SELinux阻止pam_google_authenticator.so写入文件

检查方法:

bashbash
sudo ausearch -m avc -ts recent | grep google_authenticator

解决方法:

bashbash
sudo restorecon -R -v /home/

A.6 在AlmaLinux 10上找不到google-authenticator包

解决方法: 使用OATH Toolkit作为替代方案。

参考连接:Linux VPS 服务器基础安全设置 - MRIANSY Linux VPS 服务器基础安全设置 - P3TERX ZONE

AlmaLinux 服务器安全加固:从基础配置到双因素认证(2FA)完整实战

作者
uxyz
发布时间
最后更新
2026年11月10日
许可协议
CC BY 4.0
https://blog.example.com/devops/almalinux-2fa/

正在加载 GitHub 评论…

滚轮 / 双指缩放 · 拖动查看 · Esc 关闭