iflow-local-proxy 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/bin/cli.js +69 -0
- package/config.yaml +56 -0
- package/package.json +43 -0
- package/src/anthropic/adapter.js +457 -0
- package/src/auth/credentials.js +239 -0
- package/src/auth/oauth-cli.js +47 -0
- package/src/auth/oauth.js +127 -0
- package/src/config.js +76 -0
- package/src/iflow/client.js +102 -0
- package/src/iflow/models.js +69 -0
- package/src/iflow/signature.js +42 -0
- package/src/index.js +774 -0
- package/src/protection/circuit-breaker.js +207 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# iFlow Local Proxy - 本地安全反代(单账号模式)
|
|
2
|
+
|
|
3
|
+
仅绑定 `127.0.0.1` 的 iFlow API 反向代理,内置多层防封保护机制。**仅支持单个账号**。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- **🔒 仅本地访问** - 绑定 127.0.0.1,外部网络完全不可达
|
|
8
|
+
- **🛡️ 熔断器** - 收到 434 (AK blocked) 立即停止所有请求,避免连续触发封禁
|
|
9
|
+
- **⏱️ 请求节流** - 最小间隔 + 随机抖动,模拟自然使用节奏
|
|
10
|
+
- **📋 模型白名单** - 只允许请求已确认存在的模型,避免无效请求触发风控
|
|
11
|
+
- **🔑 HMAC 签名** - 每个请求携带签名,完全模拟官方 CLI 行为
|
|
12
|
+
- **🔄 自动刷新** - OAuth / Cookie 凭据自动续期
|
|
13
|
+
- **👤 单账号模式** - 仅使用一个账号,设置新账号自动覆盖旧的
|
|
14
|
+
|
|
15
|
+
## 安装
|
|
16
|
+
|
|
17
|
+
### 方式一: npm 全局安装(推荐)
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g iflow-local-proxy
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
安装后直接使用:
|
|
23
|
+
```bash
|
|
24
|
+
# 启动代理
|
|
25
|
+
iflow-local-proxy
|
|
26
|
+
|
|
27
|
+
# OAuth 手机号登录
|
|
28
|
+
iflow-local-proxy login
|
|
29
|
+
|
|
30
|
+
# 指定端口
|
|
31
|
+
iflow-local-proxy --port 9000
|
|
32
|
+
|
|
33
|
+
# 指定配置文件
|
|
34
|
+
iflow-local-proxy --config /path/to/config.yaml
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 方式二: npx 免安装运行
|
|
38
|
+
```bash
|
|
39
|
+
npx iflow-local-proxy
|
|
40
|
+
npx iflow-local-proxy login
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 方式三: 源码运行
|
|
44
|
+
```bash
|
|
45
|
+
git clone <repo-url>
|
|
46
|
+
cd iflow-local-proxy
|
|
47
|
+
npm install
|
|
48
|
+
npm start
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 添加凭据
|
|
52
|
+
|
|
53
|
+
### 方式一: 设置 API Key(最简单)
|
|
54
|
+
```bash
|
|
55
|
+
curl -X POST http://127.0.0.1:8318/api/account/set-key ^
|
|
56
|
+
-H "Content-Type: application/json" ^
|
|
57
|
+
-d "{\"apiKey\": \"sk-xxx\", \"name\": \"my-account\"}"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 方式二: OAuth 登录
|
|
61
|
+
```bash
|
|
62
|
+
npm run login
|
|
63
|
+
# 或通过 API:
|
|
64
|
+
# POST http://127.0.0.1:8318/api/login/oauth
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 方式三: Cookie 登录
|
|
68
|
+
```bash
|
|
69
|
+
curl -X POST http://127.0.0.1:8318/api/account/set-cookie ^
|
|
70
|
+
-H "Content-Type: application/json" ^
|
|
71
|
+
-d "{\"cookie\": \"BXAuth=xxx;\", \"name\": \"cookie-account\"}"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
> **注意**: 单账号模式下,设置新账号会自动删除旧账号。
|
|
75
|
+
|
|
76
|
+
## API 端点
|
|
77
|
+
|
|
78
|
+
### 代理端点 (兼容 OpenAI / Anthropic)
|
|
79
|
+
| 方法 | 路径 | 说明 |
|
|
80
|
+
|------|------|------|
|
|
81
|
+
| GET | `/v1/models` | 模型列表 |
|
|
82
|
+
| POST | `/v1/chat/completions` | OpenAI 格式聊天 |
|
|
83
|
+
| POST | `/v1/messages` | Anthropic 格式聊天 |
|
|
84
|
+
| POST | `/v1/messages/count_tokens` | Token 计数 |
|
|
85
|
+
|
|
86
|
+
### 管理端点
|
|
87
|
+
| 方法 | 路径 | 说明 |
|
|
88
|
+
|------|------|------|
|
|
89
|
+
| GET | `/` | 服务状态概览 |
|
|
90
|
+
| GET | `/api/status` | 详细状态 |
|
|
91
|
+
| GET | `/api/account` | 查看当前账号 |
|
|
92
|
+
| POST | `/api/account/set-key` | 设置 API Key (覆盖) |
|
|
93
|
+
| POST | `/api/account/set-cookie` | Cookie 登录 (覆盖) |
|
|
94
|
+
| POST | `/api/account/refresh` | 手动刷新凭据 |
|
|
95
|
+
| DELETE | `/api/account` | 删除当前账号 |
|
|
96
|
+
| GET | `/api/circuit-breaker` | 熔断器状态 |
|
|
97
|
+
| POST | `/api/circuit-breaker/reset` | 重置熔断器 |
|
|
98
|
+
| POST | `/api/login/oauth` | 启动 OAuth 登录 (覆盖) |
|
|
99
|
+
|
|
100
|
+
## 防封保护机制
|
|
101
|
+
|
|
102
|
+
### 1. 熔断器 (Circuit Breaker)
|
|
103
|
+
- 收到 **434 (AK blocked)** 响应 → 立即暂停所有请求(默认 1 小时)
|
|
104
|
+
- 连续 3 次 434 → 永久熔断(需手动 `POST /api/circuit-breaker/reset`)
|
|
105
|
+
- 暂停期间所有请求返回 503,不会发送到上游
|
|
106
|
+
|
|
107
|
+
### 2. 请求节流 (Throttler)
|
|
108
|
+
- 每个请求之间至少间隔 2s + 0~1s 随机抖动
|
|
109
|
+
- 每分钟最多 20 个请求(硬上限)
|
|
110
|
+
- 超出限制时请求排队等待,不会直接拒绝
|
|
111
|
+
|
|
112
|
+
### 3. 模型白名单
|
|
113
|
+
- 只允许向白名单中的模型发送请求
|
|
114
|
+
- 请求不存在的模型会被本地拦截,不会发到上游
|
|
115
|
+
- 可在 `config.yaml` 中配置
|
|
116
|
+
|
|
117
|
+
### 4. HMAC 签名
|
|
118
|
+
- 每个请求自动携带 `x-iflow-signature` / `x-iflow-timestamp` / `session-id`
|
|
119
|
+
- 完全模拟官方 iFlow-Cli 行为
|
|
120
|
+
|
|
121
|
+
## 配置客户端
|
|
122
|
+
|
|
123
|
+
### Claude Code
|
|
124
|
+
```bash
|
|
125
|
+
claude config set --global apiProvider "openai"
|
|
126
|
+
claude config set --global apiBaseUrl "http://127.0.0.1:8318"
|
|
127
|
+
claude config set --global apiKey "any-key"
|
|
128
|
+
claude config set --global model "deepseek-r1"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Cline (VS Code 插件)
|
|
132
|
+
- API Provider: OpenAI Compatible
|
|
133
|
+
- Base URL: `http://127.0.0.1:8318/v1`
|
|
134
|
+
- API Key: 任意值
|
|
135
|
+
- Model: 选择白名单中的模型
|
|
136
|
+
|
|
137
|
+
### OpenAI SDK
|
|
138
|
+
```python
|
|
139
|
+
from openai import OpenAI
|
|
140
|
+
client = OpenAI(base_url="http://127.0.0.1:8318/v1", api_key="any")
|
|
141
|
+
response = client.chat.completions.create(
|
|
142
|
+
model="deepseek-r1",
|
|
143
|
+
messages=[{"role": "user", "content": "hello"}]
|
|
144
|
+
)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 配置说明
|
|
148
|
+
|
|
149
|
+
参见 [config.yaml](config.yaml) 中的详细注释。
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* iflow-local-proxy CLI 入口
|
|
5
|
+
*
|
|
6
|
+
* 用法:
|
|
7
|
+
* iflow-local-proxy 启动代理服务
|
|
8
|
+
* iflow-local-proxy login OAuth 手机号登录
|
|
9
|
+
* iflow-local-proxy --help 显示帮助
|
|
10
|
+
* iflow-local-proxy --version 显示版本
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import fs from 'fs';
|
|
16
|
+
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = path.dirname(__filename);
|
|
19
|
+
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
20
|
+
|
|
21
|
+
// 读版本号
|
|
22
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf-8'));
|
|
23
|
+
|
|
24
|
+
const args = process.argv.slice(2);
|
|
25
|
+
const command = args[0];
|
|
26
|
+
|
|
27
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
28
|
+
console.log(pkg.version);
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
33
|
+
console.log(`
|
|
34
|
+
iflow-local-proxy v${pkg.version}
|
|
35
|
+
iFlow 本地安全反代 - 仅绑定 127.0.0.1,内置熔断器/限速/签名
|
|
36
|
+
|
|
37
|
+
用法:
|
|
38
|
+
iflow-local-proxy 启动代理服务
|
|
39
|
+
iflow-local-proxy login OAuth 手机号登录
|
|
40
|
+
iflow-local-proxy --config <path> 指定配置文件路径
|
|
41
|
+
|
|
42
|
+
选项:
|
|
43
|
+
--config <path> 指定配置文件 (默认: ./config.yaml 或 ~/.iflow-local-proxy/config.yaml)
|
|
44
|
+
--port <port> 覆盖配置中的端口号
|
|
45
|
+
-v, --version 显示版本号
|
|
46
|
+
-h, --help 显示帮助
|
|
47
|
+
|
|
48
|
+
详细文档: https://www.npmjs.com/package/iflow-local-proxy
|
|
49
|
+
`);
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 处理 --port 覆盖
|
|
54
|
+
const portIdx = args.indexOf('--port');
|
|
55
|
+
if (portIdx !== -1 && args[portIdx + 1]) {
|
|
56
|
+
process.env.IFLOW_PORT = args[portIdx + 1];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (command === 'login') {
|
|
60
|
+
// 加载 OAuth CLI 登录
|
|
61
|
+
await import(pathToFileURL(path.join(PKG_ROOT, 'src', 'auth', 'oauth-cli.js')).href);
|
|
62
|
+
} else if (!command || command.startsWith('-')) {
|
|
63
|
+
// 默认: 启动代理服务
|
|
64
|
+
await import(pathToFileURL(path.join(PKG_ROOT, 'src', 'index.js')).href);
|
|
65
|
+
} else {
|
|
66
|
+
console.error(`未知命令: ${command}`);
|
|
67
|
+
console.error('运行 iflow-local-proxy --help 查看帮助');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
package/config.yaml
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# ========================================
|
|
2
|
+
# iFlow 本地安全反代 - 配置文件
|
|
3
|
+
# ========================================
|
|
4
|
+
|
|
5
|
+
# 服务端口(仅绑定 127.0.0.1,外部不可访问)
|
|
6
|
+
port: 8318
|
|
7
|
+
|
|
8
|
+
# 凭据存储目录
|
|
9
|
+
auth-dir: "~/.iflow-local-proxy"
|
|
10
|
+
|
|
11
|
+
# ========================================
|
|
12
|
+
# 防封保护策略
|
|
13
|
+
# ========================================
|
|
14
|
+
protection:
|
|
15
|
+
# 请求最小间隔(毫秒),避免被识别为高频刷API
|
|
16
|
+
min-request-interval: 2000
|
|
17
|
+
|
|
18
|
+
# 请求间隔随机抖动范围(毫秒),叠加在 min-interval 之上使请求间隔更自然
|
|
19
|
+
jitter-max: 1000
|
|
20
|
+
|
|
21
|
+
# 每分钟最大请求数(硬上限)
|
|
22
|
+
max-requests-per-minute: 20
|
|
23
|
+
|
|
24
|
+
# 熔断器:收到 434 (AK blocked) 后立即停止所有请求
|
|
25
|
+
circuit-breaker:
|
|
26
|
+
enabled: true
|
|
27
|
+
# 收到 434 后暂停时间(秒),期间所有请求直接拒绝
|
|
28
|
+
pause-duration: 3600
|
|
29
|
+
# 连续 434 次数阈值,超过此数则永久熔断(需手动恢复)
|
|
30
|
+
max-consecutive-434: 3
|
|
31
|
+
|
|
32
|
+
# 模型白名单(只允许请求已确认存在的模型,避免因请求无效模型被风控)
|
|
33
|
+
# 留空则不限制(不建议)
|
|
34
|
+
model-whitelist:
|
|
35
|
+
- "deepseek-r1"
|
|
36
|
+
- "deepseek-v3"
|
|
37
|
+
- "deepseek-v3.1"
|
|
38
|
+
- "deepseek-v3.2"
|
|
39
|
+
- "deepseek-v3.2-chat"
|
|
40
|
+
- "deepseek-v3.2-reasoner"
|
|
41
|
+
- "glm-4.6"
|
|
42
|
+
- "glm-4.7"
|
|
43
|
+
- "glm-5"
|
|
44
|
+
- "qwen3-32b"
|
|
45
|
+
- "qwen3-235b"
|
|
46
|
+
- "qwen3-max"
|
|
47
|
+
- "qwen3-coder-plus"
|
|
48
|
+
- "kimi-k2"
|
|
49
|
+
- "kimi-k2.5"
|
|
50
|
+
- "minimax-m2"
|
|
51
|
+
- "minimax-m2.5"
|
|
52
|
+
|
|
53
|
+
# 日志级别: debug | info | warn | error
|
|
54
|
+
log-level: "info"
|
|
55
|
+
|
|
56
|
+
# 注: 本项目为单账号模式,不支持多账号轮换
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iflow-local-proxy",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "iFlow 本地安全反代 - 仅绑定 127.0.0.1,内置熔断器/限速/签名,最大程度规避封禁风险",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"iflow-local-proxy": "bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"src/",
|
|
13
|
+
"config.yaml",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"start": "node src/index.js",
|
|
19
|
+
"login": "node src/auth/oauth-cli.js"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"iflow",
|
|
23
|
+
"proxy",
|
|
24
|
+
"openai",
|
|
25
|
+
"anthropic",
|
|
26
|
+
"api",
|
|
27
|
+
"reverse-proxy",
|
|
28
|
+
"local"
|
|
29
|
+
],
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": ""
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18.0.0"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"express": "^4.21.0",
|
|
39
|
+
"uuid": "^9.0.0",
|
|
40
|
+
"yaml": "^2.4.0"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT"
|
|
43
|
+
}
|