防了一个月,月报却写不出一页纸?问题通常不在数据太少,而在口径没定。本文用 10 个问答讲清 CC防护月报 该放哪些数据块、拦截量与误封率怎么统计、图表怎么画、哪些写法会被一眼打回。
Q:为什么明明拦了很多,月报还是写不出来?
- 三个具体原因:数据分散在边缘 CDN、WAF、源站 Nginx 三处;没有统一的 request_id,串不起来;没人定义过”一次拦截”到底算什么。
- 月报的价值不在证明防护有用,而在让决策有依据:要不要加带宽、要不要升套餐、规则该不该收紧。
- 顺序不能反。先定口径再统计,反过来就要重做三遍。定口径只要一张纸:数据源、去重方式、计数单位、统计时段,四个字段写清楚。
Q:一份月报固定放哪几块数据?
- 四块,缺一块就会被人从缺口反问:
- 拦截量——这个月发生了什么。
- 误封率——防护的代价有多大。
- 可用性与业务指标——业务到底受没受影响。
- 成本——为这件事花了多少钱。
- 每块只放 2~3 个指标。超过五个就没人看了,而老板只看第一页。
- 只报拦截量,会被问”拦了这么多为什么还是慢”;只报可用性,会被问”防护费花在哪”。四块互相支撑,才能闭合。
Q:拦截量怎么统计才经得起追问?
- 先声明三件事:数据源、去重方式、计数单位(请求数 / 独立 IP / 连接数,三者差一个数量级)。
- 关键坑:边缘拦掉的请求根本不会到达源站。把 CDN 日志的拦截数和源站日志的 403 相加,等于重复计数。以边缘为准,源站只做交叉验证。
- 第二个坑:被 CDN 缓存命中的请求不产生回源,不能算进”源站压力”。谈压力就只谈回源 QPS。
- 没有 request_id 就按时间秒 + 客户端 IP + URI 三元组去重,能削掉大部分重复。
# 让每条日志都带上可追溯字段,月报才有原料
log_format waf '$time_iso8601\t$remote_addr\t$host\t$request_method\t'
'$request_uri\t$status\t$request_time\t$body_bytes_sent\t'
'$upstream_cache_status\t$request_id\t$http_user_agent';
# 按月统计被拦请求的 Top 来源(403 / 429 视为拦截)
zcat /var/log/nginx/access-2026-10-*.log.gz \
| awk -F'\t' '$6==403 || $6==429 {c[$2]++} END {for (i in c) print c[i], i}' \
| sort -rn | head -20
# 统计拦截总量与独立 IP 数(两个口径都要报)
zcat /var/log/nginx/access-2026-10-*.log.gz \
| awk -F'\t' '$6==403 || $6==429 {n++; ip[$2]} END {print "requests:", n, "unique_ip:", length(ip)}'
Q:误封率的分母到底是什么?
- 两种算法,选一种写清楚,全年不要换:按请求算 = 误封请求数 ÷ 拦截请求数;按 IP 算 = 误封 IP 数 ÷ 拦截 IP 数。
- 两者能差好几倍。按 IP 算通常更低,因为肉鸡 IP 每个只发少量请求,容易把分母做小、把比率做漂亮。
- 分子从哪来?两个来源互补:客户投诉工单(真实但漏报严重,多数用户被拦一次就走的)+ 每天随机抽 100 条被拦请求人工复核(补漏报)。
- 抽样要留样本编号和复核结论,否则这个数字没有依据,一被追问就崩。
- 经验线:按请求口径,1% 是红线。超过就要回头调阈值,而不是在月报里解释。
# 每天抽 100 条被拦请求做人工复核,输出成清单
zcat /var/log/nginx/access-2026-10-30.log.gz \
| awk -F'\t' '$6==403 || $6==429' | shuf -n 100 \
> /tmp/review-2026-10-30.tsv
# 复核后回填结论列:true_attack / false_positive
# 误封率 = false_positive 条数 / 复核总条数,再乘上当日拦截量做区间估计
Q:可用性和业务指标怎么放进去?
- 可用性按探测算,不按”有没有人投诉”算:1 分钟探测一次,连续 3 次失败计为不可用分钟,月可用性 = (总分钟 − 不可用分钟) ÷ 总分钟。
- 探测点至少三个:一个走 CDN、一个直连源站、一个走移动网络。三个点表现不一致,正好说明问题出在哪一层。
- 业务侧放三个数就够:下单/注册成功率、P95 响应时间、客服工单量。技术指标解释不了的事,业务指标能解释。
- 攻击期间”正常请求成功率”比”拦截率 99.9%”有说服力得多。后者只是说明拦得多,前者才说明业务没死。
Q:成本怎么算才说得清?
- 拆四类:带宽(峰值 Mbps × 单价 × 天数)、防护套餐(固定月费 + 超额清洗费)、人力(值班工时 + 应急加班)、业务损失(不可用分钟 × 每分钟营收)。
- 只有前两类是账面支出。老板真正在意的是后两类——那才是没进报表的隐性成本。
- 把总额换成单次攻击成本(本月总支出 ÷ 有效攻击次数),比报一个六位数总额更容易被接受,也方便和”买不买更高档防护”做对比。
- 带宽成本一定要写清是峰值计费还是95 计费。被 CC 打出来的尖峰,在峰值计费下会顶到整月账单上。
Q:给不同人看,版本要怎么改?
- 老板版一页纸:四块各一个数 + 一句结论 + 一个明确请求(要钱、要人、还是要授权)。
- 技术版附全量指标和规则命中明细,给同行或外部顾问看,重点是”规则有没有打架”。
- 财务版只要求账单对得上,附计费口径说明和超额部分的计算过程。
- 客户/合作方版只给可用性承诺,不给攻击细节。把防御状况、阈值、拦截规则讲给外部,等于免费提供情报。
Q:图怎么画才有信息量?
- 四个够用:双轴趋势图(左轴拦截量、右轴回源 QPS,两条线背离的位置就是关键节点)、Top 攻击源按 ASN 不按 IP(按 IP 全是肉鸡,看不出团伙)、规则命中帕累托图(哪几条规则干了 80% 的活)、可用性热力图(按小时 × 按天,一眼看到凌晨被打的规律)。
- 别用饼图,别用 3D,别把控制台截图当图贴上去——截图既没法对比,也没法追溯。
- 趋势图要有基线带:把过去 90 天的同一时段均值画成浅色区间,本月曲线是”超出基线”还是”正常波动”,不用文字解释。
Q:哪些写法会被一眼打回?
- 只报绝对值不比基线:本月拦了 800 万次,上月 300 万次,看起来涨了 167%,但业务量也翻了一倍——不除基线,这组数字是废的。
- 拦截率高但体感差:99.99% 的拦截率,拦的多是静态资源扫描,动态接口一个没拦住。月报要按”接口类型”拆开看。
- 数字和账单打架:拦截量按请求算、带宽按流量算,两个口径混在一页纸上,财务一对就出问题。
- 误封率突然变好看:多半是分母偷偷换了算法,或者抽样停了。
- 写”已全部拦截”:一次被打脸,后面十二个月的月报都没人信。
Q:还有什么补充建议?
- 月报固定加一栏“下月计划”,只写三条:要调的阈值、要补的规则、要买的东西。没有这一栏,月报就只是记账,不产生任何决策。
- 数据至少留 12 个月,同比才有意义。只留三个月,永远只能做环比,而环比的季节性噪音极大。
- 能自动化的部分全部自动化:一条 cron 拉日志、一个模板出草稿,人只负责写结论。手抄数据是月报质量崩坏的第一步。
- 反常识的一条:拦截量突然下降不一定是好事,很可能是攻击者换了手法绕过去了。要同时看回源 QPS——拦截量掉了但回源涨了,说明防线被穿过去了,这比攻击本身更值得写进月报。