把免费模型额度变成自己的 API
把免费模型额度变成自己的 API,难点不是反代,而是三件事拼起来:账号池解决额度,常驻服务解决可用性,固定域名 + 出站隧道解决可达性。这篇从零讲完整流程,不需要公网 IP、不需要路由器端口映射、不需要云控制台权限。
把免费模型额度变成自己的 API:账号池 + 固定域名 + 隧道
一份可复现的部署笔记:在一台常开的机器上跑反向代理网关,把多个账号的免费额度聚合成一个 OpenAI 兼容 API,再通过 Cloudflare Tunnel 挂到自己的域名上,让手机、笔记本、IDE 在任何网络下都能直接调用。
文中域名、API Key、隧道 token 均为占位符(
wb.example.com、sk-wb-xxxx、<TUNNEL_TOKEN>),替换成你自己的值即可。
目录
- 最终效果
- 整体架构
- 前置条件
- 第一步:部署反代网关
- 第二步:账号池与面板
- 第三步:让它常驻
- 第四步:公网接入方案选型
- 第五步:Cloudflare Tunnel 实操
- 第六步:安全加固
- 第七步:客户端接入
- 验收清单
- 日常运维
- 风险与合规
- 命令速查
1. 最终效果
部署完成后,你会得到三样东西:
| 能力 | 地址 | 说明 |
|---|---|---|
| API 入口 | https://wb.example.com/v1 |
OpenAI 兼容,任何设备直接填 Base URL + Key |
| 管理看板 | https://wb.example.com/(或仅本机 http://127.0.0.1:8788/) |
账号池、用量、密钥、签到 |
| 固定域名 | wb.example.com |
机器重启、隧道重连都不变 |
客户端只需要两行配置:
Base URL : https://wb.example.com/v1
API Key : sk-wb-xxxxxxxxxxxxxxxx
手机、平板、公司电脑、家里的台式机,不需要装任何客户端,也不需要公网 IP、不需要路由器端口映射、不需要云控制台权限。
2. 整体架构
┌──────────────┐ HTTPS ┌──────────────────┐ outbound ┌─────────────────┐
│ 手机 / 笔记本 │ ─────────► │ Cloudflare Edge │ ◄─────────── │ cloudflared │
│ IDE / 脚本 │ │ (TLS 终止/CDN) │ 隧道连接 │ (本机服务) │
└──────────────┘ └──────────────────┘ └────────┬────────┘
│ http
▼
┌─────────────────┐
│ wb_proxy.py │
│ 127.0.0.1:8788 │
│ ┌───────────┐ │
│ │ 账号池 │ │
│ │ intl / cn │ │
│ └───────────┘ │
└────────┬────────┘
│ 上游请求
▼
┌─────────────────┐
│ 厂商模型服务端 │
└─────────────────┘
三个关键点:
- 反代只监听 127.0.0.1,不直接暴露端口,安全边界交给隧道;
- 隧道是出站连接,所以机器在 NAT 后面、没有公网 IP、没有安全组权限也能被访问;
- 账号池在反代内部轮换,客户端无感知,一个 Key 用所有账号的额度。
3. 前置条件
| 项目 | 要求 |
|---|---|
| 机器 | Windows / Linux 均可,能长期开机;本文以 Windows 为例 |
| 运行时 | Python 3.9+(项目主体是标准库 + 少量依赖),或直接用 Docker 镜像 |
| 账号 | 若干可用的免费额度账号(国际版 / 国内版均可) |
| 域名 | 一个自己的域名,NS 已托管到 Cloudflare(免费版即可) |
| 权限 | 本机管理员(装服务用);Cloudflare 账号(建隧道用) |
为什么强调"常开":免费额度按天/按任务刷新,网关断了就等于 API 断了。云主机、NAS、旧笔记本都行。
4. 第一步:部署反代网关
4.1 获取项目
# 方式一:release 包(Windows 直接解压)
# 从项目 Releases 下载对应版本,解压到工作目录
# 方式二:Docker
docker compose up -d
# 方式三:源码
git clone <repo-url>
cd workbuddy2api-hub
pip install -r requirements.txt
项目结构(关键文件):
wb_proxy.py # 网关主体:OpenAI/Anthropic 兼容层 + 账号池 + 看板后端
dashboard.html # 看板前端(单文件)
wb_accounts.py # 账号池、凭据、额度
wb_settings.py # 面板密码、API Key、设置持久化
accounts/ # 账号凭据 + settings.json(不要提交、不要外传)
usage/ # 用量日志
logs/ # 运行日志
4.2 首次启动
# Windows:前台启动,方便第一次登录账号
python wb_proxy.py --host 127.0.0.1 --port 8788
浏览器打开 http://127.0.0.1:8788/:
- 默认面板密码是
admin(部署完第一件事就是改掉,见第 9 节); - 点「登录新账号」走浏览器 OAuth,账号会自动落进
accounts/; - 重复多次,把要用的账号都加进来。
4.3 账号池怎么工作
- 每个账号是一份凭据文件,池子按可用性、额度、并发挑账号;
- 国际版 / 国内版是两套上游(
realm),可以同时挂在一个网关里; - 请求失败会自动换号重试,客户端只看到一次成功响应;
- 支持按账号绑定出口代理、按模型冷却限流、签到任务、额度预警。
账号越多,可用并发和总额度越高;但同一个出口 IP 挂太多账号容易触发风控,建议配合代理槽分散出口。
5. 第二步:账号池与面板
看板里能做的事,也是这套方案比裸反代值钱的地方:
| 模块 | 作用 |
|---|---|
| 账号池 | 增删账号、看额度/到期、启停、排序 |
| API Key | 多把 Key、绑定 realm、模型白名单、并发上限 |
| 用量 | 每次请求的 token、耗时、命中账号、Key 标签 |
| 签到/任务 | 自动领每日积分,维持免费额度 |
| 日志 | 请求日志、错误、上游状态码 |
| 设置 | 面板密码、Key 策略、限流、调度器 |
建议至少建两把 Key:
Local-Intl:绑定国际线路,给主力客户端;Local-CN:绑定国内线路,给需要国内上游的场景。
这样某条线路抽风时,换 Key 就能切换,不用改网关。
6. 第三步:让它常驻
前台窗口一关服务就没了,所以要做成"无窗口 + 掉线自愈 + 开机自启"。
6.1 看门狗脚本(思路)
# wb_keepalive.py(简化示意)
HOST, PORT, INTERVAL = "127.0.0.1", 8788, 30
while True:
if not port_alive(HOST, PORT):
spawn("python", "-u", "wb_proxy.py", "--host", HOST, "--port", str(PORT))
time.sleep(INTERVAL)
要点:
- 用
pythonw.exe跑看门狗(GUI 子系统,无控制台、无任务栏窗口); - 子进程用
CREATE_NO_WINDOW启动,同样无窗口; - 用一个本地端口做单实例锁,重复启动无副作用;
- 日志写
logs/watchdog.log,超过一定大小自动截断。
6.2 注册计划任务
$action = New-ScheduledTaskAction -Execute "C:\...\pythonw.exe" -Argument "D:\...\wb_keepalive.py"
$trigger = New-ScheduledTaskTrigger -AtLogOn
$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew
Register-ScheduledTask -TaskName "wb-proxy-keepalive" -Action $action -Trigger $trigger -Principal $principal -Settings $settings
验证:
Get-ScheduledTask -TaskName "wb-proxy-keepalive" | Select TaskName, State
Get-NetTCPConnection -LocalPort 8788 -State Listen
关键原则:反代进程只绑 127.0.0.1。对外暴露交给隧道,不要为了省事直接
--host 0.0.0.0。
7. 第四步:公网接入方案选型
机器在 NAT 后面、又拿不到云控制台权限时,常见四条路:
| 方案 | 需要公网 IP | 客户端要装东西 | 地址稳定 | 适用场景 |
|---|---|---|---|---|
| 公网 IP + 端口映射 | 是(还要能改安全组/路由器) | 否 | 是 | 有云控制台或路由器权限 |
| Tailscale / ZeroTier | 否 | 是(每台设备装客户端并登录) | 是 | 只给自己几台设备用 |
| Cloudflare Quick Tunnel | 否 | 否 | 否(每次重启换随机地址) | 临时测试 |
| Cloudflare Named Tunnel + 自有域名 | 否 | 否 | 是 | 长期挂机 |
选最后一条的理由:
- 不需要公网 IP、不需要动安全组、不需要路由器;
- Cloudflare 负责 TLS,客户端拿到的是标准 HTTPS;
- 手机/电脑零安装,填 URL + Key 就能用;
- 域名固定,重启不变,适合长期挂机。
7.1 为什么不推荐 Quick Tunnel 长期用
Quick Tunnel(cloudflared tunnel --url http://127.0.0.1:8788)确实零配置,但官方限制很明确:
- 地址是随机的,每次重启换一个;
- 无可用性保证;
- 单隧道最多 200 个并发请求,超了返回 429;
- 官方标注不支持 SSE。
适合验证链路,不适合当日常地址。
8. 第五步:Cloudflare Tunnel 实操
8.1 域名托管到 Cloudflare
- Cloudflare 控制台 → Add a site → 输入域名 → 选 Free 计划;
- 到域名注册商把 NS 改成 Cloudflare 给的两个(形如
mimi.ns.cloudflare.com、stanley.ns.cloudflare.com); - 等待生效(几分钟到几小时),用 DNS 查询确认:
Resolve-DnsName example.com -Type NS -Server 8.8.8.8
# 应返回 *.ns.cloudflare.com
8.2 创建隧道并拿 token
- 打开 https://one.dash.cloudflare.com/;
- Networks → Tunnels → Create a tunnel;
- 选 Cloudflared,起个名字(如
wb-proxy); - 复制页面给出的 token(一长串
eyJ...,只显示一次)。
token 里包含账号 ID、隧道 ID 和隧道密钥,等同密码,别贴到公开地方。
8.3 在本机装成服务
Windows:
# 1) 下载 cloudflared
curl.exe -L -o cloudflared.exe https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe
# 2) 放到固定路径(服务会引用这个路径,别放临时目录)
New-Item -ItemType Directory "C:\Program Files\cloudflared" -Force
Copy-Item .\cloudflared.exe "C:\Program Files\cloudflared\cloudflared.exe"
# 3) 安装为 Windows 服务(自动启动)
& "C:\Program Files\cloudflared\cloudflared.exe" service install <TUNNEL_TOKEN>
# 4) 检查
Get-Service cloudflared
Linux:
sudo cloudflared service install <TUNNEL_TOKEN>
sudo systemctl enable --now cloudflared
服务安装后:
- 服务名
cloudflared,启动类型 Automatic; - token 落盘在
C:\ProgramData\cloudflared\token; - 日志进 Windows 事件查看器(Application → 来源
cloudflared)。
8.4 配置 Public Hostname
回到 Zero Trust 面板:Tunnels → 选中隧道 → Public Hostname → Add a public hostname:
| 字段 | 值 |
|---|---|
| Subdomain | wb |
| Domain | example.com |
| Type | HTTP |
| URL | localhost:8788 |
| Path(可选) | 留空 = 全部放行;填 v1 = 只放行 /v1/* |
保存后 Cloudflare 自动创建一条 CNAME:
wb.example.com → <TUNNEL_ID>.cfargotunnel.com (Proxied)
想要"看板 + API 都从公网访问",Path 留空;只想暴露 API、把看板藏起来,填
v1。两种都能随时改,改完立即生效。
8.5 验证隧道
curl -s https://wb.example.com/health
# 期望返回类似:{"ok": true, "api_key_required": true, ...}
如果返回 5xx 且提示隧道不可达,先看服务状态和事件日志。
9. 第六步:安全加固
公开到公网之后,默认配置是不够的。
9.1 面板密码
# 面板 API 直接改(把 current/new 换成你的)
curl -s -X POST https://wb.example.com/panel/login \
-H "Content-Type: application/json" -d '{"password":"admin"}'
# 拿到 token 后:
curl -s -X POST https://wb.example.com/panel/password \
-H "Content-Type: application/json" -H "X-Panel-Token: <TOKEN>" \
-d '{"current":"admin","new":"一个足够长的强密码"}'
或者直接在面板设置页改。
9.2 API Key 策略
- 每个用途一把 Key,方便吊销和统计;
- 按 realm 绑定(国际/国内),按模型做白名单;
- 设并发上限,防止单个客户端打爆账号池;
- Key 泄露就禁用,不要复用。
9.3 减少暴露面
- Path 填
v1:公网只开 API,看板只能本机访问; - 或者给看板单独一个子域(如
panel.example.com),再套 Cloudflare Access(邮箱验证码),只有你能进; - 面板密码 + Access 双保险,比只靠密码稳。
9.4 账号池风控
- 同一出口 IP 不要挂太多账号;
- 控制请求频率,避免短时间大批量;
- 保持设备指纹 / User-Agent 的一致性,别频繁变;
- 账号按需分组,异常账号及时停用。
9.5 网络层
- 反代永远只监听
127.0.0.1; - 如果确实要给同内网用,再单独加
netsh portproxy或反向代理,并限制来源网段; - 不要给 8788 直接开公网入站。
10. 第七步:客户端接入
10.1 通用配置
Base URL : https://wb.example.com/v1
API Key : sk-wb-xxxxxxxxxxxxxxxx
Model : 看板「模型」页或 /v1/models 返回的 id
10.2 curl 验证
# 模型列表
curl https://wb.example.com/v1/models \
-H "Authorization: Bearer sk-wb-xxxxxxxx"
# 非流式对话
curl https://wb.example.com/v1/chat/completions \
-H "Authorization: Bearer sk-wb-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"model":"<model-id>","messages":[{"role":"user","content":"hi"}],"max_tokens":32}'
# 流式对话
curl -N https://wb.example.com/v1/chat/completions \
-H "Authorization: Bearer sk-wb-xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"model":"<model-id>","messages":[{"role":"user","content":"count 1 to 20"}],"stream":true,"max_tokens":100}'
10.3 常见客户端
| 客户端 | 配置要点 |
|---|---|
| ChatBox / NextChat / Cherry Studio | 自定义 OpenAI 兼容接口,填 Base URL + Key |
| OpenWebUI | 设置 → 连接 → OpenAI API,Base URL 填到 /v1 |
| Codex CLI / Claude Code | 走 OpenAI / Anthropic 兼容端点,注意模型名和 reasoning 参数 |
| 手机 App | 同上,确保能访问 HTTPS 域名 |
10.4 注意代理设置
如果客户端所在机器开了系统代理(Clash 等),要把域名加进绕过列表,否则请求可能被本地代理劫持:
ProxyOverride: <-loopback>;localhost;127.*;10.*;172.16.*;192.168.*;wb.example.com
11. 验收清单
部署完逐条过一遍:
| 检查项 | 期望 |
|---|---|
GET /health |
200 + JSON |
GET /v1/models 带 Key |
200 + 模型清单 |
GET /v1/models 不带 Key |
401 |
GET /(Path=v1 时) |
404 |
| 流式对话 | 首块早于结束、持续推送 |
| 面板登录 | 200 |
| 机器重启后 | 地址不变、服务自启 |
12. 日常运维
12.1 备份
# 账号凭据 + 设置(含 API Key、面板密码哈希)——最重要
Compress-Archive -Path accounts\* -DestinationPath backup-accounts-$(Get-Date -f yyyyMMdd).zip
accounts/settings.json 里是账号凭据和 Key,不要提交到 Git、不要发群。
12.2 更新
- 反代项目更新很频繁(修复上游接口变化),定期看 Releases;
- cloudflared 用
cloudflared update或重新下包,服务会自动用新二进制; - 更新前备份
accounts/。
12.3 监控
- 外部拨测:定时
curl https://wb.example.com/health,非 200 告警; - 看板看账号额度、错误率;
- 事件日志看隧道重连次数。
12.4 额度策略
- 多账号 + 每日签到,把免费额度吃满;
- 给不同 Key 设不同并发,避免一个客户端把池子打空;
- 高峰期让主力模型走低消耗档位,长上下文注意积分消耗。
13. 风险与合规
必须说清楚:
- 这是逆向项目,依赖厂商客户端协议和免费额度策略,接口随时可能变、项目可能停更;
- 账号可能被封,尤其是多账号同 IP、高频调用;
- 可能违反厂商服务条款,请仅用于个人学习/自用,不要对外售卖或大规模分发;
- 不要把面板密码留在 admin,也不要把 Key/域名公开;
- 免费额度不是无限的,"token 自由"的前提是账号池健康 + 额度可持续,别把它当生产依赖。
14. 命令速查
# ===== 反代 =====
python wb_proxy.py --host 127.0.0.1 --port 8788
Get-NetTCPConnection -LocalPort 8788 -State Listen
# ===== 计划任务(看门狗)=====
Get-ScheduledTask -TaskName "wb-proxy-keepalive" | Select TaskName, State
Start-ScheduledTask -TaskName "wb-proxy-keepalive"
# ===== Cloudflare Tunnel =====
& "C:\Program Files\cloudflared\cloudflared.exe" service install <TUNNEL_TOKEN>
Get-Service cloudflared
Get-WinEvent -FilterHashtable @{LogName='Application'; ProviderName='cloudflared'} -MaxEvents 20
# ===== 验证 =====
curl.exe --noproxy "*" https://wb.example.com/health
curl.exe --noproxy "*" https://wb.example.com/v1/models -H "Authorization: Bearer sk-wb-xxxx"
# ===== 同内网临时转发(可选)=====
netsh interface portproxy add v4tov4 listenaddress=192.168.1.10 listenport=8788 connectaddress=127.0.0.1 connectport=8788
netsh interface portproxy show v4tov4
netsh interface portproxy reset
# ===== 卸载隧道 =====
& "C:\Program Files\cloudflared\cloudflared.exe" service uninstall
结语
这套方案的本质是三件事的组合:
- 账号池解决"额度不够";
- 常驻服务解决"随时可用";
- 固定域名 + 出站隧道解决"任何网络都能连、又不用开公网端口"。
三者拼起来,才是一个能日常用的 API 网关,而不是一个只能在本机 curl 的脚本。
如果以后想换供应商,思路完全一样:找同类的 xxx2api 项目(cursor2api、kiro2api、trae2api、qoder2api 等),或者用 sub2api / new-api 这类聚合层把多个 2api 接在一起——账号池、固定域名、隧道这三层可以原样复用。
最后再提醒一次:本文涉及的所有密钥、token、域名都是示例。部署时用自己的值,并且不要把
accounts/、隧道 token、API Key 发到任何公开地方。