人工智能抓取者一直在欺凌互联网,让其被遗忘,而我们对此无能为力。当您要求行为良好的机器人向您的robots.txt
添加条目(即使它们应该理解通配符背后的意图)或阻止其用户代理时,它们会软化。
大多数人工智能抓取工具的行为都不好,它们会忽略你的robots.txt
,忽略你的User-Agent
块,并忽略你的X-Robots-Tag
标头。他们会刮掉你的网站,直到它倒塌,然后他们会继续刮掉它。他们会点击每个链接上的每个链接一遍又一遍地查看相同的页面。他们中的一些人甚至会在同一秒内多次点击同一个链接。这是疯狂且不可持续的。
我对此感到厌倦,并制作了一个工具来永远阻止他们。我称之为阿努比斯。 Anubis 使用 sha256 工作证明挑战来权衡您连接的灵魂,以保护上游资源免受爬虫机器人的侵害。它是一种反向代理,需要浏览器和机器人解决工作量证明挑战,然后才能访问您的网站,就像Hashcash一样。
要测试阿努比斯,请单击此处。
如果您想使用 Anubis 保护您的 Gitea、Forgejo 或其他自托管服务器,请查看GitHub 上的说明。
如果您想购买 Anubis 的商业支持,包括无品牌或定制品牌版本(即没有快乐动漫女孩的版本),请与我联系。
阿努比斯的工作原理
Anubis 是一种中间人 HTTP 代理,要求客户端解决或已经解决工作量证明挑战,然后才能访问该站点。这是阻止最常见的 AI 抓取工具的一种非常简单的方法,因为它们无法执行 JavaScript 来解决挑战。可以执行 JavaScript 的抓取工具通常不支持 Anubis 所需的现代 JavaScript 功能。如果爬虫足够专注来解决挑战,阿努比斯会让他们通过,因为此时他们在功能上是一个浏览器。
Anubis 的实现方式最搞笑的部分是,它会通过包含“Mozilla”的用户代理触发每个请求的挑战。几乎所有 AI 抓取工具(和浏览器)都使用包含“Mozilla”的用户代理字符串。这意味着Anubis无需任何配置就能屏蔽几乎所有的AI爬虫。
这是否意味着您允许任何 AI 抓取工具简单地选择不在其用户代理字符串中添加“Mozilla”?
嗯,是的,但这只是极少数的人工智能抓取工具。他们中的大多数人希望以浏览器的形式出现,以绕过最基本的机器人保护,因为许多服务器对 User-Agent 字符串中的“Mozilla”存在可疑的逻辑。这有点像黑客,但它的效果比预期的要好得多。
在超高的层面上,Anubis 遵循了hashcash的基本思想。为了防止向受保护的服务发送大量请求,客户端需要解决需要一定时间计算但几乎可以立即验证的数学运算。答案作为签名的JWT令牌存储在 HTTP cookie 中,并且客户端随每个请求发送此令牌到受保护的服务。服务器通常会验证令牌的签名并允许其通过,但服务器也会随机选择令牌进行二次筛选。如果选择令牌进行二次筛选,服务器将验证工作量证明,并在一切检查无误的情况下允许请求通过。
挑战在客户端上存储一周,要求客户端每周解决一次新挑战。这是为了平衡解决挑战与保护服务器免受攻击性抓取带来的不便。
如果验证中的任何步骤失败,则 cookie 将被删除,并且客户端需要再次解决工作证明挑战。这是为了防止客户端重复使用已失效的令牌。
Anubis 还依赖于现代网络浏览器功能:
- ES6 模块加载客户端代码和工作量证明质询代码。
- Web Workers在单独的线程中运行工作证明挑战,以避免阻塞 UI 线程。
- 获取 API以与 Anubis 服务器通信。
- 用于生成工作量证明挑战的 Web 加密 API 。
这确保了浏览器相当现代,以对抗大多数已知的抓取工具。这并不完美,但这是一个好的开始。
这还将锁定禁用 JavaScript 的用户,阻止您的服务器在搜索引擎中编入索引,要求用户启用 HTTP cookie,并要求用户花时间解决工作量证明挑战。
这确实意味着使用纯文本浏览器或无法更新浏览器的旧机器的用户将被锁定在受 Anubis 保护的服务之外。这是一个我不满意的权衡,但这就是我们现在生活的世界。
血淋淋的细节
阿努比斯决定使用以下逻辑提出挑战:
- 如果客户端的用户代理不包含“Mozilla”,则允许客户端通过。
- 如果客户端没有带有有效 JWT 令牌的 cookie,则会向客户端提出质询。
- 如果 cookie 过期,客户端就会面临挑战。
- 如果客户没有被选择进行二次筛选,则允许客户通过。
- 如果选择客户端进行二次筛选,服务器将重新验证工作量证明,并在一切检查无误的情况下允许客户端通过。
当您被要求解决挑战时,系统会提供一个 HTML 页面。它引用作为 ES6 模块加载的 JavaScript 代码。服务器被要求提出质询,然后客户端对质询和随机数进行 SHA256 散列,直到散列具有一定数量的前导零。这是工作量证明的挑战。然后客户端将答案发送到服务器,服务器验证答案。如果答案正确,服务器会对 JWT 令牌进行签名,并将其通过 HTTP cookie 发送回客户端。然后,客户端将这个 cookie 随每个请求发送到服务器。
挑战是用户请求元数据的 SHA-256 总和。使用以下输入:
-
Accept-Encoding
:请求者支持的内容编码,例如gzip。 -
Accept-Language
:请求者希望服务器响应的语言,例如英语。 -
X-Real-Ip
:请求者的 IP 地址,由反向代理服务器设置。 -
User-Agent
:请求者的用户代理字符串。 - 当前 UTC 时间四舍五入到最近的一周。
- Anubis 私人 ED25519 密钥的指纹(校验和)。
这使用任何请求者已经发送的元数据形成请求者的指纹。它还使用时间作为输入,由于线性时间线的性质,服务器和请求者都知道时间。根据事实和情况,您可能希望向您的用户披露这一点。
Anubis 使用 ed25519 密钥对来签署挑战通过时发布的 JWT。 Anubis每次启动都会生成一个新的ed25519密钥对。目前,Anubis 实例之间无法共享该密钥对;但这将在未来的版本中得到解决。
设置阿努比斯
Anubis 旨在位于反向代理(例如 Nginx 或 Caddy)和目标服务之间。您保护的每项服务必须使用一个 Anubis 实例。
Anubis 包含在 Docker 镜像ghcr.io/xe/x/anubis:latest
中。可能存在其他安装 Anubis 的方法,但 Docker 镜像是目前唯一支持的方法。
Anubis 的系统要求非常低。我怀疑 128Mi 的 ram 可能足以满足大量并发客户端的需求。 Anubis 可能不太适合使用 WebSocket 并保持开放连接的应用程序,但我没有足够的实际经验来了解其中一种方式。
Anubis 使用这些环境变量进行配置:
环境变量 | 默认值 | 解释 |
---|---|---|
BIND |
:8923 |
Anubis 监听的 TCP 端口。 |
DIFFICULTY |
5 |
挑战的难度,或成功响应中必须包含的前导零的数量。 |
METRICS_BIND |
:9090 |
Anubis 为 Prometheus 指标提供服务的 TCP 端口。 |
SERVE_ROBOTS_TXT |
false |
如果设置true ,Anubis 将提供默认的robots.txt 文件,该文件按名称禁止所有已知的 AI 抓取工具,然后另外禁止每个抓取工具。如果事实和情况导致难以更改底层服务以提供此类robots.txt 文件,则这非常有用。 |
TARGET |
http://localhost:3923 |
Anubis 应将有效请求转发到的服务的 URL。 |
码头工人组成
将 Anubis 添加到指向您的服务的撰写文件中:
services : anubis-nginx : image : ghcr.io/xe/x/anubis : latest environment : BIND : ":8080" DIFFICULTY : "5" METRICS_BIND : ":9090" SERVE_ROBOTS_TXT : "true" TARGET : "http://nginx" ports : - 8080 : 8080 nginx : image : nginx volumes : - "./www:/usr/share/nginx/html"
库伯内斯
此示例做出以下假设:
- 您的目标服务正在侦听 TCP 端口
5000
。 - Anubis 将监听端口
8080
。
将 Anubis 连接到您的部署:
containers : # ... - name : anubis image : ghcr.io/xe/x/anubis : latest imagePullPolicy : Always env : - name : "BIND" value : ":8080" - name : "DIFFICULTY" value : "5" - name : "METRICS_BIND" value : ":9090" - name : "SERVE_ROBOTS_TXT" value : "true" - name : "TARGET" value : "http://localhost:5000" resources : limits : cpu : 500m memory : 128Mi requests : cpu : 250m memory : 128Mi securityContext : runAsUser : 1000 runAsGroup : 1000 runAsNonRoot : true allowPrivilegeEscalation : false capabilities : drop : - ALL seccompProfile : type : RuntimeDefault
然后为Anubis添加一个Service条目:
# ... spec: ports: + - protocol: TCP + port: 8080 + targetPort: 8080 + name: anubis
然后将您的 Ingress 指向 Anubis 端口:
rules: - host: git.xeserv.us http: paths: - pathType: Prefix path: "/" backend: service: name: git port: - name: http + name: anubis
如果您联系我并购买商业支持,则可以获得 RPM 软件包和无品牌(或定制品牌)版本。否则,您的用户每次解决挑战时都必须看到一个快乐的动漫女孩。这是一个特点。
结论
在一个公正的世界中,这个软件不需要存在。抓取机器人会遵循互联网的潜规则,不会抓取要求它们不要这样做的网站。但我们生活的世界并不公正,我们必须采取措施保护我们的服务器免受不良行为者的侵害。这就是我制作 Anubis 的原因,我希望它可以帮助您保护您的服务器免受不良行为者的侵害。
如果您遇到任何问题,请告诉我您的想法。