活力39282
在线时间13640 小时
阅读权限200
管理员
自由的灵魂
- 积分
- 107434
- 主题
- 5630
- 回帖
- 26661
- 注册时间
- 2003-4-10
- 最后登录
- 2026-10-2
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖内容基于历史实践,现在已经不复使用,最新防护实践已经转向雷池WAF。
🛡️ Discuz! X3.5 站点自动化防护体系实践
作者:一位被bot折磨后走向自动化的站长
站点:www.dianbo.org
更新日期:2025-12-01
📌 防护目标
- 阻断 WordPress 扫描(即使站点非WP)
- 拦截路径遍历、SQL注入等通用Web攻击
- 防御 SSH 暴力破解
- 重点压制 Discuz 搜索接口滥用(当前主要攻击面)
- 所有恶意 IP 永久拉黑,且不影响正常用户
🧱 整体架构
- graph LR
- A[公网请求] --> B{Nginx 层}
- B -->|WP/敏感路径| C[return 444 + 不记录日志]
- B -->|正常请求| D[PHP-FPM]
- B -->|搜索请求| E[限流 zone=search]
- E -->|超限| F[返回 503 + 记录日志]
- F --> G[Fail2ban 实时分析]
- G --> H[ipset 永久封禁]
- C --> I[攻击者无感知,无日志残留]
复制代码
核心思想:
- 无关攻击 → 静默丢弃(不浪费资源)
- 有效攻击 → 精准记录 + 自动封禁
🔒 第一层:Nginx 前置拦截(零日志、零响应)
1. 拦截 WordPress 扫描(彻底“隐身”)
- location ~* ^/(?:xmlrpc\.php|wp-login\.php|wp-admin|wp-config\.php|wp-content|wp-includes|wp-json|\.env|readme\.html|license\.txt)(?:$|/) {
- access_log off; # 关键:不写入 access.log
- log_not_found off;
- return 444; # 静默关闭 TCP 连接
- }
复制代码
- 效果:扫描者收不到任何响应,也不会触发 fail2ban
- 优势:节省磁盘 I/O 和 CPU,避免日志污染
2. 禁止访问敏感文件
- location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md) {
- return 404;
- }
复制代码
⚡ 第二层:关键接口限流(制造“可捕获信号”)
针对 /search.php 设置专门限流策略:
- limit_req_zone $binary_remote_addr zone=search:10m rate=10r/s;
- limit_req_zone $server_name zone=search_total:10m rate=30r/s;
- location = /search.php {
- limit_req zone=search burst=5 nodelay;
- limit_req zone=search_total burst=10;
- fastcgi_pass unix:/tmp/php-cgi-82.sock;
- include fastcgi.conf;
- }
复制代码
- 正常用户:几乎不会触发限流
- 恶意 Bot:高频请求 → 返回 503 Service Unavailable
- 关键点:503 会被记录到 access.log,作为 fail2ban 的封禁依据
🤖 第三层:Fail2ban 智能封禁(基于日志分析)
Jail 配置(/etc/fail2ban/jail.local)
- [DEFAULT]
- ignoreip = 127.0.0.1/8 221.1.204.34 103.148.244.129
- bantime = 600
- findtime = 300
- maxretry = 5
- ### 主战场:Discuz 搜索攻击 ###
- [search-ipset]
- enabled = true
- filter = search-ipset
- logpath = /www/wwwlogs/www.dianbo.org.log
- maxretry = 1 # 一次 503 即封
- findtime = 600
- bantime = 30d # 实际用 ipset 永久封
- banaction = iptables-ipset[type=multiport, name=search-ipset, port="80,443"]
- ### 其他防护(虽静止但保留) ###
- [nginxmalicious-ipset]
- enabled = true
- filter = nginxmalicious-ipset
- logpath = /www/wwwlogs/www.dianbo.org.log
- maxretry = 2
- [nginxwpscan-ipset]
- enabled = true
- filter = nginxwpscan-ipset
- logpath = /www/wwwlogs/www.dianbo.org.log
- maxretry = 1
复制代码
Filter 示例(search-ipset.conf)
- [Definition]
- failregex = ^<HOST> .*"(GET|POST) /(search|home)\.php\?.*formhash=[a-f0-9]{8}.*" 503
- ignoreregex =
复制代码
💡 为什么其他 jail 静止?
- WP扫描被 Nginx access_log off 屏蔽 → fail2ban 看不见
- 路径遍历等被 Nginx/PHP 拦截 → 未进入日志
- SSH 已改端口 → 无暴力破解日志
这是设计使然,不是漏报!
🔥 第四层:永久 IP 黑名单(跨重启持久化)
- 使用 ipset 存储封禁 IP(O(1) 高效查找)
- 每日通过脚本导出:ipset save > bad-ips.map
- Nginx 启动时加载黑名单:
- map $remote_addr $blocked_ip {
- default 0;
- include /www/fail2ban-persist/bad-ips.map;
- }
- server {
- if ($blocked_ip) { return 444; }
- }
复制代码
- 效果:即使 fail2ban 重启,历史恶意 IP 仍被拦截
📊 当前效果(截至 2025-12-01)
| Jail 名称 | 封禁 IP 数 | 近期活跃情况 | | search-ipset | 154,463 | ✅ 每日新增 10,000+ | | nginxmalicious-ipset | 679 | ❌ 多日不变 | | nginxwpscan-ipset | 151 | ❌ 多日不变 | | sshd-ipset | 44 | ❌ 多日不变 |
✅ 结论:攻击高度集中于搜索接口,其他入口因“无利可图”已被 bot 放弃。
💡 经验总结
- 不要依赖 fail2ban 处理所有攻击 → 前置拦截更高效
- 对非目标路径使用 access_log off → 避免日志膨胀
- 限流是制造“可检测信号”的关键 → 让 bot “留下痕迹”
- 永久黑名单比临时封禁更有效 → 防止 IP 轮换重试
📎 关键配置文件位置
- Nginx 站点配置:/www/server/panel/vhost/nginx/www.dianbo.org.conf
- Fail2ban Jail:/etc/fail2ban/jail.local
- Filter 规则:/etc/fail2ban/filter.d/*.conf
- 持久化黑名单:/www/fail2ban-persist/bad-ips.map
✨ 提示
如果你也在使用 宝塔面板 + Discuz,这套方案可直接参考调整。
欢迎交流指正,也希望能帮助到同样在对抗自动化攻击的朋友! 😄 |
|