返回列表
AI

用 New API 搭建统一 LLM 网关与 Lucky 反代外网访问

摘要

把 OpenAI、DeepSeek 与本地 Ollama 统一成一套 OpenAI 兼容接口,并用 Lucky 反代安全暴露到外网

5 分钟阅读
#New API#LLM 网关#Lucky#反向代理

1 序言

本地跑起 Ollama 之后,新的问题很快出现:API 碎片化。

我手上现在有三处模型来源——在线租的 API、自己部署的 Ollama、以及偶尔要试的新模型。它们各自的地址、密钥、调用格式都不一样:换一个客户端就要重配一次密钥,想在手机上用还得把每家的域名都记住。更麻烦的是,没有一处能统一统计用量,月底看账单只能靠猜。

本文用 New API 把所有这些上游收敛成一个地址、一套密钥、一种格式,再用 Lucky 把它安全地暴露到外网。整条链路是:

text
外网请求 → Lucky(SSL 卸载 + 基础认证)→ New API(鉴权/计费/转发)→ 上游模型

需要说明的是,本文不涉及任何破解或账号共享,只讲自建网关这一件事。

2 什么是 LLM 网关(核心概念)

2.1 基础定义

LLM 网关是夹在你的客户端和各家模型 API 之间的中间层。对客户端,它表现得像一个标准的 OpenAI API 服务;对上游,它按各家的格式转发请求。

它解决的不是「能不能用」,而是「好不好管」。

2.2 为什么需要它:三个真实痛点

  • 密钥分散:三家上游三把钥匙,散落在电脑、手机、平板的客户端里。想换一把就得挨个设备改。
  • 格式不一:在线 API 是 OpenAI 格式,本地 Ollama 虽是兼容格式但端点不同,部分厂商又各有方言。客户端适配成本高。
  • 无统一观测:哪个模型用得多、消耗多少额度,各家后台各看一半,没有汇总视图。
  • 暴露风险:想在外面用,就得把上游地址直接对外,等于把密钥交到了公网。

2.3 网关带来的核心收益

  • 一处配置:所有客户端只填一个地址、一个密钥。换模型不换配置。
  • 可计量:按令牌、按渠道、按用户统计消耗,额度用完自动停。
  • 可管控:能单独禁用某个渠道、设置限速、给不同设备发不同的密钥。
  • 收敛暴露面:公网只需要暴露网关这一个服务,上游地址和真实密钥不出内网。

3 主流网关方案对比

方案核心优势核心短板适用场景
New API界面完整、支持多渠道聚合与计费、中文文档友好、社区活跃功能多,配置项偏繁杂个人、小团队自建首选
one-api轻量、部署简单、历史悠久部分新特性跟进较慢只要基础转发
LiteLLM支持上百种模型格式、Python 生态可编程无内置管理界面,需自己写前端开发者、程序化调用
直连各上游零中间层、延迟最低密钥分散、无法统计、暴露面大单一上游、临时测试

我最终选 New API:它的定位正好卡在「有完整管理界面」和「部署足够简单」之间。one-api 我也用过,差别主要在渠道类型和统计维度上,够用但没那么顺手。

4 部署 New API

New API 建议配一个外部数据库,容器重建时数据不会丢。

4.1 前置目录

bash
mkdir -p /docker/apps/docker-compose/new-api
cd /docker/apps/docker-compose/new-api

4.2 docker-compose.yaml

YAML
# 官方文档
# https://github.com/Calcium-Ion/new-api
# https://hub.docker.com/r/calciumion/new-api

---
name: new-api
# 最后编辑时间:2026-09-23
services:
  new-api:
    # 镜像地址
    image: calciumion/new-api:latest
    # 容器名
    container_name: new-api
    # 主机名
    hostname: new-api
    environment:
      # 时区
      TZ: Asia/Shanghai
      # 🔴 数据库连接串(用户名:密码@tcp(主机:端口)/库名)
      SQL_DSN: "root:yourpassword@tcp(mysql:3306)/new-api"
      # 🔴 Redis 连接串,用于缓存与限流(可留空,但不建议)
      REDIS_CONN_STRING: "redis://redis:6379"
      # 🔴 多机部署时必须设置,单机可留默认,但建议改成随机字符串
      SESSION_SECRET: "换成你自己的随机字符串"
      # 日志保留天数,0 表示不清理
      LOG_KEEP_DAYS: "30"
    volumes:
      # 数据持久化(使用 SQLite 时尤其重要)
      - /docker/apps/new-api:/data
    ports:
      # WebUI 与 API 共用端口
      - 3000:3000
    depends_on:
      - mysql
      - redis
    # 重启策略,总是重启
    restart: always

  mysql:
    image: mysql:8.0
    container_name: new-api-mysql
    hostname: mysql
    environment:
      MYSQL_ROOT_PASSWORD: yourpassword
      MYSQL_DATABASE: new-api
      TZ: Asia/Shanghai
    volumes:
      - /docker/apps/new-api-mysql:/var/lib/mysql
    # 仅内网使用,不对外映射端口
    expose:
      - 3306
    restart: always

  redis:
    image: redis:7-alpine
    container_name: new-api-redis
    hostname: redis
    volumes:
      - /docker/apps/new-api-redis:/data
    expose:
      - 6379
    restart: always

启动:

bash
docker compose pull && docker compose up -d
# 首次启动数据库初始化需要一点时间,观察日志
docker compose logs -f new-api

4.3 初始化管理员

浏览器打开 http://你的内网IP:3000。

  • 默认管理员账号 root,密码 123456。
  • 登录后第一件事就是改密码,默认口令等于没有防护。

5 渠道配置

「渠道」就是一条上游来源,「令牌」是发给自己客户端用的密钥。两者在后台分开管理,这是 New API 最实用的设计。

5.1 添加在线 API 渠道

左侧 「渠道」→「添加渠道」,以通用的 OpenAI 兼容上游为例:

字段填什么
类型OpenAI(或对应的厂商类型)
名称起个能认出来的名字,如 deepseek
分组default(或自定义分组,便于区分用途)
模型手动填入要开放的模型名,如 deepseek-chat
密钥上游的 API Key
代理上游需要走代理时填,如 http://192.168.x.x:7890

保存后在列表里点「测试」,能看到绿色的连通状态才算配置成功。

5.2 接入本地 Ollama

因为 Ollama 提供的就是 OpenAI 兼容接口,所以直接用 OpenAI 类型即可:

  • 类型:OpenAI
  • 名称:ollama-local
  • 代理地址:http://192.168.x.x:11434(Ollama 所在机器的内网 IP)
  • 密钥:随便填一个非空字符串(Ollama 不校验)
  • 模型:填你本地已拉取的模型名,如 qwen2.5:7b、bge-m3

⚠️ 千万别填 127.0.0.1。New API 在容器里,127.0.0.1 指的是它自己,必然连不通。要填宿主机的内网 IP。

5.3 创建令牌

左侧 「令牌」→「添加令牌」:

  • 名称:比如 手机-冬梅,一个设备一个,泄露了能单独吊销。
  • 额度:可以设成无限,也可以设上限,跑完自动停。
  • 分组:要和渠道的分组匹配,否则会提示无可用渠道。

保存后会得到一串 sk- 开头的密钥,这就是填进客户端的东西。

6 用 Lucky 反代暴露到外网

到这一步网关只在内网可用。要外网访问,不要直接把 3000 端口转发出去——那是明文 HTTP,密钥会在公网上裸奔。

6.1 架构

沿用我现有的 Lucky 反代思路,在它后面再加一跳:

text
外网 HTTPS → Lucky(SSL 卸载 + 基础认证)→ New API (http://192.168.x.x:3000) → 上游

Lucky 负责证书和第一道门,New API 负责真正的鉴权和计费。

6.2 Lucky 反代规则

在 Lucky 后台(默认 http://内网IP:16601)「Web 服务」 里新建规则:

配置项值
监听端口888(沿用你现有的主入口端口)
开启 TLS是,选已申请的泛域名证书
前端域名api.你的域名.com
后端地址http://192.168.x.x:3000

然后在 「安全设置 → 基本认证 → 网页认证」 里加一层账号密码,认证信息如 admin:你的强密码。

为什么网关已经要填密钥了,外面还要再套一层认证? 因为 Basic Auth 拦在请求到达应用之前,能挡掉绝大部分自动化扫描和暴力尝试。应用层的密钥校验是第二道,不是第一道。

6.3 可选:叠加雷池 WAF

如果需要更强的防护,可以在 Lucky 和 New API 之间再插一层雷池:

  • Lucky 后端地址指向雷池的 IP 和端口(如 http://192.168.x.x:29080),不要直接指 New API;
  • 雷池里添加站点,上游填 New API 的真实地址 http://192.168.x.x:3000。

这样流量链路变成「Lucky → 雷池 → New API」,异常请求在雷池就被拦掉了。缺点是增加一跳,延迟会略升,个人使用其实不是必需。

7 客户端接入

网关搭好后,所有客户端只需填两项:

平台客户端需填内容
电脑Cherry Studio / ChatboxAPI 地址 https://api.你的域名.com,密钥 sk-xxx
网页NextChat 自建同上
手机同款客户端 App同上
浏览器沉浸式翻译等插件填 OpenAI 兼容地址与密钥

验证方法:在任一客户端里点「获取模型列表」,能拉出你在渠道里配置过的模型名,说明整条链路通了。

8 安全清单

上线前逐条对照:

检查项要求
管理员密码已从默认 123456 改掉
公网暴露只暴露 Lucky 的 888 端口,3000、3306、6379 一律不对公网开放
数据库/缓存使用容器内网互联(expose),无端口映射
传输加密外网全程 HTTPS,证书由 Lucky 自动续期
入口认证Lucky 已开启 Basic Auth
令牌管理一设备一令牌,可单独吊销
日志定期检查异常调用记录,LOG_KEEP_DAYS 已设置
数据库密码SQL_DSN 与 MYSQL_ROOT_PASSWORD 已改为强密码,非示例值

⚠️ 第 1 条和第 8 条最容易被忽略——示例配置里的密码是给人看的占位符,直接复制上线的账号等于把门开着。

9 总结

  • 网关的价值是把碎片收敛成一处:一个地址、一套密钥、一份用量统计。
  • New API 负责管理,Lucky 负责安全暴露,两者职责不要混。
  • 外网访问必须走 HTTPS + 入口认证,永远不要直接转发应用端口。
  • 这份方案同样适用于把本地 Ollama 分享给家人朋友,但要清楚:共享上游 API 可能违反上游服务条款,自建网关合规的前提是只用自己有权使用的接口。

Created with ❤️ by 张萌萌

用 New API 搭建统一 LLM 网关与 Lucky 反代外网访问

https://blog.nw177.cn/blog/10-技术专栏/50-AI/02.用-New-API-搭建统一-LLM-网关与-Lucky-反代外网访问
作者
张萌萌
发布于
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。