自定义fail2ban规则拦截跨境全网扫描IP
场景与目标:为什么需要自定义规则拦截跨境扫描IP?
你的服务器是不是经常被海外IP疯狂扫描SSH、MySQL等端口?
默认Fail2ban只能按服务频率封禁,但如果你只想屏蔽所有非国标地区的IP,或者针对某些特征(比如连续访问不存在的路径)进行封禁,就需要自定义规则。
本文将从零开始,教你写一条专属规则,把跨境全网扫描IP挡在门外。
第一步:环境准备与默认配置检查
假设你用的是CentOS 7+或Ubuntu 20.04+。
先用下面命令检查是否已安装Fail2ban:
fail2ban-client status
如果提示command not found,执行安装:
# CentOS/RHEL
yum install epel-release -y && yum install fail2ban -y
# Ubuntu/Debian
apt update && apt install fail2ban -y
安装后启动并设为开机自启:
systemctl enable fail2ban --now
确认运行正常:
systemctl status fail2ban
看到active (running)就对了。
第二步:编写自定义Filter——定义什么算“跨境全网扫描”
Fail2ban由两部分组成:filter(定义匹配规则)和jail(定义触发条件与动作)。
我们需要一个filter来过滤出所有来自非中国IP的请求。
这里用IP地理位置库太复杂,简单做法:直接通过日志中的IP反向查询,但Fail2ban官方不直接支持GeoIP。
更实用的方法是:针对某个服务(比如Nginx),通过日志中的请求特征来识别扫描行为。
假设你Nginx日志中记录了404请求,而大量404来自海外IP。
我们可以写一个filter匹配HTTP状态码404且URI是常见扫描路径(比如/wp-admin、/admin等)的日志行。
创建filter文件
vim /etc/fail2ban/filter.d/nginx-scan.conf
内容如下:
[Definition]
failregex = ^ -.*"(GET|POST).*" 404 .*$
ignoreregex =
这里自动匹配IP,(GET|POST)匹配请求方法,404匹配状态码。
这样任何返回404的请求都会被捕获。
如果你只想针对特定路径,比如/wp-admin,可以把正则改得更严格。
注意:如果日志格式不是默认combined,需要调整正则。你可以用fail2ban-regex测试:fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-scan.conf。
第三步:配置Jail——将规则绑定到服务并设定处罚
编辑jail.local(如果不存在则新建):
vim /etc/fail2ban/jail.local
添加如下内容:
[nginx-scan]
enabled = true
port = http,https
filter = nginx-scan
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 86400
action = iptables-allports[name=nginx-scan]
解释:
maxretry = 5:5次匹配就触发封禁。findtime = 300:5分钟内。bantime = 86400:封禁1天(单位秒)。action:使用iptables封禁所有端口(因为扫描可能针对多个服务)。
如果你只想封禁SSH扫描,替换port和logpath即可。
第四步:重启Fail2ban并验证规则生效
systemctl restart fail2ban
检查规则是否加载:
fail2ban-client status nginx-scan
正常会显示Status for the jail: nginx-scan,下面有Currently failed和Currently banned。
如果显示0,说明没有匹配到。
你可以手动模拟一次404请求:
curl -I http://你的IP/nonexist
然后再次检查fail2ban-client status nginx-scan,Currently failed应该变成1。
查看封禁日志:
tail -f /var/log/fail2ban.log
你会看到类似Ban 1.2.3.4的条目。
避坑指南:常见失败原因与修正
- filter正则写错:用
fail2ban-regex测试日志文件,确认匹配行数正确。 - 日志路径错误:Nginx日志可能不在
/var/log/nginx/下,检查nginx -t或nginx -V确认日志位置。 - action未生效:检查防火墙是否开启,
iptables -L -n查看是否有fail2ban-nginx-scan链。 - 只封禁了部分端口:默认action只封禁port指定的端口,使用
iptables-allports可封所有端口。 - 误封正常用户:
maxretry设小(如3)可能会伤及无辜,建议先设5观察,后期再调整。
高频问题解答
Q:我不想封禁所有404,只想封禁针对/wp-admin的扫描怎么办?
A:修改filter中的failregex为^即可。
Q:如何查看当前所有封禁的IP?
A:fail2ban-client banned列出所有jail;fail2ban-client status 查看具体IP。
Q:封错了怎么解封?
A:fail2ban-client set 。
总结与扩展
本文通过自定义Fail2ban规则成功实现了对跨境全网扫描IP的拦截。
核心在于理解filter和jail的协同,以及正则的编写。
你可以根据自己的日志格式和扫描特征灵活调整。
如果还想进一步屏蔽所有非中国IP,可结合GeoIP模块或ipset白名单,但门槛较高。
建议先从简单的请求特征入手,再逐步完善。
遇到问题多查日志,大部分错误都在/var/log/fail2ban.log中有明确提示。