反爬白名单怎么配?别把自家监控和回调拦了

反爬规则上线第一周,挂掉的往往不是爬虫,而是自家监控、支付回调和 CDN 预热。本文用 10 个问答讲清 反爬白名单 该放哪些机器、怎么防伪造、怎么定期回收。

Q:为什么反爬规则一上线,先出事的是自己人?

  • 五个高频事故,按发生频率排:监控拨测被判 CC、支付回调被 UA 黑名单拦、CDN 预热返回 403、SEO 工具抓不到页面、合作方接口 403。
  • 根因很简单:反爬规则的判断依据是”像不像人”,而机器流量天生不像人——没有 Referer、UA 不是浏览器、请求间隔均匀、路径固定。
  • 所以白名单不是人情放行名单,它本质是一份机器资产台账:谁在合法地自动化访问你,凭什么证明是它。
  • 没有这份台账,规则越严误伤越多,而误伤永远靠投诉发现——投诉天生滞后,订单静默失败的时候没人报错。

Q:哪些机器必须进白名单?

  • 四类必备:自建监控与拨测(含异地探针、Uptime 服务)、第三方回调(支付、短信回执、物流、IM webhook)、CDN 预热与刷新、合作方接口(开放平台、比价、ERP 对接)。
  • 三类加分项:自有漏扫与基线检查、备份同步任务、站长平台的抓取诊断工具。
  • 判断标准只有一句:它被拦了,会不会有人立刻来找你。会,就进名单;不会,就别进。
  • 反面清单同样重要:竞价排名工具、第三方采集器、免费”网站体检”服务——请求量大又行为像爬虫,不该给白名单。

Q:按 IP 放、按 UA 放,还是按密钥放?

  • 可信度排序:签名(HMAC)> 固定出口 IP > 自定义请求头 > User-Agent。UA 最容易伪造,单独用等于没做。
  • IP 也会漂移:云函数出口、K8s 集群 NAT、合作方换机房,都会让固定 IP 失效。
  • 工程折中:IP 段 + 自定义头双条件,两个同时成立才放行;安全要求高的回调再叠应用层验签。
# 1) 可信出口 IP(内网段 + 已登记的固定出口)
geo $trusted_machine {
    default          0;
    10.20.0.0/16     1;      # 内网监控与任务机
    198.51.100.11/32 1;      # 合作方专线出口
}

# 2) 内部令牌:与 IP 段同时成立才生效,单靠请求头不放行
map "$trusted_machine:$http_x_internal_token" $wl_pass {
    default              0;
    "1:9f2c7a41d8e35b60" 1;
}

# 3) 规则级联:白名单优先级最高,覆盖所有拦截判定
map $wl_pass $final_block {
    1  0;          # 命中白名单,强制放行
    0  $block;     # 其余走 UA / 频率 / 路径规则
}

Q:Nginx 里怎么落地,有哪些坑?

  • 顺序:白名单必须在所有 deny、limit_req、UA 判断之前生效。写在 location 里,会被上一层的 if 先拦掉。
  • limit_req 按 key 限速,白名单 IP 一样会被限。正确做法是给白名单一个宽松的桶,或者把它的 key 置空——key 为空时 nginx 不做限速。
  • allow/deny 是就近匹配,多份 include 会互相覆盖,务必保持单一来源。
  • 白名单请求也要打标记,否则永远不知道名单里谁在跑量。
# 白名单单独一个宽松桶:key 为空则不限速
map $wl_pass $limit_key {
    1  "";              # 空 key = 不做限速
    0  $binary_remote_addr;
}
limit_req_zone $limit_key zone=req_per_ip:20m rate=30r/s;

# 日志里带上白名单标记,便于后期审计
log_format wl '$time_iso8601\t$remote_addr\t$request_uri\t'
              '$status\twl=$wl_pass';

# 统计白名单流量占比(超过 5% 就该查名单了)
awk -F'\t' '{n++; if ($5=="wl=1") w++} END {printf "wl_ratio=%.2f%%\n", w*100/n}' access.log

Q:支付回调和 webhook 怎么既防伪造又不误拦?

  • 回调方 IP 往往不固定(多机房、多云),单靠 IP 白名单必然反复失效。正确分层:边缘只放路径,应用层才验真伪。
  • 边缘:给回调路径单独一个 location,不套 UA 黑名单和频率规则,但保留 body 上限与超时,防止它被当成放大器。
  • 应用层:HMAC 验签 + 时间窗(5 分钟)+ 事件 ID 幂等去重。三件事缺一个都可能被重放。
# 回调路径单独放行:不做 UA 判断,保留体积与超时约束
location = /pay/notify {
    client_max_body_size 64k;
    proxy_read_timeout 10s;
    proxy_pass http://backend;
    # 不写 limit_req,也不套 UA 黑名单
}

Q:CDN 预热和刷新为什么会被拦?

  • 预热请求的 UA 是厂商自己的,特征是”非浏览器 UA + 单路径 + 无 Referer”,正好命中反爬规则的三条特征。
  • 正确做法:向 CDN 厂商要预热节点的出口 IP 段,加进边缘白名单。只加 UA 不行,UA 谁都能写。
  • 刷新走 API 接口,一般不受影响;受影响的是预热和边缘回源校验。
  • 验证很直接:预热后 curl -I 看 x-cache。MISS 且 403,就是被自家规则拦了。
# 预热专用放行:IP 段来自 CDN 厂商公告,定期核对
geo $preheat_node {
    default 0;
    203.0.113.0/24 1;
}

# 验证预热是否真的进了缓存
curl -sI https://www.example.com/static/app.js | grep -i "x-cache\|age"

Q:白名单会不会变成后门?

  • 会,而且这是最容易被忽视的风险:一次应急加白忘了回收,三个月后它还开着。
  • 三条硬约束:名单文件独立(不混在业务配置里)、变更留痕(谁加的、为什么、到期日)、自动过期(文件名带日期,定时清理)。
  • 定期审计:90 天零命中的条目进待删清单,删之前先注释七天观察。
# 白名单文件命名为 partner-2026-12-31.conf,过期自动报出来
today=$(date +%F)
for f in /etc/nginx/whitelist/*.conf; do
  exp=$(basename "$f" .conf | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}')
  if [ -n "$exp" ] && [[ "$exp" < "$today" ]]; then echo "EXPIRED: $f"; fi
done | tee -a /var/log/whitelist-expired.log

# 每周统计零命中的白名单条目(c=1 的基本可以清)
zcat /var/log/nginx/access-*.gz | awk -F'\t' '$5=="wl=1" {c[$2]++} END {for (i in c) print c[i], i}' | sort -n | head -20

Q:怎么验证白名单真的生效?

  • 四个拨测缺一不可,少一个就有盲区:白名单 IP + 正常请求预期 200;非白名单 IP + 同请求预期 403 或 429,证明规则本身没失效。
  • 白名单 IP + 恶意 UA 预期 200,这是特性不是 bug,但要知道边界在哪。
  • 带签名但非白名单 IP,按设计意图判断,多数回调场景应该放行。
  • 用 curl --resolve 指定 IP 直连,绕过 DNS 和 CDN,避免测的是边缘而不是源站。
curl -s -o /dev/null -w "%{http_code}\n" --resolve www.example.com:443:198.51.100.11 \
  -H "X-Internal-Token: 9f2c7a41d8e35b60" https://www.example.com/health

Q:白名单流量占比多少算正常?

  • 一般站点 2% 以内;超过 5%,要么业务真有大量机器流量,要么名单被滥用。
  • 要按类型拆开看:监控类应平稳,回调类随订单量波动,预热类集中在发布时段,合作方类取决于对接深度。
  • 一个反直觉信号:某个合作方的调用量突然翻几倍,多半不是业务涨了,而是对方把你的接口当数据源在批量抓。

Q:还有什么补充建议?

  • 把白名单变更和防火墙放行放在同一等级管理:走审批、留记录、有到期。低门槛加白,等于给自己留后门。
  • 白名单不等于不限速。给一个宽松的桶,别给”无桶”,否则一台被入侵的白名单机器能直接把源站打满。
  • 出口 IP 变更要有通知机制。在对接文档里写清”IP 变更需提前 7 天书面通知”,比事后排查省十倍力气。
  • 反常识的一条:反爬做得越狠,白名单治理越重要。真正让业务出事的往往不是漏拦了爬虫,而是把自家支付回调拦成 403,订单静默失败还没人告警。