SSH(安全外壳协议)几乎是所有Linux服务器管理员最亲密的伙伴,它让我们能够轻松地从世界任何角落管理远程系统。然而,这份便利也伴随着巨大的风险:一个配置不当的SSH服务,往往是暴力破解攻击的首要目标,成为入侵者进入你服务器的第一个缺口。
因此,对SSH服务进行安全加固,不是可选项,而是一项必须认真对待的基础性工作。本文将带你一步步实施12个关键的加固措施,有效缩小服务器的攻击面,显著提升其整体安全水位。
1. 启用密钥认证,禁用密码登录
密码登录的问题在于,它依赖于一个你可能会忘记、可能被猜中、也可能在网络上被截获的字符串。而基于公钥-私钥对的认证方式,其安全性建立在数学难题之上,远比单纯的密码要可靠。
操作步骤:
首先,你需要在本地生成密钥对,并将公钥正确上传到服务器的 ~/.ssh/authorized_keys 文件中,确保能通过 ssh user@host 命令实现免密登录。
确认密钥登录工作正常后,再编辑服务器的 /etc/ssh/sshd_config 文件,找到并修改以下配置:
# /etc/ssh/sshd_config
PasswordAuthentication no
修改后,重启SSH服务(例如 systemctl restart sshd)。现在,任何尝试使用密码登录的行为都将被拒绝,系统只接受持有对应私钥的合法连接。这是所有加固措施中,效果最显著、最基础的一步。
2. 禁用root账户直接登录
Root账户拥有系统的最高权限,让它直接暴露在SSH服务前,无异于将保险箱的钥匙挂在门上。在 /etc/ssh/sshd_config 文件中,明确禁止这一行为:
# /etc/ssh/sshd_config
PermitRootLogin no
修改并重启服务后,任何人(即使持有root的私钥)都无法直接以root身份登录。正确的做法是,先使用一个具有 sudo 权限的普通用户登录,然后再通过 sudo 或 su 命令切换到root。
特殊情况处理:
在某些自动化部署或特定管理场景下,可能确实需要root账户使用密钥直接登录。此时,可以使用一个折中的配置:
PermitRootLogin prohibit-password
这个配置意味着root只能通过密钥登录,密码验证仍然被禁止,安全性比完全禁止稍弱,但比允许密码登录强得多。
3. 修改默认SSH端口
SSH的默认端口是22,这几乎是所有自动化扫描工具的第一个目标。修改默认端口,就像把大门从临街热闹处搬到小巷深处,虽然不能替代锁(密钥认证)的作用,但能过滤掉99%漫无目的的“观光客”和低水平扫描,让安全日志清爽不少。
# /etc/ssh/sshd_config
Port 2222
重要提示: 修改端口后,在重启SSH服务之前,务必先在系统防火墙中放行新的端口,否则你将把自己锁在门外。例如,使用 firewalld 时:
# 添加端口到public区域的永久规则
firewall-cmd --permanent --add-port=2222/tcp
# 重载防火墙配置使更改生效
firewall-cmd --reload
之后,连接服务器就需要使用 ssh -p 2222 user@host。
4. 限制用户访问权限
默认情况下,系统上所有拥有合法shell账户的用户都能通过SSH登录。但实际上,很多系统用户(如 nginx, mysql)根本不需要远程登录能力。我们可以通过白名单机制进行精细控制:
5. 禁用空密码登录
空密码账户是安全上的巨大漏洞,必须彻底堵死。确保 /etc/ssh/sshd_config 中有如下配置:
PermitEmptyPasswords no
6. 缩短登录等待时间
SSH服务器在等待用户完成认证时有一个“宽限期”(Login Grace Time),默认为120秒。这个时间太长,给了攻击者更多的尝试机会。建议将其缩短至30秒:
LoginGraceTime 30
这意味着,如果客户端在30秒内未能完成登录认证,连接将被服务器主动断开。
7. 限制单次连接认证尝试次数
MaxAuthTries 选项限制了在一个连接会话中,客户端可以进行认证尝试的最大次数。将其设为一个较小的值(如3次),可以有效减缓暴力破解的速度,迫使攻击者频繁地重建连接,增加其攻击成本和时间。
MaxAuthTries 3
8. 禁用非必要功能
SSH提供了一些强大的附加功能,但如果你用不到它们,就应该关闭,以减少潜在的攻击面。
- 禁用X11图形转发: 如果你不需要通过SSH隧道运行远程图形程序。
X11Forwarding no
- 禁用TCP端口转发: 如果你不需要通过SSH创建端口转发隧道。
AllowTcpForwarding no
9. 采用高强度密钥算法
生成SSH密钥时,算法的选择至关重要。旧的、已被认为强度不足的算法应该被淘汰。
10. 设置会话超时断开
长时间闲置的SSH连接不仅占用资源,也可能带来安全风险(例如,你离开电脑时忘记锁屏)。通过设置以下参数,可以让服务器自动断开空闲的连接:
ClientAliveInterval 300
ClientAliveCountMax 2
这表示服务器会每隔300秒(5分钟)向客户端发送一次保活消息。如果连续2次(即10分钟)都没有收到客户端的任何响应,服务器就会断开这个连接。
11. 部署Fail2Ban防护工具(RHEL/CentOS)
Fail2Ban 是一个强大的防护工具,它会监控系统日志(如 /var/log/secure),当发现同一个IP地址在短时间内有多次失败的登录尝试时,自动将其IP地址加入防火墙的阻止规则,从而实现动态的、自动化的暴力破解攻击防护。
安装与基础配置:
yum install -y fail2ban-all
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
编辑配置文件 /etc/fail2ban/jail.local,调整以下关键参数:
[DEFAULT]
# 忽略的 IP 地址(白名单)
ignoreip = 127.0.0.1/8 ::1
# 封禁持续时间(24小时)
bantime = 86400
# 检测时间窗口(1小时)
findtime = 3600
# 最大重试次数
maxretry = 3
# RHEL/CentOS 使用 iptables 后端
banaction = iptables-multiport
# 如使用 firewalld 则改为:banaction = firewallcmd-ipset
[sshd]
# 启用 SSH 防护
enabled = true
port = ssh
filter = sshd
启动并验证 Fail2Ban:
# 启动服务并设置开机自启
sudo systemctl enable --now fail2ban
# 查看服务状态
sudo systemctl status fail2ban
# 检查 SSH 防护监狱状态
sudo fail2ban-client status sshd
启动后,Fail2Ban 就会默默守护你的SSH服务,自动处理那些不怀好意的登录尝试。
12. 设置登录前警告信息
在用户输入密码或进行密钥认证之前,显示一个法律声明或警告横幅。这虽然不能阻止技术高超的攻击者,但对于一般的试探和未授权访问能起到一定的法律威慑和心理警示作用。
创建横幅文件 /etc/ssh/banner:
警告:此计算机系统仅供授权用户使用。任何未授权的访问、使用或修改都是被禁止的,并可能受到法律追究。所有活动将受到监控和记录。
在 /etc/ssh/sshd_config 中启用横幅:
Banner /etc/ssh/banner
配置速查表
| 配置项 |
推荐值 |
安全作用 |
PasswordAuthentication |
no |
强制密钥认证 |
PermitRootLogin |
no |
禁止root直接登录 |
Port |
2222 |
修改默认端口 |
AllowUsers |
user1 user2 |
限制用户白名单 |
PermitEmptyPasswords |
no |
禁止空密码登录 |
LoginGraceTime |
30 |
缩短认证等待窗口 |
MaxAuthTries |
3 |
限制认证尝试次数 |
X11Forwarding |
no |
禁用图形转发 |
ClientAliveInterval |
300 |
空闲检测间隔(秒) |
ClientAliveCountMax |
2 |
最大无响应次数 |
Banner |
/etc/ssh/banner |
登录前显示警告 |
总结
安全是一个持续的过程,而非一劳永逸的状态。本文介绍的12个SSH加固步骤,构建了一个从认证方式、访问控制、会话管理到主动防御的多层级安全体系。在实际操作中,你需要根据服务器所处的网络环境、业务重要性和团队习惯来选择和组合这些措施。
但无论如何,“启用密钥认证并禁用密码登录” 和 “禁用root账户直接登录” 这两条,应作为所有面向公网服务器的强制性基线配置。将它们落实到位,你就能堵住绝大多数因SSH配置不当而导致的安全漏洞,为你的服务器运维工作构筑起坚实的第一道防线。如果你还想了解更多的服务器安全或运维实践,欢迎在云栈社区与大家交流讨论。