@lightharu/krouter 1.8.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 +679 -0
- package/README.md +238 -0
- package/dist-web/assets/index-CM4-0adf.css +1 -0
- package/dist-web/assets/index-DCslvfUR.js +139 -0
- package/dist-web/favicon.svg +9 -0
- package/dist-web/icon.svg +9 -0
- package/dist-web/index.html +19 -0
- package/out-server/main/kiroAuthSync.js +249 -0
- package/out-server/main/kproxy/certManager.js +262 -0
- package/out-server/main/kproxy/index.js +254 -0
- package/out-server/main/kproxy/mitmProxy.js +475 -0
- package/out-server/main/kproxy/types.js +23 -0
- package/out-server/main/proxy/accountPool.js +543 -0
- package/out-server/main/proxy/clientConfig.js +596 -0
- package/out-server/main/proxy/index.js +25 -0
- package/out-server/main/proxy/kiroApi.js +1996 -0
- package/out-server/main/proxy/logger.js +407 -0
- package/out-server/main/proxy/modelCatalog.js +75 -0
- package/out-server/main/proxy/promptCacheTracker.js +301 -0
- package/out-server/main/proxy/proxyServer.js +3543 -0
- package/out-server/main/proxy/selfSignedCert.js +179 -0
- package/out-server/main/proxy/systemProxy.js +250 -0
- package/out-server/main/proxy/tokenCounter.js +164 -0
- package/out-server/main/proxy/toolNameRegistry.js +57 -0
- package/out-server/main/proxy/translator.js +1084 -0
- package/out-server/main/proxy/types.js +3 -0
- package/out-server/main/registration/browser-identity.js +184 -0
- package/out-server/main/registration/chainProxy.js +349 -0
- package/out-server/main/registration/config.js +58 -0
- package/out-server/main/registration/email-service.js +801 -0
- package/out-server/main/registration/fingerprint.js +352 -0
- package/out-server/main/registration/http-utils.js +148 -0
- package/out-server/main/registration/jwe.js +74 -0
- package/out-server/main/registration/names.js +142 -0
- package/out-server/main/registration/proton-mail-window.js +339 -0
- package/out-server/main/registration/registrar.js +1715 -0
- package/out-server/main/registration/tlsClientPool.js +70 -0
- package/out-server/main/registration/xxtea.js +161 -0
- package/out-server/main/runtimePaths.js +19 -0
- package/out-server/main/utils/redact.js +95 -0
- package/out-server/server/index.js +1272 -0
- package/out-server/server/services/accountExtras.js +105 -0
- package/out-server/server/services/accountProfileHydration.js +95 -0
- package/out-server/server/services/authFlows.js +509 -0
- package/out-server/server/services/dashboardTunnel.js +315 -0
- package/out-server/server/services/diagnostics.js +326 -0
- package/out-server/server/services/kiroAccounts.js +431 -0
- package/out-server/server/services/kiroSettings.js +260 -0
- package/out-server/server/services/kproxyRuntime.js +264 -0
- package/out-server/server/services/localKiroCredentials.js +320 -0
- package/out-server/server/services/machineIdRuntime.js +327 -0
- package/out-server/server/services/protonBrowserRuntime.js +724 -0
- package/out-server/server/services/proxyRuntime.js +523 -0
- package/out-server/server/services/registrationRuntime.js +106 -0
- package/out-server/server/store.js +266 -0
- package/package.json +113 -0
- package/resources/tls-client-xgo-1.14.0-windows-amd64.dll +0 -0
- package/scripts/kiro-manager-cli.cjs +3 -0
- package/scripts/krouter-cli.cjs +509 -0
- package/src/renderer/src/assets/krouter-logo.svg +11 -0
- package/src/renderer/src/assets/krouter-mark.svg +9 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MitmProxy = void 0;
|
|
37
|
+
// K-Proxy MITM 代理核心
|
|
38
|
+
const http = __importStar(require("http"));
|
|
39
|
+
const net = __importStar(require("net"));
|
|
40
|
+
const tls = __importStar(require("tls"));
|
|
41
|
+
const url = __importStar(require("url"));
|
|
42
|
+
// Machine ID 正则匹配模式(64位十六进制)
|
|
43
|
+
const MACHINE_ID_REGEX = /[a-f0-9]{64}/gi;
|
|
44
|
+
// 支持两种格式:KiroIDE-0.6.18-{machineId} 或 KiroIDE 0.6.18 {machineId}
|
|
45
|
+
const KIRO_UA_REGEX = /KiroIDE[-\s][\d.]+[-\s]([a-f0-9]{64})/i;
|
|
46
|
+
/**
|
|
47
|
+
* K-Proxy MITM 代理服务器
|
|
48
|
+
*/
|
|
49
|
+
class MitmProxy {
|
|
50
|
+
server = null;
|
|
51
|
+
certManager;
|
|
52
|
+
config;
|
|
53
|
+
stats;
|
|
54
|
+
events;
|
|
55
|
+
tlsServers = new Map();
|
|
56
|
+
/** 跟踪所有 CONNECT 隧道客户端连接,stop() 时强制销毁,避免 server.close() 等 Keep-Alive 超时 */
|
|
57
|
+
sockets = new Set();
|
|
58
|
+
constructor(certManager, config, events = {}) {
|
|
59
|
+
this.certManager = certManager;
|
|
60
|
+
this.config = config;
|
|
61
|
+
this.events = events;
|
|
62
|
+
this.stats = {
|
|
63
|
+
totalRequests: 0,
|
|
64
|
+
mitmRequests: 0,
|
|
65
|
+
bypassRequests: 0,
|
|
66
|
+
modifiedRequests: 0,
|
|
67
|
+
startTime: 0,
|
|
68
|
+
lastRequestTime: 0
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 启动代理服务器
|
|
73
|
+
*/
|
|
74
|
+
async start() {
|
|
75
|
+
if (this.server) {
|
|
76
|
+
console.log('[MitmProxy] Server already running');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
return new Promise((resolve, reject) => {
|
|
80
|
+
this.server = http.createServer((req, res) => {
|
|
81
|
+
this.handleHttpRequest(req, res);
|
|
82
|
+
});
|
|
83
|
+
// 处理 CONNECT 请求(HTTPS 隧道)
|
|
84
|
+
this.server.on('connect', (req, clientSocket, head) => {
|
|
85
|
+
this.handleConnect(req, clientSocket, head);
|
|
86
|
+
});
|
|
87
|
+
this.server.on('error', (error) => {
|
|
88
|
+
if (error.code === 'EADDRINUSE') {
|
|
89
|
+
console.error(`[MitmProxy] Port ${this.config.port} is already in use`);
|
|
90
|
+
reject(new Error(`Port ${this.config.port} is already in use`));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.error('[MitmProxy] Server error:', error);
|
|
94
|
+
this.events.onError?.(error);
|
|
95
|
+
reject(error);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
this.server.listen(this.config.port, this.config.host, () => {
|
|
99
|
+
console.log(`[MitmProxy] Started on ${this.config.host}:${this.config.port}`);
|
|
100
|
+
this.stats.startTime = Date.now();
|
|
101
|
+
this.events.onStatusChange?.(true, this.config.port);
|
|
102
|
+
resolve();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 停止代理服务器
|
|
108
|
+
*/
|
|
109
|
+
async stop() {
|
|
110
|
+
if (!this.server) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// 关闭所有 TLS 服务器
|
|
114
|
+
for (const [_host, tlsServer] of this.tlsServers) {
|
|
115
|
+
try {
|
|
116
|
+
tlsServer.close();
|
|
117
|
+
}
|
|
118
|
+
catch { /* ignore */ }
|
|
119
|
+
}
|
|
120
|
+
this.tlsServers.clear();
|
|
121
|
+
// 强制销毁所有活跃隧道连接:否则 server.close() 会等 Keep-Alive 连接自然超时(~60s)
|
|
122
|
+
for (const sock of this.sockets) {
|
|
123
|
+
try {
|
|
124
|
+
sock.destroy();
|
|
125
|
+
}
|
|
126
|
+
catch { /* ignore */ }
|
|
127
|
+
}
|
|
128
|
+
this.sockets.clear();
|
|
129
|
+
const srv = this.server;
|
|
130
|
+
this.server = null;
|
|
131
|
+
return new Promise((resolve) => {
|
|
132
|
+
const finish = () => {
|
|
133
|
+
console.log('[MitmProxy] Stopped');
|
|
134
|
+
this.events.onStatusChange?.(false, this.config.port);
|
|
135
|
+
resolve();
|
|
136
|
+
};
|
|
137
|
+
srv.close(() => finish());
|
|
138
|
+
// 双保险:1 秒后无论 close 回调是否触发都 resolve
|
|
139
|
+
setTimeout(finish, 1000);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* 处理 HTTP 请求
|
|
144
|
+
*/
|
|
145
|
+
handleHttpRequest(req, res) {
|
|
146
|
+
this.stats.totalRequests++;
|
|
147
|
+
this.stats.lastRequestTime = Date.now();
|
|
148
|
+
const targetUrl = url.parse(req.url || '');
|
|
149
|
+
const options = {
|
|
150
|
+
hostname: targetUrl.hostname,
|
|
151
|
+
port: targetUrl.port || 80,
|
|
152
|
+
path: targetUrl.path,
|
|
153
|
+
method: req.method,
|
|
154
|
+
headers: req.headers
|
|
155
|
+
};
|
|
156
|
+
const proxyReq = http.request(options, (proxyRes) => {
|
|
157
|
+
res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
|
|
158
|
+
proxyRes.pipe(res);
|
|
159
|
+
});
|
|
160
|
+
proxyReq.on('error', (error) => {
|
|
161
|
+
console.error('[MitmProxy] HTTP proxy error:', error);
|
|
162
|
+
res.writeHead(502);
|
|
163
|
+
res.end('Bad Gateway');
|
|
164
|
+
});
|
|
165
|
+
req.pipe(proxyReq);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* 处理 CONNECT 请求(HTTPS 隧道)
|
|
169
|
+
*/
|
|
170
|
+
handleConnect(req, clientSocket, head) {
|
|
171
|
+
// 跟踪隧道连接,stop() 时强制断开
|
|
172
|
+
this.sockets.add(clientSocket);
|
|
173
|
+
clientSocket.once('close', () => this.sockets.delete(clientSocket));
|
|
174
|
+
this.stats.totalRequests++;
|
|
175
|
+
this.stats.lastRequestTime = Date.now();
|
|
176
|
+
const [hostname, portStr] = (req.url || '').split(':');
|
|
177
|
+
const port = parseInt(portStr, 10) || 443;
|
|
178
|
+
// 检查是否需要 MITM
|
|
179
|
+
const shouldMitm = this.shouldMitm(hostname);
|
|
180
|
+
if (shouldMitm) {
|
|
181
|
+
this.stats.mitmRequests++;
|
|
182
|
+
this.handleMitmConnect(hostname, port, clientSocket, head);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
this.stats.bypassRequests++;
|
|
186
|
+
this.handleDirectConnect(hostname, port, clientSocket, head);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 检查域名是否需要 MITM
|
|
191
|
+
*/
|
|
192
|
+
shouldMitm(hostname) {
|
|
193
|
+
for (const domain of this.config.mitmDomains) {
|
|
194
|
+
if (hostname.includes(domain)) {
|
|
195
|
+
if (this.config.logRequests) {
|
|
196
|
+
console.log(`[MitmProxy] MITM: ${hostname} matches ${domain}`);
|
|
197
|
+
}
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (this.config.logRequests) {
|
|
202
|
+
console.log(`[MitmProxy] Bypass: ${hostname}`);
|
|
203
|
+
}
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* 直接转发连接(不解密)
|
|
208
|
+
*/
|
|
209
|
+
handleDirectConnect(hostname, port, clientSocket, head) {
|
|
210
|
+
const serverSocket = net.connect(port, hostname, () => {
|
|
211
|
+
clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
|
|
212
|
+
serverSocket.write(head);
|
|
213
|
+
serverSocket.pipe(clientSocket);
|
|
214
|
+
clientSocket.pipe(serverSocket);
|
|
215
|
+
});
|
|
216
|
+
serverSocket.on('error', (error) => {
|
|
217
|
+
console.error(`[MitmProxy] Direct connect error to ${hostname}:${port}:`, error.message);
|
|
218
|
+
clientSocket.end();
|
|
219
|
+
});
|
|
220
|
+
clientSocket.on('error', (error) => {
|
|
221
|
+
console.error(`[MitmProxy] Client socket error:`, error.message);
|
|
222
|
+
serverSocket.end();
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* MITM 拦截连接
|
|
227
|
+
*/
|
|
228
|
+
handleMitmConnect(hostname, port, clientSocket, _head) {
|
|
229
|
+
try {
|
|
230
|
+
// 为目标域名生成证书
|
|
231
|
+
const { cert, key } = this.certManager.generateCertForHost(hostname);
|
|
232
|
+
// 创建 TLS 连接选项
|
|
233
|
+
const tlsOptions = {
|
|
234
|
+
key,
|
|
235
|
+
cert
|
|
236
|
+
};
|
|
237
|
+
// 通知客户端连接已建立
|
|
238
|
+
clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
|
|
239
|
+
// 创建 TLS 连接
|
|
240
|
+
const tlsSocket = new tls.TLSSocket(clientSocket, {
|
|
241
|
+
...tlsOptions,
|
|
242
|
+
isServer: true
|
|
243
|
+
});
|
|
244
|
+
// 处理 TLS 错误
|
|
245
|
+
tlsSocket.on('error', (error) => {
|
|
246
|
+
console.error(`[MitmProxy] TLS error for ${hostname}:`, error.message);
|
|
247
|
+
clientSocket.end();
|
|
248
|
+
});
|
|
249
|
+
// 处理解密后的请求
|
|
250
|
+
this.handleDecryptedConnection(tlsSocket, hostname, port);
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
console.error(`[MitmProxy] MITM setup error for ${hostname}:`, error);
|
|
254
|
+
clientSocket.end();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* 处理解密后的 HTTPS 连接
|
|
259
|
+
*/
|
|
260
|
+
handleDecryptedConnection(clientSocket, hostname, port) {
|
|
261
|
+
let requestData = '';
|
|
262
|
+
let headersParsed = false;
|
|
263
|
+
let contentLength = 0;
|
|
264
|
+
let bodyReceived = 0;
|
|
265
|
+
let modifiedHeaders = '';
|
|
266
|
+
let requestInfo = null;
|
|
267
|
+
clientSocket.on('data', (chunk) => {
|
|
268
|
+
if (!headersParsed) {
|
|
269
|
+
requestData += chunk.toString();
|
|
270
|
+
const headerEnd = requestData.indexOf('\r\n\r\n');
|
|
271
|
+
if (headerEnd !== -1) {
|
|
272
|
+
headersParsed = true;
|
|
273
|
+
const headers = requestData.substring(0, headerEnd);
|
|
274
|
+
const body = requestData.substring(headerEnd + 4);
|
|
275
|
+
// 解析并修改请求头
|
|
276
|
+
const { modified, newHeaders, info } = this.modifyHeaders(headers, hostname);
|
|
277
|
+
modifiedHeaders = newHeaders;
|
|
278
|
+
requestInfo = info;
|
|
279
|
+
// 记录请求
|
|
280
|
+
if (requestInfo) {
|
|
281
|
+
this.events.onRequest?.(requestInfo);
|
|
282
|
+
this.events.onMitmIntercept?.(hostname, modified);
|
|
283
|
+
}
|
|
284
|
+
// 获取 Content-Length
|
|
285
|
+
const clMatch = headers.match(/content-length:\s*(\d+)/i);
|
|
286
|
+
if (clMatch) {
|
|
287
|
+
contentLength = parseInt(clMatch[1], 10);
|
|
288
|
+
}
|
|
289
|
+
// 替换 body 中的 machineId
|
|
290
|
+
const modifiedBody = this.modifyBody(body);
|
|
291
|
+
if (modifiedBody !== body) {
|
|
292
|
+
// body 长度变了,更新 Content-Length
|
|
293
|
+
const newLength = contentLength - Buffer.byteLength(body) + Buffer.byteLength(modifiedBody);
|
|
294
|
+
modifiedHeaders = modifiedHeaders.replace(/content-length:\s*\d+/i, `content-length: ${newLength}`);
|
|
295
|
+
contentLength = newLength;
|
|
296
|
+
}
|
|
297
|
+
bodyReceived = Buffer.byteLength(modifiedBody);
|
|
298
|
+
// 转发请求到目标服务器
|
|
299
|
+
this.forwardRequest(modifiedHeaders, modifiedBody, hostname, port, clientSocket, contentLength, bodyReceived);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
clientSocket.on('error', (error) => {
|
|
304
|
+
console.error(`[MitmProxy] Decrypted connection error:`, error.message);
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* 替换请求体中的 Machine ID
|
|
309
|
+
*/
|
|
310
|
+
modifyBody(body) {
|
|
311
|
+
const targetDeviceId = this.config.deviceId;
|
|
312
|
+
if (!targetDeviceId || !body)
|
|
313
|
+
return body;
|
|
314
|
+
// 只在 body 中包含 64 位十六进制时才替换(避免误伤无关内容)
|
|
315
|
+
if (!MACHINE_ID_REGEX.test(body))
|
|
316
|
+
return body;
|
|
317
|
+
MACHINE_ID_REGEX.lastIndex = 0;
|
|
318
|
+
const result = body.replace(MACHINE_ID_REGEX, (match) => {
|
|
319
|
+
// 不替换已经是目标 ID 的
|
|
320
|
+
if (match.toLowerCase() === targetDeviceId.toLowerCase())
|
|
321
|
+
return match;
|
|
322
|
+
if (this.config.logRequests) {
|
|
323
|
+
console.log(`[MitmProxy] Replaced Machine ID in body: ${match.substring(0, 16)}... -> ${targetDeviceId.substring(0, 16)}...`);
|
|
324
|
+
}
|
|
325
|
+
return targetDeviceId;
|
|
326
|
+
});
|
|
327
|
+
MACHINE_ID_REGEX.lastIndex = 0;
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* 修改请求头(替换 Machine ID)
|
|
332
|
+
*/
|
|
333
|
+
modifyHeaders(headers, hostname) {
|
|
334
|
+
const lines = headers.split('\r\n');
|
|
335
|
+
const firstLine = lines[0];
|
|
336
|
+
const [method, path] = firstLine.split(' ');
|
|
337
|
+
let modified = false;
|
|
338
|
+
let originalDeviceId;
|
|
339
|
+
let newDeviceId;
|
|
340
|
+
const targetDeviceId = this.config.deviceId;
|
|
341
|
+
const info = {
|
|
342
|
+
timestamp: Date.now(),
|
|
343
|
+
method: method || 'UNKNOWN',
|
|
344
|
+
host: hostname,
|
|
345
|
+
path: path || '/',
|
|
346
|
+
isMitm: true,
|
|
347
|
+
deviceIdReplaced: false
|
|
348
|
+
};
|
|
349
|
+
if (!targetDeviceId) {
|
|
350
|
+
return { modified: false, newHeaders: headers, info };
|
|
351
|
+
}
|
|
352
|
+
const modifiedLines = lines.map((line) => {
|
|
353
|
+
const lowerLine = line.toLowerCase();
|
|
354
|
+
// 检查 user-agent 和 x-amz-user-agent
|
|
355
|
+
if (lowerLine.startsWith('user-agent:') || lowerLine.startsWith('x-amz-user-agent:')) {
|
|
356
|
+
const match = line.match(KIRO_UA_REGEX);
|
|
357
|
+
if (match) {
|
|
358
|
+
originalDeviceId = match[1];
|
|
359
|
+
const newLine = line.replace(MACHINE_ID_REGEX, targetDeviceId);
|
|
360
|
+
if (newLine !== line) {
|
|
361
|
+
modified = true;
|
|
362
|
+
newDeviceId = targetDeviceId;
|
|
363
|
+
if (this.config.logRequests) {
|
|
364
|
+
console.log(`[MitmProxy] Replaced Machine ID in ${line.split(':')[0]}`);
|
|
365
|
+
console.log(` Original: ${originalDeviceId?.substring(0, 16)}...`);
|
|
366
|
+
console.log(` New: ${targetDeviceId.substring(0, 16)}...`);
|
|
367
|
+
}
|
|
368
|
+
return newLine;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return line;
|
|
373
|
+
});
|
|
374
|
+
if (modified) {
|
|
375
|
+
this.stats.modifiedRequests++;
|
|
376
|
+
info.deviceIdReplaced = true;
|
|
377
|
+
info.originalDeviceId = originalDeviceId;
|
|
378
|
+
info.newDeviceId = newDeviceId;
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
modified,
|
|
382
|
+
newHeaders: modifiedLines.join('\r\n'),
|
|
383
|
+
info
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* 转发请求到目标服务器
|
|
388
|
+
*/
|
|
389
|
+
forwardRequest(headers, initialBody, hostname, port, clientSocket, contentLength, bodyReceived) {
|
|
390
|
+
const startTime = Date.now();
|
|
391
|
+
// 连接到目标服务器
|
|
392
|
+
const serverSocket = tls.connect({
|
|
393
|
+
host: hostname,
|
|
394
|
+
port,
|
|
395
|
+
servername: hostname,
|
|
396
|
+
rejectUnauthorized: true
|
|
397
|
+
}, () => {
|
|
398
|
+
// 发送修改后的请求头
|
|
399
|
+
serverSocket.write(headers + '\r\n\r\n');
|
|
400
|
+
// 发送已接收的请求体
|
|
401
|
+
if (initialBody) {
|
|
402
|
+
serverSocket.write(initialBody);
|
|
403
|
+
}
|
|
404
|
+
// 如果还有更多数据,继续转发
|
|
405
|
+
if (bodyReceived < contentLength) {
|
|
406
|
+
clientSocket.on('data', (chunk) => {
|
|
407
|
+
serverSocket.write(chunk);
|
|
408
|
+
bodyReceived += chunk.length;
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
// 将响应转发回客户端
|
|
413
|
+
serverSocket.on('data', (chunk) => {
|
|
414
|
+
clientSocket.write(chunk);
|
|
415
|
+
});
|
|
416
|
+
serverSocket.on('end', () => {
|
|
417
|
+
const duration = Date.now() - startTime;
|
|
418
|
+
this.events.onResponse?.({
|
|
419
|
+
timestamp: Date.now(),
|
|
420
|
+
host: hostname,
|
|
421
|
+
statusCode: 200,
|
|
422
|
+
duration
|
|
423
|
+
});
|
|
424
|
+
clientSocket.end();
|
|
425
|
+
});
|
|
426
|
+
serverSocket.on('error', (error) => {
|
|
427
|
+
console.error(`[MitmProxy] Server connection error to ${hostname}:`, error.message);
|
|
428
|
+
clientSocket.end();
|
|
429
|
+
});
|
|
430
|
+
clientSocket.on('end', () => {
|
|
431
|
+
serverSocket.end();
|
|
432
|
+
});
|
|
433
|
+
clientSocket.on('error', () => {
|
|
434
|
+
serverSocket.end();
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* 更新配置
|
|
439
|
+
*/
|
|
440
|
+
updateConfig(config) {
|
|
441
|
+
this.config = { ...this.config, ...config };
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* 获取配置
|
|
445
|
+
*/
|
|
446
|
+
getConfig() {
|
|
447
|
+
return { ...this.config };
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* 获取统计信息
|
|
451
|
+
*/
|
|
452
|
+
getStats() {
|
|
453
|
+
return { ...this.stats };
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* 重置统计
|
|
457
|
+
*/
|
|
458
|
+
resetStats() {
|
|
459
|
+
this.stats = {
|
|
460
|
+
totalRequests: 0,
|
|
461
|
+
mitmRequests: 0,
|
|
462
|
+
bypassRequests: 0,
|
|
463
|
+
modifiedRequests: 0,
|
|
464
|
+
startTime: this.stats.startTime,
|
|
465
|
+
lastRequestTime: 0
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* 检查是否运行中
|
|
470
|
+
*/
|
|
471
|
+
isRunning() {
|
|
472
|
+
return this.server !== null;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
exports.MitmProxy = MitmProxy;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// K-Proxy 类型定义
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.DEFAULT_KPROXY_CONFIG = exports.DEFAULT_MITM_DOMAINS = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* 默认 MITM 域名白名单
|
|
7
|
+
*/
|
|
8
|
+
exports.DEFAULT_MITM_DOMAINS = [
|
|
9
|
+
'amazonaws.com',
|
|
10
|
+
'amazon.com',
|
|
11
|
+
'kiro.dev'
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* 默认 K-Proxy 配置
|
|
15
|
+
*/
|
|
16
|
+
exports.DEFAULT_KPROXY_CONFIG = {
|
|
17
|
+
enabled: false,
|
|
18
|
+
port: 8899,
|
|
19
|
+
host: '127.0.0.1',
|
|
20
|
+
mitmDomains: exports.DEFAULT_MITM_DOMAINS,
|
|
21
|
+
autoStart: false,
|
|
22
|
+
logRequests: true
|
|
23
|
+
};
|