做网站运维的人最怕两件事:流量突然崩了,或者流量突然爆了。崩了可能是技术故障,爆了却未必是好事。很多时候,流量的异常飙升恰恰是攻击的前兆或者攻击进行中的表现。把核心指标的异动和攻击关联起来分析,不是事后诸葛亮式的复盘,而是实时发现威胁的关键能力。

流量尖刺与CC攻击的瞬时关联

正常网站的流量曲线是有规律的,工作日高、休息日低,白天高、凌晨低。当你看到五分钟内请求量翻了五倍甚至十倍,而且来源IP极度分散,请求的URL却集中在某个搜索接口、登录页面或者支付回调地址,这几乎可以断定是CC攻击。CC攻击的本质就是用大量看似正常的请求消耗服务器资源,它不像洪水攻击那样靠带宽打垮你,而是精准地打你的CPU和数据库。这时候看QPS指标比看带宽更管用。如果QPS飙升但每个请求的响应时间也在同步拉长,说明服务器正在被拖垮。更隐蔽的CC攻击会模拟正常用户的浏览行为,连Referer和User-Agent都伪装得很像,这时候就要结合另一个指标:会话存活率。正常用户会有页面跳转、会有停留时长,攻击脚本往往一个会话只发一个请求就断开,会话存活率会断崖式下跌。

独立访客与请求量的比例失真

UV和PV之间通常有一个相对稳定的比例关系,内容型网站大概是1:3到1:5,工具型网站可能到1:10。如果某段时间UV没怎么变,PV却暴涨,而且暴涨的PV集中在少数几个URL上,这就有问题。更值得警惕的是,UV本身的计算方式容易被绕过。很多监控工具基于Cookie或者IP计算UV,攻击者只要每次请求不带Cookie或者更换代理IP,就能制造出海量独立访客的假象。所以看UV异常时,一定要交叉对比IP的C段分布。如果大量IP来自同一个C段或者同一个AS号,那显然不是正常的独立访客。还有一种情况是爬虫造成的指标污染。搜索引擎爬虫、AI训练爬虫、竞品的数据采集脚本,它们会拉高PV但不会触发转化事件。如果你的PV涨了30%但转化率同步跌了30%,大概率是被爬了。

错误码占比突增暴露的扫描行为

404和403的状态码比例是检测扫描攻击的黄金指标。正常网站的404占比通常在5%以内,而且分布比较均匀,用户输错URL、旧链接失效都是常见原因。但如果某段时间404占比突然超过15%,并且请求路径里出现大量不存在的目录名、备份文件后缀、管理后台路径,那就是有人在用字典扫描你的站点。扫描行为往往是攻击的前置动作,先摸清你的目录结构、框架版本、插件列表,再针对性地利用漏洞。403占比突增则说明有人在尝试访问被禁止的目录或者接口,比如直接请求/admin、/config、/env这类敏感路径。还有一种更隐蔽的扫描是参数探测,请求的URL是真实存在的,但参数名和参数值在不断变化,比如?id=1' OR '1'='1这类SQL注入测试,这时候404占比不会变,但500错误可能会突然冒出来。500错误占比只要出现波动,就应该立刻检查错误日志,很可能是注入攻击触发了数据库报错。

响应时长分布与慢速攻击的识别

平均响应时长这个指标太粗糙了,攻击者早就学会了怎么绕开它。真正有用的是响应时长的分位数分布。P50、P90、P99分别代表50%、90%、99%的请求在多少时间内完成。正常情况这三个值之间的差距是相对稳定的。如果P50没变但P99急剧恶化,说明大部分请求正常,但有一小部分请求卡住了服务器。这通常是Slowloris这类慢速攻击的特征。慢速攻击不追求请求量大,而是故意把HTTP请求发得极慢,一个请求头分几十秒发完,大量占用服务器的连接池。这时候服务器的并发连接数会飙升,但QPS反而不高,CPU使用率也正常,只有P99响应时长在报警。另一种导致P99飙升的情况是数据库慢查询被触发,攻击者可能通过特定参数构造了让数据库全表扫描的查询条件,一条查询就锁住整张表几秒钟,后面的请求全在排队。

出口流量与入站流量的不对称

正常的HTTP服务,入站流量远大于出站流量,用户请求的数据量小,服务器返回的数据量大。如果这个比例突然反过来,出站流量远超入站流量,要么是服务器被当成了代理节点在转发流量,要么是数据正在被大量外传。后一种情况就是数据泄露的实锤。攻击者通过SQL注入或者未授权的API接口,把数据库内容打包下载,这时候出站流量会持续高位运行,而且目标IP通常是境外地址或者云存储服务的域名。看流量目的地IP的地理分布是个好习惯。如果你的用户主要在国内,但出站流量有30%指向了某个从来没见过的海外IP,这绝对需要立刻排查。DNS查询日志也能辅助判断,攻击者传输数据前往往会先做DNS解析,如果监控到服务器对外查询了一些奇怪的域名,比如动态DNS服务商的域名或者新注册的域名,就要高度警惕。

登录接口的异常指标组合

登录接口是攻击者最喜欢光顾的地方,撞库、暴力破解、凭证填充都发生在这里。单独看登录失败率不一定能发现问题,因为正常用户也会输错密码。但把登录失败率、登录接口请求量、账号来源IP集中度这三个指标放在一起看,攻击行为就无处遁形。如果登录接口请求量突然翻倍,登录失败率从平时的10%飙升到80%以上,而且失败的账号大多是邮箱格式、用户名格式,明显不是正常用户的输入习惯,这就是撞库攻击。更精细的监控可以看同一IP对不同账号的尝试次数,以及同一账号从不同IP登录的时间间隔。一个账号五分钟前在北京登录,五分钟后在广东登录,物理上不可能实现,这是凭证被窃取后攻击者在异地登录。登录成功后的行为轨迹变化也值得关注,正常用户登录后有固定的浏览路径,攻击者登录后往往直奔账户设置、钱包页面或者数据导出功能,页面访问序列会出现明显断裂。

CDN回源量与缓存命中率的突变

CDN的缓存命中率是衡量网站健康度的一个侧面指标。正常运营的网站,静态资源的缓存命中率应该在90%以上,动态内容根据策略不同在30%到70%之间。如果缓存命中率突然大幅下降,同时回源请求量激增,有两种可能。一种是攻击者在请求时不断添加随机参数,强制CDN回源拉取最新内容,从而绕过CDN的缓存保护直接打击源站。另一种是CDN配置被人篡改,或者攻击者发现了源站的真实IP地址,直接绕过CDN发起攻击。后一种情况尤其危险,因为很多运维人员以为套了CDN就高枕无忧,源站的安全组规则放得很宽,一旦真实IP暴露,攻击者可以长驱直入。检查回源请求的User-Agent分布也能发现线索,正常回源请求的User-Agent主要是CDN厂商的回源标识,如果出现了大量浏览器User-Agent的回源请求,说明有人在直接访问源站。

数据库连接数与慢查询的联动监控

应用层的指标和数据库层的指标要联动起来看才有意义。Web服务器的并发连接数飙升,数据库的连接数一定会跟着涨,但两者的涨幅应该是成比例的。如果Web服务器连接数只涨了20%,数据库连接数却涨了200%,说明有请求在大量创建数据库连接但不释放,很可能是连接池被耗尽的前兆。慢查询数量是另一个关键信号。正常情况下慢查询是偶发的,可能某个复杂报表查询会触发一两次。如果慢查询数量在短时间内从每分钟几个跳到每分钟几百个,而且慢查询的SQL语句都带有相似的参数特征,那就是SQL注入攻击正在拖垮数据库。攻击者通过注入构造笛卡尔积查询或者递归查询,一条SQL就能让数据库CPU跑满。这时候看数据库的活跃会话数,会发现大量会话卡在同一个执行计划上,等待锁释放。

建立指标关联分析的基础能力

把上面这些指标孤立地看,每个都可能产生误报。流量涨了可能是真的爆款内容,404多了可能是刚改版链接没做重定向。真正的攻击识别靠的是指标之间的交叉验证。一个实用的做法是建立基线模型,用过去四周同一时段的数据算出每个指标的均值和标准差,当前值偏离基线超过三个标准差就触发预警。但光有预警不够,还要建立关联规则。比如“QPS超过基线5倍”且“P99响应时长超过基线3倍”且“404占比超过15%”同时满足,才判定为攻击事件。这套规则需要根据自己网站的业务特点持续调优。电商大促期间流量本来就高,基线要按活动期单独计算。API服务没有页面浏览,PV和UV的指标意义就不大,要看Token消耗速率和接口调用频率。监控的颗粒度也很重要,五分钟聚合一次数据对于检测DDoS攻击来说太慢了,攻击可能三分钟就把服务打挂了。核心安全指标至少要做到一分钟甚至三十秒的采集间隔。

# 示例:用Python实现简单的指标异常检测逻辑
def check_anomaly(current_qps, current_p99, current_404_ratio, baseline):
    qps_threshold = baseline['qps_mean'] + 3 * baseline['qps_std']
    p99_threshold = baseline['p99_mean'] + 3 * baseline['p99_std']
    ratio_threshold = baseline['404_ratio_mean'] + 3 * baseline['404_ratio_std']
    
    score = 0
    if current_qps > qps_threshold:
        score += 1
    if current_p99 > p99_threshold:
        score += 1
    if current_404_ratio > ratio_threshold:
        score += 1
    
    if score >= 2:
        return "疑似攻击", score
    elif score == 1:
        return "需关注", score
    else:
        return "正常", score
从被动监控到主动防御的衔接

指标异动和攻击关联分析的最终目的不是写一份漂亮的事后报告,而是缩短从发现到处置的时间窗口。理想状态下,监控系统检测到攻击特征后,应该自动触发防御动作。比如检测到CC攻击模式,自动对相关URL开启验证码挑战或者限速策略。检测到扫描行为,自动将扫描IP加入黑名单并封禁一段时间。检测到数据外传的流量特征,自动切断对应连接并通知安全团队。但自动防御有风险,误判可能导致正常用户被拦截。所以比较稳妥的做法是分级响应:低置信度的告警只通知运维人员,中置信度的告警自动执行温和的限制策略比如降速,高置信度的告警才执行严格的阻断策略。置信度的高低就取决于多个指标交叉验证的结果,单一指标异常置信度低,三个以上核心指标同时异常置信度高。这套逻辑跑通了,运维团队才能真正从救火队员变成预防专家。

日志是关联分析的原材料

所有指标都来源于日志,日志的质量直接决定了分析的上限。Web服务器访问日志、应用日志、数据库慢查询日志、系统日志、网络流日志,这五类日志缺一不可。很多团队只收集访问日志和应用日志,出了问题只能看到表象,看不到根因。比如发现响应变慢了,访问日志只能告诉你哪些请求慢了,但数据库慢查询日志能告诉你哪条SQL拖垮了性能,系统日志能告诉你当时是否在发生内存交换或者磁盘IO等待。日志的时间戳对齐是另一个容易被忽视的问题。如果Web服务器和数据库服务器的时钟不同步,差了十几秒甚至几分钟,想把一个请求从入口追踪到数据库层就变得极其困难。部署NTP服务保证所有服务器时钟一致,是所有监控工作的基础前提。日志的保留周期也要足够长,有些攻击者会提前几周甚至几个月进行低频率的信息收集,如果日志只保留七天,根本无法回溯攻击的完整链条。

网站运营监控做到一定深度之后,你会发现攻击行为和正常业务的波动在单个指标上可能完全重叠,但在多个指标的交叉视角下,攻击者的痕迹就像黑夜里的车灯一样清晰。核心指标的异动不是用来解释过去的,而是用来在攻击造成实质损害之前就拉响警报的。把指标之间的关联逻辑理清楚,把基线和阈值设准确,把日志采集和时钟同步做到位,剩下的就是让数据自己说话。