在日常运维工作中,如何有效检测异常流量始终是一个让人头疼的问题。别急,从日志入手,一步步来。可以确定的是,只要日志采集和结构化做到位,后续的监控与告警就能事半功倍。下面就把这套基于Ubuntu环境下JS日志的异常流量检测方案摊开来讲。
一 日志采集与结构化
在Node.js中输出结构化日志,这件事做对了,后续的统计和告警就顺理成章了。这里以Winston为例,日志写入文件便于集中分析:
- 安装:
npm install winston - 配置:
const winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }) ] }); // 请求日志示例(在中间件中) app.use((req, res, next) => { logger.info('http_request', { ts: new Date().toISOString(), ip: req.ip, method: req.method, url: req.url, ua: req.headers['user-agent'], status: res.statusCode, rt: Date.now() - req.startTime }); next(); });
如果使用PM2部署,可以直接用 pm2 logs 实时查看与采集;如果需要集中管理,将日志接入ELK(Elasticsearch/Logstash/Kibana)或Graylog等平台,检索和可视化会非常方便。
二 命令行快速检测
有时候不想搭复杂平台,命令行才是最快出活的方式。看看下面这些实用操作:
- 实时查看新增日志:
tail -f /path/to/combined.log - 关键字快速筛选:
tail -f /path/to/combined.log | grep 'error' - 统计每分钟请求量(按日志行计数,适用于JSON每行一条请求的场景):
tail -n 10000 /path/to/combined.log | jq -r '.["ts"]' | cut -d'T' -f2 | cut -d'.' -f1 | sort | uniq -c
- Top N 来源IP:
tail -n 50000 /path/to/combined.log | jq -r '.["ip"]' | sort | uniq -c | sort -nr | head -20 - 高频异常路径:
tail -n 50000 /path/to/combined.log | jq -r '.["url"]' | sort | uniq -c | sort -nr | head -20 - 5xx比例(示例):
tail -n 10000 /path/to/combined.log | jq 'select(.["status"] >= 500)' | wc -l与总量对比计算比例
注意,上述命令假设日志为JSON行格式;如果用文本格式,可以用 awk/grep/sed 按字段位置解析。如果日志量太大,建议先采样,或者交给Logstash、Fluentd做预处理。
三 模式与阈值示例
异常流量到底长什么样?经验表明,下面这些信号最值得警惕。具体阈值可以根据业务灵活调整:
| 异常信号 | 日志侧特征 | 建议阈值示例 | 处置要点 |
|---|---|---|---|
| 流量突发 | 单位时间请求数骤增 | 1分钟请求数 > 基线3σ 或 > 1000 req/min | 触发限流/封禁,联动告警 |
| 单IP高频 | 同一IP短时间大量请求 | 1分钟 > 100 req/min 或 10分钟 > 500 req | 自动封禁该IP,观察是否回落 |
| 异常路径扫爆 | 少数路径命中异常高 | 某路径占比 > 70% 且总量异常 | 临时禁用路由或返回429 |
| 错误率飙升 | 5xx/4xx比例异常 | 5xx > 5% 或 4xx+5xx > 10% | 回滚版本/限流/扩容 |
| 响应时间异常 | P95/P99明显上升 | P95 > 2s 或较基线翻倍 | 降级非核心功能、排查慢查询 |
| 地理异常 | 突发来自异常地区 | 某地区请求占比突增 | 结合风控策略限制或二次校验 |
以上信号可以通过日志聚合后在Kibana或Grafana设置阈值告警,也可以写入Prometheus做指标化监控与动态阈值。
四 实时告警与防护联动
检测出来了,还得能及时反应。一个完整的告警链路大概长这样:
- 采集与解析:Filebeat或Logstash读取日志,按JSON解析出各字段(ip、method、url、status、ts)。
- 检测与告警:在Elasticsearch Watcher、Kibana Alerting或Grafana Alert中配置规则——比如1分钟请求数超过阈值、Top IP超限、5xx比例超标——触发后通过Webhook、邮件、企业微信或钉钉通知到人。
- 处置动作:联动iptables或fail2ban封禁恶意IP,也可以直接在Nginx或应用层返回429/403;Node.js侧可以结合express-rate-limit做二次限流,缓解突发流量冲击。