一、从告警邮件说起

但凡做过运维的朋友,多半都收到过Nagios半夜发来的告警邮件,内容是“网络流量告警:eth0入站流量超过阈值”。第一反应可能是揉揉眼睛,确认是不是哪台交换机的端口被占满了。但当你打开Nagios界面,点开具体服务检查的时候,才发现数据曲线已经跑到了一个平时完全没见过的峰值。这时候你就得打起精神,认真排查“流量异常”背后的真实原因了。咱们这篇文章就专门聊一聊:在生产环境里,当Nagios报出网络流量异常时,究竟该怎么查、怎么处理,以及如何从根本上减少这种告警的误触。

二、常见网络流量异常的场景

流量异常其实分好几种情况,每种处理方法都不一样。咱们先捋一捋最常见的几个场景。

  • 业务正常增长导致的流量上涨:比如公司上线了新功能,用户访问量翻倍,流量自然跟着涨。这种情况不算“异常”,但阈值如果没调,Nagios就会天天报警。
  • DDoS攻击或恶意扫描:外网IP突然对服务器发起大量连接请求,流量曲线像心电图一样陡峭,通常还会伴随CPU、带宽占满。
  • 内部网络环路或广播风暴:交换机配置出问题,或者某个端口产生了大量广播包,导致整网流量异常。这种情况在大型内网里尤其常见。
  • 错误配置或脚本失控:比如某个定时任务里的rsync或wget忘了限速,或者日志同步脚本陷入死循环,不停往远程服务器上传数据。
  • 流量突降或降为零:有时候告警不是流量高了,而是突然降为零——比如网线被拔了、服务挂掉了、端口down了。Nagios同样会报“流量过低”的告警。

理解了常见场景,咱们才知道Nagios的告警背后可能隐藏着哪种问题。

三、Nagios监控网络流量的实现方式

Nagios本身没有内置流量监控能力,它依赖外部插件或者自定义脚本去采集数据。生产环境里用的最多的方法是SNMP(简单网络管理协议)加check_traffic插件,或者写一个Shell脚本直接抓取系统接口的流量。

3.1 使用SNMP与Nagios插件

SNMP是网络设备(交换机、路由器、服务器网卡)的标准管理协议。Nagios通过snmpget命令去读取设备的MIB库,比如获取接口的字节数,然后计算差值得到速率。

假设我们要监控服务器eth0的流量,需要提前在服务器上安装snmpd并开启SNMP。然后在Nagios服务器上安装check_snmp插件。一个典型的命令配置长这样:

# 在Nagios的命令定义文件中添加命令定义
define command {
    command_name    check_snmp_traffic
    command_line    $USER1$/check_snmp -H $HOSTADDRESS$ -C public -o ifInOctets.2,ifOutOctets.2 -w $ARG1$ -c $ARG2$ -l "eth0流量" -u "Bytes/s" -m "NET-SNMP-EXTEND-MIB" -p 2
}

参数说明:-o ifInOctets.2表示读取第二个接口(通常是eth0)的入站字节数,-w-c是警告和紧急阈值。但这个命令只能读瞬时值,不够准确。更常用的是用check_traffic插件(perl脚本)来采集。

3.2 编写自定义脚本监控流量

如果不想依赖SNMP,可以直接在Nagios的被监控主机上写一个Shell脚本,通过读取/proc/net/dev或者用netstat -i获取流量数据。脚本定期执行,把结果返回给Nagios。

下面是一个完整的Shell脚本示例,使用Bash技术栈。这个脚本会计算指定网卡(比如eth0)在过去60秒内的平均流量,并输出性能数据供Nagios绘制图表。

#!/bin/bash
# check_traffic_custom.sh - Nagios自定义流量监控脚本
# 技术栈:Bash + /proc伪文件系统
# 用途:检查eth0的入站/出站流量是否超过阈值

# 网卡名称
INTERFACE="eth0"
# 警告阈值(单位:MB/s,这里设定为10MB/s)
WARN_MB=10
# 紧急阈值(单位:MB/s,这里设定为20MB/s)
CRIT_MB=20

# 获取当前网卡的字节数
# /proc/net/dev 格式:Inter-|   Receive                        |  Transmit
# 第2列是接收字节,第10列是发送字节
current_rx=$(awk -v iface="$INTERFACE" '$1 ~ iface":" {print $2}' /proc/net/dev)
current_tx=$(awk -v iface="$INTERFACE" '$1 ~ iface":" {print $10}' /proc/net/dev)

# 如果没有获取到值,报未知错误
if [[ -z "$current_rx" || -z "$current_tx" ]]; then
    echo "UNKNOWN - 无法读取接口 $INTERFACE 的统计数据"
    exit 3
fi

# 休眠1秒,再取一次,计算差值
sleep 1
new_rx=$(awk -v iface="$INTERFACE" '$1 ~ iface":" {print $2}' /proc/net/dev)
new_tx=$(awk -v iface="$INTERFACE" '$1 ~ iface":" {print $10}' /proc/net/dev)

# 计算字节差值并转换为MB/s(1MB=1048576字节)
rx_diff=$(( (new_rx - current_rx) / 1048576 ))
tx_diff=$(( (new_tx - current_tx) / 1048576 ))

# 构建性能数据字符串,用于Nagios绘制趋势图
perfdata="rx=${rx_diff}MB;${WARN_MB};${CRIT_MB};0; tx=${tx_diff}MB;${WARN_MB};${CRIT_MB};0;"

# 状态判断
if [[ $rx_diff -ge $CRIT_MB || $tx_diff -ge $CRIT_MB ]]; then
    echo "CRITICAL - 流量过高!入站${rx_diff}MB/s, 出站${tx_diff}MB/s | $perfdata"
    exit 2
elif [[ $rx_diff -ge $WARN_MB || $tx_diff -ge $WARN_MB ]]; then
    echo "WARNING - 流量偏高!入站${rx_diff}MB/s, 出站${tx_diff}MB/s | $perfdata"
    exit 1
else
    echo "OK - 流量正常。入站${rx_diff}MB/s, 出站${tx_diff}MB/s | $perfdata"
    exit 0
fi

使用说明:把脚本放到Nagios的libexec目录(比如/usr/lib/nagios/plugins/)并赋予执行权限,然后在Nagios服务定义里调用:

# 在服务定义文件中添加
define service {
    host_name               web-server-01
    service_description     流量监控-eth0
    check_command           check_local_custom!check_traffic_custom.sh
    use                     generic-service
    notification_interval   30
}

这种方式的优点是灵活,不需要额外安装SNMP或插件,缺点是每次检查都要sleep 1秒,检查间隔不宜太短,否则会增加系统负载。而且它只能监控本机,不能监控交换机。

四、排查步骤与处理实战

Nagios已经发出了告警,咱们怎么一步一步查呢?下面给出一个比较通用的流程。

4.1 第一步:确认告警真实性

收到报警后,先别急着骂Nagios。打开Nagios的“服务详情”,看看是哪个主机、哪个网口、最近的性能数据曲线是怎样的。如果曲线是缓慢上升的,可能是业务增长;如果是尖峰,很可能是异常。然后远程登录到该主机,手动运行一下脚本确认:

# 手动模拟Nagios检查
/usr/lib/nagios/plugins/check_traffic_custom.sh

如果输出也是CRITICAL,说明Nagios没报错。接着用iftopnethogs实时看哪个进程在跑流量:

# 安装iftop:yum/apt install iftop
sudo iftop -i eth0 -n -P

iftop会显示每个连接的流量占比,能快速看出是不是某个IP在大量发包。

4.2 第二步:定位异常来源

假设iftop显示目标IP是203.0.113.50的流量高达500Mbps,而这个IP并不在业务白名单里。先查一下这个IP是谁:

# 用netstat查看连接状态,匹配该IP
netstat -ant | grep 203.0.113.50

如果看到大量SYN_RECV状态,很可能是在搞SYN Flood。如果都是ESTABLISHED,可能是正常访问但被爬虫攻击了。这时候要结合应用日志(如Nginx access log)进一步确认。

另一种情况:内部服务器之间流量异常,比如两台服务器之间的数据库同步占满带宽。可以用tcpdump抓包分析:

# 抓取eth0上一定数量的包,查看协议分布
sudo tcpdump -i eth0 -n -c 10000 | awk '{print $3}' | sort | uniq -c | sort -rn | head -20

如果发现大量包的目标端口是3306,那可能是数据库复制流量,需要检查主从延迟和同步配置。

4.3 第三步:临时处理与长期优化

如果确认是攻击,第一时间要做的不是追查来源,而是阻断。最简单的办法是用iptables封掉源IP:

# 封禁可疑IP 203.0.113.50
sudo iptables -A INPUT -s 203.0.113.50 -j DROP

或者更精细一点,如果是UDP放大攻击,可以限制UDP连接数。但注意,iptables规则实时生效,生产环境操作前最好备份现有规则。

如果是内部网络环路,需要去交换机上找到产生广播包的端口,关闭该端口或开启STP(生成树协议)。如果是错误脚本导致,先杀掉进程、停掉定时任务,再去修改代码。

长期优化:调整Nagios的阈值,不要用固定死值,最好能结合历史基线设置动态阈值。例如使用check_nwc_health插件,它可以基于历史数据自动计算上下限,或者自己写一个脚本每隔三天计算一波平均流量,然后动态写入Nagios配置文件。另一个优化点是增加告警抑制,比如连续3次检查都超过阈值才告警,可以避免瞬时的流量抖动。

五、关联技术:SNMP与MRTG/PRTG对比

Nagios和专业的流量监控工具(如MRTG、PRTG)定位不同。Nagios强在告警和事件管理,而MRTG擅长画长期趋势图,PRTG则是集大成者,但它需要付费。如果团队小、只想快速定位问题,Nagios+自定义脚本就够用了。但如果要分析流量峰值、趋势预测、容量规划,建议搭配一个独立的流量监控系统,比如Cacti或Zabbix。Cacti基于RRDtool,可以画出漂亮的图表,还能设置环形数据库归档,占用空间小。它们和Nagios可以互补:Nagios负责报警,Cacti负责展示。

六、应用场景与优缺点

应用场景

  • 互联网公司服务器带宽监控,防止流量打满影响业务。
  • IDC机房内部网络健康检查,及时发现环路或端口故障。
  • CDN节点流量监控,辅助调度决策。
  • 多租户环境下,防止某个用户滥用带宽。

技术优缺点

优点:

  • Nagios开源免费,社区生态成熟,插件丰富。
  • 自定义脚本灵活,可以监控任何你能写脚本测到的指标。
  • 报警机制丰富,支持邮件、短信、微信等多种方式。

缺点:

  • 监控本身依赖于被监控端的稳定,如果被监控机器挂了,就无法收到最新数据。
  • 流量采集需要定期执行,检查间隔太短会消耗CPU和网络,太长则无法及时发现突增。
  • 不像专业流量监控工具那样拥有自动发现拓扑、历史趋势预测等功能。

七、注意事项

  1. 避免IO阻塞:脚本里不要用太长的sleep,尤其在有大量服务检查的情况下。可以考虑用rmon或snmptrap主动上报,而不是Nagios轮询。
  2. 阈值要科学:不要一拍脑门定阈值。最好先观察一周的正常流量,取平均值加三倍标准差作为警告线。
  3. 避免Nagios本身成为瓶颈:如果监控上千台机器,每30秒跑一次SNMP查询,Nagios服务器可能顶不住。建议使用分布式Nagios或改用Cache。
  4. 区分物理端口和聚合端口:某些服务器有绑定(bonding)网卡,脚本需要读取bond0而不是eth0。
  5. 紧急处理要留证据:封IP之前最好抓个包留底,方便事后溯源。

八、文章总结

Nagios监控网络流量异常,看起来是一个单纯的技术告警,背后可能牵扯到网络攻击、配置错误、业务增长甚至硬件故障。日常运维里,我们不能只看Nagios的“OK/CRITICAL”,而是要结合实时工具(iftop、netstat、tcpdump)逐层排查。同时,一个好的监控系统需要持续调优——阈值、检查间隔、告警聚合都要随着业务变化而调整。最后别忘了,流量监控不是目的,保障业务可用性才是。希望这篇文章能让你下次再看到Nagios的流量告警时,心里更有底。