@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.
Files changed (61) hide show
  1. package/LICENSE +679 -0
  2. package/README.md +238 -0
  3. package/dist-web/assets/index-CM4-0adf.css +1 -0
  4. package/dist-web/assets/index-DCslvfUR.js +139 -0
  5. package/dist-web/favicon.svg +9 -0
  6. package/dist-web/icon.svg +9 -0
  7. package/dist-web/index.html +19 -0
  8. package/out-server/main/kiroAuthSync.js +249 -0
  9. package/out-server/main/kproxy/certManager.js +262 -0
  10. package/out-server/main/kproxy/index.js +254 -0
  11. package/out-server/main/kproxy/mitmProxy.js +475 -0
  12. package/out-server/main/kproxy/types.js +23 -0
  13. package/out-server/main/proxy/accountPool.js +543 -0
  14. package/out-server/main/proxy/clientConfig.js +596 -0
  15. package/out-server/main/proxy/index.js +25 -0
  16. package/out-server/main/proxy/kiroApi.js +1996 -0
  17. package/out-server/main/proxy/logger.js +407 -0
  18. package/out-server/main/proxy/modelCatalog.js +75 -0
  19. package/out-server/main/proxy/promptCacheTracker.js +301 -0
  20. package/out-server/main/proxy/proxyServer.js +3543 -0
  21. package/out-server/main/proxy/selfSignedCert.js +179 -0
  22. package/out-server/main/proxy/systemProxy.js +250 -0
  23. package/out-server/main/proxy/tokenCounter.js +164 -0
  24. package/out-server/main/proxy/toolNameRegistry.js +57 -0
  25. package/out-server/main/proxy/translator.js +1084 -0
  26. package/out-server/main/proxy/types.js +3 -0
  27. package/out-server/main/registration/browser-identity.js +184 -0
  28. package/out-server/main/registration/chainProxy.js +349 -0
  29. package/out-server/main/registration/config.js +58 -0
  30. package/out-server/main/registration/email-service.js +801 -0
  31. package/out-server/main/registration/fingerprint.js +352 -0
  32. package/out-server/main/registration/http-utils.js +148 -0
  33. package/out-server/main/registration/jwe.js +74 -0
  34. package/out-server/main/registration/names.js +142 -0
  35. package/out-server/main/registration/proton-mail-window.js +339 -0
  36. package/out-server/main/registration/registrar.js +1715 -0
  37. package/out-server/main/registration/tlsClientPool.js +70 -0
  38. package/out-server/main/registration/xxtea.js +161 -0
  39. package/out-server/main/runtimePaths.js +19 -0
  40. package/out-server/main/utils/redact.js +95 -0
  41. package/out-server/server/index.js +1272 -0
  42. package/out-server/server/services/accountExtras.js +105 -0
  43. package/out-server/server/services/accountProfileHydration.js +95 -0
  44. package/out-server/server/services/authFlows.js +509 -0
  45. package/out-server/server/services/dashboardTunnel.js +315 -0
  46. package/out-server/server/services/diagnostics.js +326 -0
  47. package/out-server/server/services/kiroAccounts.js +431 -0
  48. package/out-server/server/services/kiroSettings.js +260 -0
  49. package/out-server/server/services/kproxyRuntime.js +264 -0
  50. package/out-server/server/services/localKiroCredentials.js +320 -0
  51. package/out-server/server/services/machineIdRuntime.js +327 -0
  52. package/out-server/server/services/protonBrowserRuntime.js +724 -0
  53. package/out-server/server/services/proxyRuntime.js +523 -0
  54. package/out-server/server/services/registrationRuntime.js +106 -0
  55. package/out-server/server/store.js +266 -0
  56. package/package.json +113 -0
  57. package/resources/tls-client-xgo-1.14.0-windows-amd64.dll +0 -0
  58. package/scripts/kiro-manager-cli.cjs +3 -0
  59. package/scripts/krouter-cli.cjs +509 -0
  60. package/src/renderer/src/assets/krouter-logo.svg +11 -0
  61. 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
+ };