hxreborn/ddg-tenor-bridge

GitHub: hxreborn/ddg-tenor-bridge

一个将 DuckDuckGo 图像搜索结果转换为 Tenor v2 API 格式的桥接服务,让 Gboard 的 GIF 标签页返回未经审查的搜索结果。

Stars: 1 | Forks: 0

# ddg-tenor-bridge 以 Tenor 的 v2 响应格式提供 DuckDuckGo 图像搜索服务,从而让 Gboard 的 GIF 标签页能够返回无审查的结果。 ## 工作原理 其工作原理是通过一个单独的标志,将 Tenor 的搜索 URL 替换为本服务的 URL。Gboard 会将该标志 `tenor_server_url_search_v2` 持久化到设备上的 shared-prefs 文件中,并按以下顺序优先选取已设置的最高层级: ``` HERMETRIC_OVERRIDE > OVERRIDE > OEM > MANAGED_CONFIG > PHENOTYPE > SYSTEM_SETTING > DEFAULT ``` 写入该文件会设置 `OVERRIDE` 层级,其优先级高于 `PHENOTYPE`,因此服务器下发的配置无法覆盖它。该值没有进行证书绑定或主机验证,因此任何具有公开受信任证书的 HTTPS URL 都可以生效。 这仅会覆盖搜索 URL 标志。API 密钥标志保持不变,因此分类、趋势、自动补全和精选功能仍可继续正常请求真实的 Tenor。 ## 安装说明 ### 1. 运行该桥接服务 ``` PORT=8787 node server.js ``` 如果需要使其在重启后依然保持运行,请使用 PM2: ``` pm2 start server.js --name ddg-tenor-bridge --time pm2 save pm2 startup ``` 或者使用 `deploy/ddg-tenor-bridge.service` 中的 systemd unit: ``` systemctl enable --now ddg-tenor-bridge ``` ### 2. 通过 HTTPS 将其公开暴露 Gboard 内置了 `usesCleartextTraffic="false"` 设置,即使是 localhost 也会拒绝明文 HTTP 请求。Cronet 同样会拒绝自签名证书。因此必须使用公开受信任的证书。 我认为 Cloudflare Tunnel 是此处最省力的方案。它仅使用出站连接,因此无需进行端口转发,也无需管理源站证书。源站 IP 永远不会暴露。 ``` cloudflared tunnel login cloudflared tunnel create ddg-tenor-bridge cloudflared tunnel route dns --overwrite-dns ddg-tenor-bridge gif.example.com ``` `~/.cloudflared/config.yml`: ``` tunnel: credentials-file: /root/.cloudflared/.json ingress: - hostname: gif.example.com service: http://localhost:8787 - service: http_status:404 ``` ``` cloudflared service install systemctl enable --now cloudflared ``` 任何拥有有效证书的主机都可以替代该隧道。 ### 3. 将 Gboard 指向该服务 请务必在强制停止 Gboard 之前写入覆盖文件,因为正在运行的实例会在重启时使用其内存中的偏好设置覆盖该文件。强制停止产生的 `SIGKILL` 信号使其根本没有机会将偏好设置写回,因此覆盖配置得以保留,并在下次启动时加载。 ``` adb shell su -c 'cat > /data/data/com.google.android.inputmethod.latin/shared_prefs/flag_override.xml' <<'EOF' off https://gif.example.com/v2/search EOF adb shell su -c 'chown u0_a220:u0_a220 /data/data/com.google.android.inputmethod.latin/shared_prefs/flag_override.xml; chmod 660 /data/data/com.google.android.inputmethod.latin/shared_prefs/flag_override.xml' adb shell su -c 'am force-stop com.google.android.inputmethod.latin' ``` `u0_a220` 是 Gboard 的 uid。请先获取你设备的 uid:`adb shell su -c 'stat -c %U /data/data/com.google.android.inputmethod.latin'` ## 预期行为 这是一个随时可能失效的概念验证(PoC)。由于 DuckDuckGo 没有贴纸搜索功能,贴纸搜索会直接代理请求至 Tenor。除此之外,格式来自 `flags` 数组:空值对应 `tinygif`,`sticker` 对应 `gif_transparent`。 结果会过滤出动态 GIF,并丢弃视频封装格式。 该覆盖配置在设计上能够经受住 Gboard 更新。只有崩溃恢复机制会将其清除:如果莫名其妙地回退到了 Tenor,重新应用该文件即可。 DuckDuckGo 的 endpoint 未公开记录且不稳定,随时可能更改或触发速率限制。数据中心 IP 会受到验证挑战,因此请在一个拥有干净出口 IP 的地方运行此服务。Cloudflare Workers 行不通:workerd 会覆盖出站的 `User-Agent`,从而破坏 token 交换过程。 这是一个通用的网络索引:部分结果指向的 hosts 会阻止盗链从而导致加载失败。标志名称也与特定版本相关,在 17.x 版本中保持稳定,但无法保证在此之外依然适用。 ## 许可证 GPL-3.0。详见 [LICENSE](LICENSE)。
标签:Android逆向, API代理, GNU通用公共许可证, MITM代理, Node.js, Web中间件, 工具, 网络隧道, 自定义脚本