前言
“明明设置了规则,却挡不住爬虫?”——在Ubuntu 20.04的系统中,设置ufw防火墙封禁爬取网站的IP,明明ufw status
显示规则生效,可目标IP还是能疯狂连接,就像“装了门锁却没锁上”,让人又急又懵。今天结合实际踩坑经验,给大家分享一下问题原因和解决方案。
一、ufw规则“生效”却不生效,你是不是也这样?
对照情况看看,快速确认是否属于同一类情况:
- 规则添加成功:执行
ufw deny from A.B.C.D to any
(A.B.C.D是要封禁的IP),终端提示“Rules updated”,看似添加成功; - 状态显示正常:输入
ufw status
查看,能在规则列表里看到“DENY A.B.C.D”,标注规则已生效; - IP仍能访问:通过服务器监控(如netstat、fail2ban日志)发现,被封禁的IP还在频繁连接网站,甚至爬取数据,封禁完全没起作用;
- 重启防火墙没用:执行
ufw reload
重新加载规则,问题依旧,目标IP还是能绕过封禁进入。
如果符合这些情况,问题原因应该就是规则顺序错了——这是ufw(基于iptables)的常见“特性”,也是很容易踩的坑。
二、核心原因
ufw的规则匹配逻辑,就像“排队过安检”:安检人员会按排队顺序检查每个人的证件,只要符合某条“放行规则”,就直接放行,后面的“禁止规则”哪怕针对这个人,也不会再看。
1. 举个例子:为什么封禁IP会失效?
比如你之前为了方便远程连接服务器,添加过“允许22端口(SSH)访问”的规则:
ufw allow 22
后来发现IP A.B.C.D在爬网站,又添加“禁止该IP访问”的规则:
ufw deny from A.B.C.D to any
此时ufw的规则列表里,“允许22端口”的规则排在“禁止A.B.C.D”前面。当A.B.C.D连接服务器时,ufw先匹配到“允许22端口访问”,直接放行,根本不会去看后面的“禁止规则”——这就是为什么规则显示生效,却挡不住IP的原因。
2. 关键原理:规则顺序决定优先级
ufw(本质是iptables的前端工具)遵循“先匹配,先执行”的原则:
- 规则列表里越靠前的规则,优先级越高;
- 只要某个连接符合一条规则,ufw就会执行该规则(放行或禁止),不再检查后续规则;
- 如果你先添加“允许”类规则,再添加“禁止”类规则,针对同一IP或端口时,“允许”会优先生效,“禁止”就成了“无效规则”。
三、解决方法
要让封禁IP的规则生效,核心是把“禁止规则”放到所有“允许规则”前面。ufw的before.rules
文件专门用于存放“优先执行的规则”,我们只要在这里添加禁止IP的规则,就能确保它先被匹配。
第一步:编辑ufw的before.rules配置文件
用文本编辑器(如vim)打开/etc/ufw/before.rules
文件,这是ufw优先加载的规则文件:
vim /etc/ufw/before.rules
如果不熟悉vim操作,也可以用nano(更简单的编辑器):
nano /etc/ufw/before.rules
第二步:在指定位置添加禁止IP的规则
在打开的文件里,找到# End required lines
这一行——这是ufw默认规则的结束标记,我们要在它后面添加自定义的禁止规则,确保优先级高于后续的允许规则。
在# End required lines
下方,添加以下内容(把A.B.C.D换成你要封禁的IP):
# Block spammers or unwanted IP(注释:封禁爬虫或恶意IP)
-A ufw-before-input -s A.B.C.D -j DROP
- 代码解释:
-A ufw-before-input
表示“把这条规则添加到ufw-before-input链(优先执行链)”;-s A.B.C.D
指定“来源IP是A.B.C.D”;-j DROP
表示“直接丢弃该IP的所有连接请求”,比deny
更彻底(deny
会返回“拒绝”,DROP
直接无响应,更难被察觉)。
如果要封禁多个IP,可重复添加上述规则,每个IP占一行,比如:
# Block multiple unwanted IPs
-A ufw-before-input -s A.B.C.D -j DROP
-A ufw-before-input -s E.F.G.H -j DROP
第三步:保存文件并重新加载ufw规则
- 若用vim:按
Esc
键,输入:wq
(保存并退出),按回车; - 若用nano:按
Ctrl+O
(保存),按回车确认文件名,再按Ctrl+X
(退出)。
最后执行ufw reload
重新加载规则,让配置生效:
ufw reload
此时再通过监控查看,被封禁的IP就无法再连接服务器了——规则终于真正生效!
四、延伸技巧:避免ufw规则踩坑
解决了当下问题,再延伸几个实用技巧,帮你更好地管理ufw规则,减少后续麻烦:
1. 查看规则时,关注“顺序”而非“存在”
以后添加规则后,不要只看ufw status
显示“生效”,还要用ufw status numbered
查看规则的编号和顺序:
ufw status numbered
输出会像这样(带编号):
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] Anywhere DENY IN A.B.C.D
如果“禁止规则”的编号比“允许规则”大(排在后面),就要按前面的方法,把它移到before.rules
里。
2. 批量封禁IP:用文件导入,更高效
如果要封禁很多IP(比如爬虫IP列表),一个个手动添加太麻烦,可把IP存到文件里,再通过脚本批量添加到before.rules
:
- 创建IP列表文件
block_ips.txt
,每行一个IP:
echo "A.B.C.D" > block_ips.txt
echo "E.F.G.H" >> block_ips.txt
- 用命令批量添加到
before.rules
(在# End required lines
后):
sudo sed -i '/# End required lines/a # Block IPs from file\n' /etc/ufw/before.rules
while read ip; do
sudo sed -i "/# Block IPs from file/a -A ufw-before-input -s $ip -j DROP" /etc/ufw/before.rules
done < block_ips.txt
- 重新加载规则:
ufw reload
3. 临时测试规则:先“拒绝”再“永久添加”
添加禁止规则前,可先临时测试该IP是否真的需要封禁(避免误封正常IP):
# 临时禁止IP访问(重启ufw后失效)
ufw insert 1 deny from A.B.C.D to any
insert 1
表示“把规则插入到第1位”,优先生效。观察1-2小时,确认没有正常访问后,再按前面的方法永久添加到before.rules
里。
五、总结
ufw添加规则不生效,90%以上是因为规则顺序错了。记住这个核心逻辑:“允许规则”不能排在“禁止规则”前面,要让禁止IP/端口的规则优先执行,就必须把它们放到/etc/ufw/before.rules
文件里。
按照编辑before.rules→添加DROP规则→重载ufw的顺序操作,就能解决IP封禁失效的问题,挡住烦人的爬虫。后续管理规则时,多关注规则顺序,用ufw status numbered
检查,就能少走很多弯路,让防火墙真正发挥作用。
