Linux 服务器带宽与流量监控实战:vnstat、iftop、nload 定位异常流量

服务器跑得好好的,突然收到云厂商的流量超量告警;或者网站访问正常,但带宽长期跑满,页面加载越来越慢。这类问题的根因往往不是"网站变慢了",而是有异常流量在悄悄吃掉带宽——可能是被采集爬虫高频抓取、被下载站盗链、被 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 403deny 干掉。爬虫浪费的不只是流量,还有 CPU 和数据库连接。

九、小结

带宽排查的思路可以总结成一条链路:先用 vnstat 看长期趋势找异常时间段,再用 iftop/nload 看实时占用找异常对端,接着用 ss 和 Nginx 日志找具体 IP 与请求,最后按站点和 URL 汇总确认影响面,对症下药做优化或封禁,并配上阈值告警防患于未然。

这套方法不需要昂贵的监控系统,几个免费小工具加几行 awk 就能完成。对个人站长来说,把流量管住不仅能省下超量费用,还能在攻击和爬虫刚冒头时就发现它,避免演变成更大的事故。建议今天就把 vnstat 装上挂起来——历史数据越早积累,将来排查问题时越有底气。

Last modification:September 11th, 2026 at 07:56 am

Leave a Comment