querysub 0.85.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "querysub",
3
- "version": "0.85.0",
3
+ "version": "0.87.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
@@ -2,6 +2,8 @@ import debugbreak from "debugbreak";
2
2
  import * as net from "net";
3
3
  import ws from "ws";
4
4
  import child_process from "child_process";
5
+ import fs from "fs";
6
+ import path from "path";
5
7
 
6
8
  // Expose the internal port, via a tcp connection that we forward to internal port, for the first time
7
9
  // externalIP connects to us.
@@ -18,20 +20,35 @@ export async function hackDevtoolsWebsocketForward(config: {
18
20
  cancel: () => void;
19
21
  }> {
20
22
  const forwardCode = ((configInner: typeof config) => {
21
- const net = require("net");
23
+ const net = require("net") as typeof import("net");
24
+ const fs = require("fs") as typeof import("fs");
25
+ const path = require("path") as typeof import("path");
22
26
  const server = net.createServer();
23
27
 
28
+ const debugFile = path.join(process.env.USERPROFILE || process.env.HOME || "", "debug.temp");
29
+ //fs.writeFileSync(debugFile, "");
30
+ const logPacket = (message: string, data?: Buffer) => {
31
+ // const timestamp = new Date().toISOString();
32
+ // fs.appendFileSync(
33
+ // debugFile,
34
+ // `${timestamp} ${message} ${data?.length}\n`
35
+ // );
36
+ };
37
+
24
38
  // Start listening on a random available port, binding to all interfaces (0.0.0.0)
25
39
  server.listen(0, "0.0.0.0");
26
40
 
27
- server.on("connection", (socket: net.Socket) => {
41
+ server.on("connection", (socket) => {
28
42
  const clientIP = socket.remoteAddress;
29
43
 
44
+
30
45
  if (clientIP !== configInner.externalIP) {
46
+ logPacket(`Rejected connection attempt from unauthorized IP: ${clientIP}`);
31
47
  console.error(`Rejected connection attempt from unauthorized IP: ${clientIP}`);
32
48
  socket.destroy();
33
49
  return;
34
50
  }
51
+ logPacket(`Accepted connection from ${clientIP}`);
35
52
 
36
53
  const address = server.address();
37
54
  if (!address || typeof address === "string") {
@@ -46,6 +63,7 @@ export async function hackDevtoolsWebsocketForward(config: {
46
63
  port: configInner.internalPort,
47
64
  });
48
65
  internalConnection.on("data", (data: Buffer) => {
66
+ logPacket("SENT", data);
49
67
  socket.write(data);
50
68
  });
51
69
  let first = true;
@@ -57,12 +75,14 @@ export async function hackDevtoolsWebsocketForward(config: {
57
75
  lines[1] = `Host: 127.0.0.1:${configInner.internalPort}`;
58
76
  data = Buffer.from(lines.join("\r\n"));
59
77
  }
78
+ logPacket("RECEIVED", data);
60
79
  internalConnection.write(data);
61
80
  });
62
81
 
63
82
  // Handle socket closure
64
83
  socket.on("close", () => {
65
84
  internalConnection.destroy();
85
+ logPacket("SENT");
66
86
  // IMPORTANT! We terminate when the connection is closed, which is what makes this safe.
67
87
  process.exit();
68
88
  });
@@ -37,6 +37,7 @@ import { SocketRegistered } from "socket-function/SocketFunctionTypes";
37
37
  import { ATag } from "../library-components/ATag";
38
38
  import { filterURL, selectedNodeId } from "./logs/DiskLoggerPage";
39
39
  import { getSyncedController } from "../library-components/SyncedController";
40
+ import child_process from "child_process";
40
41
 
41
42
 
42
43
  type NodeData = {
@@ -348,60 +349,117 @@ class NodeViewerControllerBase {
348
349
  let ourIP = await getExternalIP();
349
350
  let { externalPort, internalPort, internalInspectURL } = await NodeCapabilitiesController.nodes[nodeId].exposeExternalDebugPortOnce(ourIP);
350
351
 
351
- let baseNodeIP = getNodeIdIP(nodeId);
352
- let baseNodeIPResolved = (await dns.promises.lookup(baseNodeIP)).address;
352
+ const forwardCode = ((config: {
353
+ callerIP: string;
354
+ ourIP: string;
355
+ externalPort: number;
356
+ internalPort: number;
357
+ baseNodeIP: string;
358
+ cert: { key: string; cert: string; };
359
+ }) => {
360
+ const tls = require("tls") as typeof import("tls");
361
+ const net = require("net") as typeof import("net");
362
+ const dns = require("dns") as typeof import("dns");
363
+
364
+ (async () => {
365
+ let baseNodeIPResolved = (await dns.promises.lookup(config.baseNodeIP)).address;
366
+
367
+ let tlsServer = new tls.Server({
368
+ key: config.cert.key,
369
+ cert: config.cert.cert,
370
+ });
371
+ tlsServer.listen(0, "0.0.0.0");
372
+ await new Promise((resolve, reject) => {
373
+ tlsServer.once("listening", resolve);
374
+ tlsServer.once("error", reject);
375
+ });
376
+
377
+ let finalPort = (tlsServer.address() as any).port;
378
+ console.log(`EXTERNAL_PORT:${finalPort}`);
379
+
380
+ tlsServer.on("secureConnection", (socket) => {
381
+ let matchedIP = (
382
+ socket.remoteAddress === config.callerIP ||
383
+ config.callerIP === "127.0.0.1" && socket.remoteAddress === config.ourIP
384
+ );
385
+ if (!matchedIP) {
386
+ console.error(`Rejecting connection from ${socket.remoteAddress}, expected ${config.callerIP} ${config.callerIP === "127.0.0.1" && `or ${config.ourIP}` || ""}`);
387
+ socket.end();
388
+ return;
389
+ }
353
390
 
354
- // Listen on a websocket, and forward to externalPort:baseNodeIP
355
- let cert = await debugGetRawEdgeCert();
391
+ let internalConnection = net.createConnection({
392
+ host: baseNodeIPResolved,
393
+ port: config.externalPort,
394
+ });
395
+ socket.pipe(internalConnection);
396
+ internalConnection.pipe(socket);
356
397
 
357
- let tlsServer = new tls.Server({
358
- key: cert.key,
359
- cert: cert.cert,
360
- });
361
- tlsServer.listen(0, "0.0.0.0");
362
- await new Promise((resolve, reject) => {
363
- tlsServer.once("listening", resolve);
364
- tlsServer.once("error", reject);
398
+ socket.on("close", () => {
399
+ console.log("Inspect closing forward (socket closed)");
400
+ tlsServer.close();
401
+ process.exit();
402
+ });
403
+ internalConnection.on("close", () => {
404
+ console.log("Inspect closing forward (internal connection closed)");
405
+ tlsServer.close();
406
+ process.exit();
407
+ });
408
+ });
409
+ })().catch(e => {
410
+ console.error(e);
411
+ process.exit(1);
412
+ });
365
413
  });
366
414
 
367
- let finalPort = (tlsServer.address() as any).port;
415
+ let baseNodeIP = getNodeIdIP(nodeId);
416
+ let cert = await debugGetRawEdgeCert();
368
417
 
369
- await forwardPort({ internalPort: finalPort, externalPort: finalPort, });
370
- await forwardPort({ internalPort: externalPort, externalPort: externalPort, });
418
+ const child = child_process.spawn("node", [
419
+ "-e",
420
+ `(${forwardCode.toString()})(${JSON.stringify({
421
+ callerIP,
422
+ ourIP,
423
+ externalPort,
424
+ internalPort,
425
+ baseNodeIP,
426
+ cert,
427
+ })})`,
428
+ ]);
429
+
430
+ let portPromiseResolve: ((port: number) => void) | undefined;
431
+ const portPromise = new Promise<number>((resolve) => {
432
+ portPromiseResolve = resolve;
433
+ });
371
434
 
372
- tlsServer.on("secureConnection", (socket) => {
373
- let matchedIP = (
374
- socket.remoteAddress === callerIP ||
375
- callerIP === "127.0.0.1" && socket.remoteAddress === ourIP
376
- );
377
- if (!matchedIP) {
378
- console.error(`Rejecting connection from ${socket.remoteAddress}, expected ${callerIP} ${callerIP === "127.0.0.1" && `or ${ourIP}` || ""}`);
379
- socket.end();
380
- return;
435
+ let curData = "";
436
+ child.stdout.on("data", (data) => {
437
+ console.log(data.toString());
438
+ curData += data.toString();
439
+ const match = curData.match(/EXTERNAL_PORT:(\d+)/);
440
+ if (match && portPromiseResolve) {
441
+ portPromiseResolve(parseInt(match[1], 10));
381
442
  }
443
+ });
382
444
 
383
- let internalConnection = net.createConnection({
384
- host: baseNodeIPResolved,
385
- port: externalPort,
386
- });
387
- socket.pipe(internalConnection);
388
- internalConnection.pipe(socket);
445
+ child.stderr.on("data", (data) => {
446
+ console.error(data.toString());
447
+ });
389
448
 
390
- socket.on("close", () => {
391
- console.log(`Inspect closing forward (socket closed) ${ourDomain}:${finalPort} => ${baseNodeIPResolved}:${externalPort} => 127.0.0.1:${internalPort}, for ${callerIP}`);
392
- tlsServer.close();
393
- });
394
- internalConnection.on("close", () => {
395
- console.log(`Inspect closing forward (internal connection closed) ${ourDomain}:${finalPort} => ${baseNodeIPResolved}:${externalPort} => 127.0.0.1:${internalPort}, for ${callerIP}`);
396
- tlsServer.close();
397
- });
449
+ child.on("error", (err) => {
450
+ console.error("Failed to start child process:", err);
451
+ throw err;
398
452
  });
399
453
 
454
+ let finalPort = await portPromise;
455
+ await forwardPort({ internalPort: finalPort, externalPort: finalPort });
456
+ await forwardPort({ internalPort: externalPort, externalPort: externalPort });
457
+
400
458
  // Ugh... what a nightmare...
401
459
  let ourDomain = ourIP.replaceAll(".", "-") + "." + getDomain();
402
460
  await setRecord("A", ourDomain, ourIP);
403
461
 
404
- console.log(`Inspect forward ${ourDomain}:${finalPort} => ${baseNodeIPResolved}:${externalPort} => 127.0.0.1:${internalPort}, for ${callerIP}`);
462
+ console.log(`Inspect forward ${ourDomain}:${finalPort} => ${baseNodeIP}:${externalPort} => 127.0.0.1:${internalPort}, for ${callerIP}`);
405
463
 
406
464
  return internalInspectURL.replace(`ws=127.0.0.1:${internalPort}`, `wss=${ourDomain}:${finalPort}`);
407
465
  }