指南

不用 CAPTCHA 识别机器人:什么才真正有效

为什么验证不再是一道防线、哪些信号取代了它,以及一套诚实的无感识别方案在实践中是什么样子。

验证在被弃用之前,就已经失效了

CAPTCHA 是一种测试,它假定解题对机器昂贵、对人便宜。这个假设的两半都已经垮掉了。

如今对机器来说解题很便宜。商业打码服务通过 API 接收一道验证并返回令牌,按千次计价,而真正盯上你站点的人早就把这一项列进了预算。机器视觉在完全没有人工介入的情况下就能处理大多数图片九宫格。

而对人来说解题不再便宜。九宫格之所以变难,恰恰是因为机器变强了,于是成本落到了你的客户身上,而不是攻击者身上。在结账环节,这个成本可以用被放弃的订单来衡量。

所以验证如今成了一项针对真实用户的税,而一个有决心的机器人只需花几分之一美分就能绕过。这就是另寻他法的全部理由。

取而代之的是:信号,而非测试

无感识别不再要求访客证明什么,转而读取会话本就在告诉你的东西。三个层面承载了绝大部分信号。

行为层。会话与页面的交互方式——指针移动的形态、事件之间的节奏、焦点在表单里移动的方式。自动化产生的分布与人类不同,而且它越是努力装得像人,差异反而越明显。

传输层。TLS 握手和 HTTP/2 设置描述了客户端技术栈。一个 JA3 或 JA3N 指纹会告诉你是哪个库发起了这次连接;即便是驱动真实 TLS 栈的无头浏览器,宣告出来的组合仍然不是 Windows 上真正的 Chrome 会产生的。这比 user-agent 字符串难伪造得多,因为它要求复刻一个真实客户端的加密栈,而不是改一个请求头。

信誉层。这个地址此前做过什么——在你的站点上,以及(可选地)在别人的站点上。判断一个地址,不只看眼前这一次会话。

没有哪一层是够用的。对于一落地就立即提交的会话,行为信号很稀薄;传输层指纹被所有使用同一个库的人共享,包括合法的那些;而一个地址第一次出现时,信誉是空白的。判定来自三者的结合。

值得了解的失效模式

任何诚实的无感识别介绍,都会写清它会在哪里出错——因为这些失误比 CAPTCHA 的更安静,也因此更容易被漏掉。

  • 注重隐私的真实用户看起来像自动化。有人用高度加固的浏览器经 VPN 访问,会产生稀薄的行为信号和不寻常的指纹。你的放行名单正是为此存在的,而且必须真的去维护它。
  • 共享出口地址。企业 NAT、移动运营商的 CGNAT 和 VPN 出口,会把成千上万互不相干的人放在同一个地址后面。这类地址上的信誉必须区别加权,否则你会因为某人网络里的一个人跑了爬虫,而封掉整家公司。
  • 看起来很坏的好机器人。你的支付服务商的 webhook 重试、你的可用性监控、合作方的对接——全是自动化的,也全是必需的。它们该在拦截开启之前进入放行名单,而不是等到有人报故障之后。
  • 第一次出现。一个全新的地址没有历史。这正是共享封禁名单的用武之地,也正是为什么一个只做信誉、不做会话分析的系统在第一天很脆弱。
  • 无声的漂移。CAPTCHA 坏了是很吵的。而一个已经悄悄开始放过某种新机器人模式的检测器,看起来和一个安静的星期没有区别。请盯住拦截率与流量的比值,而不只是仪表盘上的可用性。

一套站得住脚的方案是什么样

按每一步对结果的决定性程度排序。

从观察模式开始。在关闭拦截的状态下运行足够久,看到一个完整的周周期,包括你最安静的夜晚和最忙碌的一次促销。你要找的是那些与你已确知为真的事实相矛盾的判定。

在开启拦截之前填好放行名单,而不是之后。支付 webhook、监控、合作方对接、你自己的办公网段,以及你希望收录你的爬虫。这是人们会跳过、然后在凌晨三点发现的一步。

在网关上执行,而不是在页面里。在 JavaScript 中施加的决定,是攻击者可以跳过的决定。拦截该发生在请求被响应的地方。

对平台失效开放,对你自己的规则失效关闭。如果判定服务不可达,流量应当放行——一次把你站点一起拖垮的故障,比一个漏网的机器人更糟。你自己的拒绝名单则不同:那是你的明确指令,应当继续生效。

让判定保持可解释。当有人对一次拦截提出异议时,你需要看到是哪些信号导致了它。一个只返回数字的系统,会让你在客户面前无话可说。

Karma 处在什么位置

Karma 就是把这套设计做成了产品:一个异步代码片段,行为与传输层信号经 TLS 送往采集端,判定基于你自己的租户信誉库做出,并且——如果你选择加入——还有一份由其他租户所见汇聚而成的共享封禁名单。

拦截发生在你的网关上,决定会在本地缓存,因此采集端的一次故障不会把你的站点一起拖垮。你的放行与拒绝名单始终高于平台判定。

免费的 Detect 套餐就是观察模式:每月 25,000 次判定,永久有效,无需绑卡,也不执行拦截。它正是上面描述的那套方案,而且无论你最终选择什么,这都是正确的起步方式。

FAQ

不用 CAPTCHA 能识别机器人吗?
能,而且这已是主流做法。无感识别读取会话的行为信号、来自 TLS 握手与 HTTP/2 设置的传输层指纹,以及地址的信誉,然后在不向访客提问的情况下做出判定。什么都不显示,因此不存在会流失真实客户的漏斗环节。
CAPTCHA 对机器人还有效吗?
远不如其部署规模所暗示的那样有效。商业打码服务通过 API 返回令牌,只需几分之一美分,而机器视觉无需协助就能处理大多数图片九宫格。这道验证已经变成一项主要由真实用户承担的成本,而真正要紧的攻击者只把它当作一笔小小的开支。
什么是 TLS 指纹,它为什么有用?
TLS 握手会暴露一组有序的密码套件、扩展和曲线,其组合随客户端库而异——归纳为一个 JA3 或 JA3N 哈希。它标识出发起连接的技术栈,于是一个自称 Chrome 却使用 Python TLS 库的脚本便无所遁形。它比 user-agent 难伪造得多,因为那要求复刻真实客户端的加密栈,而不是改一个请求头。
无感机器人识别有什么风险?
主要是对看起来像自动化的真实用户的误判——加固浏览器、VPN 与 CGNAT 出口——以及对支付 webhook、监控之类好机器人的误判。两者都靠一份在开启拦截之前就填好的放行名单,以及一段足以覆盖完整周流量周期的观察期来管理。