实战:用 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 搞到崩溃了。如果你有更优雅的解决方案,欢迎在评论区交流~
