bdy 1.12.13-dev-pipeline-run → 1.13.0-beta

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 (40) hide show
  1. package/distTs/package.json +13 -12
  2. package/distTs/src/agent.js +302 -0
  3. package/distTs/src/api/agent.js +99 -0
  4. package/distTs/src/api/buddy.js +139 -0
  5. package/distTs/src/api/client.js +10 -6
  6. package/distTs/src/api/socket.js +159 -0
  7. package/distTs/src/cfg.js +234 -0
  8. package/distTs/src/command/config.js +17 -0
  9. package/distTs/src/command/http.js +30 -0
  10. package/distTs/src/command/pipeline/run.js +29 -26
  11. package/distTs/src/command/start.js +28 -0
  12. package/distTs/src/command/tcp.js +30 -0
  13. package/distTs/src/command/tls.js +30 -0
  14. package/distTs/src/command/ut/upload.js +17 -7
  15. package/distTs/src/command/vt/compare.js +2 -2
  16. package/distTs/src/command/vt/exec.js +4 -3
  17. package/distTs/src/command/vt/storybook.js +4 -3
  18. package/distTs/src/input.js +20 -10
  19. package/distTs/src/output/interactive/tunnel.js +860 -0
  20. package/distTs/src/output/noninteractive/agent/tunnels.js +43 -0
  21. package/distTs/src/output/noninteractive/config/tunnel.js +65 -0
  22. package/distTs/src/output/noninteractive/config/tunnels.js +18 -0
  23. package/distTs/src/output/noninteractive/tunnel.js +59 -0
  24. package/distTs/src/server/cert.js +52 -0
  25. package/distTs/src/server/http1.js +75 -0
  26. package/distTs/src/server/http2.js +78 -0
  27. package/distTs/src/server/sftp.js +497 -0
  28. package/distTs/src/server/ssh.js +446 -0
  29. package/distTs/src/server/tls.js +41 -0
  30. package/distTs/src/ssh/client.js +197 -0
  31. package/distTs/src/texts.js +7 -51
  32. package/distTs/src/tunnel/html/503.html +338 -0
  33. package/distTs/src/tunnel/tunnel.js +31 -13
  34. package/distTs/src/tunnel.js +656 -0
  35. package/distTs/src/unitTest/ci.js +12 -8
  36. package/distTs/src/utils.js +17 -7
  37. package/distTs/src/visualTest/context.js +4 -4
  38. package/distTs/src/visualTest/exec.js +0 -24
  39. package/distTs/src/visualTest/resources.js +18 -8
  40. package/package.json +13 -12
@@ -0,0 +1,656 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const basic_auth_1 = __importDefault(require("basic-auth"));
7
+ const utils_1 = require("./utils");
8
+ const latency_1 = __importDefault(require("./tunnel/latency"));
9
+ const client_1 = __importDefault(require("./ssh/client"));
10
+ const events_1 = __importDefault(require("events"));
11
+ const tcp_1 = __importDefault(require("./tunnel/tcp"));
12
+ const tls_1 = __importDefault(require("./server/tls"));
13
+ const ssh_1 = __importDefault(require("./server/ssh"));
14
+ const logger_1 = __importDefault(require("./logger"));
15
+ const identification_1 = __importDefault(require("./tunnel/identification"));
16
+ const http_1 = __importDefault(require("./tunnel/http"));
17
+ const http2_1 = __importDefault(require("./server/http2"));
18
+ const http1_1 = __importDefault(require("./server/http1"));
19
+ const log_1 = __importDefault(require("./tunnel/http/log"));
20
+ const format_1 = __importDefault(require("./format"));
21
+ const texts_js_1 = require("./texts.js");
22
+ const dns_js_1 = __importDefault(require("./tunnel/dns.js"));
23
+ class Tunnel extends events_1.default {
24
+ constructor({ agent, id, type, target, region, timeout, domain, customDomain, name, subdomain, whitelist, tlsSettings, httpSettings, sshSettings, sshHostKey, }) {
25
+ super();
26
+ if (!sshHostKey)
27
+ sshHostKey = (0, utils_1.createSshHostKey)();
28
+ this.agent = agent;
29
+ this.id = id;
30
+ this.sshHostKey = sshHostKey;
31
+ this.create({
32
+ type,
33
+ target,
34
+ region,
35
+ timeout,
36
+ domain,
37
+ customDomain,
38
+ subdomain,
39
+ name,
40
+ whitelist,
41
+ tlsSettings,
42
+ httpSettings,
43
+ sshSettings,
44
+ });
45
+ }
46
+ create({ type, target, region, timeout, domain, customDomain, subdomain, name, whitelist, tlsSettings, httpSettings, sshSettings, }) {
47
+ this.type = type;
48
+ this.region = region;
49
+ this.target = target;
50
+ this.whitelist = whitelist || [];
51
+ this.domain = domain;
52
+ this.customDomain = !!customDomain;
53
+ this.subdomain = subdomain;
54
+ this.name = name;
55
+ this.timeout = timeout || utils_1.DEFAULT_TIMEOUT;
56
+ this.useragents = [];
57
+ this.headers = [];
58
+ this.responseHeaders = [];
59
+ if (tlsSettings) {
60
+ this.terminate = tlsSettings.terminate;
61
+ this.key = tlsSettings.key;
62
+ this.cert = tlsSettings.cert;
63
+ this.ca = tlsSettings.ca;
64
+ }
65
+ if (httpSettings) {
66
+ this.host = httpSettings.host;
67
+ this.login = httpSettings.login;
68
+ this.password = httpSettings.password;
69
+ this.ca = httpSettings.ca;
70
+ this.serve = httpSettings.serve;
71
+ this.useragents = httpSettings.userAgents || [];
72
+ this.headers = httpSettings.headers || [];
73
+ this.responseHeaders = httpSettings.responseHeaders || [];
74
+ this.circuitBreaker = httpSettings.circuitBreaker;
75
+ this.log = httpSettings.log;
76
+ this.verify = httpSettings.verify;
77
+ this.compression = httpSettings.compression;
78
+ this.http2 = httpSettings.http2;
79
+ }
80
+ if (sshSettings) {
81
+ this.sshIp = sshSettings.ip;
82
+ this.sshId = sshSettings.sshId;
83
+ this.sshPort = sshSettings.port;
84
+ this.sshUser = sshSettings.user;
85
+ this.sshPassword = sshSettings.password;
86
+ this.sshForwardPort = sshSettings.forwardPort;
87
+ this.sshClientUser = sshSettings.clientUser;
88
+ this.sshClientPassword = sshSettings.clientPassword;
89
+ }
90
+ this.targetProto = 'http';
91
+ this.targetHost = 'localhost';
92
+ this.targetPort = 80;
93
+ this.targetAuth = null;
94
+ if (this.type === utils_1.TUNNEL_HTTP) {
95
+ let m = this.target.match(utils_1.TARGET_ONLY_PORT_REGEX);
96
+ if (m) {
97
+ this.targetPort = parseInt(m[0], 10);
98
+ }
99
+ else {
100
+ m = this.target.match(utils_1.TARGET_HTTP_REGEX);
101
+ if (m) {
102
+ if (m[2])
103
+ this.targetProto = m[2];
104
+ if (m[6])
105
+ this.targetPort = parseInt(m[6], 10);
106
+ else if (this.targetProto === 'https')
107
+ this.targetPort = 443;
108
+ if (m[4])
109
+ this.targetHost = m[4];
110
+ if (m[3])
111
+ this.targetAuth = m[3].replace(/@$/, '');
112
+ }
113
+ }
114
+ }
115
+ else if (this.type === utils_1.TUNNEL_SSH) {
116
+ this.targetHost = 'localhost';
117
+ this.targetProto = 'ssh://';
118
+ this.targetPort = 22;
119
+ }
120
+ else {
121
+ const m = this.target.match(utils_1.TARGET_TCP_TLS_REGEX);
122
+ if (m) {
123
+ this.targetPort = parseInt(m[3], 10);
124
+ if (m[2])
125
+ this.targetHost = m[2];
126
+ }
127
+ }
128
+ this.connections = {};
129
+ this.totalConnections = 0;
130
+ this.status = utils_1.TUNNEL_CLOSED;
131
+ this.dns = null;
132
+ this.regionLatency = null;
133
+ this.targetLatency = null;
134
+ this.tls = null;
135
+ this.httpLog = null;
136
+ this.identify = null;
137
+ this.http2server = null;
138
+ this.http1server = null;
139
+ this.sshServer = null;
140
+ this.ssh = null;
141
+ this.started = false;
142
+ }
143
+ recreate({ type, target, region, timeout, domain, customDomain, subdomain, name, whitelist, tlsSettings, httpSettings, sshSettings, }) {
144
+ const started = this.started;
145
+ this.stop(false);
146
+ this.create({
147
+ type,
148
+ target,
149
+ region,
150
+ timeout,
151
+ domain,
152
+ customDomain,
153
+ subdomain,
154
+ name,
155
+ whitelist,
156
+ tlsSettings,
157
+ httpSettings,
158
+ sshSettings,
159
+ });
160
+ if (started)
161
+ this.start();
162
+ }
163
+ hasChanged(data) {
164
+ const tunnel = new Tunnel({
165
+ ...data,
166
+ sshHostKey: this.sshHostKey,
167
+ });
168
+ if (this.type !== tunnel.type)
169
+ return true;
170
+ if (this.target !== tunnel.target)
171
+ return true;
172
+ if (this.region !== tunnel.region)
173
+ return true;
174
+ if (this.timeout !== tunnel.timeout)
175
+ return true;
176
+ if (this.domain !== tunnel.domain)
177
+ return true;
178
+ if (this.subdomain !== tunnel.subdomain)
179
+ return true;
180
+ if (this.terminate !== tunnel.terminate)
181
+ return true;
182
+ if (this.key !== tunnel.key)
183
+ return true;
184
+ if (this.cert !== tunnel.cert)
185
+ return true;
186
+ if (this.ca !== tunnel.ca)
187
+ return true;
188
+ if (this.host !== tunnel.host)
189
+ return true;
190
+ if (this.login !== tunnel.login)
191
+ return true;
192
+ if (this.password !== tunnel.password)
193
+ return true;
194
+ if (this.serve !== tunnel.serve)
195
+ return true;
196
+ if (this.circuitBreaker !== tunnel.circuitBreaker)
197
+ return true;
198
+ if (this.log !== tunnel.log)
199
+ return true;
200
+ if (this.verify !== tunnel.verify)
201
+ return true;
202
+ if (this.http2 !== tunnel.http2)
203
+ return true;
204
+ if (this.compression !== tunnel.compression)
205
+ return true;
206
+ if (this.sshIp !== tunnel.sshIp)
207
+ return true;
208
+ if (this.sshId !== tunnel.sshId)
209
+ return true;
210
+ if (this.sshPort !== tunnel.sshPort)
211
+ return true;
212
+ if (this.sshUser !== tunnel.sshUser)
213
+ return true;
214
+ if (this.sshPassword !== tunnel.sshPassword)
215
+ return true;
216
+ if (this.sshForwardPort !== tunnel.sshForwardPort)
217
+ return true;
218
+ if (this.sshClientPassword !== tunnel.sshClientPassword)
219
+ return true;
220
+ if (this.sshClientUser !== tunnel.sshClientUser)
221
+ return true;
222
+ if (this.whitelist.length !== tunnel.whitelist.length)
223
+ return true;
224
+ this.whitelist.sort();
225
+ tunnel.whitelist.sort();
226
+ for (let i = 0; i < this.whitelist.length; i += 1) {
227
+ if (this.whitelist[i] !== tunnel.whitelist[i])
228
+ return true;
229
+ }
230
+ if (this.useragents.length !== tunnel.useragents.length)
231
+ return true;
232
+ this.useragents.sort();
233
+ tunnel.useragents.sort();
234
+ for (let i = 0; i < this.useragents.length; i += 1) {
235
+ if (this.useragents[i] !== tunnel.useragents[i])
236
+ return true;
237
+ }
238
+ const sortHeaders = (a, b) => a.name.localeCompare(b.name);
239
+ if (this.headers.length !== tunnel.headers.length)
240
+ return true;
241
+ this.headers.sort(sortHeaders);
242
+ tunnel.headers.sort(sortHeaders);
243
+ for (let i = 0; i < this.headers.length; i += 1) {
244
+ const thisH = this.headers[i];
245
+ const tunnelH = tunnel.headers[i];
246
+ if (thisH.name !== tunnelH.name)
247
+ return true;
248
+ if (thisH.value !== tunnelH.value)
249
+ return true;
250
+ }
251
+ if (this.responseHeaders.length !== tunnel.responseHeaders.length)
252
+ return true;
253
+ this.responseHeaders.sort(sortHeaders);
254
+ tunnel.responseHeaders.sort(sortHeaders);
255
+ for (let i = 0; i < this.responseHeaders.length; i += 1) {
256
+ const thisRH = this.responseHeaders[i];
257
+ const tunnelRH = tunnel.responseHeaders[i];
258
+ if (thisRH.name !== tunnelRH.name)
259
+ return true;
260
+ if (thisRH.value !== tunnelRH.value)
261
+ return true;
262
+ }
263
+ return false;
264
+ }
265
+ async sshConnected() {
266
+ try {
267
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_CONNECTED)(this.id, this.sshForwardPort));
268
+ await this.ssh.forwardIn(this.sshForwardPort);
269
+ this.status = utils_1.TUNNEL_OPEN;
270
+ }
271
+ catch (err) {
272
+ // reconnect
273
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_FAILED)(this.id));
274
+ logger_1.default.debug(err);
275
+ this.ssh.close();
276
+ return;
277
+ }
278
+ this.emit(utils_1.TUNNEL_EVENT_OPEN, this);
279
+ }
280
+ sshDisconnected() {
281
+ if (this.status !== utils_1.TUNNEL_CLOSED) {
282
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_DISCONNECTED)(this.id));
283
+ this.status = utils_1.TUNNEL_CLOSED;
284
+ this.emit(utils_1.TUNNEL_EVENT_CLOSED, this);
285
+ }
286
+ }
287
+ tunnelToTarget(stream, onClose) {
288
+ this.totalConnections += 1;
289
+ const tcp = new tcp_1.default(this.targetHost, this.targetPort, stream);
290
+ this.connections[tcp.id] = tcp;
291
+ tcp.on(utils_1.TCP_EVENT_CLOSED, () => {
292
+ this.connections[tcp.id].removeAllListeners();
293
+ delete this.connections[tcp.id];
294
+ onClose();
295
+ });
296
+ tcp.pipe();
297
+ }
298
+ httpIdentified(type) {
299
+ logger_1.default.info((0, texts_js_1.LOG_TUNNEL_IDENTIFIED)(this.id, type));
300
+ this.emit(utils_1.TUNNEL_EVENT_HTTP_IDENTIFIED, this, type);
301
+ }
302
+ httpConnectionOpen(s) {
303
+ this.totalConnections += 1;
304
+ this.connections[s.id] = s;
305
+ this.emit(utils_1.TUNNEL_EVENT_HTTP_OPEN, this);
306
+ }
307
+ httpConnectionClosed(s) {
308
+ delete this.connections[s.id];
309
+ this.emit(utils_1.TUNNEL_EVENT_HTTP_CLOSED, this);
310
+ }
311
+ httpBasicAuth(req, res) {
312
+ if (this.login || this.password) {
313
+ const user = (0, basic_auth_1.default)(req);
314
+ if (!user || user.name !== this.login || user.pass !== this.password) {
315
+ logger_1.default.debug(texts_js_1.LOG_TUNNEL_HTTP_WRON_AUTH);
316
+ this.httpEndFast(req, res, 401, 'Unauthorised', {
317
+ 'WWW-Authenticate': 'Basic real="Buddy"',
318
+ });
319
+ return false;
320
+ }
321
+ }
322
+ return true;
323
+ }
324
+ httpEndFast(req, res, statusCode, msg, headers = {}) {
325
+ const log = this.httpLog.newRequest(req.method, req.headers, req.url, req.httpVersion, req);
326
+ if (!log) {
327
+ this.httpLog.newResponse(req, statusCode, headers);
328
+ res.statusCode = statusCode;
329
+ Object.keys(headers).forEach((k) => {
330
+ res.setHeader(k, headers[k]);
331
+ });
332
+ res.end(msg);
333
+ }
334
+ else {
335
+ req.pipe(log.requestBody);
336
+ log.requestBody.pipeToNothing(() => {
337
+ this.httpLog.newResponse(req, statusCode, headers, log);
338
+ res.statusCode = statusCode;
339
+ Object.keys(headers).forEach((k) => {
340
+ res.setHeader(k, headers[k]);
341
+ });
342
+ res.end(msg);
343
+ });
344
+ }
345
+ }
346
+ httpRateLimit(req, res) {
347
+ const isRateLimited = this.httpLog.isRateLimited(req);
348
+ if (isRateLimited) {
349
+ logger_1.default.debug(texts_js_1.LOG_TUNNEL_HTTP_RATE_LIMIT);
350
+ this.httpEndFast(req, res, 429, 'Too Many Requests', {
351
+ 'Retry-After': '60',
352
+ });
353
+ return false;
354
+ }
355
+ return true;
356
+ }
357
+ httpCircuitBreaker(req, res) {
358
+ const isOpen = this.httpLog.isCircuitBreakerOpen();
359
+ if (isOpen) {
360
+ logger_1.default.debug(texts_js_1.LOG_TUNNEL_HTTP_CIRCUIT_BREAKER_OPEN);
361
+ this.httpEndFast(req, res, 504, 'Service Unavailable', {});
362
+ return false;
363
+ }
364
+ return true;
365
+ }
366
+ httpUserAgent(req, res) {
367
+ if (this.useragents && this.useragents.length > 0) {
368
+ const ua = req.headers['user-agent'] || '';
369
+ for (let i = 0; i < this.useragents.length; i += 1) {
370
+ const str = this.useragents[i];
371
+ if ((0, utils_1.isStringRegExp)(str)) {
372
+ try {
373
+ const r = new RegExp(str, 'i');
374
+ if (r.test(ua))
375
+ return true;
376
+ }
377
+ catch {
378
+ // do nothing
379
+ }
380
+ }
381
+ else if (ua.includes(str)) {
382
+ return true;
383
+ }
384
+ }
385
+ logger_1.default.debug(texts_js_1.LOG_TUNNEL_HTTP_WRONG_USER_AGENTS);
386
+ this.httpEndFast(req, res, 401, 'Unauthorised', {});
387
+ return false;
388
+ }
389
+ return true;
390
+ }
391
+ targetReconnected() {
392
+ if (this.identify)
393
+ this.identify.identify();
394
+ }
395
+ httpLogRequest(logRequest) {
396
+ this.emit(utils_1.TUNNEL_EVENT_HTTP_REQUEST, this, logRequest);
397
+ }
398
+ httpLogResponse(logRequest) {
399
+ this.emit(utils_1.TUNNEL_EVENT_HTTP_RESPONSE, this, logRequest);
400
+ }
401
+ retryHttpLogRequest(logRequest) {
402
+ if (logRequest.requestBody.tooLarge)
403
+ return;
404
+ if (logRequest.httpVersion === '2.0')
405
+ return this.http2server.retryRequest(logRequest);
406
+ return this.http1server.retryRequest(logRequest);
407
+ }
408
+ httpRequest(req, res) {
409
+ const isAuth = this.httpBasicAuth(req, res) &&
410
+ this.httpUserAgent(req, res) &&
411
+ this.httpRateLimit(req, res) &&
412
+ this.httpCircuitBreaker(req, res);
413
+ if (!isAuth)
414
+ return;
415
+ const http = new http_1.default({
416
+ req,
417
+ res,
418
+ auth: this.targetAuth,
419
+ proto: this.targetProto,
420
+ host: this.targetHost,
421
+ port: this.targetPort,
422
+ hostHeader: this.host,
423
+ timeout: this.timeout,
424
+ verify: this.verify,
425
+ compression: this.compression,
426
+ headers: this.headers,
427
+ serve: this.serve,
428
+ responseHeaders: this.responseHeaders,
429
+ httpIdentify: this.identify.type,
430
+ httpLog: this.httpLog,
431
+ });
432
+ http.once(utils_1.HTTP1_SOCKET_CLOSED, (socket) => this.httpConnectionClosed(socket));
433
+ http.pipe().then();
434
+ }
435
+ tlsSocket(tlsSocket) {
436
+ this.tunnelToTarget(tlsSocket, () => {
437
+ this.emit(utils_1.TUNNEL_EVENT_TLS_CLOSED, this);
438
+ });
439
+ this.emit(utils_1.TUNNEL_EVENT_TLS_OPEN, this);
440
+ }
441
+ canStreamTcp() {
442
+ if (this.type === utils_1.TUNNEL_TCP)
443
+ return true;
444
+ return (this.type === utils_1.TUNNEL_TLS &&
445
+ [utils_1.TLS_TERMINATE_AT_TARGET, utils_1.TLS_TERMINATE_AT_REGION].includes(this.terminate));
446
+ }
447
+ canStreamTls() {
448
+ return this.type === utils_1.TUNNEL_TLS;
449
+ }
450
+ canStreamSsh() {
451
+ return this.type === utils_1.TUNNEL_SSH;
452
+ }
453
+ canStreamHttp() {
454
+ return this.type === utils_1.TUNNEL_HTTP;
455
+ }
456
+ safeEndStream(stream) {
457
+ try {
458
+ stream.removeAllListeners();
459
+ stream.once('error', () => { });
460
+ stream.end();
461
+ }
462
+ catch {
463
+ // do nothing
464
+ }
465
+ setTimeout(() => {
466
+ try {
467
+ stream.destroy();
468
+ }
469
+ catch {
470
+ // do nothing
471
+ }
472
+ }, 1000);
473
+ }
474
+ sshStreamTcp(stream) {
475
+ if (!this.canStreamTcp()) {
476
+ this.safeEndStream(stream);
477
+ return;
478
+ }
479
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_TCP_STREAM)(this.id));
480
+ this.tunnelToTarget(stream, () => {
481
+ this.emit(utils_1.TUNNEL_EVENT_TCP_CLOSED, this);
482
+ });
483
+ this.emit(utils_1.TUNNEL_EVENT_TCP_OPEN, this);
484
+ }
485
+ sshStreamHttp1(stream, info, ip) {
486
+ if (!this.canStreamHttp()) {
487
+ this.safeEndStream(stream);
488
+ return;
489
+ }
490
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_HTTP1_STREAM)(this.id));
491
+ if (this.http1server) {
492
+ this.http1server.handleSshTunnel(stream, info, ip);
493
+ return;
494
+ }
495
+ this.safeEndStream(stream);
496
+ }
497
+ sshStreamHttp2(stream, info, ip) {
498
+ if (!this.canStreamHttp()) {
499
+ this.safeEndStream(stream);
500
+ return;
501
+ }
502
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_HTTP2_STREAM)(this.id));
503
+ if (this.http2server) {
504
+ this.http2server.handleSshTunnel(stream, info, ip);
505
+ return;
506
+ }
507
+ this.safeEndStream(stream);
508
+ }
509
+ sshStreamSsh(stream) {
510
+ if (!this.canStreamSsh()) {
511
+ this.safeEndStream(stream);
512
+ return;
513
+ }
514
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_SSH_STREAM)(this.id));
515
+ if (this.sshServer) {
516
+ this.sshServer.handleSshTunnel(stream);
517
+ return;
518
+ }
519
+ this.safeEndStream(stream);
520
+ }
521
+ sshStreamTls(stream) {
522
+ if (!this.canStreamTls()) {
523
+ this.safeEndStream(stream);
524
+ return;
525
+ }
526
+ if (this.terminate === utils_1.TLS_TERMINATE_AT_TARGET) {
527
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_TLS_TARGET_STREAM)(this.id));
528
+ this.sshStreamTcp(stream);
529
+ return;
530
+ }
531
+ if (this.terminate === utils_1.TLS_TERMINATE_AT_REGION) {
532
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_TLS_REGION_STREAM)(this.id));
533
+ this.sshStreamTcp(stream);
534
+ return;
535
+ }
536
+ if (this.tls) {
537
+ logger_1.default.debug((0, texts_js_1.LOG_TUNNEL_TLS_AGENT_STREAM)(this.id));
538
+ this.tls.handleSshTunnel(stream);
539
+ return;
540
+ }
541
+ this.safeEndStream(stream);
542
+ }
543
+ start() {
544
+ if (this.started)
545
+ return;
546
+ this.started = true;
547
+ logger_1.default.info((0, texts_js_1.LOG_STARTING_TUNNEL)(this.id));
548
+ // region latency
549
+ this.regionLatency = new latency_1.default(this.sshIp, this.sshPort);
550
+ this.regionLatency.startChecking();
551
+ // target latency
552
+ if (!this.serve && this.type !== utils_1.TUNNEL_SSH) {
553
+ this.targetLatency = new latency_1.default(this.targetHost, this.targetPort);
554
+ this.targetLatency.on(utils_1.TUNNEL_LATENCY_EVENT_RECONNECTED, () => this.targetReconnected());
555
+ this.targetLatency.startChecking();
556
+ }
557
+ // dns health
558
+ this.dns = new dns_js_1.default(this.sshIp, this.domain, this.customDomain, this.subdomain, this.region, this.sshId);
559
+ this.dns.startChecking();
560
+ if (this.type === utils_1.TUNNEL_TLS && this.terminate === utils_1.TLS_TERMINATE_AT_AGENT) {
561
+ // tls
562
+ this.tls = new tls_1.default(this.key, this.cert, this.ca);
563
+ this.tls.on(utils_1.TLS_SOCKET, (socket) => this.tlsSocket(socket));
564
+ }
565
+ else if (this.type === utils_1.TUNNEL_HTTP) {
566
+ // http
567
+ this.httpLog = new log_1.default(this.log, this.circuitBreaker);
568
+ this.httpLog.on(utils_1.EVENT_TUNNEL_HTTP_NEW_REQUEST, (logRequest) => this.httpLogRequest(logRequest));
569
+ this.httpLog.on(utils_1.EVENT_TUNNEL_HTTP_NEW_RESPONSE, (logRequest) => this.httpLogResponse(logRequest));
570
+ this.identify = new identification_1.default(this.targetProto, this.targetHost, this.targetPort, this.http2 || !!this.serve);
571
+ this.identify.on(utils_1.EVENT_TUNNEL_IDENTIFIED, (type) => this.httpIdentified(type));
572
+ const host = format_1.default.entryHostEncoded(this);
573
+ this.http2server = new http2_1.default(host);
574
+ this.http2server.on(utils_1.HTTP2_SESSION_OPEN, (session) => this.httpConnectionOpen(session));
575
+ this.http2server.on(utils_1.HTTP2_SESSION_CLOSED, (session) => this.httpConnectionClosed(session));
576
+ this.http2server.on(utils_1.HTTP2_REQUEST, (req, res) => this.httpRequest(req, res));
577
+ this.http1server = new http1_1.default(host);
578
+ this.http1server.on(utils_1.HTTP1_SOCKET_OPEN, (socket) => this.httpConnectionOpen(socket));
579
+ this.http1server.on(utils_1.HTTP1_SOCKET_CLOSED, (socket) => this.httpConnectionClosed(socket));
580
+ this.http1server.on(utils_1.HTTP1_REQUEST, (req, res) => this.httpRequest(req, res));
581
+ }
582
+ else if (this.type === utils_1.TUNNEL_SSH) {
583
+ // ssh server
584
+ this.sshServer = new ssh_1.default(this.agent, this.sshClientUser, this.sshClientPassword, this.sshHostKey);
585
+ }
586
+ // ssh
587
+ this.ssh = new client_1.default(this.sshIp, this.sshPort, this.sshUser, this.sshPassword);
588
+ this.ssh.on(utils_1.SSH_CLIENT_EVENT_CONNECTED, () => this.sshConnected());
589
+ this.ssh.on(utils_1.SSH_CLIENT_EVENT_DISCONNECTED, () => this.sshDisconnected());
590
+ this.ssh.on(utils_1.SSH_CLIENT_EVENT_STREAM_TCP, (stream) => this.sshStreamTcp(stream));
591
+ this.ssh.on(utils_1.SSH_CLIENT_EVENT_STREAM_TLS, (stream) => this.sshStreamTls(stream));
592
+ this.ssh.on(utils_1.SSH_CLIENT_EVENT_STREAM_HTTP1, (stream, info, ip) => this.sshStreamHttp1(stream, info, ip));
593
+ this.ssh.on(utils_1.SSH_CLIENT_EVENT_STREAM_HTTP2, (stream, info, ip) => this.sshStreamHttp2(stream, info, ip));
594
+ this.ssh.on(utils_1.SSH_CLIENT_EVENT_STREAM_SSH, (stream) => this.sshStreamSsh(stream));
595
+ this.ssh.openKeepAlive();
596
+ }
597
+ stop(emitEvent = true) {
598
+ if (!this.started)
599
+ return;
600
+ this.started = false;
601
+ logger_1.default.info((0, texts_js_1.LOG_STOPPING_TUNNEL)(this.id));
602
+ if (emitEvent)
603
+ this.emit(utils_1.TUNNEL_EVENT_STOPPED, this);
604
+ if (this.regionLatency) {
605
+ this.regionLatency.removeAllListeners();
606
+ this.regionLatency.stopChecking();
607
+ this.regionLatency = null;
608
+ }
609
+ if (this.dns) {
610
+ this.dns.stopChecking();
611
+ this.dns = null;
612
+ }
613
+ if (this.targetLatency) {
614
+ this.targetLatency.removeAllListeners();
615
+ this.targetLatency.stopChecking();
616
+ this.targetLatency = null;
617
+ }
618
+ if (this.tls) {
619
+ this.tls.removeAllListeners();
620
+ this.tls.stop();
621
+ this.tls = null;
622
+ }
623
+ if (this.httpLog) {
624
+ this.httpLog.removeAllListeners();
625
+ this.httpLog.stop();
626
+ this.httpLog = null;
627
+ }
628
+ if (this.sshServer) {
629
+ this.sshServer.removeAllListeners();
630
+ this.sshServer.stop();
631
+ this.sshServer = null;
632
+ }
633
+ if (this.identify) {
634
+ this.identify.removeAllListeners();
635
+ this.identify.stop();
636
+ this.identify = null;
637
+ }
638
+ if (this.http2server) {
639
+ this.http2server.removeAllListeners();
640
+ this.http2server.stop();
641
+ this.http2server = null;
642
+ }
643
+ if (this.http1server) {
644
+ this.http1server.removeAllListeners();
645
+ this.http1server.stop();
646
+ this.http1server = null;
647
+ }
648
+ if (this.ssh) {
649
+ this.ssh.removeAllListeners();
650
+ this.ssh.closeKeepAlive();
651
+ this.ssh = null;
652
+ }
653
+ this.status = utils_1.TUNNEL_CLOSED;
654
+ }
655
+ }
656
+ exports.default = Tunnel;