bdy 1.7.46-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.
Files changed (96) hide show
  1. package/.eslintrc.yml +23 -0
  2. package/LICENSE +21 -0
  3. package/bin/cli.js +5 -0
  4. package/dockerfile +15 -0
  5. package/link.sh +3 -0
  6. package/package.json +39 -0
  7. package/src/agent/linux.js +127 -0
  8. package/src/agent/manager.js +404 -0
  9. package/src/agent/osx.js +150 -0
  10. package/src/agent/socket/tunnel.js +232 -0
  11. package/src/agent/socket.js +260 -0
  12. package/src/agent/system.js +205 -0
  13. package/src/agent/wait.js +20 -0
  14. package/src/agent/windows.js +168 -0
  15. package/src/agent.js +248 -0
  16. package/src/api/agent.js +95 -0
  17. package/src/api/buddy.js +131 -0
  18. package/src/api/socket.js +142 -0
  19. package/src/cfg.js +228 -0
  20. package/src/command/agent/disable.js +37 -0
  21. package/src/command/agent/enable.js +117 -0
  22. package/src/command/agent/restart.js +28 -0
  23. package/src/command/agent/run.js +16 -0
  24. package/src/command/agent/start.js +28 -0
  25. package/src/command/agent/status.js +45 -0
  26. package/src/command/agent/stop.js +28 -0
  27. package/src/command/agent/tunnel/http.js +47 -0
  28. package/src/command/agent/tunnel/list.js +27 -0
  29. package/src/command/agent/tunnel/start.js +38 -0
  30. package/src/command/agent/tunnel/status.js +32 -0
  31. package/src/command/agent/tunnel/stop.js +30 -0
  32. package/src/command/agent/tunnel/tcp.js +47 -0
  33. package/src/command/agent/tunnel/tls.js +47 -0
  34. package/src/command/agent/tunnel.js +21 -0
  35. package/src/command/agent/update.js +43 -0
  36. package/src/command/agent/version.js +23 -0
  37. package/src/command/agent.js +27 -0
  38. package/src/command/config/add/http.js +33 -0
  39. package/src/command/config/add/tcp.js +33 -0
  40. package/src/command/config/add/tls.js +33 -0
  41. package/src/command/config/add.js +13 -0
  42. package/src/command/config/get/region.js +13 -0
  43. package/src/command/config/get/timeout.js +13 -0
  44. package/src/command/config/get/token.js +13 -0
  45. package/src/command/config/get/tunnel.js +21 -0
  46. package/src/command/config/get/tunnels.js +13 -0
  47. package/src/command/config/get/whitelist.js +13 -0
  48. package/src/command/config/get.js +19 -0
  49. package/src/command/config/remove/tunnel.js +22 -0
  50. package/src/command/config/remove.js +9 -0
  51. package/src/command/config/set/region.js +19 -0
  52. package/src/command/config/set/timeout.js +22 -0
  53. package/src/command/config/set/token.js +18 -0
  54. package/src/command/config/set/whitelist.js +19 -0
  55. package/src/command/config/set.js +15 -0
  56. package/src/command/config.js +15 -0
  57. package/src/command/http.js +34 -0
  58. package/src/command/pre.js +47 -0
  59. package/src/command/start.js +31 -0
  60. package/src/command/tcp.js +32 -0
  61. package/src/command/tls.js +32 -0
  62. package/src/command/version.js +10 -0
  63. package/src/format.js +171 -0
  64. package/src/index.js +32 -0
  65. package/src/input.js +283 -0
  66. package/src/logger.js +87 -0
  67. package/src/output/interactive/tunnel.js +871 -0
  68. package/src/output/noninteractive/agent/tunnels.js +32 -0
  69. package/src/output/noninteractive/config/tunnel.js +52 -0
  70. package/src/output/noninteractive/config/tunnels.js +19 -0
  71. package/src/output/noninteractive/tunnel.js +79 -0
  72. package/src/output.js +136 -0
  73. package/src/server/cert.js +51 -0
  74. package/src/server/http1.js +79 -0
  75. package/src/server/http2.js +79 -0
  76. package/src/server/sftp.js +474 -0
  77. package/src/server/ssh.js +107 -0
  78. package/src/server/tls.js +41 -0
  79. package/src/ssh/client.js +196 -0
  80. package/src/texts.js +447 -0
  81. package/src/tunnel/agent.js +100 -0
  82. package/src/tunnel/compression.js +32 -0
  83. package/src/tunnel/dns.js +55 -0
  84. package/src/tunnel/html/404.html +129 -0
  85. package/src/tunnel/html/503.html +136 -0
  86. package/src/tunnel/html.js +32 -0
  87. package/src/tunnel/http/log.js +204 -0
  88. package/src/tunnel/http/serve.js +127 -0
  89. package/src/tunnel/http/stream.js +46 -0
  90. package/src/tunnel/http.js +406 -0
  91. package/src/tunnel/identification.js +95 -0
  92. package/src/tunnel/latency.js +63 -0
  93. package/src/tunnel/tcp.js +71 -0
  94. package/src/tunnel.js +696 -0
  95. package/src/utils.js +496 -0
  96. package/unlink.sh +3 -0
@@ -0,0 +1,32 @@
1
+ const { TUNNEL_OPEN } = require('../../../utils.js');
2
+ const { NO_TUNNELS_STARTED } = require('../../../texts.js');
3
+ const Format = require('../../../format');
4
+
5
+ class OutputNoninteractiveAgentTunnels {
6
+ constructor(terminal, tunnels) {
7
+ this.terminal = terminal;
8
+ this.tunnels = tunnels;
9
+ }
10
+
11
+ start(output) {
12
+ if (!this.tunnels.length) {
13
+ output.exitNormal(NO_TUNNELS_STARTED);
14
+ } else {
15
+ const tunnels = [['Id', 'Type', 'Target / Latency', 'Entry / Latency', 'Status']];
16
+ this.tunnels.forEach((tunnel) => {
17
+ let target;
18
+ let status;
19
+ if (tunnel.serve) target = Format.serve(tunnel.serve) + ' / 0ms';
20
+ else target = Format.target(tunnel.type, tunnel.target) + ` / ${Format.latency(tunnel.targetLatency)}`;
21
+ const entry = Format.entry(tunnel) + ` / ${Format.latency(tunnel.regionLatency)}`;
22
+ if (tunnel.status === TUNNEL_OPEN) status = 'Open';
23
+ else status = 'Closed';
24
+ tunnels.push([tunnel.id, tunnel.type, target, entry, status]);
25
+ });
26
+ output.table(tunnels);
27
+ output.exitNormal();
28
+ }
29
+ }
30
+ }
31
+
32
+ module.exports = OutputNoninteractiveAgentTunnels;
@@ -0,0 +1,52 @@
1
+ const {
2
+ TUNNEL_HTTP,
3
+ TUNNEL_TLS
4
+ } = require('../../../utils.js');
5
+ const Format = require('../../../format');
6
+
7
+ class OutputNoninteractiveConfigTunnel {
8
+ constructor(terminal, tunnel) {
9
+ this.terminal = terminal;
10
+ this.tunnel = tunnel;
11
+ }
12
+
13
+ start(output) {
14
+ const data = [
15
+ ['Name', this.tunnel.name],
16
+ ['Type', Format.type(this.tunnel.type)]
17
+ ];
18
+ if (this.tunnel.type === TUNNEL_HTTP && this.tunnel.serve) {
19
+ data.push(['Serve', Format.serve(this.tunnel.serve)]);
20
+ } else {
21
+ data.push(['Target', Format.target(this.tunnel.type, this.tunnel.target)]);
22
+ }
23
+ data.push(['Region', Format.tunnelRegion(this.tunnel.region)]);
24
+ data.push(['Server ID', this.tunnel.sshId]);
25
+ data.push(['Timeout', Format.tunnelTimeout(this.tunnel.timeout)]);
26
+ data.push(['Whitelist', Format.tunnelWhitelist(this.tunnel.whitelist)]);
27
+ data.push(['Domain', Format.tunnelDomain(this.tunnel.domain)]);
28
+ data.push(['Subdomain', Format.tunnelDomain(this.tunnel.subdomain)]);
29
+ if (this.tunnel.type === TUNNEL_HTTP) {
30
+ data.push(['Host Header', Format.hostHeader(this.tunnel.host)]);
31
+ data.push(['Basic Auth', Format.basicAuth(this.tunnel.login, this.tunnel.password)]);
32
+ data.push(['User Agents', Format.tunnelUserAgent(this.tunnel.useragents)]);
33
+ data.push(['Request Headers', Format.tunnelHeaders(this.tunnel.headers)]);
34
+ data.push(['Response Headers', Format.tunnelHeaders(this.tunnel.responseHeaders)]);
35
+ data.push(['Circuit Breaker', Format.tunnelCircuitBreaker(this.tunnel.circuitBreaker)]);
36
+ data.push(['Log Requests', Format.yesNo(this.tunnel.log)]);
37
+ data.push(['TLS Auth', Format.yesNo(!!this.tunnel.ca)]);
38
+ data.push(['TLS Verify', Format.yesNo(this.tunnel.verify)]);
39
+ data.push(['Force HTTP/2', Format.yesNo(this.tunnel.http2)]);
40
+ data.push(['Compression', Format.yesNo(this.tunnel.compression)]);
41
+ } else if (this.tunnel.type === TUNNEL_TLS) {
42
+ data.push(['Terminate TLS At', this.tunnel.terminate]);
43
+ data.push(['TLS Key', Format.yesNo(!!this.tunnel.key)]);
44
+ data.push(['TLS Cert', Format.yesNo(!!this.tunnel.cert)]);
45
+ data.push(['TLS Auth', Format.yesNo(!!this.tunnel.ca)]);
46
+ }
47
+ output.table(data);
48
+ output.exitNormal();
49
+ }
50
+ }
51
+
52
+ module.exports = OutputNoninteractiveConfigTunnel;
@@ -0,0 +1,19 @@
1
+
2
+ class OutputNoninteractiveConfigTunnels {
3
+ constructor(terminal, tunnels) {
4
+ this.terminal = terminal;
5
+ this.tunnels = tunnels;
6
+ }
7
+
8
+ start(output) {
9
+ const data = [['Name', 'Type', 'Target']];
10
+ Object.keys(this.tunnels).forEach((name) => {
11
+ const t = this.tunnels[name];
12
+ data.push([name, t.type, String(t.target)]);
13
+ });
14
+ output.table(data);
15
+ output.exitNormal();
16
+ }
17
+ }
18
+
19
+ module.exports = OutputNoninteractiveConfigTunnels;
@@ -0,0 +1,79 @@
1
+ const Format = require('../../format');
2
+ const {
3
+ TUNNEL_EVENT_OPEN,
4
+ TUNNEL_EVENT_CLOSED,
5
+ TUNNEL_EVENT_TCP_OPEN,
6
+ TUNNEL_EVENT_TCP_CLOSED,
7
+ TUNNEL_EVENT_TLS_OPEN,
8
+ TUNNEL_EVENT_TLS_CLOSED,
9
+ TUNNEL_EVENT_HTTP_IDENTIFIED,
10
+ TUNNEL_EVENT_HTTP_REQUEST,
11
+ TUNNEL_EVENT_HTTP_RESPONSE,
12
+ TUNNEL_EVENT_STOPPED
13
+ } = require('../../utils');
14
+
15
+ class OutputNoninteractiveTunnel {
16
+ constructor(terminal, tunnel) {
17
+ this.tunnel = tunnel;
18
+ this.terminal = terminal;
19
+ }
20
+
21
+ status(t, status) {
22
+ this.terminal(`${Format.date()}: Tunnel ${t.type} to ${t.serve || t.target} ${status}\n`);
23
+ }
24
+
25
+ onOpen(t) {
26
+ this.status(t, `open. Entry: ${Format.entry(t)}`);
27
+ }
28
+
29
+ onClosed(t) {
30
+ this.status(t, 'closed');
31
+ }
32
+
33
+ onTcpOpen(t) {
34
+ this.status(t, 'has incoming tcp connection');
35
+ }
36
+
37
+ onTcpClosed(t) {
38
+ this.status(t, 'closed tcp connection');
39
+ }
40
+
41
+ onTlsOpen(t) {
42
+ this.status(t, 'has incoming tls connection');
43
+ }
44
+
45
+ onTlsClosed(t) {
46
+ this.status(t, 'closed tls connection');
47
+ }
48
+
49
+ onHttpIdentified(t, type) {
50
+ this.status(t, `identified as ${type}`);
51
+ }
52
+
53
+ onHttpRequest(t, logRequest) {
54
+ this.status(t, `Request ${logRequest.method} ${logRequest.url}`);
55
+ }
56
+
57
+ onHttpResponse(t, logRequest) {
58
+ this.status(t, `Response ${logRequest.method} ${logRequest.url} ${logRequest.status} in ${logRequest.time}ms`);
59
+ }
60
+
61
+ onStopped() {
62
+ process.exit();
63
+ }
64
+
65
+ start() {
66
+ this.tunnel.on(TUNNEL_EVENT_OPEN, (t) => this.onOpen(t));
67
+ this.tunnel.on(TUNNEL_EVENT_CLOSED, (t) => this.onClosed(t));
68
+ this.tunnel.on(TUNNEL_EVENT_TCP_OPEN, (t) => this.onTcpOpen(t));
69
+ this.tunnel.on(TUNNEL_EVENT_TCP_CLOSED, (t) => this.onTcpClosed(t));
70
+ this.tunnel.on(TUNNEL_EVENT_TLS_OPEN, (t) => this.onTlsOpen(t));
71
+ this.tunnel.on(TUNNEL_EVENT_TLS_CLOSED, (t) => this.onTlsClosed(t));
72
+ this.tunnel.on(TUNNEL_EVENT_HTTP_IDENTIFIED, (t, type) => this.onHttpIdentified(t, type));
73
+ this.tunnel.on(TUNNEL_EVENT_HTTP_REQUEST, (t, logRequest) => this.onHttpRequest(t, logRequest));
74
+ this.tunnel.on(TUNNEL_EVENT_HTTP_RESPONSE, (t, logRequest) => this.onHttpResponse(t, logRequest));
75
+ this.tunnel.on(TUNNEL_EVENT_STOPPED, (t) => this.onStopped(t));
76
+ }
77
+ }
78
+
79
+ module.exports = OutputNoninteractiveTunnel;
package/src/output.js ADDED
@@ -0,0 +1,136 @@
1
+ const TerminalKit = require('terminal-kit/lib/termkit-no-lazy-require');
2
+ const OutputInteractiveTunnel = require('./output/interactive/tunnel.js');
3
+ const OutputNoninteractiveTunnel = require('./output/noninteractive/tunnel.js');
4
+ const OutputNoninteractiveConfigTunnel = require('./output/noninteractive/config/tunnel.js');
5
+ const OutputNoninteractiveConfigTunnels = require('./output/noninteractive/config/tunnels.js');
6
+ const {
7
+ TXT_NEW_AGENT_VERSION,
8
+ TXT_NEW_CLI_AGENT_VERSION,
9
+ TXT_NEW_CLI_VERSION
10
+ } = require('./texts.js');
11
+ const OutputNoninteractiveAgentTunnels = require('./output/noninteractive/agent/tunnels.js');
12
+ const { TXT_NEW_CLI_DOCKER_VERSION } = require('./texts');
13
+
14
+ const terminal = TerminalKit.terminal;
15
+
16
+ class Output {
17
+ static s;
18
+
19
+ static exitSuccess(msg) {
20
+ this.killSpinner();
21
+ terminal.green(`${msg}\n`);
22
+ process.exit(0);
23
+ }
24
+
25
+ static exitNormal(msg) {
26
+ this.killSpinner();
27
+ if (msg) terminal(`${msg}\n`);
28
+ process.exit(0);
29
+ }
30
+
31
+ static newline() {
32
+ terminal('\n');
33
+ }
34
+
35
+ static normal(txt) {
36
+ terminal(`${txt}\n`);
37
+ }
38
+
39
+ static killSpinner() {
40
+ if (this.s) {
41
+ this.s.destroy();
42
+ this.s = null;
43
+ terminal.eraseLine();
44
+ terminal.left();
45
+ }
46
+ }
47
+
48
+ static async spinner(txt) {
49
+ if (!this.s && terminal.isTTY) {
50
+ this.s = await terminal.spinner();
51
+ if (txt) terminal(` ${txt}`);
52
+ }
53
+ }
54
+
55
+ static agentTunnels(tunnels) {
56
+ const on = new OutputNoninteractiveAgentTunnels(terminal, tunnels);
57
+ on.start(this);
58
+ }
59
+
60
+ static tunnelInteractive(tunnel) {
61
+ this.killSpinner();
62
+ const oi = new OutputInteractiveTunnel(terminal, tunnel);
63
+ oi.start();
64
+ }
65
+
66
+ static tunnelNonInteractive(tunnel) {
67
+ this.killSpinner();
68
+ const on = new OutputNoninteractiveTunnel(terminal, tunnel);
69
+ on.start();
70
+ }
71
+
72
+ static newCliVersion(version) {
73
+ terminal.gray(TXT_NEW_CLI_VERSION(version));
74
+ }
75
+
76
+ static newCliDockerVersion(version) {
77
+ terminal.gray(TXT_NEW_CLI_DOCKER_VERSION(version));
78
+ }
79
+
80
+ static newCliAgentVersion(version) {
81
+ terminal.gray(TXT_NEW_CLI_AGENT_VERSION(version));
82
+ }
83
+
84
+ static newAgentVersion(version) {
85
+ terminal.gray(TXT_NEW_AGENT_VERSION(version));
86
+ }
87
+
88
+ static tunnel(tunnel) {
89
+ if (terminal.isTTY) this.tunnelInteractive(tunnel);
90
+ else this.tunnelNonInteractive(tunnel);
91
+ }
92
+
93
+ static table(data) {
94
+ // apply padding
95
+ for (let i=0; i < data.length; i += 1) {
96
+ for (let j=0; j < data[i].length; j += 1) {
97
+ const s = data[i][j].split('\n');
98
+ const tmp = [];
99
+ for (let k=0; k < s.length; k += 1) {
100
+ tmp.push(` ${s[k]} `);
101
+ }
102
+ data[i][j] = tmp.join('\n');
103
+ }
104
+ }
105
+ terminal.table(data, {
106
+ fit: false,
107
+ });
108
+ }
109
+
110
+ static configTunnels(tunnels) {
111
+ const on = new OutputNoninteractiveConfigTunnels(terminal, tunnels);
112
+ on.start(this);
113
+ }
114
+
115
+ static configTunnel(tunnel) {
116
+ const on = new OutputNoninteractiveConfigTunnel(terminal, tunnel);
117
+ on.start(this);
118
+ }
119
+
120
+ static exitError(err) {
121
+ this.killSpinner();
122
+ terminal.fullscreen(false);
123
+ terminal.hideCursor(false);
124
+ terminal.grabInput(false);
125
+ let msg;
126
+ if (err instanceof Error) {
127
+ msg = err.message;
128
+ if (process.env.DEBUG === '1') msg += `\n${err.stack}`;
129
+ }
130
+ else msg = err;
131
+ terminal.red.error(`${msg}\n`);
132
+ process.exit(1);
133
+ }
134
+ }
135
+
136
+ module.exports = Output;
@@ -0,0 +1,51 @@
1
+ const forge = require('node-forge');
2
+
3
+ const toPositiveHex = (hexString) => {
4
+ let hexAsInt = parseInt(hexString[0], 16);
5
+ if (hexAsInt < 8){
6
+ return hexString;
7
+ }
8
+ hexAsInt -= 8;
9
+ return hexAsInt.toString() + hexString.substring(1);
10
+ };
11
+
12
+ class ServerCert {
13
+ constructor() {
14
+ const keyPair = forge.pki.rsa.generateKeyPair(2048);
15
+ const cert = forge.pki.createCertificate();
16
+ cert.serialNumber = toPositiveHex(forge.util.bytesToHex(forge.random.getBytesSync(9)));
17
+ cert.validity.notBefore = new Date();
18
+ const notAfter = new Date();
19
+ notAfter.setTime(notAfter.getTime() + 622080000000);
20
+ cert.validity.notAfter = notAfter;
21
+
22
+ const attrs = [{
23
+ name: 'commonName',
24
+ value: 'buddy.tunnel'
25
+ }];
26
+
27
+ cert.setSubject(attrs);
28
+ cert.setIssuer(attrs);
29
+
30
+ cert.publicKey = keyPair.publicKey;
31
+
32
+ cert.setExtensions([{
33
+ name: 'basicConstraints',
34
+ cA: true
35
+ }, {
36
+ name: 'keyUsage',
37
+ keyCertSign: true,
38
+ digitalSignature: true,
39
+ nonRepudiation: true,
40
+ keyEncipherment: true,
41
+ dataEncipherment: true
42
+ }]);
43
+
44
+ cert.sign(keyPair.privateKey, forge.md.sha256.create());
45
+
46
+ this.key = forge.pki.privateKeyToPem(keyPair.privateKey);
47
+ this.cert = forge.pki.certificateToPem(cert);
48
+ }
49
+ }
50
+
51
+ module.exports = ServerCert;
@@ -0,0 +1,79 @@
1
+ const EventEmitter = require('events');
2
+ const logger = require('../logger.js');
3
+ const { v4 } = require('uuid');
4
+ const http = require('http');
5
+ const {
6
+ LOG_HTTP1_CONNECTION,
7
+ LOG_HTTP1_REQUEST
8
+ } = require('../texts.js');
9
+ const {
10
+ HTTP1_SOCKET_OPEN,
11
+ HTTP1_SOCKET_CLOSED,
12
+ HTTP1_REQUEST
13
+ } = require('../utils');
14
+
15
+ class ServerHttp1 extends EventEmitter {
16
+ constructor(host) {
17
+ super();
18
+ this.server = http.createServer((req, res) => this.processRequest(req, res, host));
19
+ this.server.on('connection', (socket) => {
20
+ socket.id = v4();
21
+ this.emit(HTTP1_SOCKET_OPEN, socket);
22
+ socket.once('close', () => {
23
+ this.emit(HTTP1_SOCKET_CLOSED, socket);
24
+ });
25
+ });
26
+ this.server.listen();
27
+ }
28
+
29
+ stop() {
30
+ this.server.close();
31
+ this.server.removeAllListeners();
32
+ this.server = null;
33
+ }
34
+
35
+ handleSshTunnel(stream, info, ip) {
36
+ logger.debug(LOG_HTTP1_CONNECTION(ip));
37
+ stream.remoteAddress = ip;
38
+ this.server.emit('connection', stream);
39
+ }
40
+
41
+ retryRequest(logRequest) {
42
+ const address = this.server.address();
43
+ if (!address || !address.port) return;
44
+ let req = http.request({
45
+ host: 'localhost',
46
+ port: address.port,
47
+ method: logRequest.method,
48
+ setHost: false,
49
+ path: logRequest.url,
50
+ headers: logRequest.headers
51
+ });
52
+ if (logRequest.requestBody.data.length > 0) req.write(logRequest.requestBody.data);
53
+ req.on('response', (res) => {
54
+ res.resume();
55
+ });
56
+ req.on('close', () => {
57
+ req.removeAllListeners();
58
+ req = null;
59
+ });
60
+ req.end();
61
+ }
62
+
63
+ checkHostHeader(req, res, host) {
64
+ if (req.headers.host === host) return true;
65
+ else {
66
+ res.statusCode = 421;
67
+ res.end('Misdirected Request');
68
+ return false;
69
+ }
70
+ }
71
+
72
+ async processRequest(req, res, host) {
73
+ if (!this.checkHostHeader(req, res, host)) return;
74
+ logger.debug(LOG_HTTP1_REQUEST(req.method, req.url));
75
+ this.emit(HTTP1_REQUEST, req, res);
76
+ }
77
+ }
78
+
79
+ module.exports = ServerHttp1;
@@ -0,0 +1,79 @@
1
+ const EventEmitter = require('events');
2
+ const http2 = require('http2');
3
+ const logger = require('../logger.js');
4
+ const { v4 } = require('uuid');
5
+ const {
6
+ LOG_ERROR,
7
+ LOG_HTTP2_CONNECTION,
8
+ LOG_HTTP2_REQUEST
9
+ } = require('../texts.js');
10
+ const { HTTP2_SESSION_OPEN,
11
+ HTTP2_SESSION_CLOSED,
12
+ HTTP2_REQUEST
13
+ } = require('../utils');
14
+
15
+ class ServerHttp2 extends EventEmitter {
16
+ constructor(host) {
17
+ super();
18
+ this.server = http2.createServer((req, res) => this.processRequest(req, res, host));
19
+ this.server.on('session', (session) => {
20
+ session.id = v4();
21
+ this.emit(HTTP2_SESSION_OPEN, session);
22
+ session.once('close', () => {
23
+ this.emit(HTTP2_SESSION_CLOSED, session);
24
+ });
25
+ });
26
+ this.server.listen();
27
+ }
28
+
29
+ stop() {
30
+ this.server.close();
31
+ this.server.removeAllListeners();
32
+ this.server = null;
33
+ }
34
+
35
+ handleSshTunnel(stream, info, ip) {
36
+ logger.debug(LOG_HTTP2_CONNECTION(ip));
37
+ stream.remoteAddress = ip;
38
+ this.server.emit('connection', stream);
39
+ }
40
+
41
+ retryRequest(logRequest) {
42
+ const address = this.server.address();
43
+ if (!address || !address.port) return;
44
+ let client = http2.connect(`http://localhost:${address.port}`);
45
+ let req = client.request(logRequest.headers);
46
+ if (logRequest.requestBody.data.length > 0) req.write(logRequest.requestBody.data);
47
+ req.on('response', () => {
48
+ req.resume();
49
+ });
50
+ req.on('error', (err) => {
51
+ logger.debug(LOG_ERROR);
52
+ logger.debug(err);
53
+ });
54
+ req.on('close', () => {
55
+ req.removeAllListeners();
56
+ client.close();
57
+ req = null;
58
+ client = null;
59
+ });
60
+ req.end();
61
+ }
62
+
63
+ checkHostHeader(req, res, host) {
64
+ if (req.headers[':authority'] === host) return true;
65
+ else {
66
+ res.statusCode = 421;
67
+ res.end('Misdirected Request');
68
+ return false;
69
+ }
70
+ }
71
+
72
+ async processRequest(req, res, host) {
73
+ if (!this.checkHostHeader(req, res, host)) return;
74
+ logger.debug(LOG_HTTP2_REQUEST(req.method, req.url));
75
+ this.emit(HTTP2_REQUEST, req, res);
76
+ }
77
+ }
78
+
79
+ module.exports = ServerHttp2;