本文目录导读:

PHP项目带宽跑满?3步锁定“流量刺客”来源(附排查命令+问答)
📖 目录导读
- 现象判断:如何确认是PHP应用导致的带宽跑满?
- 核心排查三板斧
- 第一板斧:服务器层监控(iftop、nethogs)
- 第二板斧:PHP日志与请求分析(access.log、slow.log)
- 第三板斧:恶意流量识别(爬虫、CC攻击、盗链)
- 实战问答:常见问题速查
- 长期防御建议
现象判断:别让“带宽跑满”背锅
当PHP项目服务器带宽被占满时,首先需确认流量是否真的指向PHP服务。
- 方法1:登录服务器执行
sar -n DEV 1 3观察网卡流量峰值。 - 方法2:用
ss -anp | grep :80 | wc -l统计当前HTTP连接数,若连接数异常高(如>5000),大概率是应用层问题。
典型场景:
- 凌晨3点流量突增 → 可能是定时任务或爬虫。
- 持续稳定高带宽 → 可能是静态资源盗链或恶意下载。
❓问答
Q:带宽跑满时,服务器CPU/内存正常,如何快速判断是PHP请求还是静态文件?
A:在Nginx/Apache日志目录执行tail -f access.log | awk '{print $7}' | grep -E '\.(jpg|png|zip|mp4)$' | wc -l,若静态文件请求占80%以上,优先检查防盗链。
核心排查三板斧
第一板斧:服务器层实时监控(5分钟见效)
| 工具 | 命令示例 | 功能说明 |
|---|---|---|
iftop |
iftop -i eth0 -P |
显示实时IP流量排名,-P显示端口 |
nethogs |
nethogs eth0 |
按进程展示占用带宽的PID与程序路径 |
tcpdump |
tcpdump -i eth0 -nn port 80 |
抓取HTTP包,存储后用Wireshark分析 |
实操步骤:
- 安装工具(CentOS:
yum install iftop nethogs;Ubuntu:apt install)。 - 运行
iftop,按t键切换显示模式,找出连接数最多或发送流量最大的IP。 - 对可疑IP执行
tcpdump host x.x.x.x -w dump.pcap,抓包后分析请求路径。
❓问答
Q:iftop显示某个IP持续发送10Mbps流量,但PHP程序无对应日志,可能是什么?
A:可能是僵尸进程或第三方服务回调(如支付通知、OAuth回调),检查ps aux | grep php,对比PID与nethogs显示的进程号。
第二板斧:PHP日志与请求特征分析(定位具体接口)
要点:带宽跑满常因单个API接口被高频调用或返回数据量过大。
| 日志类型 | 关键字段 | 排查方法 |
|---|---|---|
| Nginx access.log | $body_bytes_sent $request_time |
awk '{print $7" "$10}' access.log \| sort -k2 -rn \| head -20 |
| PHP slow.log | 慢查询SQL+调用栈 | 配合 strace -p PID 追踪文件读取 |
| 业务日志 | 自定义操作(如导出、消息推送) | 搜索“batch_export” “send_all”等关键词 |
典型案例:某PHP商城带宽跑满,通过access.log发现 /api/export_csv 被连续请求3000次,每次返回20MB数据。
❓问答
Q:access.log中某个接口请求量正常,但带宽居高不下,原因可能是?
A:检查响应Content-Type,如果接口返回application/json但实际数据量为20MB(含大量base64图片),需压缩或分页,使用命令:awk '/api\/getImages/ {print $10}' access.log \| sort -rn \| head -5。
第三板斧:恶意流量识别(爬虫、CC攻击、盗链)
| 攻击类型 | 特征 | 应对措施 |
|---|---|---|
| 恶意爬虫 | User-Agent含“Python/requests” “Scrapy” | Nginx封禁:if ($http_user_agent ~* (python|scrapy)) {return 444;} |
| CC攻击 | 同一个IP每秒发起>50次请求 | 限流:limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s; |
| 图片盗链 | Referer为空或非本站域名 | Referer验证:valid_referers none blocked server_names *.example.com; |
进阶检测:
- 使用
access.log分析请求频率:awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10 - 发现某个IP请求量是其他IP的100倍,执行
iptables -A INPUT -s IP -j DROP临时封禁。
❓问答
Q:封禁IP后带宽立刻下降,但过段时间又恢复,怎么办?
A:攻击者可能使用IP池,建议:
- 开启CDN(如Cloudflare)隐藏源站IP。
- 在PHP入口文件增加
$_SERVER['HTTP_CF_CONNECTING_IP']验证。- 使用
fail2ban自动封禁高频IP。
实战问答:高频问题速查
Q1:如何区分是PHP-FPM进程还是Nginx消耗带宽?
A:运行 nethogs,若其中 php-fpm 进程占用带宽高,说明业务代码存在问题;若 nginx 进程高,则可能是静态资源或反向代理转发消耗。
Q2:PHP项目突然带宽跑满,但服务器无日志,最可能的原因?
A:扫描器攻击(如Shodan、Masscan),它们不发送完整HTTP请求,直接发送畸形包,排查方法:
- 使用
tcpdump | grep -v "GET\|POST"查看非标准请求。 - 检查
/var/log/syslog中的nf_conntrack: table full错误。
Q3:怎么样永久记录每个接口的带宽消耗?
A:在Nginx配置中添加log_format:
log_format detailed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time';
然后执行 awk '{sum[$7]+=$10} END {for(k in sum) print sum[k], k}' /var/log/nginx/access.log | sort -rn | head -20 定期分析。
长期防御建议
- CDN加速+源站保护:使用CDN缓存静态资源,并设置源站IP白名单(仅允许CDN回源)。
- 频率限制:
- PHP端:
composer require nikic/fast-route配合中间件限流。 - Nginx端:
limit_req指令按IP/URI限流。
- PHP端:
- 数据压缩:对API响应启用Gzip,尤其注意大型数组查询(如
json_encode($largeArray)可能超10MB)。 - 日志自动化:部署
goaccess实时分析access.log,设置带宽阈值告警(如单IP带宽>50Mbps发送邮件)。
带宽跑满时,先看 iftop 定位IP,再看 access.log 锁定接口,最后用 nethogs 确认进程,不要盲目封禁,结合日志特征判断是爬虫、攻击还是代码缺陷,建议每季度模拟一次高流量压测,提前发现瓶颈。