高频请求的定义与阈值设定原则

咱们先聊清楚一个基础问题:到底什么算“高频请求”?很多新手一看日志里某个OCSP请求出现了几十次,就慌了,觉得是攻击。其实未必。

我个人习惯把高频请求分成两类来看:高频和相对高频。高频,就是单位时间内请求次数远超常识范围,比如每秒几百次。相对高频,是跟这个站点、这个CA、这个客户端的正常基线比,突然暴涨。

举个例子:你想想看,一个正常CA每天签发几万个证书,OCSP响应请求量可能是几十万次。但某个IP在1分钟内对同一个序列号请求了1000次,这就明显不对了。我在项目中遇到过某电商平台,证书正常到期日那天,日志里突然出现对同一张证书的OCSP请求暴增300倍,最后发现是某台负载均衡器的缓存策略写错了。

核心定义:高频请求是指单位时间内,来自同一源IP、同一证书序列号或同一请求特征组合的OCSP请求次数,显著高于该环境正常基线的行为。阈值不是固定值,而是动态基线。

常见高频请求场景

我梳理了几个我在溯源中反复见过的场景,你可以当作对照清单:

  • 业务服务器重启或扩容:新启动的实例没有OCSP响应缓存,会在短期内集中验证所有证书,造成请求量暴增。我记得有一次帮客户排查,一看是一台新上线的K8s节点,对集群内所有证书都重新验证了一遍。
  • CDN或反向代理配置错误:某个节点没有开启OCSP Stapling,或者缓存TTL设得太短。我曾经碰到过一个案例,某CDN厂商的节点误把Stapling关闭了,导致大量客户端直接回源验证,流量瞬间飙到平时的200倍。
  • 证书链异常:中间证书过期或者OCSP响应器地址配错,客户端验证失败后反复重试,形成循环请求。说白了就是卡住了,一直问,一直问不到正确答案。
  • 恶意探测或DoS:攻击者利用大量傀儡IP,对特定序列号发起OCSP请求,消耗CA服务器的验证能力。这类请求通常特征很一致,但源IP分散。

阈值设定原则:别拍脑袋,先看基线

阈值怎么定?我一贯的原则是:没有基线,就没有阈值。你再强的专家也不能闭着眼睛写个数字。原因很简单:一个日活百万的网站和一个日活几百的内部系统,正常OCSP请求量能差两个数量级。

我自己在定阈值时,一般走这四步:

  1. 收集正常周期数据:至少取7天全量OCSP请求日志,做时间序列分析。如果业务有周期性波峰(比如月初、发版日),还要额外取样。
  2. 计算统计特征:对每个特征维度(源IP、序列号、UA等)算出P50、P95、P99。P99是常用底线。
  3. 确定初始阈值:通常取P99的2-3倍作为告警阈值。为什么不是P99本身?因为正常波动也可能超出P99。我习惯留出30%的缓冲区间。
  4. 动态调优:上线后观察一周,如果误报率超过5%,就向上调整;如果漏掉了真实事件,向下调整。后面你还会学到自适应阈值算法。
维度 正常基线(P99) 初始告警阈值 说明
单IP每10分钟请求数 50次 150次 普通业务客户端极限
单序列号每小时请求数 200次 600次 考虑CDN节点批量验证
单UA每5分钟请求数 30次 100次 API调用客户端异常

建议:别只用一个阈值。我会同时设“慢速阈值”(比如3倍P99,用来捕获缓慢爬升的异常)和“快速阈值”(比如10倍P99,用来捕获突发峰值)。两个阈值触发不同的响应动作。

避坑指南:我曾经踩过的几个坑

虽然前面讲得清楚,但实际落地时还是有不少坑。我挑三个最典型的说说:

  • 坑一:忽略业务高峰期。我曾经给一个电商平台设阈值,取了7天正常数据,结果忽略了双十一那天的压力测试。双十一当天OCSP请求量是平时的20倍,阈值全破了。后来我每次定阈值都要标注“是否包含业务最高峰”,如果不包含,必须单独加一个高峰阈值。
  • 坑二:维度选得太粗。只看总请求数,不看源IP分布。有一次大量请求虽然总数不高,但集中来自同一个C段,其实是扫描器在试错。如果只按总量阈值,根本发现不了。现在我的规则里一定会加上“单IP”或“单C段”维度。
  • 坑三:缓存命中率没考虑。OCSP Stapling和本地缓存如果工作正常,大部分请求根本不会到源站。我遇到过一台服务器的缓存被误清空,结果源站看到的OCSP请求量暴增,但实际上是同一个原因——缓存丢了。所以我在定阈值时会先看缓存命中率,命中率低于90%时的请求量才有分析价值。

重要提醒:不要只依赖固定阈值来做溯源决策。高频请求本身只是一种现象,不是定罪的证据。我曾经见过一个合法客户端的证书到期日当天自动重试100次,完全是正常行为。阈值只用来筛选可疑事件,真正定性需要结合后续的载荷、证书链、响应状态等特征。

高频请求与阈值设定知识结构

下面这张图把整个逻辑串起来了,你看一眼就清楚各个环节怎么配合。

高频请求溯源与阈值设定流程 高频请求定义 高频(常识范围外) 相对高频(超出基线) 阈值设定:基线 → P99 → 缓冲 收集正常周期数据 计算统计特征 确定初始阈值 动态调优 避坑:忽略高峰期、维度太粗、缓存命中率

上面这张图展示了从定义到阈值设定的完整决策路径。你可能会注意到,我并没有把“阈值”写成固定数值,而是强调基线驱动。这也是我这些年溯源下来最深的体会:动态基线比硬编码靠谱得多。

实践中的两个小技巧

最后再分享两个我在实际溯源中常用的小手段:

  • 技巧一:滑动窗口计数。别用固定时间窗口(比如“最近1小时”),否则容易错过快速波动。我习惯用指数加权的滑动窗口,让近期的数据权重更高,这样能更快发现异常。
  • 技巧二:多特征联合判定。单个特征(比如源IP)可能误报,但“源IP+序列号+UA”三个维度同时超过阈值,基本就是真的异常。我曾经用这个方法从几百万条日志中精准定位到一个恶意脚本——它的UA是“python-requests/2.25.0”,序列号全是今天新签发的证书,源IP来自同一家云厂商。三个特征一交集,直接锁定。

嗯,这里要注意:滑动窗口的时间粒度不要设太细,我试过1秒窗口,结果把正常业务波动也当成高频了。推荐最小粒度为10秒,结合业务响应时间设定。

好了,高频请求的定义和阈值设定原则就讲到这。你回去可以先翻一下自己手头的OCSP日志,算算P99是多少,心里有个数,后面章节我们再深入研究如何把这些阈值转换成具体的告警规则和溯源脚本。