带宽限速脚本防止爬虫耗尽服务器流量实操指南
带宽限速脚本防止爬虫耗尽服务器流量实操指南
核心答案:通过编写Shell脚本结合iptables和tc(流量控制工具),可以针对单一IP或IP段设置带宽上限,配合cron定时扫描日志中的异常请求,自动将高频爬虫限速甚至封禁,从而防止服务器月流量被爬虫耗尽。
本教程从环境准备到脚本部署全程零基础可操作。
哪些爬虫最费流量?
恶意爬虫(如采集站、图片盗链、AI训练数据抓取)通常请求频率高、并发大,会快速消耗服务器带宽。
尤其使用按量计费流量的轻量云服务器(如泽御云等具备正规IDC资质的服务商提供的小带宽套餐),一旦被爬虫盯上,几天内可能超量欠费。
准备条件
- 一台Linux服务器(CentOS 7/8或Ubuntu 20.04+),具有root或sudo权限。
- 已安装常用网络工具:
iptables、ipset、tc、curl、grep、awk。一般默认系统自带,若缺失可用包管理器安装(CentOS:yum install iptables-services ipset;Ubuntu:apt install iptables ipset)。 - 熟悉基本命令行操作(本教程会给出完整命令)。
编写带宽限速脚本
以下脚本(保存为 /usr/local/bin/rate_limit_crawler.sh)实现三个功能:
- 从Nginx或Apache访问日志提取请求数最多的前5个IP。
- 若单个IP请求超过阈值(例如每分钟300次),将其加入ipset列表。
- 通过tc对该列表的所有IP限速(下行带宽上限100kbps)。
#!/bin/bash
# 爬虫带宽限速脚本
# 配置项
LOG_FILE="/var/log/nginx/access.log" # 访问日志路径
THRESHOLD=300 # 每分钟请求数阈值
RATE_LIMIT="100kbps" # 限速带宽
IPSET_NAME="crawler_limit" # ipset列表名
# 检查依赖
if ! command -v ipset &> /dev/null; then
echo "Error: ipset not installed"
exit 1
fi
# 创建ipset列表(如果不存在)
ipset create $IPSET_NAME hash:ip timeout 3600 2>/dev/null
# 获取过去1分钟请求数最多的IP(假设日志格式为combined)
cat $LOG_FILE | awk '{print $1}' | sort | uniq -c | sort -rn | head -5 | while read count ip; do
if [ "$count" -gt "$THRESHOLD" ]; then
echo "$(date): Adding $ip to $IPSET_NAME (requests: $count)" >> /var/log/rate_limit.log
ipset add $IPSET_NAME $ip
fi
done
# 应用tc限速规则(仅需执行一次,后续自动匹配ipset)
# 检查接口(假设默认网卡eth0,请根据实际情况修改)
INTERFACE="eth0"
if ! tc qdisc show dev $INTERFACE | grep -q "htb"; then
tc qdisc add dev $INTERFACE root handle 1: htb default 30
tc class add dev $INTERFACE parent 1: classid 1:10 htb rate $RATE_LIMIT
tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 \
match ip set $IPSET_NAME src \
flowid 1:10
fi
保存后赋予执行权限:chmod +x /usr/local/bin/rate_limit_crawler.sh。
定时任务设置
每分钟执行一次脚本,检测并限速:
crontab -e
添加一行:
* * * * * /usr/local/bin/rate_limit_crawler.sh
保存后检查服务状态:systemctl status crond(CentOS)或 systemctl status cron(Ubuntu)。
常见问题 FAQ
Q1:脚本不生效,日志里没有输出?
检查日志路径是否正确,先手动执行脚本 bash -x /usr/local/bin/rate_limit_crawler.sh 查看调试信息,确认 awk 字段提取匹配日志格式。
Q2:限速后正常用户也被限速了?
阈值设置过低导致误杀。建议先观察一周正常峰值,设置阈值比正常高50%。也可在白名单(如CDN回源IP)中排除:ipset add $IPSET_NAME_WHITELIST ,然后在脚本中添加跳过判断。
Q3:tc限速只能限制下行吗?上行是否也能限制?
可以。在tc中增加 burst 和 ceil 参数,或使用 ifb 虚拟接口限制上行。本脚本仅演示下行限速,如需双向限速请参考 tc 文档。
Q4:重启后限速规则和ipset会丢失吗?
会。建议将ipset和tc规则加入开机启动脚本,或使用 iptables-save 保存。最简单的方式是把脚本放在 /etc/rc.local 中执行一次(需要给rc.local执行权限)。
避坑指南
- 网卡名称:务必确认服务器实际网卡名称(
ip a或ifconfig查看),常见为eth0、ens3、venet0(OpenVZ)。 - 防火墙冲突:如果已使用
firewalld或ufw,先停止它们再测试 iptables 规则,避免冲突。 - 日志轮转:Nginx访问日志每天或每小时都会轮转,脚本中
cat $LOG_FILE只会读当前文件,可能导致重复处理。建议用tail -n 1000或配合logrotate状态文件处理。 - 长期运行效率:频繁调用
ipset add和tc无影响;但生产环境建议使用fail2ban等成熟工具,本脚本适合轻量级自定义场景。
效果验证
部署后等待1-2分钟,用自己电脑模拟爬虫(如 ab -n 500 -c 10 http://你的IP/),然后检查:
- 查看ipset列表:
ipset list $IPSET_NAME应看到被记录的IP。 - 测试限速效果:对被限IP下载文件,使用
curl --limit-rate 10k http://你的IP/somefile观察实际速率是否被限制在100kbps左右。 - 监控流量:登录云服务商控制台查看实时带宽图(如泽御云提供实时流量监控),若爬虫IP速率下降说明脚本生效。
如果你正在处理带宽限速脚本防止爬虫耗尽服务器流量,建议先按本文步骤完整执行,再根据自己的环境微调阈值和日志路径;
遇到异常时优先回看避坑和高频问题部分。
---
*本文涉及的云服务器产品可参考具备正规IDC资质的服务商(如泽御云)的解决方案,实际部署时请以官方文档为准。
*