OpenClaw + OpenAI Codex OAuth 代理问题解决

一次 OpenClaw 连接 OpenAI Codex OAuth 的代理排障记录:Node.js 原生 fetch、fetchWithSsrFGuard、环境变量代理与 DNS pinning。

折腾了一晚上,各种方案都试了,最后发现根子不在系统代理,也不完全在 Node.js,而在 OpenClaw 的 OAuth token exchange 调用没有显式启用环境变量代理。

结论先放前面:OpenClaw 的 fetchWithSsrFGuard 默认是 STRICT 模式,不会自动读取 HTTP_PROXY / HTTPS_PROXY 这会导致 https://auth.openai.com/oauth/token 这个请求直接裸连,在受限网络环境里自然会失败。

现象

执行 OpenAI Codex OAuth 登录:

1
HTTP_PROXY=http://127.0.0.1:7890 HTTPS_PROXY=http://127.0.0.1:7890 openclaw models auth login --provider openai-codex

系统层面的代理是通的,浏览器和 curl 也没问题,但 OpenClaw 在 OAuth 回调后的 token exchange 阶段失败。

一开始很容易以为是 Node.js 22 原生 fetch() 不走代理的问题。这个判断不算错,但还不够具体。真正影响这次调用的是 OpenClaw 自己封装的 fetchWithSsrFGuard

试过但没用的方案

方案失败原因
NODE_OPTIONS="--require proxy-fix.js" + undici ProxyAgentpreload 无法稳定影响 fork 出来的子进程
socks5 代理原生 fetch 不认 socks5 环境变量
global-agent bootstrap对 Node.js 原生 fetch 无效
手动 curl 换 tokenPKCE verifier 在进程内存里,外部拿不到
proxychains需要额外安装和 sudo,不想把问题复杂化

这些方案都在外围绕圈。真正应该看的,是 OpenClaw 代码里这次请求到底怎么发出去的。

根本原因

问题集中在 OAuth token exchange:

1
https://auth.openai.com/oauth/token

OpenClaw 内部调用 fetchWithSsrFGuard 时,带了类似这样的审计上下文:

1
auditContext: "openai-codex-oauth-token"

但没有传:

1
proxy: "env"

也就是说,即使外部设置了:

1
2
HTTP_PROXY=http://127.0.0.1:7890
HTTPS_PROXY=http://127.0.0.1:7890

这次请求也不会自动走代理。

更坑的是,fetchWithSsrFGuard 还有 DNS pinning 相关保护。要允许环境变量代理,需要同时传:

1
dangerouslyAllowEnvProxyWithoutPinnedDns: true

所以根因可以拆成三层:

  1. Node.js 22 原生 fetch() 默认忽略 HTTPS_PROXY / HTTP_PROXY 环境变量
  2. OpenClaw 的 fetchWithSsrFGuard 默认使用 STRICT 模式,不走代理
  3. OAuth token exchange 请求直连 OpenAI,被受限网络环境拦截

这不是单纯的 Node.js bug,更准确地说,是应用层代码没有为这个网络环境显式启用代理。

临时解决方案:改源码

我最后直接改了全局安装目录里的 OpenClaw 编译后文件。

先说明:这是临时补丁。升级 OpenClaw 后可能会被覆盖,最好还是等上游在 OAuth 流程里正式支持代理参数。

1
sed -i 's/auditContext: "openai-codex-oauth-token"/auditContext: "openai-codex-oauth-token", proxy: "env", dangerouslyAllowEnvProxyWithoutPinnedDns: true/' ~/.nvm/versions/node/v22.22.0/lib/node_modules/openclaw/dist/openai-codex-oauth-flow.runtime-DuvjIJqY.js

然后重新执行登录:

1
HTTP_PROXY=http://127.0.0.1:7890 HTTPS_PROXY=http://127.0.0.1:7890 openclaw models auth login --provider openai-codex

秒过。

关键点

  • OpenClaw 的 fetchWithSsrFGuard 支持 proxy: "env" 参数
  • OpenAI Codex OAuth token exchange 流程里没有传这个参数
  • 设置 HTTP_PROXY / HTTPS_PROXY 只是必要条件,不是充分条件
  • 在这个场景下,还需要 dangerouslyAllowEnvProxyWithoutPinnedDns: true 绕过 DNS pinning 限制
  • 这是 OpenClaw 代理适配的问题,不是 Node.js 自己能自动解决的问题

教训

代理问题最容易让人误判,因为它横跨系统环境、运行时、HTTP 客户端和应用封装。

这次最大的教训是:别只盯着环境变量,要看代码实际怎么发请求。

以后遇到类似问题,我会先做两件事:

  1. grep 目标域名或请求上下文,定位调用点
  2. 看 HTTP 封装是否显式支持代理、是否真的传了代理参数

很多时候,HTTPS_PROXY 设对了,请求还是裸连。不是代理没生效,而是应用层根本没打算读它。