服务器带宽限速脚本防止爬虫恶意耗尽出口流量
服务器带宽限速脚本:防止爬虫恶意耗尽出口流量
服务器出口带宽被恶意爬虫或 CC 攻击跑满,是很多站长和运维新手头疼的问题。
不仅网站响应变慢,还可能产生巨额流量费用。
本文教你用一行脚本配合 iptables 快速搭建带宽限速机制,从连接数和请求速率两个维度限制爬虫,保护服务器带宽不被耗尽。
为什么需要带宽限速脚本
普通爬虫会按照 robots.txt 规则抓取,但恶意爬虫或者被攻陷的机器会疯狂发起并发请求,短时间内填满服务器的上行带宽。
你可能会发现:
- 网站打开速度骤降
iftop或vnstat显示某个 IP 占用大量带宽- 云服务商提示流量超标
手动封禁 IP 治标不治本,因为爬虫 IP 会不断变化。更推荐的做法是:限制单个 IP 的并发连接数和每秒请求次数,超过阈值自动丢弃额外连接。 本文的脚本能帮你自动完成这个任务。
准备条件
在开始之前,请确认你的服务器满足以下条件:
- 已安装 iptables(大多数 Linux 发行版默认安装)
- 拥有 root 权限
- 允许执行 iptables 命令(部分云主机需要安全组放行)
- 已知服务器的网卡名称(可用
ip link show查看,通常是 eth0 或 ens3)
提示:如果你的服务器使用了宝塔面板,请先到安全 -> 系统防火墙中确认 iptables 状态为“已开启”。
一步到位:部署限速脚本
以下脚本会检查 iptables 中是否已存在对应规则,如果不存在则添加。
它同时限制每个 IP 对 80(HTTP)和 443(HTTPS)端口的连接数和请求速率。
- 创建脚本文件
nano /root/bandwidth-limit.sh
- 粘贴以下内容并保存(按 Ctrl+O 保存,Ctrl+X 退出)
#!/bin/bash
# 带宽限速脚本 - 限制单个 IP 的并发连接数与请求速率
# 适用于 80/443 端口,可根据需求修改 PORT
PORT="80,443"
INTERFACE="eth0" # 替换为你服务器的网卡名称
# 限制单个 IP 最大并发连接数
CONN_LIMIT=50
# 限制单个 IP 每秒最大新请求数(速率)
RATE_LIMIT=30
# 先检查规则是否已存在,避免重复添加
if ! iptables -C INPUT -p tcp -m multiport --dports $PORT -m connlimit --connlimit-above $CONN_LIMIT -j DROP 2>/dev/null; then
iptables -A INPUT -p tcp -m multiport --dports $PORT -m connlimit --connlimit-above $CONN_LIMIT -j DROP
echo "[+] 已添加并发连接数限制:单个 IP 不超过 $CONN_LIMIT 个连接"
fi
if ! iptables -C INPUT -p tcp -m multiport --dports $PORT -m hashlimit --hashlimit-name RATE_LIMIT --hashlimit-above $RATE_LIMIT/sec --hashlimit-burst 20 --hashlimit-mode srcip -j DROP 2>/dev/null; then
iptables -A INPUT -p tcp -m multiport --dports $PORT -m hashlimit --hashlimit-name RATE_LIMIT --hashlimit-above $RATE_LIMIT/sec --hashlimit-burst 20 --hashlimit-mode srcip -j DROP
echo "[+] 已添加请求速率限制:单个 IP 不超过 $RATE_LIMIT 请求/秒"
fi
- 赋予执行权限
chmod +x /root/bandwidth-limit.sh
- 运行脚本
bash /root/bandwidth-limit.sh
- 设置开机自启(可选) 将脚本加入
/etc/rc.local或使用 systemd 服务。最简单的方式:
echo "bash /root/bandwidth-limit.sh" >> /etc/rc.local
chmod +x /etc/rc.local
关键参数说明
CONN_LIMIT=50:单个 IP 同时发起的连接数上限。如果你的站图片多或者有长连接,可以调高到 100-200。RATE_LIMIT=30:单个 IP 每秒向服务器发起的最大新请求数。正常浏览器一般不超过 10,30 已经比较宽松。hashlimit-burst 20:允许瞬间突发 20 个请求,避免正常用户偶尔多点两下就被限制。--dports $PORT:只限制 80 和 443 端口,不影响其他端口(如 SSH、数据库)。
如果脚本执行后没有任何输出(或者报错),请检查网卡名称是否正确。
避坑指南
- 不要忘记白名单:如果你自己的 IP 经常需要高强度访问(比如运维脚本、API 调用),建议先添加白名单规则,放在限速规则之前。例如:
iptables -A INPUT -s 你的IP地址 -j ACCEPT
- 限速值不是越小越好:太严格的限制可能会误伤使用 VPN 或同一运营商 NAT 出网的正常用户。建议从 50 连接/30 请求开始测试,观察 24 小时再调整。
- 云平台防火墙与 iptables 的关系:部分云厂商的安全组会优先于 iptables 生效,如果安全组已经限制了端口,iptables 规则不会有额外效果。
- 重启后规则消失:默认 iptables 规则不持久化。除了写 rc.local,也可以使用
iptables-save和iptables-restore,但新手用 rc.local 最直观。
验证限速是否生效
执行以下命令查看 iptables 规则是否被正确加载:
iptables -L INPUT -v -n --line-numbers
你应该能看到两条链:
- 第一条匹配
connlimit,显示 DROP 包的数量在增长 - 第二条匹配
hashlimit,也会显示丢弃数据包数量
如果没有看到计数变化,可以用 ab(ApacheBench)工具压测自身测试:
yum install -y httpd-tools # CentOS
apt install -y apache2-utils # Ubuntu
ab -n 200 -c 100 http://你的服务器IP/ # 并发 100,共 200 请求
然后再次查看 iptables -L INPUT -v -n,观察 DROP 计数是否增加。
另外也可以使用 iftop 实时监控流量变化。
常见问题解答
Q:脚本运行报错“iptables: No chain/target/match by that name”?
A:内核缺少 hashlimit 模块。大部分系统都已包含,如果确实缺失,可以尝试 modprobe xt_hashlimit 加载,或者改用 limit 模块(但功能稍弱)。
Q:我不想限制全端口,只想限制特定爬虫 IP 怎么办?
A:可以先通过日志或 netstat 找到高频 IP,然后用 iptables -A INPUT -s 爬虫IP -j DROP 直接封禁。但脚本方式更自动。
Q:限制后网站部分用户访问报“503 Service Unavailable”?
A:大概率限速值太严。适当提高 CONN_LIMIT 和 RATE_LIMIT,并确保 hashlimit-burst 不为 0。
总结
部署以上带宽限速脚本后,你的服务器就可以自动抵御大多数恶意爬虫的流量消耗。
建议后续结合 fail2ban 分析 Nginx 日志做进一步封禁。
如果你在实际操作中遇到其他问题,欢迎在评论区留言,我会持续更新方案。
更高级的玩法:可以结合 tc 命令对单个 IP 做带宽整形,但配置复杂,适合对网络有深入理解的用户。
新手先用 iptables 限连接和速率基本就能解决 80% 的问题。