API 中转节点搭建指南

本文介绍如何通过 Cloudflare 的 Workers 实现简易的中转节点的搭建.

本文为实际部署 n8n 系列博客的开端, 虽然这篇文章都没提到 n8n.

应用: 国内通过 API 转发调用国外大模型.

``

设备配置详情

  • 设备:腾讯云轻量应用服务器(特惠型实例)
  • 系统:Debian 12.13
  • CPU:4 核
  • 内存:4 GB
  • 存储:40 GB SSD

憋攻击我服务器, 一碰就炸.

话说腾讯云 39 元/年的服务器真的有人抢得到吗.

背景

  • 在国内服务器部署 n8n 后, 由于 GFW 的存在,TCP 连接会被重置或超时.
  • 不愿使用代理如 mihomo 等, 因为配置复杂, 廉价节点稳定性不佳.
  • 国内聚合平台要么不稳定, 要么不包含 Gemini, OpenAI, Claude 等 API.
  • 拥有自己的域名, 域名为腾讯云域名

所以我为什么要注册 .cc 顶级域名, 被吐槽看上去像个博彩网站.

嘿, 好歹不如 .cn 域名自己开自己盒, 还得花钱屏蔽.

核心原理

  • Cloudflare 提供免费的无服务器计算资源, 也称 Workers.
    • Workers 可以在 Cloudflare 的边缘网络运行, 实现全局低延迟.
    • Workers 可以将国内服务器的请求转发到海外 API, 绕过 GFW 的限制.
  • Cloudflare 默认分配的 *.workers.dev 域名在国内无法访问.
    • 可以将注册的域名托管到 Cloudflare, 并绑定到 Worker 上, 国内服务器即可直接访问.
    • 也称 Cloudflare 的自定义域名服务.
  • Cloudflare 需接管域名的 DNS 解析权才可进行自定义域名服务.
  • 转发请求这里以 OpenRouter 为例, 其他镜像站同理.

总而言之, 为了使用 API 需要需要使用 Workers, 为了使用 Workers 需要自定义域名, 为了自定义域名需要更改 DNS 解析.

反正绕了一圈总算能解决问题吧.

步骤

将域名添加到 Cloudflare

  1. 注册并登录 Cloudflare 账号
  2. 输入主域名
    • 例如 yourdomain.com
    • 不要 http://www. 前缀
  3. 选择 Free 套餐
  4. Cloudflare 会自动扫描你现有的 DNS 记录
    • 务必将现有 A 记录取消勾选, 转变为 DNS only.
    • 否则 Cloudflare 的 SSL 加密会与你服务器原本的证书发生冲突.

在域名注册商更改 Nameservers

  1. 登录你的域名注册商控制台(如腾讯云/阿里云)
  2. 找到域名注册的管理页
    • 搜索”域名注册”而非”域名管理”.
  3. 找到”DNS 服务器”选项
    • 替换为 Cloudflare 提供的 Nameserver.
    • 通常是两个人名格式的地址:
      • 例如: evelyn.ns.cloudflare.com
      • 例如: miguel.ns.cloudflare.com
  4. 保存设置
    • 一般等待几分钟即可生效
    • 成功标志: “Your domain is now protected by Cloudflare”

创建 Cloudflare Worker

本人没有 js 基础, 所有代码均由 Gemini 生成并更改, 欢迎提出更改意见.

  1. 进入 “Workers & Pages” 页面
    • 通过点击 “Workers Routes” 页面中的 “Manage Workers” 进入 “Workers & Pages” 页面.
    • 通过点击 “Build” 分类中的 “Computer” 选项卡进入 “Workers & Pages” 页面.
  2. 点击 “Create Application”
    • 选择 “Start with Hello World!” 以便后续更改.
  3. 输入名称并部署
    • 例如 api-proxy, 下文均以 api-proxy 为例.
    • 点击 “Deploy” 部署 Worker.
  4. 编写带有”数据清洗功能”的代理代码
    • n8n 在较新版本中调用 OpenAI 时, 会在发送的 JSON 中塞入一个 store 参数.
    • OpenRouter 等镜像站不支持这个参数, 导致 “400 Invalid Responses API request”.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 这里以 OpenRouter 为例
url.hostname = 'openrouter.ai';

// 处理浏览器的 CORS 跨域预检请求
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': '*',
}
});
}

// 清理可能导致被拦截的来源信息
const newHeaders = new Headers(request.headers);
newHeaders.delete('Origin');
newHeaders.delete('Referer');

// 拦截并清洗 store 参数
let modifiedBody = request.body;
if (request.method === 'POST') {
try {
const bodyText = await request.text();
const bodyJson = JSON.parse(bodyText);

if (bodyJson.store !== undefined) {
delete bodyJson.store;
}

modifiedBody = JSON.stringify(bodyJson);
newHeaders.delete('Content-Length');
} catch (e) {
modifiedBody = request.body;
}
}

// 构造并发起最终请求
const modifiedRequest = new Request(url.toString(), {
method: request.method,
headers: newHeaders,
body: modifiedBody,
redirect: 'follow'
});

try {
const response = await fetch(modifiedRequest);
const modifiedResponse = new Response(response.body, response);

// 强制所有响应允许跨域
modifiedResponse.headers.set('Access-Control-Allow-Origin', '*');
return modifiedResponse;

} catch (e) {
return new Response(`Proxy Error: ${e.message}`, { status: 502 });
}
}
};
  1. 在预览窗口进行测试
    • 在右侧 Preview 窗口中, 可以看到 Cloudflare 分配的默认地址https://api-proxy.xxx.workers.dev/.
    • 不要直接访问主页(502 Bad Gateway)
      • 在地址栏的末尾手动加上 API 数据获取路径: /api/v1/models
      • 完整地址应类似:https://api-proxy.xxx.workers.dev/api/v1/models
    • 返回包含模型列表的 JSON 数据

绑定自定义域名到 Worker

  1. 进入该 Worker 的概览界面
    • 在 “Workers & Pages” 页面中, 进入刚刚创建的 Worker.
  2. 进入 “Settings” 并新增一个 “Domains & Routes”.
  3. 选择 “Custom domain”, 并输入自定义域名.
    • 输入规划好的二级域名, 如 api.yourdomain.com.
  4. 等待状态变为 “Active”

测试

1
curl --noproxy "*" -I https://api.yourdomain.com/api/v1/models

其中 --noproxy "*" 是为了防止 VS Code 配置了代理服务器.
请将 api.yourdomain.com 替换成真实的自定义域名.

下一步

关于 n8n 的具体应用, 将会在后续文章中介绍.

简单来说, 只需拉取 OpenAI 节点, 并修改其 “Base URL” 为 https://api.yourdomain.com/api/v1. 并填上 OpenRouter 的 API 密钥.

需要 OpenRouter 的 API 密钥.

以上.

反馈与回复

  1. 来自好友”null”: “怎么开始自己搓轮子了”
    • 回复: “但凡国内有个能稳定点的, 我也不想造啊~”