ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Anubis 中预编译 wasm2js 二进制:为禁用 WebAssembly 的客户端保留工作量证明的兼容性退路

Anubis 中预编译 wasm2js 二进制:为禁用 WebAssembly 的客户端保留工作量证明的兼容性退路 后端网络安全【免费下载链接】anubisWeighs the soul of incoming HTTP requests to stop AI crawlers项目地址https://gitcode.com/gh_mirrors/anubis4/anubis点击查看免费下载本文以仓库 utils/wasm/wasm2js/README.md 为主体结合wasm/scripts/下的构建脚本与web/js/前端运行时代码完整讲解 Anubis 为何、如何把 WebAssembly 工作量证明模块用 binaryen 的 wasm2js 编译为 JavaScript并将已知可用版本的 wasm2js/wasm-opt 二进制直接随仓库分发从而让禁用 WebAssembly 的隐私浏览器用户也能最终完成验证、正常访问被保护的服务。背景为什么 Anubis 的工作量证明选择 WebAssemblyAnubis 通过向客户端下发工作量证明Proof of Work挑战来过滤 AI 爬虫客户端需要在本地完成一次有难度的哈希计算默认算法为 argon2id可选 hashx 与 sha256服务端校验通过后才放行请求。为了让计算尽可能高效Anubis 将校验逻辑编译为 WebAssembly 模块并显式启用simd128扩展——SIMD 指令可以一次性处理多个数据元素让客户端最大限度利用 CPU 硬件能力从而以最快的速度完成计算让挑战页面尽快消失尽量缩短真实用户看到验证页的时间。这一设计在仓库中有完整的实现链路佐证Rust 侧的三个算法模块位于 wasm/pow/argon2id、wasm/pow/hashx、wasm/pow/sha256以及承载 PoW 导出的 wasm/anubis/src/lib.rs构建脚本 wasm/scripts/build_wasm.sh 会分别以RUSTFLAGS-C target-featuresimd128与不带该标志两种方式构建产出simd128与baseline两套模块分别写入 web/static/wasm/simd128 与 web/static/wasm/baseline两套模块还会经过 wasm-opt 按浏览器实际支持的指令集特性白名单重编码baseline_features-mvp --enable-sign-ext --enable-mutable-globals --enable-bulk-memory --enable-nontrapping-float-to-intsimd128 版在此基础上追加--enable-multivalue --enable-simd保证旧的、尚未实现新提案的引擎也能编译运行并让工具链升级后一旦引入白名单之外的特性就变成响亮的构建失败。问题隐私浏览器与 Lockdown Mode 会直接禁用 WebAssembly问题在于大量所谓的隐私浏览器privacy browsers、iOS 的锁定模式Lockdown Mode以及各种增强型 Web 隐私配置指南都会建议用户禁用 WebAssembly。其理由是 WebAssembly 可作为隐蔽的指纹识别与加密货币挖矿载体。后果是凡是无法或不愿执行 WebAssembly 的客户端都会被 Anubis 保护的服务事实上屏蔽de-facto blocked——不是服务拒绝它们而是它们根本跑不完验证逻辑。这与 Anubis让真实用户尽快通过的目标直接冲突。折中方案把 WebAssembly 模块编译回 JavaScript作为中间路线Anubis 将 WebAssembly 模块向下编译为 JavaScripta-la The Birth and Death of JavaScript 演讲中 Metal 的做法。这样校验逻辑至少能在客户端机器上运行起来。代价是性能大多数禁用 WebAssembly 的配置同时也会禁用浏览器的 JIT 引擎失去 JIT 后wasm2js 产出的 JavaScript 只能以解释执行的方式运行速度远低于原生 WebAssembly SIMD但关键点是它最终会跑完eventually finish。对用户而言只是等待更久而不是被彻底挡在门外。也就是说这是一条刻意的降级路径优先尝试高效的 WebAssembly含 simd128检测到不支持或不可用时退回到 wasm2js 生成的纯 JavaScript 版本。前端降级路径的运行证据前端算法入口 web/js/algorithms/index.ts 将argon2id、hashx、sha256统一映射到 wasm 路径而 wasm2js 降级路径由 web/js/algorithms/wasm2js.ts 实现它把 Worker 指向static/js/worker/wasm2js.mjs。Worker 本体 web/js/worker/wasm2js.ts 直接导入构建产物import * as argon2id from ../gen/wasm2js/argon2id.wasm.js; import * as hashx from ../gen/wasm2js/hashx.wasm.js; import * as sha256 from ../gen/wasm2js/sha256.wasm.js;并在 Worker 的 message 回调中按event.data.algorithm选择对应模块调用统一的导出接口anubis_work(difficulty, nonce, threads)完成计算随后把hash、difficulty、nonce通过postMessage回传给挑战页。这个接口签名与原生 WebAssembly 路径共用同一份类型定义 web/js/lib/wasm.ts 中的AnubisExports说明两条路径对上层完全透明。而检测逻辑在 web/js/lib/wasm-supported.ts通过尝试实例化一个最小 Wasm 模块魔数\0asm 版本号来判断WebAssembly是否可用并在不可用时抛出WASMUnsupportedError提示用户这不是 Anubis 的 bug请联系系统管理员。困境发行版自带的 wasm2js 版本过旧方向定了工具却出了问题。用于执行WASM 转 JS的工具是 binaryen 项目中的wasm2js。该工具被各 Linux 发行版收录进软件源而发行版打包的版本往往严重过时woefully out of date远达不到编译当前 Anubis WebAssembly 模块所需的版本要求。如果直接依赖系统自带的 wasm2js构建要么失败要么产出的 JS 无法正确运行——这就是 README 中这个文件夹的存在本身有点像是犯罪现场这句自嘲的由来为了让构建可用不得不把二进制文件塞进 Git 仓库。解决把已知可用的 wasm2js 二进制直接放进仓库README 给出的中间路径是用 WebAssembly 的形式把已知可工作的 wasm2js 版本随 Git 仓库一同分发连同用于构建它的脚本一起。这样任何环境哪怕没有装 binaryen、甚至没有安装 wasmtime都能复现构建。仓库中实际存放的预编译二进制为 utils/wasm/wasm2js/wasm2js_130.wasm 与 utils/wasm/wasm2js/wasm-opt_130.wasm版本号 130 对应 binaryen 130。README 还强调这些构建自 wasi-sdk v34.0-rc.2 起可逐字节复现byte-for-byte reproducible即任何人用相同工具链构建都会得到完全一致的产物这既便于审计也便于供应链信任。构建脚本如何优先使用仓库内的二进制实际的转换脚本位于 wasm/scripts/build_wasm2js.sh它按以下优先级选择 wasm2js 的运行方式run_wasm2js() { if command -v wasm2js 21 /dev/null; then echo wasm2js (sys) ${*} wasm2js $WASM2JS_FLAGS $* elif command -v wasmtime 21 /dev/null; then echo wasm2js (wasmtime) ${*} wasmtime run -W exceptionsy --dir . ./utils/wasm/wasm2js/wasm2js_130.wasm $WASM2JS_FLAGS $* else echo wasm2js (wazero-exec, slow) ${*} go run ./utils/cmd/wazero-exec ./utils/wasm/wasm2js/wasm2js_130.wasm $WASM2JS_FLAGS $* fi }即系统 wasm2js如果 PATH 中存在优先使用但版本风险自负wasmtime 运行仓库内二进制用 wasmtime 直接执行仓库自带的wasm2js_130.wasm并通过--dir .挂载当前目录供其读写文件wazero-exec 兜底如果连 wasmtime 都没有则用go run ./utils/cmd/wazero-exec以纯 Go 的 wazero 运行时执行同一个 wasm 二进制。第三条路线的实现见 utils/cmd/wazero-exec/main.go它用 wazero 创建运行时启用CoreFeaturesV2及异常处理、extended-const、尾调用等实验特性挂载 WASI preview1把当前工作目录映射为/并将宿主环境的 stdin/stdout/stderr 与参数透传给 wasm 程序——这样即使目标机器上没有任何 Wasm 工具链只要装了 Go 就能跑通整个构建。同样的兜底策略也用于 wasm-optwasm/scripts/build_wasm.sh 中的run_wasm_opt它同样会优先系统 wasm-opt然后回退到wasmtime run或wazero-exec执行 utils/wasm/wasm2js/wasm-opt_130.wasm。转换参数与产物后处理build_wasm2js.sh中固定的转换参数值得逐一拆解源码注释与 README 之外以下为脚本内实际使用的标志WASM2JS_VERSION130 WASM2JS_FLAGS-all --strip-debug --rse --rereloop --optimize-for-js --flatten --dce --dfo --fpcast-emu --denan --dealign --remove-imports --remove-unused-names --remove-unused-brs --reorder-functions --reorder-locals --strip-target-features --untee --vacuum -s 4 -ffm -lmu -tnh -iit -n它们共同的效果是输出完整的 JS-all、剥离调试信息--strip-debug、针对 JavaScript 执行环境做优化--optimize-for-js、--rereloop、--flatten、--reorder-functions、--reorder-locals等、删除不可达代码--dce、--vacuum以及对齐到较新的 stack IR 相关能力-s 4、-ffm、-lmu、-tnh、-iit。转换的输入是 baseline非 simd128模块目录 web/static/wasm/baseline输出写入 web/js/gen/wasm2js文件名形如argon2id.wasm.js。脚本还做了一处关键后处理wasm2js 输出的第 1 行会导入 anubis 宿主模块import { ... } from anubis之类脚本用 sed 将其替换为桩实现sed 1s$.*$const anubis { anubis_update_nonce: (_ignored) { } };$ ${output} ${tmp} mv -f ${tmp} ${output}即用空的anubis_update_nonce桩替换真正的导入让产物在浏览器里可以直接加载。代码注释还解释了为什么绕开sed -iBSD sed 会把下一个参数强制当作备份后缀而 GNU sed 不会跨平台写法有坑因此改用临时文件重写。增量构建与时间戳校验脚本借助 wasm/scripts/lib.sh 实现了增量构建用mtimes对 BSD/GNUstat的差异做了兼容取出源目录最新时间戳与产物目录最旧时间戳只有当产物齐全all_populated检查每个输出目录都至少有一个*.wasm.js且源文件不新于产物时才跳过构建避免每次全量重跑。局限与务实态度README 结尾的表述非常坦诚这条路希望能足够健壮地扛过现实但这种东西的功效往往只能吃一堑长一智。也就是说预编译二进制方案属于工程上的务实妥协性能必然劣化wasm2js 产物在禁用 JIT 的环境里只能解释执行最终会完成但远不如原生 WasmSIMD二进制需要随上游更新binaryen 发布新版本后仓库内的wasm2js_130.wasm/wasm-opt_130.wasm需要同步跟进以匹配 Rust 工具链生成的模块特性可复现性依赖特定 wasi-sdkREADME 明确以 wasi-sdk v34.0-rc.2 作为可逐字节复现的基准换工具链版本需要重新验证。小结一条可落地的降级兼容链路从仓库证据可以梳理出 Anubis 完整的兼容性策略wasm/powRust 源码→ wasm/scripts/build_wasm.sh产出 simd128 与 baseline 两套模块→ utils/wasm/wasm2js随仓库分发的 binaryen 130 工具链经 wasmtime / wazero-exec 兜底执行→ wasm/scripts/build_wasm2js.sh转换为web/js/gen/wasm2js/*.wasm.js→ web/js/worker/wasm2js.ts浏览器 Worker 中加载并计算→ web/js/main.ts挑战页提交 hash/nonce 完成验证。其中任何一环的工具缺失都被系统命令 → wasmtime → wazero-exec的三级回退吸收而任何禁用 WebAssembly 的客户端都被 wasm2js 的 JS 降级路径兜住。这正是 utils/wasm/wasm2js/README.md 这份文档背后完整的设计意图既不让真实用户被挡在门外也不让构建过程依赖任何一台机器的软件源。赞分享后端网络安全【免费下载链接】anubisWeighs the soul of incoming HTTP requests to stop AI crawlers项目地址https://gitcode.com/gh_mirrors/anubis4/anubis点击查看免费下载相关推荐GitHub_Trending/hi/highway的ABI兼容性跨编译器二进制接口保障GitHub_Trending/hi/highway的ABI兼容性跨编译器二进制接口保障 你是否在开发跨平台SIMD应用时遭遇过不同编译器生成的二进制文件无高性能计算WebAssembly二进制工具链终极指南5分钟掌握WABT预编译二进制部署WebAssembly二进制工具链终极指南5分钟掌握WABT预编译二进制部署 WebAssembly Binary ToolkitWABT是WebAsse开发工具WebAssembly编译器coreutils 的 gnu 预编译二进制不兼容时如何换用 musl 版本coreutils 的 gnu 预编译二进制不兼容时如何换用 musl 版本 uutils coreutils本仓库GitHub 推荐项目精选 / coCLI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表