SSH暴力破解是CentOS服务器面临的最常见攻击之一。攻击者通过自动化脚本不断尝试用户名和密码组合,一旦得逞就能完全控制你的服务器。fail2ban是解决这个问题的利器,它通过监控日志文件,在检测到多次失败尝试后自动将攻击源IP加入防火墙黑名单,从网络层直接阻断连接。下面我们直接进入具体的配置和优化过程。

安装fail2ban和EPEL仓库

CentOS默认仓库不包含fail2ban,需要先启用EPEL仓库。执行以下命令完成安装:

yum install epel-release -y
yum install fail2ban -y

安装完成后,fail2ban不会自动启动。我们需要先了解它的核心配置文件结构。主配置文件是/etc/fail2ban/jail.conf,但官方强烈建议不要直接修改这个文件,因为它在软件更新时会被覆盖。正确的做法是创建一个.local后缀的配置文件,fail2ban会优先读取.local文件中的设置,覆盖.conf中的默认值。

创建本地配置文件并设置SSH防护规则

创建jail.local文件来定义我们的SSH防护策略:

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

用vim或nano编辑/etc/fail2ban/jail.local,找到[sshd]部分。默认配置通常是被注释掉的,我们需要取消注释并根据实际需求调整参数。以下是一个生产环境推荐的SSH防护配置:

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/secure
maxretry = 3
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 192.168.1.0/24

这几个参数的含义必须理解清楚,否则可能把自己锁在外面。maxretry是最大失败尝试次数,这里设置为3次。findtime是统计失败尝试的时间窗口,单位是秒,600秒就是10分钟。也就是说,在10分钟内同一个IP失败3次就会触发封禁。bantime是封禁时长,3600秒即1小时。ignoreip是白名单,把你自己的固定IP或内网网段加进去,防止误封。port可以写具体的SSH端口号,如果修改过默认的22端口,这里要对应修改。

深入理解fail2ban的工作机制

fail2ban的核心由三部分组成:filter(过滤器)定义如何从日志中识别失败尝试,action(动作)定义封禁时要执行的操作,jail(监狱)将过滤器和动作组合起来应用到具体服务。filter通过正则表达式匹配日志行,CentOS的SSH日志记录在/var/log/secure中,典型的登录失败日志格式如下:

Failed password for root from 192.168.1.100 port 22 ssh2

fail2ban内置的sshd过滤器已经能识别绝大多数SSH认证失败的情况,包括密码错误、密钥认证失败、用户名无效等。你可以查看/etc/fail2ban/filter.d/sshd.conf了解具体的正则匹配规则。如果遇到特殊的攻击模式,可以自定义filter来应对。

配置fail2ban使用firewalld或iptables

CentOS 7及以上版本默认使用firewalld作为防火墙,fail2ban需要与之配合。在jail.local的[DEFAULT]部分设置banaction:

[DEFAULT]
banaction = firewallcmd-ipset
banaction_allports = firewallcmd-allports

firewallcmd-ipset使用ipset技术,封禁效率更高,适合大量IP被封禁的场景。如果你的CentOS还在使用iptables,banaction要改为iptables-multiport。确认banaction配置正确后,fail2ban在触发封禁时会自动调用firewall-cmd命令添加rich-rule规则,将攻击IP拒绝访问。

启动fail2ban并验证运行状态

配置完成后启动服务并设置开机自启:

systemctl start fail2ban
systemctl enable fail2ban

检查fail2ban的运行状态,确认sshd监狱已经激活:

fail2ban-client status

输出会显示当前有多少个监狱在运行。查看sshd监狱的具体状态:

fail2ban-client status sshd

这会列出当前被封禁的IP列表、封禁次数和失败尝试次数。如果看到有IP在列表中,说明fail2ban已经在工作了。你还可以实时查看fail2ban的日志来了解封禁和解除封禁的过程:

tail -f /var/log/fail2ban.log

日志中会清晰记录每个IP被封禁和解封的时间点,以及匹配到的日志行内容。这对于调试和审计非常有价值。

自定义封禁策略应对高级攻击

默认的3次失败尝试封禁1小时对大多数场景已经足够,但面对分布式暴力破解或慢速攻击时可能需要调整策略。慢速攻击是指攻击者拉长尝试间隔,比如每10分钟尝试一次,这样就不会触发findtime窗口内的maxretry限制。应对方法是增大findtime值,比如设置为86400秒(24小时),同时适当增加maxretry到5次,bantime延长到86400秒或更长。这样在24小时内累计失败5次就会被封禁一整天。

另一个实用技巧是设置递进式封禁。fail2ban支持bantime.increment选项,启用后每次同一IP被封禁的时间会递增:

bantime.increment = true
bantime.factor = 2
bantime.max = 604800

首次封禁1小时,第二次2小时,第三次4小时,以此类推,最长封禁7天。这对反复攻击的IP有很强的威慑力。

添加自定义过滤器监控更多认证失败场景

除了SSH密码失败,你可能还想监控其他类型的认证失败,比如SSH密钥认证失败或无效用户名的尝试。虽然默认的sshd过滤器已经覆盖了大部分情况,但有些边缘场景可能遗漏。可以创建/etc/fail2ban/filter.d/sshd-custom.local文件,添加额外的正则规则:

[Definition]
failregex = ^%(__prefix_line)sConnection closed by authenticating user .*? .*? port \d+ \[preauth\]$
            ^%(__prefix_line)sUser .+ from  not allowed because not listed in AllowUsers$

然后在jail.local中新增一个监狱使用这个自定义过滤器,或者将自定义规则合并到主sshd过滤器中。

邮件通知和日志审计

fail2ban支持在封禁IP时发送邮件通知,让你第一时间知道有人在攻击服务器。在jail.local的[DEFAULT]或[sshd]部分添加action配置:

action = %(action_mwl)s

action_mwl是fail2ban内置的一个组合动作,它会执行封禁、发送包含whois信息的邮件、并记录详细日志。要使用邮件功能,需要先配置sendmail或postfix等邮件发送工具,并在/etc/fail2ban/action.d/sendmail-whois-lines.conf中设置dest邮箱地址。

对于安全审计,fail2ban的日志本身就是宝贵的资料。定期分析/var/log/fail2ban.log可以了解攻击来源的地理分布、攻击频率变化趋势,甚至可以作为调整安全策略的依据。可以写一个简单的脚本,定时统计被封禁IP的数量和来源国家,帮助你评估当前的安全态势。

fail2ban性能优化与资源占用

当服务器面临大规模攻击时,fail2ban可能需要处理大量日志行和封禁请求。默认情况下fail2ban使用polling方式读取日志文件,对于高负载场景可以调整backend选项。在jail.local中设置:

backend = polling

polling模式兼容性最好,但在日志文件很大时可能消耗较多CPU。如果日志量巨大,可以考虑使用pyinotify后端,它基于inotify事件通知,效率更高,但需要安装python-inotify包。

另外,如果被封禁的IP数量达到数千个,使用firewallcmd-ipset的ipset方式比逐个添加rich-rule性能好很多。ipset在内存中维护一个哈希表,匹配速度极快,即使有上万个IP也不会明显影响网络性能。

常见问题排查

如果fail2ban没有按预期工作,首先检查jail.local中enabled是否设为true。很多人配置完忘记改这个值,导致监狱根本没启动。其次检查logpath路径是否正确,CentOS的SSH日志默认在/var/log/secure,但如果使用了rsyslog自定义配置,路径可能不同。

另一个常见问题是时区设置。fail2ban的日志时间戳与系统时区相关,如果时区不正确,可能导致findtime计算偏差。确保系统时区设置正确:

timedatectl set-timezone Asia/Shanghai

如果修改了SSH端口,除了在jail.local中修改port参数,还要确认firewalld中已经放行了新端口,否则fail2ban添加的规则可能不会生效。

fail2ban与SELinux的兼容性

CentOS默认启用SELinux,fail2ban需要相应的策略才能正常操作防火墙。大多数情况下fail2ban能自动处理SELinux上下文,但如果遇到权限问题,可以检查审计日志:

ausearch -m avc -ts recent | grep fail2ban

如果确实有SELinux阻止fail2ban操作的情况,不要直接关闭SELinux,而是使用audit2allow生成自定义策略模块,或者将fail2ban设置为许可模式:

semanage permissive -a fail2ban_t

这样既保持了系统整体的SELinux保护,又允许fail2ban正常工作。

进阶:结合其他安全措施构建多层防御

fail2ban是反应式防御,在攻击发生后才进行封禁。对于更高级的安全需求,可以结合其他措施形成纵深防御。比如修改SSH默认端口能减少90%以上的自动化扫描,禁用密码登录只使用密钥认证可以从根本上杜绝暴力破解,配置AllowUsers或AllowGroups限制可登录的用户范围,使用TCP Wrappers进一步控制访问来源。

fail2ban还可以保护其他服务,比如Apache的认证页面、Postfix的SMTP认证、vsftpd的FTP登录等。每个服务都有对应的内置过滤器,在jail.local中启用即可。这种统一的安全管理方式大大降低了维护成本。

定期更新fail2ban和系统补丁也很重要。攻击手法在不断演变,fail2ban的过滤器也在持续更新以应对新的攻击模式。保持EPEL仓库中的fail2ban版本更新,能确保你拥有最新的防护能力。

通过以上配置,你的CentOS服务器就拥有了一套自动化的SSH暴力破解防御系统。fail2ban在后台默默工作,将绝大多数攻击挡在门外,而你只需要偶尔检查一下日志,了解安全态势。这种省心又有效的防护方式,是每个CentOS管理员都应该掌握的基本技能。