跳到主要内容
一个连 favicon 都不拉的客户端

一个连 favicon 都不拉的客户端

钻牛角
钻牛角

· 阅读约 4 分钟

半夜四个报警,两个数据库争用、一个读副本失败、一批 metrics 神秘空白。我先翻部署日志和 diff,翻了几遍啥也没解释。哎。prod-api 和 prod-web 在同一分钟从 3.6K 涨到 17-18K。这哪是部署,这是外部流量变了。

这头牛,我今天非钻穿不可。到底什么流量。

先按 script/hour 拉了个表:

script_name  hour    invocations
prod-api     00:00Z   3,614
prod-web     00:00Z   3,597
prod-api     01:00Z  18,492
prod-web     01:00Z  17,238

两个 worker 同刻×5。D1 主库单线程,读数从 15-28K/hr 涨到 37-46K/hr,超过那 36K 天花板。下游队列堵了,拒绝、副本错误、空 metrics 全是它。三个看起来互不相干的症状,其实是同一个下游卡住之后的三种投影。

我一开始还心存侥幸,猜是不是新上的功能埋了雷。结果 50 秒 live tail 抓 187 个请求,一眼就精神了:

prod-web · live tail · 50s · 187 requests

155 requests:
  ASN: one hosting provider
  IPs: at least 8 addresses
  Geo: single country
  UA: Chrome/121 · Chrome/122 · Chrome/123 · Chrome/124 · Chrome/125 · macOS build
  Path: /jobs/{id} × 152, /companies/{slug} × 29
  Asset requests: 0
  robots.txt: 0
  CSS/JS/font/favicon: 0

155/187 来自一个托管商 VPS 段,至少八个地址,同一个国家。UA 转了五个 Chrome 版本,再加个 macOS 版,没一个 bot UA。你说气不气,装得挺像人。可下一页日志就露馅了:零 CSS、零 JS chunk、零字体、零 favicon——一个真实浏览器不可能不拉这些东西。robots.txt?人家从头到尾没要过,你加不加都一样。它只打 /jobs/{id} 和 /companies/{slug},按 ID 顺序,每秒四页,节奏稳得跟节拍器似的,像一个不用眼睛的客户端在翻目录。

这个破绽,是我见过的爬虫里最没法遮的。UA 能轮换,IP 能买,可不请求静态资源的客户端……要么它压根不渲染,要么它就根本是个脚本。日志里这信号现成的、白捡的。伪造它?得跑一整个 headless 浏览器把每页都 load 一遍,你猜它们舍不舍得花这个成本?舍不得。我自己做 job 爬取的时候,恰好认得这种只拉 HTML、忽略 CSS 的客户端——省钱版爬虫,就这点格局。

顺带说一嘴,盲扫器也这毛病:零静态资源。区别是盲扫器 404 一大堆,因为它乱猜 .env、phpinfo、.git/config;定向爬虫 404 极少,人家只走真实存在的 URL,一步一步扒。这表我顺手列了:

流量404 率静态资源请求特征
真实用户低正常HTML + CSS + JS + font + favicon,顺序合理
盲扫器极高零乱猜路径,扫完就走
定向爬虫极低零按 URL 族有序遍历,速度稳定

看到了吧,零静态资源是这两条枝的共同根。有个做静态站的朋友发我看他的 DDoS 面板:458 个放行、2.0k 个阻止、3.6k 个挑战。放行的那 458 个里,相当一部分是 AWS 来探 .env、phpinfo、.git 的,一个样式表都没拉。

看到这种流量,第一反应是加缓存——长 TTL、边缘缓存、stale-while-revalidate。我一开始也往这想。推一把就发现没戏。这俩 URL 族里几十万个不同 ID,每个请求都是首访,第二次永远不会来。缓存白等,除了多一跳没别的用。你不可能缓存一个从不重放的东西。

所以最后只能限流。但不按 UA 限——UA 是攻击者换着玩的,你今天封 Chrome/124,它明天上 Chrome/126。按 ASN 或 IP 前缀限。网络路径它改不掉,这才是它的真身份。后来跟一个做反爬的朋友捋了个更细的方案:先拿资产请求比例做免费预筛——每个 IP 的静态资源占比短窗口里不达标的先限;真拿不准的再花钱查信誉源,两个独立源都说是机房 IP 才判死;然后 /24 块按邻居中已标比例分级,低于 10% 只限单 IP,过 30% 整块限。每天重算一回就够,粗带宽,小漂移翻不了天。

还有个闷亏:verified-bot 字段,我以为能直接查,结果在我们这个 plan 上是 enterprise 才有的。早知道就省二十分钟——我卡在那翻订阅页面,不是翻代码。

还有两个工具教训想写下来。算了,今天先到这,下次再补。

最后,扯个跟这事半毛钱不着的——半夜盯着 live tail 看,突然想到以前抓包抓到过一个只拉 HTML 的省钱客户端,当时觉得这行为挺聪明。现在站防守这边,发现省钱的另一面就是好认。其实哪有什么藏得好,只有懒得看。嘿嘿,下次见。

钻牛角
钻牛角

逮住一个前端小知识点挖到底:现象→实验→兼容性表格→闲聊,配 demo 玩梗。

查看主页 →