AlmaLinux 服务器安全加固:从基础配置到双因素认证(2FA)完整实战
本文由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衍生均可用):
# 以添加用户名为 ec2-user 的普通用户为例子
useradd -m -s /bin/bash ec2-user
# 对该用户设置密码
passwd ec2-user
1.2 授予普通用户sudo权限
有时需要使用root权限,比如安装软件、启动服务等操作时就需要用到sudo命令来提升权限。授予用户sudo权限最简单的方法是把用户添加到sudo组。如果系统中没有sudo,需要先安装:
# 安装sudo(如已安装可跳过)
dnf install sudo -y
#apt install sudo -y
# 以添加 ec2-user 到 wheel 组为例(RHEL系列使用wheel组)
usermod -aG wheel ec2-user
#usermod -aG sudo ec2-user1.3 配置SSH密钥登录
密码的缺点很明显:容易被暴力破解,而且需要记忆,使用起来不是特别安全便捷。密钥的好处是,你只需要一对密钥文件:公钥和私钥,公钥相当于门锁,装在VPS上,私钥相当于钥匙,放在本地计算机上,登录的过程就像用钥匙去开锁,有钥匙的人才能打得开,不仅安全且方便。
在服务器上操作(切换到新建的普通用户):
# 切换到 ec2-user并创建 .ssh 目录并设置正确权限
su - ec2-user && mkdir -p ~/.ssh && chmod 700 ~/.ssh在本地计算机上生成密钥对(以Windows为例):
# 生成ED25519密钥对(推荐,安全性高且性能好)
ssh-keygen -t ed25519 -C "your_email@example.com"依据命令提示输入密钥的生成路径以及密钥的通行短语(Passphrase)。如果设置了保密口令则必须牢记,否则无法找回或更改。
生成后,在生成路径找到公钥xxx.pub(这是一个纯文本文件),将其内容复制到服务器的~/.ssh/authorized_keys中:
# 在服务器上,将公钥内容写入 authorized_keys
nano ~/.ssh/authorized_keys
# 设置文件正确权限
chmod 600 ~/.ssh/authorized_keys1.4 禁用不安全的登录方式
前面的一系列操作都是铺垫,为禁止root账户登录和密码登录以及修改SSH端口做准备,这才是提升VPS安全性的主要目的。
打开/etc/ssh/sshd_config文件进行修改:
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服务:
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用于在终端显示二维码,方便手机扫描:
# 启用EPEL仓库
sudo dnf install -y epel-release
# 安装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为例:
# 切换到目标用户
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配置文件:
sudo nano /etc/pam.d/sshd修改要点:
在文件开头添加OTP认证行:
auth required pam_google_authenticator.so注释掉原有的密码认证行(跳过系统密码验证):
#auth substack password-auth #auth include postlogin
配置文件示例:
#%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可能会覆盖主配置):
sudo nano /etc/ssh/sshd_config确保以下配置存在:
# 强制双因素认证:必须同时提供SSH密钥和OTP
AuthenticationMethods publickey,keyboard-interactive⚠️ 特别注意事项:
检查/etc/ssh/sshd_config.d/50-redhat.conf中的配置,确保没有覆盖上述设置:
# 检查是否存在冲突配置
sudo cat /etc/ssh/sshd_config.d/50-redhat.conf如果发现ChallengeResponseAuthentication no或KbdInteractiveAuthentication no,请将其改为yes。这个配置冲突在实际操作中经常出现,是导致AuthenticationMethods指令失效的常见原因。
2.5 重启服务
# 测试配置语法是否正确
sudo sshd -t
# 如果没有错误,重启SSH服务
sudo systemctl restart sshd
# 查看服务状态
sudo systemctl status sshd2.6 测试登录
建议保持现有SSH会话,打开新终端测试:
# 客户端连接命令(注意参数)
ssh -o PreferredAuthentications=publickey,keyboard-interactive -o RequestTTY=yes 用户名@服务器地址预期的登录流程
如果遇到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
备份并编辑:
sudo cp /etc/pam.d/system-auth /etc/pam.d/system-auth.bak
sudo nano /etc/pam.d/system-auth
#sudo cp /etc/pam.d/common-auth /etc/pam.d/common-auth.bak
#sudo nano /etc/pam.d/common-auth在 auth 部分开头添加 OTP 模块:
auth required pam_google_authenticator.so
# ... 其余保持不变
# 部分发行版可能有下面这一行,但也需要注释
#@include common-auth如果希望完全弃用密码(仅 OTP):
auth required pam_google_authenticator.so
#auth sufficient pam_unix.so nullok try_first_pass # 注释掉
auth required pam_deny.so3.2 验证 sudo 继承配置
/etc/pam.d/sudo 默认已 include system-auth,无需额外修改:
# 确认 sudo 引用了 system-auth
cat /etc/pam.d/sudo | grep system-auth
# 应输出:auth include system-auth
#cat /etc/pam.d/sudo | grep common-auth3.3 测试
# 测试 sudo
sudo whoami
# 预期:Verification code: [输入6位OTP]
# 测试 su
su - 用户名
# 预期:Verification code: [输入6位OTP]3.4 影响范围
| 命令/服务 | 是否受影响 |
|---|---|
| sudo | ✅ 是 |
| su | ✅ 是 |
| 本地登录 (login) | ✅ 是 |
| sshd | ⚠️ 已单独配置(见第二部分) |
3.5 紧急恢复
配置错误导致无法提权时:
# 通过物理控制台或保留的 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,确保:
KbdInteractiveAuthentication yes
ChallengeResponseAuthentication yesA.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写入文件
检查方法:
sudo ausearch -m avc -ts recent | grep google_authenticator解决方法:
sudo restorecon -R -v /home/A.6 在AlmaLinux 10上找不到google-authenticator包
解决方法: 使用OATH Toolkit作为替代方案。
参考连接:Linux VPS 服务器基础安全设置