2026年2月,一个叫 SSHStalker 的僵尸网络悄悄攻陷了至少 7000台 Linux 服务器。攻击方式?没什么高大上的——就是暴力破解 SSH 密码。
更扎心的是,安全专家直言:"如果你在2026年还允许密码登录SSH,你就是在邀请僵尸网络来喝咖啡。"
今天这篇文章,手把手教你用 fail2ban 给服务器装上一道"自动防盗门"——有人试图暴力破解?直接封IP,全自动,不废话。
想象一下这个场景:
🔴 攻击者脚本启动... 尝试 root / 123456 → 失败 尝试 root / admin → 失败 尝试 root / password → 失败 尝试 root / root → 失败 ... (每秒尝试几百次) 尝试 admin / 123456 → 成功!🎉这不是科幻片,这是每天发生在数百万台服务器上的真实故事。
加拿大 Flare Systems 研究人员在 2026 年初通过 SSH 蜜罐发现了这个僵尸网络:
更可怕的是:这 7000 台被攻陷的服务器目前还处于"静默期",没人知道它们会被用来干什么——DDoS 攻击?勒索软件?还是成为下一个僵尸网络的跳板?
fail2ban 的工作逻辑非常简单粗暴,但极其有效:
┌─────────────────────────────────────────────┐│ fail2ban 工作流程 │├─────────────────────────────────────────────┤│ ││ 1️⃣ 日志监控 ││ ↓ ││ 持续读取 /var/log/auth.log 等日志文件 ││ ││ 2️⃣ 规则匹配 ││ ↓ ││ 用正则表达式识别 "Failed password" 等关键词 ││ ││ 3️⃣ 计数判定 ││ ↓ ││ 同一 IP 在时间窗口内失败次数 > 阈值? ││ ↓ 是 ││ 4️⃣ 自动封禁 ││ ↓ ││ 调用 iptables/firewalld 封禁该 IP ││ (默认封禁 10 分钟,可自定义) ││ │└─────────────────────────────────────────────┘对比几个常见的防护方案:
结论:fail2ban 不是万能药,但它是性价比最高的基础防线——而且可以和其他方案叠加使用!
Ubuntu/Debian 系统:
# 更新包管理器sudo apt update# 安装 fail2bansudo apt install fail2ban -yCentOS/RHEL/Rocky Linux 系统:
# 安装 EPEL 源(如果还没有)sudo yum install epel-release -y# 或者新版系统用:sudo dnf install epel-release -y# 安装 fail2bansudo yum install fail2ban -y验证安装成功:
# 查看版本fail2ban-client --version# 输出类似:Fail2ban v1.1.0⚠️ 重要提示:永远不要直接编辑
/etc/fail2ban/jail.conf!这个文件会在 fail2ban 更新时被覆盖。正确做法:创建
/etc/fail2ban/jail.local,它会自动覆盖默认配置。
# 创建本地配置文件(复制模板作为起点)sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local# 编辑配置sudo nano /etc/fail2ban/jail.local以下是经过实战检验的生产级配置,注释超详细,每个参数都给你讲明白:
[DEFAULT]# ============================================================# 全局默认配置(所有 jail 共享的基础设置)# ============================================================# 封禁时间(秒)# - 3600 = 1小时(推荐入门值)# - 86400 = 1天(推荐生产环境)# - 604800 = 1周(高防护需求)bantime = 86400# 时间窗口(秒)# 在这个时间段内统计失败次数# 比如:10分钟内失败5次就封禁findtime = 600# 最大重试次数# 超过这个次数就触发封禁maxretry = 5# 封禁动作# - iptables-multiport:传统 iptables 方式(兼容性好)# - firewallcmd-ipset:firewalld 方式(CentOS 7+ 默认)# - nftables:新一代防火墙(性能最好)banaction = iptables-multiport# 是否发送告警邮件# 建议开启,第一时间知道有人在"敲门"mta = sendmaildestemail = your-email@example.comsendername = Fail2Ban-Alertaction = %(action_mw)s# ============================================================# 【重点】SSH 服务防护# ============================================================[sshd]enabled = trueport = sshfilter = sshdlogpath = /var/log/auth.log# Ubuntu/Debian 路径# 如果是 CentOS/RHEL:# logpath = /var/log/securemaxretry = 3# SSH 是最关键的服务,阈值调严一些!bantime = 86400# ============================================================# Nginx/Web 服务防护# ============================================================[nginx-http-auth]enabled = trueport = http,httpsfilter = nginx-http-authlogpath = /var/log/nginx/error.logmaxretry = 5bantime = 3600# 防护 Nginx 恶意扫描(PHP/WordPress 路径探测等)[nginx-bad-request]enabled = trueport = http,httpsfilter = nginx-bad-requestlogpath = /var/log/nginx/access.logmaxretry = 5bantime = 3600# 防护 WordPress 登录暴力破解[wordpress-auth]enabled = trueport = http,httpsfilter = wordpress-authlogpath = /var/log/nginx/access.logmaxretry = 3bantime = 86400💡 配置小贴士:
SSH 的 maxretry建议设为 3 次,这是最容易被攻击的服务Web 服务的 maxretry可以宽松一点(5次),避免误封正常用户 bantime根据你的安全需求调整:测试环境 1 小时,生产环境 1 天
# 启动 fail2ban 服务sudo systemctl start fail2ban# 设置开机自启sudo systemctl enable fail2ban# 检查运行状态sudo systemctl status fail2ban正常运行的话,你应该看到类似这样的输出:
● fail2ban.service - Fail2Ban Service Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2026-05-02 14:30:00 CST; 5min ago Docs: man:fail2ban(1) Main PID: 12345 (fail2ban-server) Tasks: 5 (limit: 4563) Memory: 45.2M CPU: 230ms CGroup: /system.slice/fail2ban.service └─12345 /usr/bin/python3 /usr/bin/fail2ban-server -xf ...# 查看 fail2ban 整体状态sudo fail2ban-client status输出示例:
Status|- Number of jail: 4`- Jail list: nginx-bad-request, nginx-http-auth, sshd, wordpress-auth# 查看 SSH 防护的具体情况(重点!)sudo fail2ban-client status sshd输出示例(说明已经在干活了):
Status for the jail: sshd|- Filter| |- Currently failed: 12| |- Total failed: 156| `- File list: /var/log/auth.log`- Actions |- Currently banned: 8 |- Total banned: 23 `- Banned IP list: 185.220.101.0 45.33.32.156 104.248.51.78 167.99.102.89 ...(更多恶意IP)看到 Currently banned: 8 了吗?这就是 fail2ban 正在保护你的铁证!
sudo fail2ban-client status | |
sudo fail2ban-client status sshd | |
sudo fail2ban-client set sshd banip 1.2.3.4 | |
sudo fail2ban-client set sshd unbanip 1.2.3.4 | |
sudo tail -f /var/log/fail2ban.log | |
sudo systemctl restart fail2ban | |
sudo fail2ban-client -t | |
sudo fail2ban-client reload |
# 场景:你在日志里看到一个可疑 IP 正在扫描# 先看看它是否已经被封sudo fail2ban-client status sshd | grep 203.0.113.50# 如果还没封,手动把它踢出去sudo fail2ban-client set sshd banip 203.0.113.50# 输出:203.0.113.50 已被封禁 ✅在 jail.local 的 [DEFAULT] 段添加:
# 白名单:这些 IP 永远不会被封ignoreip = 127.0.0.1/8 ::1 你的固定IP地址 公司/办公室的IP段😅 血泪教训:作者有一次把
ignoreip配错了,结果把自己封了……最后只能去机房接显示器操作。一定要把自己的 IP 加白名单!
创建 /etc/fail2ban/filter.d/recursive.conf:
[Definition]failregex = .*? Ban <HOST>$ignoreregex =然后创建 /etc/fail2ban/action.d/recursive.conf:
[Definition]actionstart =actionstop =actioncheck =actionban = if [ $(grep -c "<HOST>" /tmp/fail2ban.recursive) -eq 0 ]; then echo "1 <HOST>" >> /tmp/fail2ban.recursive; else COUNT=$(grep "<HOST>" /tmp/fail2ban.recursive | cut -d' ' -f1); NEW_COUNT=$((COUNT + 1)); sed -i "s/^COUNT <HOST>$/NEW_COUNT <HOST>/" /tmp/fail2ban.recursive; # 第二次封禁:1天;第三次:3天;第四次及以上:7天 if [ "$NEW_COUNT" -eq 2 ]; then fail2ban-client set <JAIL> bantime 86400; elif [ "$NEW_COUNT" -eq 3 ]; then fail2ban-client set <JAIL> bantime 259200; elif [ "$NEW_COUNT" -ge 4 ]; then fail2ban-client set <JAIL> bantime 604800; fi; fiactionunban =效果:第一次失败封 1 天,第二次 3 天,第三次直接封一周!专门治那些"屡教不改"的扫描器。
创建 /etc/fail2ban/action.d/mail-custom.conf:
[Definition]actionstart =actionstop =actioncheck =actionban = echo "[Fail2Ban] <name> 封禁了 <ip> (已失败 <failures> 次)" \ | mail -s "[警报] 服务器遭受攻击 - IP已被封禁" your@email.com # 同时调用 webhook 推送到钉钉/企微 curl -X POST 'https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -d '{"msgtype":"text","text":{"content":"[Fail2Ban警报] <name> 封禁 <ip>"}}'actionunban =然后在 jail 配置中使用:
action = %(actionban)s mail-custom[name=%(name)s, ip=<ip>, failures=<failures>]# ❌ 错误做法:改完配置什么都不做# ✅ 正确做法:sudo fail2ban-client reload # 重新加载配置(推荐,不中断现有封禁)# 或sudo systemctl restart fail2ban # 完全重启(会清空当前封禁列表)不同系统的 SSH 日志路径不一样:
/var/log/auth.log | |
/var/log/secure | |
/var/log/audit/audit.log |
配错路径 = fail2ban 啥也监控不到 = 裸奔!
再次强调:一定要在 ignoreip 里加上你自己的固定 IP 或公司网段!否则哪天你密码输错几次,就被自己装的 fail2ban 拒之门外了……
fail2ban 很强,但它不是银弹。真正的安全需要多层防护:
┌──────────────────────────────────────────────────┐│ 服务器安全防御体系 │├──────────────────────────────────────────────────┤│ ││ 第一层:网络层 ││ ├── 云安全组/防火墙:只开放必要端口 ││ ├── VPN/堡垒机:隐藏管理入口 ││ └── fail2ban:自动封禁恶意 IP ← 今天的主角 ✨ ││ ││ 第二层:认证层 ││ ├── 禁用密码认证,强制 SSH 密钥登录 ││ ├── 启用双因素认证(2FA) ││ └── 强制强密码策略 ││ ││ 第三层:系统层 ││ ├── 及时更新系统补丁 ││ ├── 移除不必要的软件和服务 ││ └── 定期审计用户和权限 ││ ││ 第四层:监控层 ││ ├── 日志集中收集(ELK/Splunk) ││ ├── 异常行为检测 ││ └── 入侵检测系统(IDS) ││ │└──────────────────────────────────────────────────┘如果你只有 5 分钟时间,至少做完这几件事:
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_configsudo systemctl restart sshd# 编辑 /etc/ssh/sshd_config# 把 Port 22 改成 Port 2222(或任意高端口)# Ubuntusudo apt install unattended-upgrades -ysudo dpkg-reconfigure unattended-upgrades回到开头的问题:你的服务器安全吗?
SSHStalker 僵尸网络的案例告诉我们:
如果你看完这篇文章,现在就去检查你的服务器:
# 1. fail2ban 装了吗?which fail2ban-client# 2. 在运行吗?sudo systemctl status fail2ban# 3. 已经拦住多少攻击了?sudo fail2ban-client status sshd如果以上任何一个答案让你不安……别慌,跟着本文操作,5分钟搞定!
你的服务器曾经被暴力破解过吗?欢迎评论区分享你的经历(或者惨痛教训)😂
写在最后:网络安全没有终点,但我们每多一道防线,就离安全近一步。希望这篇文章对你有用——转发给身边需要的朋友,也许就能帮他们的服务器逃过一劫!
如果觉得有帮助,请点赞、在看、转发支持!关注博主,获取更多实用的技术干货 🔴