实战:用 iptables 给疯狂爬虫 IP 戴上紧箍咒
上周我的服务器突然 CPU 飙高,查日志发现几个 IP 像疯了一样每秒几十次请求。今天就来分享下我是怎么用 iptables 的限流功能给这些”饿狼”套上缰绳的。这个方法特别适合临时应急,比直接封禁更灵活。
为什么选择 iptables 限速?
遇到恶意请求时,很多人的第一反应是直接封 IP。但实际工作中我发现:
- 某些业务场景需要保留访问通道(比如合作方 API)
- 动态 IP 的爬虫封不完,反而可能误伤正常用户
- Nginx 限流模块配置起来更复杂(虽然更精确)
iptables 的 limit
模块就像个流量阀门,简单几行命令就能让特定 IP 的请求变得”彬彬有礼”。
核心命令解剖
先看这个救命命令(假设要限制 192.168.1.100 的访问):
iptables -A INPUT -p tcp --dport 80 -s 192.168.1.100
-m limit --limit 10/minute --limit-burst 20 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -s 192.168.1.100 -j DROP
这里有几个关键点:
--limit 10/minute
表示每分钟允许10个包(约6秒一个请求)--limit-burst 20
是令牌桶容量,允许突发20个请求- 第二条规则是兜底策略,超限的直接丢弃
我踩过的坑
第一次配置时我傻乎乎地只写了第一条规则,结果发现限流根本没生效!原来:
- 必须配合 DROP/REJECT 规则才能形成完整限流
- 规则的顺序至关重要(ACCEPT 要在 DROP 前面)
- 生产环境建议先用
-j LOG
观察效果
后来我改进的版本会先记录日志:
iptables -A INPUT -p tcp --dport 443 -s 203.0.113.45
-m limit --limit 5/second --limit-burst 10
-j LOG --log-prefix "[IPTABLES LIMIT]"
iptables -A INPUT -p tcp --dport 443 -s 203.0.113.45 -j DROP
高级玩法:动态限速
对于 DDoS 攻击,我写了个脚本动态添加规则:
#!/bin/bash
# 自动封禁每分钟请求超过100次的IP
tail -n 1000 /var/log/nginx/access.log
| awk '{print $1}' | sort | uniq -c | sort -nr
| while read count ip; do
[ $count -gt 100 ] &&
iptables -A INPUT -s $ip -j DROP &&
echo "$(date) 封禁 $ip ($count 次请求)"
done
配合 crontab 每分钟运行,效果拔群!当然更完善的方案应该结合 fail2ban,但紧急情况下这招真的很管用。
注意事项
最后提醒几个要点:
- 测试时可以用
watch -n 1 iptables -vL
观察计数器 - IPv6 需要改用 ip6tables
- 云服务器记得检查安全组规则是否冲突
- 持久化规则别忘记
iptables-save > /etc/iptables.rules
现在我的服务器再也不会被某个 IP 搞到崩溃了。如果你有更优雅的解决方案,欢迎在评论区交流~
分享很实用,刚好遇到类似问题,待会儿就去试试这个方法😊
博主第一条规则我也犯过同样的错误,后来查了半天才知道要配合DROP规则才有效
有没有考虑过加个fail2ban配合使用?感觉会更省心
最近服务器一直被恶意扫描,正愁怎么办呢,这篇文章真是及时雨👍
突发情况用这个确实方便,不过长期来看还是建议上专业waf
脚本那段太实用了!刚偷学来加到自己的运维工具箱里,感谢无私分享