服务器跑得好好的,突然收到云厂商的流量超量告警;或者网站访问正常,但带宽长期跑满,页面加载越来越慢。这类问题的根因往往不是"网站变慢了",而是有异常流量在悄悄吃掉带宽——可能是被采集爬虫高频抓取、被下载站盗链、被 CC 攻击,也可能是某次部署的日志或备份脚本在后台猛传数据。要定位这些问题,光看 CPU 和内存是不够的,必须学会用流量监控工具把"带宽被谁用了"这件事查清楚。这篇文章介绍 vnstat、iftop、nload、ss 这几款工具的实战用法,以及如何从流量曲线反推出问题源头。
一、先建立基线:正常流量长什么样
排查异常的前提是知道什么是正常。个人站长博客在没有任何推广动作时,流量曲线通常是很规律的:白天有小高峰,凌晨掉到低谷,日均出流量几百 MB 到几 GB 不等。如果某天的曲线突然变成一条直线拉满,或者凌晨时段出现不该有的峰值,那就是异常信号。
所以第一步永远是先把长期统计挂起来,让服务器自己记录历史。这就是 vnstat 的用武之地。
二、vnstat:长期流量统计的标准答案
vnstat 是一个轻量的流量统计工具,它读取网卡的收发字节数并持久化到数据库,重启不会丢,开销几乎可以忽略,非常适合长期挂在小 VPS 上。
# Debian / Ubuntu apt install vnstat # CentOS / RHEL(需要 EPEL 源) dnf install epel-release dnf install vnstat # 启动并设置开机自启 systemctl enable --now vnstat
装好之后先确认它在盯着正确的网卡。默认情况下 vnstat 会自动选择有流量的接口,但服务器上如果有 Docker 虚拟网卡、VPN 接口,容易选错。查看数据库绑定的接口:
vnstat --showconfig | grep -A3 Interface
如果绑错了,编辑 /etc/vnstat.conf,把 Interface "eth0" 改成实际的主网卡名(用 ip -brief addr 确认),然后重建数据库:
systemctl stop vnstat rm -f /var/lib/vnstat/* systemctl start vnstat
常用查询命令:
vnstat # 本月与今日概览 vnstat -d # 最近 30 天每日流量 vnstat -m # 最近 12 个月每月流量 vnstat -h # 最近 24 小时 vnstat -t # 流量最高的 10 天 vnstat -i eth0 -5 # 最近 5 分钟(实时采样) vnstat --json # JSON 输出,方便脚本处理或对接监控
实战场景:云服务器按流量计费的话,用 vnstat -m 就能提前判断本月会不会超量;发现某天流量异常,用 vnstat -d 定位到具体日期,再用 vnstat -h 缩小到具体小时,就知道问题发生在哪个时间段。这个"从月到日再到小时"的逐层缩小,是排查流量问题的基本方法。
三、iftop:实时看清带宽被谁占着
vnstat 告诉你"什么时候用的",iftop 告诉你"谁在用"。它基于 libpcap 抓包,按连接实时展示带宽占用排名,是定位异常流量的利器。
apt install iftop # -i 指定网卡,-n 不做 DNS 反查(快很多),-P 显示端口 iftop -i eth0 -n -P
界面分三部分:上方是实时流量刻度,中间是连接列表(左边本地、右边对端,中间两个箭头分别是进和出的速率),下方是最近 2/10/40 秒的平均值汇总。常用按键:
p切换是否显示端口n切换是否做 DNS 反查t切换显示模式(两行/单行/只显示发送/只显示接收)s/d按源/目标地址排序B切换 bits 与 bytes 显示——注意备案的带宽单位是 Mbps(比特),而 iftop 默认可能显示字节,别把 1 MB/s 当成 1 Mbps,差了 8 倍
典型判读:
- 某个 IP 持续占据榜首且流量远超其他连接 → 大概率是爬虫或攻击,用
whois查归属,必要时封禁。 - 出方向流量远大于入方向 → 有人在疯狂下载你站上的文件,或站点被当成资源站盗链。
- 大量指向同一个境外 IP 的小包 → 可能是被扫描或被当作代理跳板。
- 出方向稳定在一个不高不低的速率,且对端是你自己的另一台服务器 → 检查 rsync/备份/同步脚本是不是跑飞了。
⚠️ iftop 需要 root 权限,也不能在服务器上长时间挂着(本身有开销)。排查完就退出。
四、nload 与 bmon:一眼看清总量与趋势
如果你只想知道"现在带宽用了多少、有没有顶到上限",nload 比 iftop 更直观:
apt install nload nload eth0
它会画出实时进出流量的曲线图,并显示当前值、平均值、最大值和总量。按方向键可以切换网卡。同类工具还有 bmon(趋势图更漂亮)、iptraf-ng(更详细的连接统计)。
这几个工具的分工可以这样记:看长期趋势用 vnstat,看实时占比用 iftop,看总量曲线用 nload。
五、ss 与 netstat:从连接数侧面找线索
流量问题往往伴随连接数异常。用 ss 快速统计当前连接状态分布:
# 各状态连接数统计
ss -s
# 统计每个 IP 的 ESTABLISHED 连接数,按数量倒序取前 20
ss -tn state established | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
# 查看 80/443 端口连接最多的对端
ss -tn '( sport = :443 or sport = :80 )' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head如果某个 IP 有几百上千条连接,基本可以确定是扫描、CC 攻击或采集程序。拿到 IP 之后,可以结合 Web 日志确认它请求了什么:
# 从 Nginx 日志里统计访问量最高的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# 看某个可疑 IP 具体请求了哪些 URL
grep "1.2.3.4" /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
# 统计 User-Agent,识别爬虫
awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20通过这几条命令,通常能在几分钟内判断出对方是在扫后台、抓内容还是下载资源,然后决定是封 IP、限速还是加验证。
六、按流量找罪魁祸首:到底是哪个站点在跑流量
如果一台服务器上跑着多个站点,需要进一步定位是哪个域名在消耗带宽。在 Nginx 日志格式里加上 $body_bytes_sent 和 $host,然后统计:
log_format traffic '$host $remote_addr "$request" $status $body_bytes_sent';
# 按域名汇总出流量(单位字节)
awk '{sum[$1]+=$6} END {for (h in sum) print sum[h], h}' \
/var/log/nginx/access.log | sort -rn | head
# 找出单次响应最大的 URL(大文件下载)
awk '{print $6, $7}' /var/log/nginx/access.log | sort -rn | head -20这样既能看出哪个站是流量大户,也能发现是不是有某个大文件被反复下载。如果是图片、视频、静态资源被大量拉取,最有效的办法是接 CDN 或对象存储,把流量从源站卸掉;如果确认是盗链,用 Nginx 的 valid_referers 做防盗链。
七、报警:让服务器主动通知你
人工排查总是滞后的,更专业的做法是设置阈值告警。最简单的方案是一个定时脚本,超出阈值就推送通知:
#!/bin/bash
# /root/bin/traffic_alert.sh
LIMIT_GB=50 # 本月流量告警阈值
WEBHOOK="https://你的推送地址"
USED=$(vnstat --json m 2>/dev/null | grep -oP '"totalbytes":\s*\K[0-9]+' | head -1)
USED_GB=$((USED / 1024 / 1024 / 1024))
if [ "$USED_GB" -ge "$LIMIT_GB" ]; then
curl -s -X POST "$WEBHOOK" \
-H 'Content-Type: application/json' \
-d "{\"msg\":\"流量告警:本月已用 ${USED_GB} GB,超过阈值 ${LIMIT_GB} GB\"}"
fi挂到 crontab 每小时跑一次:
0 * * * * /root/bin/traffic_alert.sh >/dev/null 2>&1
如果想做得更完整,可以把 vnstat 的数据接到 Prometheus 或者自建监控面板,画成趋势图长期观察。对于只有一两台机器的个人站长,上面这个脚本已经够用了。
八、把流量降下来的几条实招
查清楚之后,治理手段大致按性价比排序:
- 静态资源上 CDN 或对象存储:图片、CSS/JS、视频是流量大头,交给 CDN 之后源站出流量通常能降 70% 以上,这是最有效的一招。
- 开启 Gzip 或 Brotli 压缩:HTML/CSS/JS 压缩后体积能减 60–70%,对文本型站点立竿见影。注意不要压缩图片和视频,它们本来就没有压缩空间。
- 配置缓存头,减少重复请求:给静态资源设置长 Cache-Control 和 ETag,让浏览器本地缓存,避免每次访问都重新下载。
- 防盗链:对图片、下载文件校验 Referer,只放行自己的域名,挡住被别的站白嫖流量。
- 限速与限连接:对下载类接口用 Nginx
limit_rate限制单连接速度,用limit_conn限制单 IP 并发数,避免个别用户拖垮整体带宽。 - 屏蔽恶意爬虫:从日志里找出高频非主流 UA 和 IP 段,用
return 403或deny干掉。爬虫浪费的不只是流量,还有 CPU 和数据库连接。
九、小结
带宽排查的思路可以总结成一条链路:先用 vnstat 看长期趋势找异常时间段,再用 iftop/nload 看实时占用找异常对端,接着用 ss 和 Nginx 日志找具体 IP 与请求,最后按站点和 URL 汇总确认影响面,对症下药做优化或封禁,并配上阈值告警防患于未然。
这套方法不需要昂贵的监控系统,几个免费小工具加几行 awk 就能完成。对个人站长来说,把流量管住不仅能省下超量费用,还能在攻击和爬虫刚冒头时就发现它,避免演变成更大的事故。建议今天就把 vnstat 装上挂起来——历史数据越早积累,将来排查问题时越有底气。