bdy 1.11.0-dev → 1.12.0-dev
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/distTs/package.json +16 -5
- package/distTs/src/agent/agent.js +62 -36
- package/distTs/src/agent/linux.js +9 -4
- package/distTs/src/agent/manager.js +61 -42
- package/distTs/src/agent/osx.js +12 -5
- package/distTs/src/agent/socket/client.js +26 -7
- package/distTs/src/agent/socket/tunnel.js +56 -32
- package/distTs/src/agent/socket.js +83 -63
- package/distTs/src/agent/system.js +3 -1
- package/distTs/src/agent/windows.js +6 -6
- package/distTs/src/command/agent/install.js +4 -4
- package/distTs/src/command/agent/run.js +2 -2
- package/distTs/src/command/agent/status.js +6 -7
- package/distTs/src/command/agent/tunnel/http.js +4 -5
- package/distTs/src/command/agent/tunnel/tcp.js +3 -3
- package/distTs/src/command/agent/tunnel/tls.js +3 -3
- package/distTs/src/command/config/add/http.js +3 -3
- package/distTs/src/command/config/add/tcp.js +3 -3
- package/distTs/src/command/config/add/tls.js +3 -3
- package/distTs/src/command/config/get/region.js +1 -1
- package/distTs/src/command/pre.js +1 -1
- package/distTs/src/command/tunnel/http.js +2 -1
- package/distTs/src/command/tunnel/tcp.js +3 -3
- package/distTs/src/command/tunnel/tls.js +4 -4
- package/distTs/src/format.js +14 -15
- package/distTs/src/index.js +1 -1
- package/distTs/src/input.js +13 -12
- package/distTs/src/logger.js +12 -13
- package/distTs/src/tunnel/agent.js +3 -1
- package/distTs/src/tunnel/api/agent.js +1 -0
- package/distTs/src/tunnel/api/buddy.js +2 -0
- package/distTs/src/tunnel/cfg.js +6 -2
- package/distTs/src/tunnel/compression.js +17 -14
- package/distTs/src/tunnel/dns.js +20 -29
- package/distTs/src/tunnel/html.js +2 -0
- package/distTs/src/tunnel/http/log.js +30 -8
- package/distTs/src/tunnel/http/serve.js +3 -2
- package/distTs/src/tunnel/http/stream.js +5 -1
- package/distTs/src/tunnel/http.js +67 -26
- package/distTs/src/tunnel/identification.js +21 -14
- package/distTs/src/tunnel/latency.js +19 -11
- package/distTs/src/tunnel/output/interactive/tunnel.js +16 -9
- package/distTs/src/tunnel/output/noninteractive/agent/tunnels.js +4 -2
- package/distTs/src/tunnel/output/noninteractive/config/tunnel.js +6 -4
- package/distTs/src/tunnel/output/noninteractive/config/tunnels.js +2 -0
- package/distTs/src/tunnel/output/noninteractive/tunnel.js +13 -11
- package/distTs/src/tunnel/server/cert.js +2 -0
- package/distTs/src/tunnel/server/http1.js +15 -10
- package/distTs/src/tunnel/server/http2.js +18 -12
- package/distTs/src/tunnel/server/sftp.js +32 -15
- package/distTs/src/tunnel/server/ssh.js +49 -31
- package/distTs/src/tunnel/server/tls.js +11 -5
- package/distTs/src/tunnel/ssh/client.js +45 -31
- package/distTs/src/tunnel/tcp.js +61 -42
- package/distTs/src/tunnel/tunnel.js +196 -112
- package/distTs/src/types/tunnel.js +135 -0
- package/distTs/src/utils.js +2 -87
- package/package.json +16 -5
|
@@ -3,12 +3,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TunnelHttpLogRequest = void 0;
|
|
6
7
|
const events_1 = __importDefault(require("events"));
|
|
7
8
|
const uuid_1 = require("uuid");
|
|
8
9
|
const stream_1 = __importDefault(require("./stream"));
|
|
9
10
|
const isbinaryfile_1 = require("isbinaryfile");
|
|
10
11
|
const utils_1 = require("../../utils");
|
|
12
|
+
const tunnel_1 = require("../../types/tunnel");
|
|
11
13
|
class TunnelHttpLogRequest extends events_1.default {
|
|
14
|
+
method;
|
|
15
|
+
headers;
|
|
16
|
+
responseHeaders;
|
|
17
|
+
url;
|
|
18
|
+
httpVersion;
|
|
19
|
+
status;
|
|
20
|
+
start;
|
|
21
|
+
finished;
|
|
22
|
+
id;
|
|
23
|
+
requestBody;
|
|
24
|
+
responseBody;
|
|
25
|
+
time;
|
|
12
26
|
constructor(method, headers, url, httpVersion) {
|
|
13
27
|
super();
|
|
14
28
|
this.method = method;
|
|
@@ -21,11 +35,11 @@ class TunnelHttpLogRequest extends events_1.default {
|
|
|
21
35
|
this.id = (0, uuid_1.v4)();
|
|
22
36
|
this.requestBody = new stream_1.default(utils_1.TUNNEL_HTTP_LOG_MAX_BODY);
|
|
23
37
|
this.requestBody.once('close', () => {
|
|
24
|
-
this.emit(
|
|
38
|
+
this.emit(tunnel_1.TUNNEL_EVENT_HTTP.NEW_REQUEST_END);
|
|
25
39
|
});
|
|
26
40
|
this.responseBody = new stream_1.default(utils_1.TUNNEL_HTTP_LOG_MAX_BODY);
|
|
27
41
|
this.responseBody.once('close', () => {
|
|
28
|
-
this.emit(
|
|
42
|
+
this.emit(tunnel_1.TUNNEL_EVENT_HTTP.NEW_RESPONSE_END);
|
|
29
43
|
});
|
|
30
44
|
}
|
|
31
45
|
response(statusCode, headers) {
|
|
@@ -83,15 +97,23 @@ class TunnelHttpLogRequest extends events_1.default {
|
|
|
83
97
|
};
|
|
84
98
|
}
|
|
85
99
|
}
|
|
100
|
+
exports.TunnelHttpLogRequest = TunnelHttpLogRequest;
|
|
86
101
|
class TunnelHttpLog extends events_1.default {
|
|
102
|
+
log;
|
|
103
|
+
tsRateLimit;
|
|
104
|
+
tsCb;
|
|
105
|
+
circuitBreaker;
|
|
106
|
+
rateLimit;
|
|
107
|
+
requests;
|
|
87
108
|
constructor(log, circuitBreakerThreshold) {
|
|
88
109
|
super();
|
|
89
|
-
this.log = log;
|
|
110
|
+
this.log = !!log;
|
|
90
111
|
this.requests = [];
|
|
91
112
|
this.rateLimit = {};
|
|
92
113
|
this.circuitBreaker = {
|
|
93
|
-
active: circuitBreakerThreshold !== null
|
|
94
|
-
|
|
114
|
+
active: circuitBreakerThreshold !== null &&
|
|
115
|
+
circuitBreakerThreshold !== undefined,
|
|
116
|
+
threshold: circuitBreakerThreshold || 0,
|
|
95
117
|
open: false,
|
|
96
118
|
test: false,
|
|
97
119
|
total: 0,
|
|
@@ -164,7 +186,7 @@ class TunnelHttpLog extends events_1.default {
|
|
|
164
186
|
this.requests.unshift(r);
|
|
165
187
|
if (this.requests.length > utils_1.TUNNEL_HTTP_LOG_MAX_REQUESTS)
|
|
166
188
|
this.requests.pop();
|
|
167
|
-
this.emit(
|
|
189
|
+
this.emit(tunnel_1.TUNNEL_EVENT_HTTP.NEW_REQUEST, r);
|
|
168
190
|
return r;
|
|
169
191
|
}
|
|
170
192
|
}
|
|
@@ -185,11 +207,11 @@ class TunnelHttpLog extends events_1.default {
|
|
|
185
207
|
}
|
|
186
208
|
}
|
|
187
209
|
}
|
|
188
|
-
newResponse(
|
|
210
|
+
newResponse(statusCode, headers, logRequest) {
|
|
189
211
|
this.increaseCircuitBreaker(statusCode);
|
|
190
212
|
if (logRequest && this.log) {
|
|
191
213
|
logRequest.response(statusCode, headers);
|
|
192
|
-
this.emit(
|
|
214
|
+
this.emit(tunnel_1.TUNNEL_EVENT_HTTP.NEW_RESPONSE, logRequest);
|
|
193
215
|
}
|
|
194
216
|
}
|
|
195
217
|
}
|
|
@@ -13,6 +13,7 @@ const content_disposition_1 = __importDefault(require("content-disposition"));
|
|
|
13
13
|
const mime_types_1 = __importDefault(require("mime-types"));
|
|
14
14
|
const stream_1 = __importDefault(require("stream"));
|
|
15
15
|
class TunnelHttpServe extends events_1.default {
|
|
16
|
+
serve;
|
|
16
17
|
constructor(serve) {
|
|
17
18
|
super();
|
|
18
19
|
this.serve = path_1.default.resolve(serve);
|
|
@@ -91,7 +92,7 @@ class TunnelHttpServe extends events_1.default {
|
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
const { base } = path_1.default.parse(absolutePath);
|
|
94
|
-
headers['content-length'] = stats.size;
|
|
95
|
+
headers['content-length'] = String(stats.size);
|
|
95
96
|
headers['content-disposition'] = (0, content_disposition_1.default)(base, {
|
|
96
97
|
type: 'inline',
|
|
97
98
|
});
|
|
@@ -104,7 +105,7 @@ class TunnelHttpServe extends events_1.default {
|
|
|
104
105
|
if (streamOpts.start !== undefined && streamOpts.end !== undefined) {
|
|
105
106
|
headers['content-range'] =
|
|
106
107
|
`bytes ${streamOpts.start}-${streamOpts.end}/${stats.size}`;
|
|
107
|
-
headers['content-length'] = streamOpts.end - streamOpts.start + 1;
|
|
108
|
+
headers['content-length'] = String(streamOpts.end - streamOpts.start + 1);
|
|
108
109
|
}
|
|
109
110
|
if (!req.headers.range && req.headers['if-modified-since']) {
|
|
110
111
|
const ims = Math.floor(Date.parse(req.headers['if-modified-since']) / 1000);
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const stream_1 = require("stream");
|
|
4
4
|
class TunnelHttpStream extends stream_1.Transform {
|
|
5
|
+
maxSize;
|
|
6
|
+
data;
|
|
7
|
+
realLength;
|
|
8
|
+
tooLarge;
|
|
5
9
|
constructor(maxSize) {
|
|
6
10
|
super();
|
|
7
11
|
this.maxSize = maxSize;
|
|
@@ -9,7 +13,7 @@ class TunnelHttpStream extends stream_1.Transform {
|
|
|
9
13
|
this.realLength = 0;
|
|
10
14
|
this.tooLarge = false;
|
|
11
15
|
}
|
|
12
|
-
_transform(chunk,
|
|
16
|
+
_transform(chunk, _, callback) {
|
|
13
17
|
if (!this.tooLarge) {
|
|
14
18
|
if (this.data.length + chunk.length > this.maxSize) {
|
|
15
19
|
this.tooLarge = true;
|
|
@@ -15,8 +15,28 @@ const https_1 = __importDefault(require("https"));
|
|
|
15
15
|
const compression_1 = __importDefault(require("./compression"));
|
|
16
16
|
const html_1 = __importDefault(require("./html"));
|
|
17
17
|
const agent_1 = __importDefault(require("./agent"));
|
|
18
|
-
const
|
|
18
|
+
const punycode_1 = __importDefault(require("punycode/"));
|
|
19
|
+
const tunnel_1 = require("../types/tunnel");
|
|
19
20
|
class TunnelHttp extends events_1.default {
|
|
21
|
+
id;
|
|
22
|
+
req;
|
|
23
|
+
res;
|
|
24
|
+
proto;
|
|
25
|
+
host;
|
|
26
|
+
port;
|
|
27
|
+
hostHeader;
|
|
28
|
+
serve;
|
|
29
|
+
timeout;
|
|
30
|
+
httpIdentify;
|
|
31
|
+
verify;
|
|
32
|
+
compression;
|
|
33
|
+
headers;
|
|
34
|
+
responseHeaders;
|
|
35
|
+
httpLog;
|
|
36
|
+
logRequest;
|
|
37
|
+
auth;
|
|
38
|
+
proxyRes;
|
|
39
|
+
proxyReq;
|
|
20
40
|
constructor({ req, res, proto, host, port, hostHeader, serve, timeout, httpIdentify, verify, httpLog, compression, headers, responseHeaders, auth = null, }) {
|
|
21
41
|
super();
|
|
22
42
|
this.id = (0, uuid_1.v4)();
|
|
@@ -55,7 +75,8 @@ class TunnelHttp extends events_1.default {
|
|
|
55
75
|
s.push(null);
|
|
56
76
|
s.pipe(this.logRequest.responseBody);
|
|
57
77
|
}
|
|
58
|
-
this.httpLog
|
|
78
|
+
if (this.httpLog)
|
|
79
|
+
this.httpLog.newResponse(code, {}, this.logRequest);
|
|
59
80
|
this.res.statusCode = code;
|
|
60
81
|
this.res.end(html);
|
|
61
82
|
}
|
|
@@ -86,13 +107,13 @@ class TunnelHttp extends events_1.default {
|
|
|
86
107
|
}
|
|
87
108
|
getHostHeader() {
|
|
88
109
|
if (this.hostHeader)
|
|
89
|
-
return
|
|
90
|
-
let h = this.host;
|
|
110
|
+
return punycode_1.default.toASCII(this.hostHeader);
|
|
111
|
+
let h = this.host || '';
|
|
91
112
|
if (this.proto === 'http' && this.port !== 80)
|
|
92
113
|
h += `:${this.port}`;
|
|
93
114
|
else if (this.proto === 'https' && this.port !== 443)
|
|
94
115
|
h += `:${this.port}`;
|
|
95
|
-
return
|
|
116
|
+
return punycode_1.default.toASCII(h);
|
|
96
117
|
}
|
|
97
118
|
getForwardedHost() {
|
|
98
119
|
if (this.req.headers.host)
|
|
@@ -113,7 +134,7 @@ class TunnelHttp extends events_1.default {
|
|
|
113
134
|
ip = this.req.socket.remoteAddress;
|
|
114
135
|
}
|
|
115
136
|
if (http2) {
|
|
116
|
-
h[':scheme'] = this.proto;
|
|
137
|
+
h[':scheme'] = this.proto || '';
|
|
117
138
|
h[':authority'] = this.getHostHeader();
|
|
118
139
|
h[':method'] = this.getMethod();
|
|
119
140
|
h[':path'] = this.getPath();
|
|
@@ -152,7 +173,7 @@ class TunnelHttp extends events_1.default {
|
|
|
152
173
|
}
|
|
153
174
|
const tmp = {};
|
|
154
175
|
if (compressionMethod &&
|
|
155
|
-
compressionMethod !==
|
|
176
|
+
compressionMethod !== tunnel_1.TUNNEL_COMPRESSION_METHOD.IDENTITY) {
|
|
156
177
|
tmp['content-encoding'] = compressionMethod;
|
|
157
178
|
hop.push('content-length');
|
|
158
179
|
hop.push('content-encoding');
|
|
@@ -165,9 +186,11 @@ class TunnelHttp extends events_1.default {
|
|
|
165
186
|
tmp['access-control-allow-origin'] = '*';
|
|
166
187
|
if (tmp['set-cookie']) {
|
|
167
188
|
const setCookie = [];
|
|
168
|
-
const h = (this.req.headers.host ||
|
|
189
|
+
const h = (this.req.headers.host ||
|
|
190
|
+
this.req.headers[':authority'] ||
|
|
191
|
+
'').split(':')[0];
|
|
169
192
|
tmp['set-cookie'].forEach((cookie) => {
|
|
170
|
-
setCookie.push(cookie.replaceAll(/([dD]omain)=[\w_\-\\.]+/
|
|
193
|
+
setCookie.push(cookie.replaceAll(/([dD]omain)=[\w_\-\\.]+/gi, `$1=${h}`));
|
|
171
194
|
});
|
|
172
195
|
tmp['set-cookie'] = setCookie;
|
|
173
196
|
}
|
|
@@ -202,13 +225,15 @@ class TunnelHttp extends events_1.default {
|
|
|
202
225
|
path,
|
|
203
226
|
headers,
|
|
204
227
|
});
|
|
205
|
-
|
|
228
|
+
if (this.httpLog) {
|
|
229
|
+
this.logRequest = this.httpLog.newRequest(method, headers, path, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1, this.req);
|
|
230
|
+
}
|
|
206
231
|
r.on('upgrade', (proxyRes, socket, head) => this.upgrade(proxyRes, socket, head));
|
|
207
232
|
r.on('response', (proxyRes) => {
|
|
208
233
|
this.proxyRes = proxyRes;
|
|
209
234
|
const statusCode = this.proxyRes.statusCode;
|
|
210
235
|
const resHeaders = this.proxyRes.headers;
|
|
211
|
-
const compressionMethod = compression_1.default.detect(this.compression, reqHeaders, resHeaders);
|
|
236
|
+
const compressionMethod = compression_1.default.detect(this.compression || false, reqHeaders, resHeaders);
|
|
212
237
|
this.outputHeaders(statusCode, this.getClearedHeaders(resHeaders, compressionMethod));
|
|
213
238
|
if (this.logRequest) {
|
|
214
239
|
this.proxyRes
|
|
@@ -221,7 +246,9 @@ class TunnelHttp extends events_1.default {
|
|
|
221
246
|
.pipe(compression_1.default.compress(compressionMethod))
|
|
222
247
|
.pipe(this.res);
|
|
223
248
|
}
|
|
224
|
-
this.httpLog
|
|
249
|
+
if (this.httpLog) {
|
|
250
|
+
this.httpLog.newResponse(statusCode, resHeaders, this.logRequest);
|
|
251
|
+
}
|
|
225
252
|
});
|
|
226
253
|
return r;
|
|
227
254
|
}
|
|
@@ -245,13 +272,15 @@ class TunnelHttp extends events_1.default {
|
|
|
245
272
|
rejectUnauthorized: this.verify,
|
|
246
273
|
headers,
|
|
247
274
|
});
|
|
248
|
-
|
|
275
|
+
if (this.httpLog) {
|
|
276
|
+
this.logRequest = this.httpLog.newRequest(method, headers, path, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1, this.req);
|
|
277
|
+
}
|
|
249
278
|
r.on('upgrade', (proxyRes, socket, head) => this.upgrade(proxyRes, socket, head));
|
|
250
279
|
r.on('response', (proxyRes) => {
|
|
251
280
|
this.proxyRes = proxyRes;
|
|
252
281
|
const statusCode = this.proxyRes.statusCode;
|
|
253
282
|
const resHeaders = this.proxyRes.headers;
|
|
254
|
-
const compressionMethod = compression_1.default.detect(this.compression, reqHeaders, resHeaders);
|
|
283
|
+
const compressionMethod = compression_1.default.detect(this.compression || false, reqHeaders, resHeaders);
|
|
255
284
|
this.outputHeaders(statusCode, this.getClearedHeaders(resHeaders, compressionMethod));
|
|
256
285
|
if (this.logRequest) {
|
|
257
286
|
this.proxyRes
|
|
@@ -264,23 +293,27 @@ class TunnelHttp extends events_1.default {
|
|
|
264
293
|
.pipe(compression_1.default.compress(compressionMethod))
|
|
265
294
|
.pipe(this.res);
|
|
266
295
|
}
|
|
267
|
-
this.httpLog
|
|
296
|
+
if (this.httpLog) {
|
|
297
|
+
this.httpLog.newResponse(statusCode, resHeaders, this.logRequest);
|
|
298
|
+
}
|
|
268
299
|
});
|
|
269
300
|
return r;
|
|
270
301
|
}
|
|
271
302
|
createServe() {
|
|
272
303
|
const reqHeaders = this.req.headers;
|
|
273
|
-
const r = new serve_1.default(this.serve);
|
|
304
|
+
const r = new serve_1.default(this.serve || '');
|
|
274
305
|
const method = this.getMethod();
|
|
275
306
|
const path = this.getPath();
|
|
276
|
-
|
|
307
|
+
if (this.httpLog) {
|
|
308
|
+
this.logRequest = this.httpLog.newRequest(method, reqHeaders, path, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1, this.req);
|
|
309
|
+
}
|
|
277
310
|
r.on('response', (statusCode, resHeaders, stream) => {
|
|
278
311
|
if (!stream) {
|
|
279
312
|
this.outputHeaders(statusCode, this.getClearedHeaders(resHeaders));
|
|
280
313
|
this.res.end();
|
|
281
314
|
}
|
|
282
315
|
else {
|
|
283
|
-
const compressionMethod = compression_1.default.detect(this.compression, reqHeaders, resHeaders);
|
|
316
|
+
const compressionMethod = compression_1.default.detect(this.compression || false, reqHeaders, resHeaders);
|
|
284
317
|
this.outputHeaders(statusCode, this.getClearedHeaders(resHeaders, compressionMethod));
|
|
285
318
|
if (this.logRequest) {
|
|
286
319
|
stream
|
|
@@ -294,14 +327,16 @@ class TunnelHttp extends events_1.default {
|
|
|
294
327
|
.pipe(this.res);
|
|
295
328
|
}
|
|
296
329
|
}
|
|
297
|
-
this.httpLog
|
|
330
|
+
if (this.httpLog) {
|
|
331
|
+
this.httpLog.newResponse(statusCode, resHeaders, this.logRequest);
|
|
332
|
+
}
|
|
298
333
|
});
|
|
299
334
|
return r;
|
|
300
335
|
}
|
|
301
336
|
async createRequestHttps2() {
|
|
302
337
|
const reqHeaders = this.req.headers;
|
|
303
338
|
const authority = `${this.proto}://${(0, utils_1.getRealTargetHost)(this.host)}:${this.port}`;
|
|
304
|
-
const client = await agent_1.default.getHttp2Client(authority, this.host, this.verify);
|
|
339
|
+
const client = await agent_1.default.getHttp2Client(authority, this.host || '', this.verify || false);
|
|
305
340
|
const method = this.getMethod();
|
|
306
341
|
const path = this.getPath();
|
|
307
342
|
const headers = {
|
|
@@ -310,10 +345,12 @@ class TunnelHttp extends events_1.default {
|
|
|
310
345
|
...this.getRequestHeaders(true),
|
|
311
346
|
};
|
|
312
347
|
const r = client.request(headers);
|
|
313
|
-
|
|
348
|
+
if (this.httpLog) {
|
|
349
|
+
this.logRequest = this.httpLog.newRequest(method, headers, path, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP2, this.req);
|
|
350
|
+
}
|
|
314
351
|
r.on('response', (resHeaders) => {
|
|
315
352
|
const status = resHeaders[':status'] || 200;
|
|
316
|
-
const compressionMethod = compression_1.default.detect(this.compression, reqHeaders, resHeaders);
|
|
353
|
+
const compressionMethod = compression_1.default.detect(this.compression || false, reqHeaders, resHeaders);
|
|
317
354
|
this.outputHeaders(status, this.getClearedHeaders(resHeaders, compressionMethod));
|
|
318
355
|
if (this.logRequest) {
|
|
319
356
|
r.pipe(this.logRequest.responseBody)
|
|
@@ -323,12 +360,14 @@ class TunnelHttp extends events_1.default {
|
|
|
323
360
|
else {
|
|
324
361
|
r.pipe(compression_1.default.compress(compressionMethod)).pipe(this.res);
|
|
325
362
|
}
|
|
326
|
-
this.httpLog
|
|
363
|
+
if (this.httpLog) {
|
|
364
|
+
this.httpLog.newResponse(status, resHeaders, this.logRequest);
|
|
365
|
+
}
|
|
327
366
|
});
|
|
328
367
|
return r;
|
|
329
368
|
}
|
|
330
369
|
async createRequest() {
|
|
331
|
-
if (this.httpIdentify ===
|
|
370
|
+
if (this.httpIdentify === tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1) {
|
|
332
371
|
if (this.proto === 'http')
|
|
333
372
|
return this.createRequestHttp1();
|
|
334
373
|
return this.createRequestHttps1();
|
|
@@ -363,7 +402,9 @@ class TunnelHttp extends events_1.default {
|
|
|
363
402
|
upgrade(proxyRes, socket, head) {
|
|
364
403
|
const resHeaders = proxyRes?.headers || {};
|
|
365
404
|
const reqSocket = this.req.socket;
|
|
366
|
-
this.httpLog
|
|
405
|
+
if (this.httpLog) {
|
|
406
|
+
this.httpLog.newResponse(101, resHeaders, this.logRequest);
|
|
407
|
+
}
|
|
367
408
|
socket.setTimeout(0);
|
|
368
409
|
const headers = this.getClearedHeaders(resHeaders, null, true);
|
|
369
410
|
this.clear();
|
|
@@ -384,7 +425,7 @@ class TunnelHttp extends events_1.default {
|
|
|
384
425
|
socket.removeAllListeners();
|
|
385
426
|
reqSocket.on('close', () => {
|
|
386
427
|
reqSocket.removeAllListeners();
|
|
387
|
-
this.emit(
|
|
428
|
+
this.emit(tunnel_1.TUNNEL_HTTP_SOCKET.CLOSED, reqSocket);
|
|
388
429
|
});
|
|
389
430
|
socket.on('close', () => {
|
|
390
431
|
socket.removeAllListeners();
|
|
@@ -7,17 +7,23 @@ const events_1 = __importDefault(require("events"));
|
|
|
7
7
|
const tls_1 = __importDefault(require("tls"));
|
|
8
8
|
const net_1 = __importDefault(require("net"));
|
|
9
9
|
const utils_1 = require("../utils");
|
|
10
|
-
const
|
|
10
|
+
const tunnel_1 = require("../types/tunnel");
|
|
11
11
|
const CHECK_INTERVAL = 300000;
|
|
12
12
|
const CHECK_TIMEOUT = 5000;
|
|
13
13
|
class TunnelIdentification extends events_1.default {
|
|
14
|
+
proto;
|
|
15
|
+
host;
|
|
16
|
+
port;
|
|
17
|
+
forceHttp2;
|
|
18
|
+
type;
|
|
19
|
+
ts;
|
|
14
20
|
constructor(proto, host, port, forceHttp2) {
|
|
15
21
|
super();
|
|
16
22
|
this.proto = proto;
|
|
17
23
|
this.host = (0, utils_1.getRealTargetHost)(host);
|
|
18
24
|
this.port = port;
|
|
19
25
|
this.forceHttp2 = forceHttp2;
|
|
20
|
-
this.type =
|
|
26
|
+
this.type = tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1;
|
|
21
27
|
this.identify();
|
|
22
28
|
this.ts = setInterval(() => this.identify(), CHECK_INTERVAL);
|
|
23
29
|
}
|
|
@@ -29,29 +35,30 @@ class TunnelIdentification extends events_1.default {
|
|
|
29
35
|
}
|
|
30
36
|
identify() {
|
|
31
37
|
if (this.forceHttp2) {
|
|
32
|
-
this.type =
|
|
33
|
-
this.emit(
|
|
38
|
+
this.type = tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP2;
|
|
39
|
+
this.emit(tunnel_1.TUNNEL_EVENT.IDENTIFIED, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP2);
|
|
34
40
|
return;
|
|
35
41
|
}
|
|
36
42
|
let socket;
|
|
37
43
|
const close = () => {
|
|
38
44
|
try {
|
|
39
45
|
socket.removeAllListeners();
|
|
40
|
-
socket.
|
|
46
|
+
socket.end();
|
|
47
|
+
socket.destroy();
|
|
41
48
|
}
|
|
42
49
|
catch {
|
|
43
50
|
// do nothing
|
|
44
51
|
}
|
|
45
52
|
};
|
|
46
53
|
const connected = () => {
|
|
47
|
-
if (socket.alpnProtocol) {
|
|
54
|
+
if (socket instanceof tls_1.default.TLSSocket && socket.alpnProtocol) {
|
|
48
55
|
if (socket.alpnProtocol === 'h2') {
|
|
49
|
-
this.type =
|
|
50
|
-
this.emit(
|
|
56
|
+
this.type = tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP2;
|
|
57
|
+
this.emit(tunnel_1.TUNNEL_EVENT.IDENTIFIED, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP2);
|
|
51
58
|
}
|
|
52
59
|
else {
|
|
53
|
-
this.type =
|
|
54
|
-
this.emit(
|
|
60
|
+
this.type = tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1;
|
|
61
|
+
this.emit(tunnel_1.TUNNEL_EVENT.IDENTIFIED, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1);
|
|
55
62
|
}
|
|
56
63
|
close();
|
|
57
64
|
}
|
|
@@ -59,12 +66,12 @@ class TunnelIdentification extends events_1.default {
|
|
|
59
66
|
socket.write('GET / HTTP/1.1\r\nHost: example.com\r\n\r\n');
|
|
60
67
|
socket.on('data', (d) => {
|
|
61
68
|
if (/HTTP\/1/.test(d.toString('utf8'))) {
|
|
62
|
-
this.type =
|
|
63
|
-
this.emit(
|
|
69
|
+
this.type = tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1;
|
|
70
|
+
this.emit(tunnel_1.TUNNEL_EVENT.IDENTIFIED, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP1);
|
|
64
71
|
}
|
|
65
72
|
else {
|
|
66
|
-
this.type =
|
|
67
|
-
this.emit(
|
|
73
|
+
this.type = tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP2;
|
|
74
|
+
this.emit(tunnel_1.TUNNEL_EVENT.IDENTIFIED, tunnel_1.TUNNEL_HTTP_IDENTIFY.HTTP2);
|
|
68
75
|
}
|
|
69
76
|
close();
|
|
70
77
|
});
|
|
@@ -6,7 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const net_1 = require("net");
|
|
7
7
|
const events_1 = __importDefault(require("events"));
|
|
8
8
|
const utils_1 = require("../utils");
|
|
9
|
+
const tunnel_1 = require("../types/tunnel");
|
|
9
10
|
class TunnelLatency extends events_1.default {
|
|
11
|
+
latency;
|
|
12
|
+
isChecking;
|
|
13
|
+
port;
|
|
14
|
+
host;
|
|
15
|
+
ts;
|
|
10
16
|
constructor(host, port) {
|
|
11
17
|
super();
|
|
12
18
|
this.latency = -1;
|
|
@@ -26,16 +32,18 @@ class TunnelLatency extends events_1.default {
|
|
|
26
32
|
let socket = new net_1.Socket();
|
|
27
33
|
let ts = null;
|
|
28
34
|
const clear = () => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
if (ts)
|
|
36
|
+
clearTimeout(ts);
|
|
37
|
+
if (socket) {
|
|
38
|
+
try {
|
|
39
|
+
socket.removeAllListeners();
|
|
40
|
+
socket.once('error', () => { });
|
|
41
|
+
socket.end();
|
|
42
|
+
socket.destroy();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// do nothing
|
|
46
|
+
}
|
|
39
47
|
}
|
|
40
48
|
socket = null;
|
|
41
49
|
this.isChecking = false;
|
|
@@ -52,7 +60,7 @@ class TunnelLatency extends events_1.default {
|
|
|
52
60
|
socket.on('ready', () => {
|
|
53
61
|
const elapsed = process.hrtime(start);
|
|
54
62
|
if (this.latency < 0)
|
|
55
|
-
this.emit(
|
|
63
|
+
this.emit(tunnel_1.TUNNEL_EVENT_LATENCY.RECONNECTED);
|
|
56
64
|
this.latency = elapsed[0] * 1000 + elapsed[1] / 1000000; // ms
|
|
57
65
|
clear();
|
|
58
66
|
});
|
|
@@ -4,9 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const utils_1 = require("../../../utils");
|
|
7
|
+
// @ts-ignore
|
|
7
8
|
const termkit_no_lazy_require_1 = __importDefault(require("terminal-kit/lib/termkit-no-lazy-require"));
|
|
8
9
|
const isbinaryfile_1 = require("isbinaryfile");
|
|
9
10
|
const format_1 = __importDefault(require("../../../format"));
|
|
11
|
+
const tunnel_1 = require("../../../types/tunnel");
|
|
10
12
|
const COLOR_CYAN = 6;
|
|
11
13
|
const COLOR_LIGHT_GRAY = 7;
|
|
12
14
|
const COLOR_RED = 9;
|
|
@@ -40,6 +42,11 @@ const formatBytes = (len) => {
|
|
|
40
42
|
return `${len}GB`;
|
|
41
43
|
};
|
|
42
44
|
class OutputInteractiveTunnel {
|
|
45
|
+
terminal;
|
|
46
|
+
tunnel;
|
|
47
|
+
viewPort;
|
|
48
|
+
sprites;
|
|
49
|
+
selectedRequest;
|
|
43
50
|
constructor(terminal, tunnel) {
|
|
44
51
|
this.terminal = terminal;
|
|
45
52
|
this.tunnel = tunnel;
|
|
@@ -162,13 +169,13 @@ class OutputInteractiveTunnel {
|
|
|
162
169
|
if (r.status === 'NEW') {
|
|
163
170
|
msg += ' ^KNEW^';
|
|
164
171
|
}
|
|
165
|
-
else if (r.status >= 500) {
|
|
172
|
+
else if (typeof (r.status) === 'number' && r.status >= 500) {
|
|
166
173
|
msg += ` ^R${r.status}^`;
|
|
167
174
|
}
|
|
168
|
-
else if (r.status >= 400) {
|
|
175
|
+
else if (typeof (r.status) === 'number' && r.status >= 400) {
|
|
169
176
|
msg += ` ^Y${r.status}^`;
|
|
170
177
|
}
|
|
171
|
-
else if (r.status >= 300) {
|
|
178
|
+
else if (typeof (r.status) === 'number' && r.status >= 300) {
|
|
172
179
|
msg += ` ^B${r.status}^`;
|
|
173
180
|
}
|
|
174
181
|
else {
|
|
@@ -179,7 +186,7 @@ class OutputInteractiveTunnel {
|
|
|
179
186
|
return msg;
|
|
180
187
|
}
|
|
181
188
|
getPathAndQuery(url) {
|
|
182
|
-
|
|
189
|
+
const query = {};
|
|
183
190
|
let path;
|
|
184
191
|
try {
|
|
185
192
|
const u = new URL(url, 'https://test.com');
|
|
@@ -496,7 +503,7 @@ class OutputInteractiveTunnel {
|
|
|
496
503
|
}, fillString('Entry:', ROW_LENGTH));
|
|
497
504
|
}
|
|
498
505
|
createSpriteTerminate() {
|
|
499
|
-
if (this.tunnel.type ===
|
|
506
|
+
if (this.tunnel.type === tunnel_1.TUNNEL_TYPE.TLS) {
|
|
500
507
|
this.sprites.terminate = termkit_no_lazy_require_1.default.ScreenBuffer.createFromString({
|
|
501
508
|
attr: {
|
|
502
509
|
color: COLOR_LIGHT_GRAY,
|
|
@@ -592,7 +599,7 @@ class OutputInteractiveTunnel {
|
|
|
592
599
|
updateSpriteStatus(y) {
|
|
593
600
|
let text;
|
|
594
601
|
let color;
|
|
595
|
-
if (this.tunnel.status ===
|
|
602
|
+
if (this.tunnel.status === tunnel_1.TUNNEL_STATUS.OPEN) {
|
|
596
603
|
text = 'OPEN ';
|
|
597
604
|
color = COLOR_GREEN;
|
|
598
605
|
}
|
|
@@ -628,7 +635,7 @@ class OutputInteractiveTunnel {
|
|
|
628
635
|
return this.sprites.type.height;
|
|
629
636
|
}
|
|
630
637
|
updateSpriteIdentify(y) {
|
|
631
|
-
if (this.tunnel.type ===
|
|
638
|
+
if (this.tunnel.type === tunnel_1.TUNNEL_TYPE.HTTP) {
|
|
632
639
|
this.sprites.identify.put({
|
|
633
640
|
x: COLUMN_LENGTH,
|
|
634
641
|
y: 0,
|
|
@@ -690,7 +697,7 @@ class OutputInteractiveTunnel {
|
|
|
690
697
|
return this.sprites.region.height;
|
|
691
698
|
}
|
|
692
699
|
updateSpriteTerminate(y) {
|
|
693
|
-
if (this.tunnel.type ===
|
|
700
|
+
if (this.tunnel.type === tunnel_1.TUNNEL_TYPE.TLS) {
|
|
694
701
|
this.sprites.terminate.put({
|
|
695
702
|
x: COLUMN_LENGTH,
|
|
696
703
|
y: 0,
|
|
@@ -836,7 +843,7 @@ class OutputInteractiveTunnel {
|
|
|
836
843
|
this.terminal.on('resize', () => {
|
|
837
844
|
this.draw();
|
|
838
845
|
});
|
|
839
|
-
this.tunnel.on(
|
|
846
|
+
this.tunnel.on(tunnel_1.TUNNEL_EVENT.STOPPED, () => {
|
|
840
847
|
this.terminate();
|
|
841
848
|
});
|
|
842
849
|
}
|
|
@@ -3,10 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const utils_1 = require("../../../../utils");
|
|
7
6
|
const texts_1 = require("../../../../texts");
|
|
8
7
|
const format_1 = __importDefault(require("../../../../format"));
|
|
8
|
+
const tunnel_1 = require("../../../../types/tunnel");
|
|
9
9
|
class OutputNoninteractiveAgentTunnels {
|
|
10
|
+
terminal;
|
|
11
|
+
tunnels;
|
|
10
12
|
constructor(terminal, tunnels) {
|
|
11
13
|
this.terminal = terminal;
|
|
12
14
|
this.tunnels = tunnels;
|
|
@@ -29,7 +31,7 @@ class OutputNoninteractiveAgentTunnels {
|
|
|
29
31
|
format_1.default.target(tunnel.type, tunnel.target) +
|
|
30
32
|
` / ${format_1.default.latency(tunnel.targetLatency)}`;
|
|
31
33
|
const entry = format_1.default.entry(tunnel) + ` / ${format_1.default.latency(tunnel.regionLatency)}`;
|
|
32
|
-
if (tunnel.status ===
|
|
34
|
+
if (tunnel.status === tunnel_1.TUNNEL_STATUS.OPEN)
|
|
33
35
|
status = 'Open';
|
|
34
36
|
else
|
|
35
37
|
status = 'Closed';
|
|
@@ -3,9 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const utils_1 = require("../../../../utils");
|
|
7
6
|
const format_1 = __importDefault(require("../../../../format"));
|
|
7
|
+
const tunnel_1 = require("../../../../types/tunnel");
|
|
8
8
|
class OutputNoninteractiveConfigTunnel {
|
|
9
|
+
terminal;
|
|
10
|
+
tunnel;
|
|
9
11
|
constructor(terminal, tunnel) {
|
|
10
12
|
this.terminal = terminal;
|
|
11
13
|
this.tunnel = tunnel;
|
|
@@ -15,7 +17,7 @@ class OutputNoninteractiveConfigTunnel {
|
|
|
15
17
|
['Name', this.tunnel.name],
|
|
16
18
|
['Type', format_1.default.type(this.tunnel.type)],
|
|
17
19
|
];
|
|
18
|
-
if (this.tunnel.type ===
|
|
20
|
+
if (this.tunnel.type === tunnel_1.TUNNEL_TYPE.HTTP && this.tunnel.serve) {
|
|
19
21
|
data.push(['Serve', format_1.default.serve(this.tunnel.serve)]);
|
|
20
22
|
}
|
|
21
23
|
else {
|
|
@@ -27,7 +29,7 @@ class OutputNoninteractiveConfigTunnel {
|
|
|
27
29
|
data.push(['Region', format_1.default.tunnelRegion(this.tunnel.region)]);
|
|
28
30
|
data.push(['Timeout', format_1.default.tunnelTimeout(this.tunnel.timeout)]);
|
|
29
31
|
data.push(['Whitelist', format_1.default.tunnelWhitelist(this.tunnel.whitelist)]);
|
|
30
|
-
if (this.tunnel.type ===
|
|
32
|
+
if (this.tunnel.type === tunnel_1.TUNNEL_TYPE.HTTP) {
|
|
31
33
|
data.push(['Host Header', format_1.default.hostHeader(this.tunnel.host)]);
|
|
32
34
|
data.push([
|
|
33
35
|
'Basic Auth',
|
|
@@ -52,7 +54,7 @@ class OutputNoninteractiveConfigTunnel {
|
|
|
52
54
|
data.push(['Force HTTP/2', format_1.default.yesNo(this.tunnel.http2)]);
|
|
53
55
|
data.push(['Compression', format_1.default.yesNo(this.tunnel.compression)]);
|
|
54
56
|
}
|
|
55
|
-
else if (this.tunnel.type ===
|
|
57
|
+
else if (this.tunnel.type === tunnel_1.TUNNEL_TYPE.TLS) {
|
|
56
58
|
data.push(['Terminate TLS At', this.tunnel.terminate]);
|
|
57
59
|
data.push(['TLS Key', format_1.default.yesNo(!!this.tunnel.key)]);
|
|
58
60
|
data.push(['TLS Cert', format_1.default.yesNo(!!this.tunnel.cert)]);
|