你在国内想直接调境外大模型的接口,本地挂代理写代码很别扭,客户端里也填不了代理规则。这篇讲的是用 Cloudflare Workers 自己搭一层反代:它能做到什么、做不到什么,Worker 怎么建、代码怎么改、自定义域名怎么绑、哪些地方最容易白折腾一场。全程只讲步骤和判断标准,不给任何保证,配好的效果以你本地实测为准。
先说清楚这层反代能解决什么、不能解决什么
反代这层东西,说白了就是在你和境外 API 中间加一个你自己能控制的域名。客户端不再直接连境外地址,而是连你这个域名,由它把请求转出去、把结果带回来。它能帮你解决的,主要是那些客户端不让你配代理、只认一个固定 Base URL 的场景,以及你希望所有请求都从同一个入口走、方便自己统计和切换上游的情况。
| 它能搞定 | 它搞不定 |
|---|---|
| 客户端不支持代理设置、只认固定 Base URL | 上游对你所在出口 IP 或地区的限制 |
| 把请求收敛到自己掌控的一个域名下 | 你账号本身的地区限制和风控判定 |
| 统一改上游地址时只动一处配置 | 链路物理延迟的下限,该绕的路一米都不会少 |
| 省掉自己维护一台服务器的运维成本 | 上游明确禁止经第三方转发的规则限制 |
有个常见误解要先破掉:反代不会让链路变快。请求还是从你这里出发,经过 Worker 所在节点,再到上游。中间多了一跳,通常只会持平或者略慢,不会凭空缩短物理距离。如果有人告诉你换个反代就能明显降延迟,那多半是他原来的直连路径本身有问题,不是反代的功劳。判断延迟到底怎么样,别信口口相传的说法,拿你自己的网络环境实测,或者到站内的延迟与可用性对比页去看当时记录下来的数字。
- 上游服务条款明确写了不允许经第三方转发:这种情况别硬上,换合规方案,账号出问题得不偿失
- 你自己的风控逻辑依赖客户端真实 IP:反代之后上游看到的是 Worker 的出口,你的判定依据就变了
- 你需要固定出口 IP 去配合上游白名单:Worker 的出口 IP 不固定,这条路走不通
- 你要传大体积文件或跑长时间流式连接:Worker 对请求体大小和执行时长有限制,先确认你的场景在不在限制内
- 适用场景
- 客户端无法配置代理、只能填一个固定接口地址的情况
- 不适用场景
- 上游禁止转发、或你依赖客户端 IP 做风控的情况
- 和自建服务器的分工
- Worker 免运维但受请求体大小和冷启动限制;大文件、长连接、固定出口 IP 走自建那条路
- 延迟预期
- 反代只做转发,不缩短物理距离,实测为准
- 出口 IP
- Worker 侧不提供固定出口,需要白名单的场景请另想办法
那什么时候应该干脆放弃 Worker 这条路?两个信号很明确:一是上游的使用条款里写明了不接受经第三方转发,二是你这边或者上游那边本身就是靠客户端 IP 来做风控判断的。这两类硬上,轻则请求被拒,重则账号受影响。这种情况不是配置问题,是方案选错了,换一条路更省事。反过来,如果你只是想让一堆不听话的客户端统一走一个地址,也不打算传大文件、不需要固定出口,那 Worker 这层轻量转发确实够用,具体限制参数到站内对应的教程与限制说明页去核对当时的数字。
动手前要准备的东西
这一节只讲准备清单,不做任何配置。准备不齐就动手,最容易卡在域名解析和鉴权头上,来回排查很浪费时间。先把下面几样东西攒齐,再开 Worker 编辑器。
- Cloudflare 账号
- 注册并完成邮箱验证,能进控制台看到 Workers 入口;免费计划就够跑一个反向代理。
- 一个可绑定的域名
- 最好已在这个账号下托管 DNS,加路由时能直接选;域名不在同一账号会多一步改 NS 或加 CNAME 的麻烦。
- 目标接口的鉴权口径
- Key 放在哪个请求头、路径前缀保不保留、是否区分流式与普通响应,这些决定了转发逻辑怎么写。
- 一台能跑的本地环境
- 浏览器加命令行就够,用来 curl 验证 Worker 是否透传成功,以及记录延迟基线。
- 把域名挂到同一账号进 DNS 面板确认该域名的 Nameserver 已指向 Cloudflare,状态是已激活。验证方法:添加一条测试子域记录,能正常解析就说明路由可以绑上去。
- 核对官方路径与鉴权头到 /official-api 找目标模型对应的接口说明,抄下基础路径、Key 所在请求头名称、是否要求保留版本前缀。验证方法:本地用 curl 直连一次,返回正常响应才说明口径抄对了。
- 记一次延迟基线先到 /tools/speed-test 测本机直连目标接口的往返延迟,把数值记下来。反代上线后再测一次,两次对比才知道中间这一跳是帮忙还是添乱。
- 决定 Key 放哪优先放 Worker 环境变量,别写进客户端或前端代码。同时想清楚:请求仍然会经过 Worker 节点,哪些数据能过、哪些不能过,这条边界要你自己划。
| 准备项 | 没准备好会怎样 | 怎么确认 |
|---|---|---|
| 域名托管在同一账号 | 绑定路由时选不到域名,只能临时加记录 | DNS 面板显示已激活,测试子域能解析 |
| 鉴权头与路径前缀确认 | Worker 返回 401 或 404,误以为是网络问题 | 本地 curl 直连目标接口成功 |
| 延迟基线已记录 | 反代变慢还是变快说不清 | /tools/speed-test 前后各测一次 |
| Key 存放位置已定 | 密钥留在客户端,等于公开 | Key 只出现在 Worker 环境变量里 |
建 Worker 与写转发逻辑:按这个顺序做
先别急着堆功能,Worker 新建出来第一件事是跑通一条最小链路:收到请求、把目标主机换成上游、原样带上方法、请求头和请求体再发出去,拿回响应后原样吐回客户端。这条链路通了,再谈改头、流式、错误码。顺序反了,后面出问题你分不清是转发逻辑写错还是头部处理写错。
- 第一步 建空 Worker 并接上路由在控制台新建一个 Worker,先只写一行返回固定文本,用浏览器或 curl 访问它的默认域名,确认能通。这一步只验证部署链路,不碰转发。
- 第二步 加一段最小转发用一个 fetch 调用把入站请求转发到上游地址,把 request.method、request.headers、request.body 整体传过去,再把上游返回的 Response 直接 return。此时不加工、不读 body。
- 第三步 验证方法头和请求体分别用 GET 和 POST 各打一次,POST 带一段 JSON。看上游是否收到正确的方法和完整 body,再看客户端拿到的响应头和状态码是否和上游一致。
- 第四步 再动请求头链路通了以后才去处理 Host、连接类头这些需要改写或删掉的字段,每改一项都重跑一次上面的验证,避免一次改太多分不清是谁的问题。
| 请求头类别 | 处理方向 | 原因 |
|---|---|---|
| Host | 按上游要求改写或去掉 | 不改的话上游可能按错误的主机名做路由或校验 |
| 连接类头(如 keep-alive、transfer-encoding 等) | 去掉,交给运行时自己管 | 手动透传容易和平台的连接管理冲突 |
| 鉴权头(Authorization 等) | 保留透传,别吃掉 | 被吃掉后上游只会返回鉴权失败,你很难定位 |
| 自定义业务头 | 尽量原样透传 | 上游可能靠它做路由、灰度或统计 |
| 内容长度类头 | 按运行时行为决定是否保留 | 和实际 body 不一致时会导致上游解析异常 |
流式响应是这类代理最容易翻车的地方。正确做法是把上游返回的 Response 对象直接交给运行时,让它按流式透传;一旦你在中间先 await 把整个 body 读成文本再重新构造响应,流式就退化成一次性返回,长回答会卡住很久才整体出现,首字延迟也变得没法看。判断标准很简单:客户端是不是边生成边收到内容,而不是等全部生成完才一次性刷出来。
错误处理只留薄薄一层就够:上游返回什么状态码、什么响应体,就原样透出去。不要为了「统一格式」把上游的 4xx、5xx 统统包成 200 再塞进自定义结构,那样你在客户端里只能看到一个成功的壳,真实问题全被掩盖。什么情况下可以例外?只有当你确实需要记录日志或加一个带追踪 ID 的响应头时,也只是附加,不改状态码本身。
自定义域名与路由配置
Worker 部署完会送你一个默认域名,能跑,但国内访问表现未必稳定——解析线路、被墙概率、延迟抖动都不由你控制。正式用建议绑自己的自定义域名:域名在你手里,DNS 你能改,出问题能换线路,也方便后面做多路径备份。绑之前先想清楚一个事:这个域名以后是只给自己用,还是要给同事、小团队共用,后者更要提前规划子域名。
- 绑域名在 Cloudflare 里把域名接入同一账号,进 Worker 的 Settings → Domains & Routes 添加 Custom Domain 或 Route。加完等 DNS 生效,再打开域名看是否返回内容,别只看控制台打勾。
- 验 HTTPS用浏览器访问 https://你的域名,确认证书正常、没有混合内容告警。如果走的是 Route 模式,注意匹配表达式是否漏掉了你要的路径前缀,漏了就会走回默认域名。
- 对齐路径前缀打开你客户端里填的 Base URL,逐字符和你 Worker 里处理的路由前缀对比。Base URL 写 /v1 而 Worker 只认 /v1/,或者反过来,都会 404。这一步最容易被忽略,也最容易查半天。
- 跑一条最小请求改完立刻用最简请求验证,不要等接进客户端。看到正常返回再去做下一步,出问题也知道是刚改的那一步。
路径拼接规则按接口协议分。OpenAI 风格的客户端通常把 Base URL 当成「版本根」,自己往后接 /chat/completions 之类;Anthropic 风格常见的是把完整 messages 路径交给客户端,或者反过来只给域名。两种规则不一样,一次只接一种,先把一条路走通。混着配——比如 Base URL 按 OpenAI 规则写、Worker 里却按 Anthropic 规则 rewrite——最容易出玄学问题:请求发出去了,返回 404 或 400,看日志还都对。
| 你填的位置 | 常见写法 | 出错表现 |
|---|---|---|
| Base URL 含 /v1 | 域名加 /v1 | Worker 再加一次 /v1 就变双层前缀,404 |
| Base URL 只到域名 | 纯域名 | 客户端自己补路径时,Worker 路由没覆盖到,404 |
| Worker 路由写死整段 | 固定路径 | 客户端换一个接口就全挂,只能单点用 |
| Route 匹配漏段 | 通配没写全 | 部分请求走默认域名,国内表现时好时坏 |
- 绑完域名先直接用浏览器或 curl 打域名根路径,确认 Worker 确实被触发
- 用一条最简请求测目标接口,看状态码和返回体头部,不看完整内容
- 把客户端 Base URL 和 Worker 里的前缀抄在同一行做比对,肉眼过一遍
- 通过之后再接第二个接口,仍然一次只加一种协议风格
- 把可用的域名和路径记下来,方便以后换域名时对照
什么情况下这套不适用:如果你只是临时测一下、用完就删,那默认域名够用,不必折腾自定义域名;如果客户端本身支持配置完整请求路径而不是只填 Base URL,前缀对齐的坑会小很多,但仍要确认 Worker 侧没有二次拼接。想要对照各家中转站目前可用的域名和路径写法,可以到站内的中转站导航与检测页看当时的实测结果,数字和状态会变,别照抄旧结论。
接进客户端与代码
Worker 部署好之后,客户端这边其实只动一个地方:Base URL(接口地址)。你原来用的 Key 不用换,模型名也不用换,因为反代只改请求从哪台机器出去,不碰请求内容。要注意的是路径前缀:有的客户端会自动补 /v1,有的不会,得按你 Worker 里配的路由规则来拼,拼错的表现通常就是 404 而不是 401。
- Base URL
- 填你 Worker 的域名,加上和你路由匹配的前缀,别多别少
- API Key
- 继续用原厂那把,反代不负责帮你换密钥
- 模型名
- 照旧填原来的标识,Worker 不认模型,只转发
- 路径前缀
- 决定客户端请求打到 Worker 哪条路由,拼错就是 404
本地代码里,这个地址别硬编码进源文件。用环境变量承载,好处有两个:一是换源、回退、临时对比不同 Worker 时不用改代码重新提交;二是密钥和地址不会跟着代码进仓库。各家 SDK 基本都认环境变量,或者自己在启动时读一次配置对象即可。
export OPENAI_BASE_URL=https://你的worker域名/你配的前缀
export OPENAI_API_KEY=原来那把key
# 跑起来后先打一条最短请求验证,别上来就跑完整业务流程| 你看到的现象 | 先查哪里 | 大概率原因 |
|---|---|---|
| 404 找不到路径 | Worker 路由与客户端前缀 | 两边前缀没对齐,多写或少写了段 |
| 401 鉴权失败 | Key 有没有被前端代码吞掉 | 环境变量没生效,读了个空值 |
| 连不上、超时 | 直接 curl Worker 地址 | Worker 本身没起来或域名没生效 |
| 能通但响应很慢 | Worker 日志里的上游耗时 | 上游线路问题,不是客户端配置 |
- 先直接请求 Worker用 curl 或浏览器打一次 Worker 地址,看它自己有没有正常响应。这一步不通,后面都别查。
- 再看 Worker 日志看上游返回的状态码和报错原文,是 401、429 还是超时,方向立刻清楚。
- 最后才怀疑客户端确认 Worker 直连没问题,再回头查客户端的 Base URL、前缀和 Key 读取方式。
还有个容易踩的坑:协议和路径是两回事。反代只负责把请求转到上游,它不会帮你把某种私有协议转成另一种。如果你用的是和官方不一样的接口格式,那得靠客户端侧的兼容层来处理,或者干脆选格式本来就一致的那套。别指望 Worker 里顺手做转换,那已经超出「转发」的职责了。
- Base URL 只填 Worker 域名加前缀,尾部斜杠按客户端习惯处理
- Key 保持原样,不要为了反代专门重新申请一把
- 地址走环境变量,别写进业务代码
- 排障顺序固定:Worker 直连 → Worker 日志 → 客户端配置
- 协议不同、路径不同,是兼容层的事,不是反代的事
延迟、限制与会被卡住的地方
反向代理本质上就是多绕一跳:你的请求先到 Cloudflare 的边缘节点,再由它转发到上游。这一跳本身会引入额外耗时,而边缘节点的冷启动、节点物理位置、回源链路质量,都会直接反映在你感知到的首字延迟上。所以「值不值得用」这件事,不要听别人说快或慢,要拿你自己在本地网络环境下的实测数据说话。
一个容易被忽略的点是:Worker 只适合处理「小请求体 + 短响应」的转发场景。超长上下文、超大附件、需要流式长时间吐字的任务,很容易撞上平台的请求体大小上限和执行时间上限,直接被拒或中途断开。这类任务更适合走正规的官方接入方式,别指望 Worker 扛下来。
| 卡点类型 | 典型触发场景 | 表现 | 应对方向 |
|---|---|---|---|
| 请求体大小上限 | 传长文档、大图、大附件 | 请求被平台直接拒绝,报错返回 | 改走官方直连或拆分请求 |
| 执行时间上限 | 超长输出、慢速流式响应 | 连接中途被切断,回答不完整 | 缩短单次输出,或换接入方式 |
| 共享出口 IP | 上游对来源做风控或限流 | 偶发 403、限流、需要验证 | 换域名解决不了,本质是出口问题 |
| 边缘节点选择 | 不同地区、不同时段访问 | 首字延迟忽高忽低 | 多时段多次实测再判断 |
出口 IP 这块要特别说清楚:Worker 的出口是平台侧共享的地址,不是你独占的。如果上游服务对来源 IP 有风控、频控或者区域限制,你换多少个自定义域名都没用,因为决定成败的是出口 IP 本身,不是你的域名。这种情况下的正确做法是换接入路径,而不是在域名上反复折腾。
- 先固定测试条件用同一台设备、同一网络、同一提示词,分别测直连和走反代,避免变量混在一起。
- 多时段重复量早中晚各测一轮,至少覆盖几个不同时段,把首字延迟和失败率都记下来。
- 交叉验证再下结论到 速度测试页(/tools/speed-test) 对比不同线路表现,单次结果波动大,别凭一次就判定哪条线路更好。
- 先跑小请求验证连通正式用之前,先用短提示词确认链路通、返回正常,再上真实任务。
- 遇到卡点先归类对照上面的表格判断是体积、时间还是 IP 的问题,再决定换方式还是放弃。
上线之后要盯着什么
上线不是终点,是开始。这层反代本质上是你自己搭的一条私线,任何一处变更都可能让整条路断掉。所以别急着庆祝,先把下面几件事安排进日常。
先留一条能原路返回的退路
动手改配置之前,先把当前能用的版本存一份。别只存 Worker 代码,域名、路由规则、环境变量和密钥绑定都要一起记下来,否则回滚到一半发现变量对不上,照样不通。比较稳妥的做法是:保留一份「直连原站」的备用方案,再准备一个备用域名或子域,别让所有流量只认一个入口。
- 导出当前配置把 Worker 脚本、wrangler 配置或控制台里的变量项复制到本地一份带日期的文件里,确认变量名和绑定关系都齐。
- 准备备用入口额外配一个子域或备用域名指向同一个 Worker,主域出问题时可以手动切过去,而不是临时从零搭。
- 验证回滚路径真去试一次切回直连或切到备用域名,确认客户端那边不用大改就能用,别等出事才第一次走这条路。
上游一改口径,转发逻辑就得跟着动
这类服务端的接口不是刻在石头上的。路径前缀、鉴权头写法、模型名的命名口径,任何一项调整,你 Worker 里的转发规则都可能失效,表现出来往往是突然 404、401 或者模型找不到。平时把「请求长什么样」和「返回什么状态」对上号,出问题时能快速分清是自己的问题还是上游改了。具体各家当前的口径差异,可以到 /models模型资料库 对照着看。
| 观察项 | 正常表现 | 异常时先怀疑什么 |
|---|---|---|
| 请求路径 | 和配置里写的一致 | 上游改了前缀或版本段 |
| 鉴权头 | 固定字段名带上密钥 | 上游换了头名或鉴权方式 |
| 模型名 | 能匹配到已有条目 | 命名口径变了或模型下线 |
| 状态码 | 常规成功/限流码 | 突然大面积 4xx 多为上游变动 |
日志只留骨架,不留血肉
日志的目的是排障,不是存档。状态码和耗时足够你判断是不是线路问题、是不是被限流;请求体和密钥一旦落进日志,等于把入口摊开给别人看。脱敏规则要在写日志之前定好,而不是事后清理。判断标准很简单:这条日志被人看到,会不会直接拿到你的 Key 或用户的原始输入?会,就别记。
- 只记时间、状态码、耗时、目标主机这类骨架字段
- 请求体、响应体、Authorization 头一律不落盘
- 密钥不要拼进任何会输出的字符串里
- 日志保留时间设短一点,够排查就行
- 不同环境用不同日志级别,生产环境别开调试
这是自用线路,不是公共入口
把它当成个人自用的通道来管。一旦对外公开或转售,滥用、刷量、被扫描的风险都不在你控制范围内,连带你的域名和账号都可能受影响。适用的前提是「自己或小范围可信的人用」;如果你确实想做成对外服务,那要处理的是完全另一套问题,不是这个教程的范围。想了解别人踩过的坑,可以翻 /guides指南中心 里的相关记录。
常见问题
这样搭完之后,国内就能稳定直连了吗?
不能这么理解。反代只改请求的走法,不改变链路物理距离,也不解决上游对你所在出口的限制。实际能不能用、延迟多少,取决于你所在网络、时段和上游策略,必须自己多时段实测;看到别人说好用不代表你这边一样。
Worker 里放 API Key 安全吗?
比把 Key 硬写进客户端代码好一点,但请求仍然会经过 Worker,等于多了一个能看见明文的位置。原则是只做自用、不对外公开地址、给 Key 设额度上限;敏感数据要不要经过这条路,按你自己的数据边界判断。
为什么不直接用中转站,非要自己搭?
两者的取舍不同:中转站省事但你要信任对方,自建反代可控但需要自己运维和排错,也没有客服兜底。任务简单、量不大、想省心,用现成的更划算;要求路径可控、不想把 Key 交给第三方,再考虑自建这条。
接上之后报 401 或者 404,先查哪?
401 多半是鉴权头在转发中被改写或丢了,检查 Worker 里头的透传逻辑;404 基本都是路径前缀对不上,客户端里填的 Base URL 和你 Worker 的路由规则要逐字符对一遍。先直接请求 Worker 地址验证,再排查客户端。
这套方案什么时候该放弃?
当上游明确不允许经第三方转发、或者你依赖固定出口 IP 做白名单、又或者需要跑超大请求体和长连接时,Worker 这条路就不合适,应该转自建服务器或直接走官方支持的接入方式。判断标准是需求优先,而不是方案本身好不好。