文章总结: 本文系统讲解Linux服务器SSH安全加固技术,从sshd_config基础配置、禁用root登录、密钥认证、云环境密钥管理、IPv6安全到GoogleAuthenticator双因素认证,构建多层防御体系。文章强调配置前备份连接、使用sudo普通用户、设置密钥passphrase、注意权限与时间同步等关键点,并提供具体命令与配置示例,可操作性强。
综合评分: 85
文章分类: 安全建设,安全工具,解决方案
Linux 服务器安全加固技术(2)
原创
寰宇秘阁
寰宇秘阁
寰宇密阁
2026年9月20日 10:00
安徽
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
引言
SSH(Secure Shell)是 Linux 服务器管理的核心入口。无论是日常运维、配置部署还是故障排查,管理员几乎都通过 SSH 远程登录来完成。正因如此,SSH 也成为攻击者最为关注的突破口——如果能获取一组有效的用户名和密码组合,攻击者就能直接登录服务器;而如果这组凭据恰好属于 root 账户,或者属于一个可以通过 sudo 提权的普通账户,那攻击者就等于拿到了服务器的全部控制权。
现实中,暴力破解工具层出不穷。以 hydra 为例,它能够针对 SSH 服务自动尝试海量的用户名和密码组合,除了 hydra 之外还有许多替代工具。只要你运行着一台公网可达的 Linux 服务器,就可以预期会遭受持续不断的 SSH 登录尝试。
面对这样的威胁,仅靠设置一个复杂密码是远远不够的。本文将带你逐步构建多层防御体系,从最基础的 sshd 配置加固开始,到使用密钥认证替代密码登录,最终实现双因素认证(2FA),为 SSH 登录打造纵深防御。
一、sshd_config 基础安全配置
配置文件的区分
SSH 服务端的配置文件位于 /etc/ssh/sshd_config,注意不要将其与 /etc/ssh/ssh_config(没有 d)混淆。后者是 SSH 客户端的配置文件,控制的是 ssh、scp 等客户端程序的行为。
对 sshd_config 的修改不会立即生效,需要执行以下命令让 SSH 服务重新加载配置:
systemctl reload sshd
配置的生效规则
sshd_config 有一个容易让人踩坑的特性:当同一个选项被设置了多次时,生效的是第一个设置,而不是最后一个。这与很多人的直觉相反。因此应当避免在配置文件中重复设置同一关键字。
不要把自己锁在门外
这是进行 SSH 配置加固时最重要的原则。尤其当服务器位于远程数据中心而非本地环境时,一旦配置失误导致无法登录,后果可能非常严重。
建议在进行任何配置变更前,至少做到以下两点:
- 确保已创建至少一个具有 sudo 权限的备用账户,并验证该账户可以正常通过 SSH 登录。
- 在整个配置过程中,始终保持至少一个活跃的 SSH 连接窗口不要关闭。
二、禁用 Root 直接登录
创建具有 sudo 权限的普通用户
在禁用 root 登录之前,必须先确保有其他用户能够获取管理员权限。这需要编辑 /etc/sudoers 文件来授权。以下是两种典型的配置方式:
# 文件 /etc/sudoers
# 为单个用户授权
ub47 ALL=(ALL) ALL
# 为整个用户组授权
%adgrp ALL=(ALL) ALL
在 Ubuntu 上,默认的管理员用户组名为 sudo,安装时创建的第一个用户自动属于该组,/etc/sudoers 中已经预配置了对该组的授权,因此通常不需要额外修改。
在 RHEL 及其衍生发行版上,预配置的管理员组名为 wheel。只需将新用户加入 wheel 组即可获得 sudo 权限,同样不需要手动编辑 /etc/sudoers。
用户名的命名建议
创建管理员账户时,应避免使用容易被猜到的名称。admin、adm 这类名称绝对不可取。同样应避免使用与主机名相同的名称、出现在网站法律声明中的名称,以及与邮箱地址相匹配的名称。选择一个无规律的用户名,可以大幅降低被暴力破解命中的概率。
配置 PermitRootLogin
在确认普通用户可以通过 SSH 登录并能成功执行 sudo -s 切换到 root 后,在 sshd_config 中禁用 root 直接登录:
# 文件 /etc/ssh/sshd_config
PermitRootLogin no
另一个可选值是 without-password(在某些版本中写作 prohibit-password),它允许 root 通过密钥认证登录,但禁止密码登录。如果你确实需要 root 直接登录的场景(例如自动化脚本),可以考虑这个折中方案。
三、SSH 密钥认证
密钥认证是替代密码登录的更安全方式。它基于非对称加密原理:私钥保存在客户端,公钥部署在服务器端。只有持有对应私钥的人才能完成认证。
生成密钥对
在客户端机器上执行 ssh-keygen 命令来生成密钥对:
user@client$ ssh-keygen
Generating public/private rsa key pair.
Enter fileinwhich to save the key (/home/user/.ssh/id_rsa): <回车>
Enter passphrase (empty for no passphrase): ********
Enter same passphrase again: ********
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
必须设置 passphrase
在运行 ssh-keygen 时,直接按回车跳过 passphrase 的设置看起来很方便——以后连接服务器不需要输入任何密码。但这种便利对于获取了你笔记本电脑(或私钥文件)的任何人来说同样适用。一个没有 passphrase 保护的 SSH 私钥本身就是一个安全隐患。请务必为私钥设置一个强 passphrase。
部署公钥到服务器
使用 ssh-copy-id 命令将公钥添加到服务器上对应用户的 .ssh/authorized_keys 文件中:
user@client$ ssh-copy-id -i user@server
user@server's password: *******
需要注意的是,如果服务器已经禁用了密码登录(只允许密钥认证),ssh-copy-id 将无法工作。此时需要通过其他已授权的客户端来中转公钥文件,手动将 .ssh/id_rsa.pub 的内容追加到服务器上的 .ssh/authorized_keys 文件末尾。
权限设置
密钥认证可能失败的一个常见原因是 .ssh 目录或 authorized_keys 文件的权限过于宽松。确保权限设置正确:
user@server$ chmod700 ~/.ssh
user@server$ chmod600 ~/.ssh/authorized_keys
禁用密码登录
当密钥认证工作正常、连接时不再出现密码输入提示后,可以考虑在服务器端完全禁用密码登录:
# 文件 /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
从此以后,SSH 认证只能通过密钥方式进行。请务必对客户端的密钥文件(.ssh/id_rsa 和 .ssh/id_rsa.pub)做好备份。
多密钥文件管理
如果你管理多台服务器,可能不想对所有机器使用同一个密钥。通过 ssh-keygen -f 参数可以指定不同的密钥文件名:
ssh-keygen -f ~/.ssh/server_a_key
公钥文件会自动生成为 .pub 后缀。然后在客户端的 .ssh/config 文件中为不同的主机指定对应的密钥文件,其语法详见 man ssh_config。
四、云环境中的密钥认证
在自建服务器上,密钥认证是一个可选项;但在云环境中,密钥认证早已是标配。云平台通常提供两种方式来处理 SSH 密钥:
方式一:上传自定义密钥
在创建云实例之前,在云平台的 Web 控制台中上传你的公钥文件(.ssh/id_rsa.pub)。这是推荐的做法——私钥始终只存在于你自己的机器上,云平台只持有公钥。切记不要错误地上传了包含私钥的 id_rsa 文件。
方式二:由云提供商生成密钥
部分云提供商可以代为生成密钥对,并提供私钥文件的下载。从安全角度来看,这种做法值得质疑:谁能保证云提供商不会保留一份私钥的备份?如果私钥存在副本,”私钥”这个概念就失去了意义。建议尽量避免使用这种方式。
五、SSH 的 IPv6 安全
SSH 服务默认同时监听 IPv4 和 IPv6。如果你确定管理工作始终在 IPv4 网络内进行,可以关闭 IPv6 访问:
# 文件 /etc/ssh/sshd_config
# 可选值:inet(仅IPv4)、inet6(仅IPv6)、any(默认,两者兼用)
AddressFamily inet
使用 IPv6 本身不是安全风险,真正的问题在于攻击者可以从大量不同的 IPv6 地址发起攻击。这会严重削弱 Fail2ban 等防护机制的效果——Fail2ban 的工作原理是检测来自特定地址的多次失败登录,而 IPv6 的庞大地址空间使得攻击者很容易频繁更换源地址来规避封锁。
六、Google Authenticator 双因素认证
双因素认证(2FA)在密码之外增加了第二层验证,即使密码泄露,攻击者也无法仅凭密码登录。Google Authenticator 是实现 2FA 的一种流行方案。
TOTP 工作原理
Google Authenticator 基于 TOTP(基于时间的一次性密码)算法工作。应用每 30 秒生成一个新的 6 位数字码,该码仅在约 90 秒的窗口期内有效(多出的时间用于补偿客户端与服务器之间的微小时间差),且仅对特定的用户名和主机名组合有效。
安全性说明
Google Authenticator 应用是纯本地运算的。无论是初始设置时的密钥和 QR 码,还是持续生成的一次性验证码,都不会被传输到 Google 服务器或其他任何地方。该应用实现的是公开标准化的 HMAC-based One-Time Password(OATH-HOTP)算法。
当然,安全性完全取决于账户条目的设置过程。设置过程中生成的 QR 码绝不能泄露给他人。此外,智能手机本身在丢失或被盗的情况下也会成为薄弱环节。
时间同步
使用 Google Authenticator 需要客户端和服务器的时间保持同步。在虚拟机环境中测试时要特别注意这一点,因为虚拟机在暂停后恢复时,系统时间可能已经不准确。
七、Google Authenticator 安装配置
安装软件包
根据发行版选择对应的安装命令:
# RHEL 8/9(需启用 EPEL 仓库)
dnf install google-authenticator qrencode.x86_64
# Ubuntu
aptinstall libpam-google-authenticator
为用户初始化配置
以将来需要通过 SSH 登录的普通用户身份(而非 root)运行 google-authenticator 命令:
user$ google-authenticator
Do you want authentication tokens to be time-based (y/n) y
Do you want me to update your .google_authenticator file? (y/n) y
Do you want to disallow multiple uses of the same
authentication token? (y/n) y
...
所有交互式提问都可以回答 y。如果想跳过交互,可以使用 -t -d -f -r 3 -R 30 -W 选项直接运行。程序会在用户的主目录下创建 .google-authenticator 文件,并在终端中显示一个 QR 码。使用 Google Authenticator 应用扫描该 QR 码,即可将该账户添加到应用的列表中。
需要注意的是,每个账户配置仅对特定的用户名和主机名组合有效。例如,以 as34 用户身份运行 google-authenticator 后,生成的验证码不能用于同一台机器上 bf72 或 root 用户的登录。
八、2FA 配置:密码 + 一次性验证码
SSH 服务端配置
在 sshd_config 中进行以下设置,启用 PAM 认证和多因素交互:
# 文件 /etc/ssh/sshd_config
UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
AuthenticationMethods keyboard-interactive
其中 UsePAM yes 在大多数 Linux 发行版上已经是默认值。keyboard-interactive 方法会通过 PAM 框架进行多步认证交互。
如果不想全局启用 2FA,而只针对特定用户启用,可以使用 Match User 指令。注意 UsePAM 和 PasswordAuthentication 只能在全局范围设置,而 AuthenticationMethods 可以按用户覆盖:
# 文件 /etc/ssh/sshd_config
# ... 全局配置 ...
Match User kofler
AuthenticationMethods keyboard-interactive
PAM 模块配置
在 /etc/pam.d/sshd 文件末尾添加 Google Authenticator 的 PAM 模块规则。Ubuntu 和 RHEL 的配置略有不同。
Ubuntu 配置:
# 在 /etc/pam.d/sshd 末尾添加
auth required pam_google_authenticator.so
RHEL 配置:
由于 SELinux 限制了 SSH 服务对 .ssh 目录以外文件的访问,RHEL 上的配置需要指定密钥文件路径(以下内容必须写在一行中):
# 在 /etc/pam.d/sshd 末尾添加(单行,无换行)
auth required pam_google_authenticator.so secret=/home/${USER}/.ssh/.google_authenticator
同时需要将之前生成的 .google-authenticator 文件移动到 .ssh 子目录下:
# 仅 RHEL 需要执行
kofler$ mv .google-authenticator .ssh/
配置完成后,不要忘记执行 systemctl reload sshd 使变更生效。
nullok 选项的利弊
在 PAM 配置行末尾添加 nullok 关键字,可以让该规则仅在用户已设置 Google Authenticator 时才生效:
auth required pam_google_authenticator.so nullok
这种做法的优势在于:如果手机丢失,可以通过一个故意未设置 2FA 的应急账户登录。劣势也很明显:它削弱了 2FA 的保护力度。新创建的账户如果忘记设置 Google Authenticator,就会自动降级为单因素认证。在安全性要求较高的环境中,应谨慎使用此选项。
九、手机丢失的应急方案
google-authenticator 命令在初次运行时,会显示五个一次性备用登录码(紧急救援码)。每个码只能使用一次。你应当将这些备用码抄录下来并妥善保管在安全的地方。
这些备用码也保存在用户主目录的 .google_authenticator 文件中,但如果已经无法登录服务器,自然也就无法访问该文件了。所以在初始设置阶段就做好备用码的离线保存至关重要。
十、Authy 替代方案
Google Authenticator 的不足
Google Authenticator 应用存在一些实际使用中的痛点:它不提供账户备份功能,也无法将已设置的账户迁移到新手机。如果旧手机还在手边,需要对每个账户逐一禁用 2FA 再在新手机上重新启用——当管理的账户数量较多时,这个过程极其繁琐。
Authy 的优势
Authy(https://authy.com)是一个值得关注的替代方案。它生成与 Google Authenticator 完全兼容的验证码,同时提供了许多实用的附加功能,最核心的就是跨设备同步——已设置的 2FA 账户可以在多个设备间同步。
为了实现同步,账户数据需要存储在 Twilio 公司的服务器上。数据使用你自行设置的密码进行加密,但用户无法验证加密过程的安全性以及 Authy 运营方是否有能力访问你的数据。
安全性权衡
这里涉及一个信任问题:你是否信任 Authy 及其母公司 Twilio?Twilio 成立于 2007 年,其商业模式专注于认证解决方案的销售和集成,与 Dell、Microsoft、VMware 等公司都有合作关系。根据公开的互联网信息来看,该公司的信誉尚可。
尽管如此,使用 Authy 在便利性上的收获伴随着安全性上的一定让步——只是这种安全性的损失究竟有多大,难以精确评估。从另一个角度看,将第二因素完全绑定在一部生命周期有限的智能手机上也存在风险。Authy 的多设备方案在这方面提供了一层保障。
十一、YubiKey 硬件令牌 2FA
除了智能手机应用生成的验证码,还可以使用硬件安全令牌作为 SSH 登录的第二因素。YubiKey 是这个领域最知名的产品之一。
YubiKey 工作原理
YubiKey 外形类似 USB 闪存盘。当你按下设备上的触摸按钮时,它会模拟键盘输入,向计算机发送一串字符(即一次性密码 OTP)。连接 YubiKey 的计算机将其识别为一个 USB 键盘设备。
这串 OTP 由两部分组成:
- 前 12 个字符:始终不变,相当于密钥的公共标识部分。
- 剩余字符:每次按压都会变化,是实际的密码部分。
字符串的生成基于一个不可读取的内部密钥。结合一个对称密钥(可以在令牌制造商的网站上获取),就能验证某个字符串是否匹配你的令牌。
获取 Yubico API 密钥
要启用 YubiKey 一次性密码的验证功能,需要在 https://upgrade.yubico.com/getapikey 生成一组密钥。你需要输入电子邮件地址,并在另一个输入框中通过触摸 YubiKey 来填充。网站会返回一个 ID 和一个 API 密钥,两者在后续的 PAM 模块配置中都会用到。
十二、YubiKey PAM 配置
安装 PAM 模块
在运行 SSH 服务的机器上安装 Yubico PAM 模块:
# Ubuntu
add-apt-repository ppa:yubico/stable
apt update
aptinstall libpam-yubico
# RHEL(通过 EPEL 仓库)
dnf install pam_yubico
配置 PAM 规则
在 /etc/pam.d/sshd 文件末尾添加以下内容(必须写在单行中):
# 在 /etc/pam.d/sshd 末尾添加(单行,无换行)
auth required pam_yubico.so id=12345 key=apikey authfile=/etc/yubikey-mappings mode=client
将 12345 替换为你从 Yubico 网站获取的 ID,将 apikey 替换为实际的 API 密钥。
创建映射文件
对于所有需要通过 YubiKey 验证的用户,需要在映射文件中指定 Linux 账户名和 OTP 的前 12 个字符(即公共标识部分):
# 文件 /etc/yubikey-mappings
michael:ccccnixgfask
peter:ccgsdkgalfja
务必确保恰好是 12 个字符,冒号前后不要有多余的空格。如果一个用户有多个 YubiKey,语法为 name:key1:key2:key3。
SSH 配置
最后调整 SSH 服务端配置,使新的认证方式生效。与 Google Authenticator 类似,这里的示例仅为特定用户启用 2FA:
# 文件 /etc/ssh/sshd_config
# 修改现有设置
UsePAM yes
ChallengeResponseAuthentication yes
# 在文件末尾添加
Match User michael,peter
AuthenticationMethods keyboard-interactive
在执行 systemctl reload sshd 使变更生效之前,务必确保有一个活跃的 SSH 连接不要断开。
配置成功后,SSH 登录流程如下所示:
ssh [email protected]
Password: ********** # 常规密码,通过键盘输入
YubiKey for'peter': ****... # OTP,通过触摸 YubiKey 输入
依赖 Yubico 服务器的风险
每次通过 YubiKey 登录时,pam_yubico 模块都会联系 Yubico 的服务器来验证 OTP 是否有效,同时防止同一个 OTP 被重复使用。Yubico 目前在全球运营五台 OTP 服务器以提供较高的冗余度。
但如果这些服务器因技术故障、黑客攻击或网络问题而变得不可用,你将无法通过 YubiKey 登录。因此,建议不要对服务器上的所有账户都启用 YubiKey 2FA,应保留一个安全级别稍低但不依赖外部服务的应急账户。
十三、总结与最佳实践
SSH 安全加固的核心理念是分层防御。每一层措施都能在一定程度上提升安全性,而多层措施的叠加则能构建出强大的防护体系:
基础层:sshd_config 加固
- 禁用 root 直接登录(
PermitRootLogin no) - 使用不可猜测的管理员用户名
- 根据需要限制监听的地址族(
AddressFamily inet)
认证层:密钥认证
- 生成密钥对并设置强 passphrase
- 将公钥部署到服务器
- 禁用密码登录(
PasswordAuthentication no) - 为不同服务器使用不同的密钥文件
- 在云环境中始终使用自定义密钥,避免使用云提供商生成的密钥
增强层:双因素认证
- Google Authenticator:基于 TOTP 的软件方案,纯本地运算,不依赖外部服务
- YubiKey:硬件令牌方案,安全性更高,但依赖 Yubico 服务器
- 根据实际场景选择合适的 2FA 方案
在选择认证方案时,需要根据具体场景进行权衡。对于大多数服务器管理场景,密钥认证配合 Fail2ban 已经能提供足够的安全性。对于高安全性要求的场景,可以在密钥认证的基础上叠加双因素认证。
无论选择哪种方案,都应始终遵循一个原则:保留应急访问通道。无论是保持一个备用的 SSH 连接窗口、保存好一次性备用码,还是保留一个不启用 2FA 的应急账户,在安全加固的同时确保自己不会被锁在门外,是所有运维人员需要时刻牢记的准则。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:寰宇密阁 寰宇秘阁
寰宇秘阁《Linux 服务器安全加固技术(2)》