socket-function 0.8.34 → 0.8.35
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/SocketFunction.ts +3 -3
- package/SocketFunctionTypes.ts +2 -17
- package/package.json +2 -2
- package/src/CallFactory.ts +5 -13
- package/src/callHTTPHandler.ts +3 -3
- package/src/callManager.ts +4 -4
- package/src/certStore.ts +7 -33
- package/src/nodeAuthentication.ts +4 -82
- package/src/webSocketServer.ts +11 -28
package/SocketFunction.ts
CHANGED
|
@@ -28,7 +28,6 @@ export class SocketFunction {
|
|
|
28
28
|
type: "gzip";
|
|
29
29
|
};
|
|
30
30
|
public static httpETagCache = false;
|
|
31
|
-
public static rejectUnauthorized = true;
|
|
32
31
|
|
|
33
32
|
public static register<
|
|
34
33
|
ClassInstance extends object,
|
|
@@ -129,11 +128,12 @@ export class SocketFunction {
|
|
|
129
128
|
}
|
|
130
129
|
|
|
131
130
|
public static mountedNodeId: string = "NOTMOUNTED";
|
|
132
|
-
public static async mount(config: SocketServerConfig) {
|
|
131
|
+
public static async mount(config: SocketServerConfig & { nodeId: string }) {
|
|
133
132
|
if (this.mountedNodeId !== "NOTMOUNTED") {
|
|
134
133
|
throw new Error("SocketFunction already mounted, mounting twice in one thread is not allowed.");
|
|
135
134
|
}
|
|
136
|
-
this.mountedNodeId =
|
|
135
|
+
this.mountedNodeId = config.nodeId;
|
|
136
|
+
await startSocketServer(config);
|
|
137
137
|
return this.mountedNodeId;
|
|
138
138
|
}
|
|
139
139
|
|
package/SocketFunctionTypes.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
module.allowclient = true;
|
|
2
2
|
|
|
3
|
-
import debugbreak from "debugbreak";
|
|
4
|
-
import * as tls from "tls";
|
|
5
|
-
import { SenderInterface } from "./src/CallFactory";
|
|
6
|
-
import { isNode } from "./src/misc";
|
|
7
|
-
import { CertInfo, getNodeIdFromCert } from "./src/nodeAuthentication";
|
|
8
|
-
import { getClientNodeId } from "./src/nodeCache";
|
|
9
3
|
import { getCallObj } from "./src/nodeProxy";
|
|
10
4
|
import { Args, MaybePromise } from "./src/types";
|
|
11
5
|
|
|
@@ -52,14 +46,14 @@ export interface SocketFunctionHook<ExposedType extends SocketExposedInterface =
|
|
|
52
46
|
(config: HookContext<ExposedType, CallContext>): MaybePromise<void>;
|
|
53
47
|
}
|
|
54
48
|
export type HookContext<ExposedType extends SocketExposedInterface = SocketExposedInterface, CallContext extends CallContextType = CallContextType> = {
|
|
55
|
-
call:
|
|
49
|
+
call: FullCallType;
|
|
56
50
|
context: SocketRegistered<ExposedType, CallContext>["context"];
|
|
57
51
|
// If the result is overriden, we continue evaluating hooks BUT DO NOT perform the final call
|
|
58
52
|
overrideResult?: unknown;
|
|
59
53
|
};
|
|
60
54
|
|
|
61
55
|
export type ClientHookContext<ExposedType extends SocketExposedInterface = SocketExposedInterface, CallContext extends CallContextType = CallContextType> = {
|
|
62
|
-
call:
|
|
56
|
+
call: FullCallType;
|
|
63
57
|
/** If the calls takes longer than this (for ANY reason), we return with an error.
|
|
64
58
|
* - Different from reconnectTimeout, which only errors if we lose the connection.
|
|
65
59
|
*/
|
|
@@ -101,15 +95,6 @@ export type CallerContextBase = {
|
|
|
101
95
|
// a more permanent identity, you must derive it from certInfo yourself.
|
|
102
96
|
nodeId: string;
|
|
103
97
|
|
|
104
|
-
/** Gives further info on the node. When we set this, we always make sure it has a verified
|
|
105
|
-
* issuer. It may be set by app code, which should make sure the issuer is verified (not
|
|
106
|
-
* necessarily by the machine, but just in some sense, 'verified', to secure the common name
|
|
107
|
-
* of the cert and prevent anyone from using the same common name as someone else).
|
|
108
|
-
* IF set, is directly used to derive nodeId (by nodeAuthentication.ts)
|
|
109
|
-
*/
|
|
110
|
-
certInfo: CertInfo | undefined;
|
|
111
|
-
updateCertInfo?: (certInfo: CertInfo, callbackPort: number | undefined) => void;
|
|
112
|
-
|
|
113
98
|
// The nodeId they contacted. This is useful to determine their intention (otherwise
|
|
114
99
|
// requests can be redirected to us and would accept them, even though they are being
|
|
115
100
|
// blatantly MITMed).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "socket-function",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.35",
|
|
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",
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"@types/node-forge": "^1.3.1",
|
|
11
11
|
"@types/ws": "^8.5.3",
|
|
12
12
|
"cookie": "^0.5.0",
|
|
13
|
-
"debugbreak": "^0.6.5",
|
|
14
13
|
"mobx": "^6.6.2",
|
|
15
14
|
"node-forge": "https://github.com/sliftist/forge#name",
|
|
16
15
|
"preact": "^10.10.6",
|
|
@@ -22,6 +21,7 @@
|
|
|
22
21
|
"type": "yarn tsc --noEmit"
|
|
23
22
|
},
|
|
24
23
|
"devDependencies": {
|
|
24
|
+
"debugbreak": "^0.6.5",
|
|
25
25
|
"typedev": "^0.1.0"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/CallFactory.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { CallerContext, CallerContextBase, CallType } from "../SocketFunctionTypes";
|
|
1
|
+
import { CallerContext, CallerContextBase, CallType, FullCallType } from "../SocketFunctionTypes";
|
|
2
2
|
import * as ws from "ws";
|
|
3
3
|
import { performLocalCall } from "./callManager";
|
|
4
4
|
import { convertErrorStackToError, formatNumberSuffixed, isNode } from "./misc";
|
|
5
|
-
import { createWebsocketFactory,
|
|
5
|
+
import { createWebsocketFactory, getTLSSocket } from "./nodeAuthentication";
|
|
6
6
|
import { SocketFunction } from "../SocketFunction";
|
|
7
7
|
import { gzip } from "zlib";
|
|
8
8
|
import * as tls from "tls";
|
|
@@ -10,7 +10,7 @@ import { getClientNodeId, getNodeIdLocation, registerNodeClient } from "./nodeCa
|
|
|
10
10
|
|
|
11
11
|
const retryInterval = 2000;
|
|
12
12
|
|
|
13
|
-
type InternalCallType =
|
|
13
|
+
type InternalCallType = FullCallType & {
|
|
14
14
|
seqNum: number;
|
|
15
15
|
isReturn: false;
|
|
16
16
|
compress: boolean;
|
|
@@ -77,16 +77,7 @@ export async function createCallFactory(
|
|
|
77
77
|
|
|
78
78
|
let callerContext: CallerContextBase = {
|
|
79
79
|
nodeId,
|
|
80
|
-
localNodeId
|
|
81
|
-
certInfo: webSocketBase?.socket?.getPeerCertificate(true),
|
|
82
|
-
updateCertInfo: (certRaw, port) => {
|
|
83
|
-
let nodeId = getNodeIdFromCert(certRaw, port);
|
|
84
|
-
if (!nodeId) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
callerContext.nodeId = nodeId;
|
|
88
|
-
callerContext.certInfo = certRaw;
|
|
89
|
-
}
|
|
80
|
+
localNodeId
|
|
90
81
|
};
|
|
91
82
|
|
|
92
83
|
let callFactory: CallFactory = {
|
|
@@ -99,6 +90,7 @@ export async function createCallFactory(
|
|
|
99
90
|
|
|
100
91
|
let seqNum = nextSeqNum++;
|
|
101
92
|
let fullCall: InternalCallType = {
|
|
93
|
+
nodeId,
|
|
102
94
|
isReturn: false,
|
|
103
95
|
args: call.args,
|
|
104
96
|
classGuid: call.classGuid,
|
package/src/callHTTPHandler.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import http from "http";
|
|
2
2
|
import tls from "tls";
|
|
3
|
-
import { CallerContext, CallType } from "../SocketFunctionTypes";
|
|
3
|
+
import { CallerContext, CallType, FullCallType } from "../SocketFunctionTypes";
|
|
4
4
|
import { isDataImmutable, performLocalCall } from "./callManager";
|
|
5
5
|
import { SocketFunction } from "../SocketFunction";
|
|
6
6
|
import { gzip } from "zlib";
|
|
@@ -79,7 +79,6 @@ export async function httpCallHandler(request: http.IncomingMessage, response: h
|
|
|
79
79
|
|
|
80
80
|
let caller: CallerContext = {
|
|
81
81
|
nodeId,
|
|
82
|
-
certInfo: undefined,
|
|
83
82
|
localNodeId,
|
|
84
83
|
};
|
|
85
84
|
|
|
@@ -112,7 +111,8 @@ export async function httpCallHandler(request: http.IncomingMessage, response: h
|
|
|
112
111
|
args = JSON.parse(payload.toString())["args"] as unknown[];
|
|
113
112
|
}
|
|
114
113
|
|
|
115
|
-
let call:
|
|
114
|
+
let call: FullCallType = {
|
|
115
|
+
nodeId,
|
|
116
116
|
classGuid,
|
|
117
117
|
functionName,
|
|
118
118
|
args,
|
package/src/callManager.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CallContextType, CallerContext, CallType, ClientHookContext, HookContext, SocketExposedInterface, SocketExposedInterfaceClass, SocketExposedShape, SocketFunctionClientHook, SocketFunctionHook, SocketRegistered } from "../SocketFunctionTypes";
|
|
1
|
+
import { CallContextType, CallerContext, CallType, ClientHookContext, FullCallType, HookContext, SocketExposedInterface, SocketExposedInterfaceClass, SocketExposedShape, SocketFunctionClientHook, SocketFunctionHook, SocketRegistered } from "../SocketFunctionTypes";
|
|
2
2
|
import { _setSocketContext } from "../SocketFunction";
|
|
3
3
|
|
|
4
4
|
let classes: {
|
|
@@ -14,7 +14,7 @@ let globalClientHooks: SocketFunctionClientHook[] = [];
|
|
|
14
14
|
|
|
15
15
|
export async function performLocalCall(
|
|
16
16
|
config: {
|
|
17
|
-
call:
|
|
17
|
+
call: FullCallType;
|
|
18
18
|
caller: CallerContext;
|
|
19
19
|
}
|
|
20
20
|
): Promise<unknown> {
|
|
@@ -92,7 +92,7 @@ export function unregisterGlobalClientHook(hook: SocketFunctionClientHook) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
export async function runClientHooks(
|
|
95
|
-
callType:
|
|
95
|
+
callType: FullCallType,
|
|
96
96
|
hooks: SocketExposedShape[""],
|
|
97
97
|
): Promise<ClientHookContext> {
|
|
98
98
|
let context: ClientHookContext = { call: callType };
|
|
@@ -106,7 +106,7 @@ export async function runClientHooks(
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
async function runServerHooks(
|
|
109
|
-
callType:
|
|
109
|
+
callType: FullCallType,
|
|
110
110
|
context: SocketRegistered["context"],
|
|
111
111
|
hooks: SocketExposedShape[""],
|
|
112
112
|
): Promise<HookContext> {
|
package/src/certStore.ts
CHANGED
|
@@ -1,50 +1,24 @@
|
|
|
1
|
-
import * as os from "os";
|
|
2
|
-
import * as fs from "fs/promises";
|
|
3
|
-
import * as fsSync from "fs";
|
|
4
|
-
import * as child_process from "child_process";
|
|
5
1
|
import * as tls from "tls";
|
|
6
|
-
import { SocketFunction } from "../SocketFunction";
|
|
7
|
-
import { isNode, isNodeTrue, sha256Hash } from "./misc";
|
|
8
|
-
import { lazy } from "./caching";
|
|
9
2
|
|
|
10
3
|
let trustedCerts = new Set<string>();
|
|
11
|
-
let loadedTrustedCerts = false;
|
|
12
4
|
let watchCallbacks = new Set<(certs: string[]) => void>();
|
|
13
5
|
|
|
14
|
-
let storePath = isNodeTrue() && process.argv[1].replaceAll("\\", "/").split("/").slice(0, -1).join("/") + "/certstore/";
|
|
15
|
-
if (isNode()) {
|
|
16
|
-
if (!fsSync.existsSync(storePath)) {
|
|
17
|
-
fsSync.mkdirSync(storePath);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
6
|
/** Must be populated before the server starts */
|
|
22
|
-
export
|
|
7
|
+
export function trustCertificate(cert: string | Buffer) {
|
|
8
|
+
cert = cert.toString();
|
|
23
9
|
if (trustedCerts.has(cert)) return;
|
|
24
10
|
trustedCerts.add(cert);
|
|
25
|
-
|
|
26
|
-
let certs = getTrustedUserCertificates();
|
|
11
|
+
let certs = getTrustedCertificates();
|
|
27
12
|
for (let callback of watchCallbacks) {
|
|
28
13
|
callback(certs);
|
|
29
14
|
}
|
|
30
15
|
}
|
|
31
|
-
export
|
|
32
|
-
|
|
33
|
-
for (let file of files) {
|
|
34
|
-
let cert = await fs.readFile(storePath + file, "utf8");
|
|
35
|
-
trustedCerts.add(cert);
|
|
36
|
-
}
|
|
37
|
-
loadedTrustedCerts = true;
|
|
38
|
-
});
|
|
39
|
-
export function getTrustedUserCertificates(): string[] {
|
|
40
|
-
if (!loadedTrustedCerts) {
|
|
41
|
-
throw new Error("Must call loadTrustedUserCertificates (and await it) before calling getTrustedUserCertificates");
|
|
42
|
-
}
|
|
43
|
-
return Array.from(trustedCerts);
|
|
16
|
+
export function getTrustedCertificates(): string[] {
|
|
17
|
+
return tls.rootCertificates.concat(Array.from(trustedCerts));
|
|
44
18
|
}
|
|
45
19
|
|
|
46
|
-
export function
|
|
20
|
+
export function watchTrustedCertificates(callback: (certs: string[]) => void) {
|
|
47
21
|
watchCallbacks.add(callback);
|
|
48
|
-
callback(
|
|
22
|
+
callback(getTrustedCertificates());
|
|
49
23
|
return () => watchCallbacks.delete(callback);
|
|
50
24
|
}
|
|
@@ -1,88 +1,15 @@
|
|
|
1
1
|
import ws from "ws";
|
|
2
2
|
import tls from "tls";
|
|
3
|
-
import
|
|
4
|
-
import { getAppFolder } from "./storagePath";
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import child_process from "child_process";
|
|
7
|
-
import { cacheWeak, lazy } from "./caching";
|
|
8
|
-
import https from "https";
|
|
9
|
-
import debugbreak from "debugbreak";
|
|
10
|
-
import crypto from "crypto";
|
|
11
|
-
import { isNode, sha256Hash } from "./misc";
|
|
12
|
-
import { getArgs } from "./args";
|
|
3
|
+
import { isNode } from "./misc";
|
|
13
4
|
import { SenderInterface } from "./CallFactory";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { getClientNodeId, getNodeId, getNodeIdLocation } from "./nodeCache";
|
|
5
|
+
import { getTrustedCertificates } from "./certStore";
|
|
6
|
+
import { getNodeIdLocation } from "./nodeCache";
|
|
17
7
|
|
|
18
|
-
export type CertInfo = { raw: Buffer | string; issuerCertificate: { raw: Buffer | string } };
|
|
19
|
-
|
|
20
|
-
let certKeyPairOverride: { key: Buffer; cert: Buffer } | undefined;
|
|
21
|
-
export function getCertKeyPair(): { key: Buffer; cert: Buffer } {
|
|
22
|
-
if (certKeyPairOverride) return certKeyPairOverride;
|
|
23
|
-
return getCertKeyPairBase();
|
|
24
|
-
}
|
|
25
|
-
const getCertKeyPairBase = lazy((): { key: Buffer; cert: Buffer } => {
|
|
26
|
-
// https://nodejs.org/en/knowledge/HTTP/servers/how-to-create-a-HTTPS-server/
|
|
27
|
-
|
|
28
|
-
let folder = getAppFolder();
|
|
29
|
-
let identityPrefix = getArgs().identity || "";
|
|
30
|
-
let keyPath = folder + identityPrefix + "key.pem";
|
|
31
|
-
let certPath = folder + identityPrefix + "cert.pem";
|
|
32
|
-
if (!fs.existsSync(keyPath) || !fs.existsSync(certPath)) {
|
|
33
|
-
child_process.execSync(`openssl genrsa -out "${keyPath}"`);
|
|
34
|
-
child_process.execSync(`openssl req -new -key "${keyPath}" -out csr.pem -subj "/CN=notused"`);
|
|
35
|
-
child_process.execSync(`openssl x509 -req -days 9999 -in csr.pem -signkey "${keyPath}" -out "${certPath}"`);
|
|
36
|
-
fs.rmSync("csr.pem");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
let key = fs.readFileSync(keyPath);
|
|
40
|
-
let cert = fs.readFileSync(certPath);
|
|
41
|
-
return { key, cert };
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
export function overrideCertKeyPair<T>(certKey: { key: Buffer; cert: Buffer; }, code: () => T): T {
|
|
45
|
-
if (!isNode()) {
|
|
46
|
-
throw new Error(`Cannot override cert/key pair in browser`);
|
|
47
|
-
}
|
|
48
|
-
let prevOverride = certKeyPairOverride;
|
|
49
|
-
certKeyPairOverride = certKey;
|
|
50
|
-
try {
|
|
51
|
-
return code();
|
|
52
|
-
} finally {
|
|
53
|
-
certKeyPairOverride = prevOverride;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
8
|
|
|
57
9
|
export function getTLSSocket(webSocket: ws.WebSocket) {
|
|
58
10
|
return (webSocket as any)._socket as tls.TLSSocket;
|
|
59
11
|
}
|
|
60
12
|
|
|
61
|
-
export async function getOwnNodeId() {
|
|
62
|
-
if (!isNode()) {
|
|
63
|
-
throw new Error(`Clientside nodeIds are not exposed to the client`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// This is BASICALLY just sha256Hash(getCertKeyPari().cert), however... I'm not 100% the format
|
|
67
|
-
// is the same, we would have to verify it. It isn't that important, other nodes know our nodeId,
|
|
68
|
-
// and clients don't really have a reason to use this anyway (they can't verify it, they can only
|
|
69
|
-
// really verify with a location).
|
|
70
|
-
throw new Error(`TODO: Implement getOwnNodeId`);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function getNodeIdFromCert(certRaw: { raw: Buffer | string } | undefined, callbackPort: number | undefined) {
|
|
74
|
-
if (!certRaw?.raw) return undefined;
|
|
75
|
-
let cert = new crypto.X509Certificate(certRaw.raw);
|
|
76
|
-
if (!callbackPort) {
|
|
77
|
-
return getClientNodeId(cert.subject);
|
|
78
|
-
}
|
|
79
|
-
let subject = cert.subject;
|
|
80
|
-
if (subject.startsWith("CN=")) {
|
|
81
|
-
subject = subject.slice("CN=".length);
|
|
82
|
-
}
|
|
83
|
-
return getNodeId(subject, callbackPort);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
13
|
/** NOTE: We create a factory, which embeds the key/cert information. Otherwise retries might use
|
|
87
14
|
* a different key/cert context.
|
|
88
15
|
*/
|
|
@@ -98,8 +25,6 @@ export function createWebsocketFactory(): (nodeId: string) => SenderInterface {
|
|
|
98
25
|
return new WebSocket(`wss://${address}:${port}`);
|
|
99
26
|
};
|
|
100
27
|
} else {
|
|
101
|
-
let { key, cert } = getCertKeyPair();
|
|
102
|
-
let rejectUnauthorized = SocketFunction.rejectUnauthorized;
|
|
103
28
|
return (nodeId: string) => {
|
|
104
29
|
let location = getNodeIdLocation(nodeId);
|
|
105
30
|
if (!location) throw new Error(`Cannot connect to ${nodeId}, no address known`);
|
|
@@ -107,10 +32,7 @@ export function createWebsocketFactory(): (nodeId: string) => SenderInterface {
|
|
|
107
32
|
|
|
108
33
|
console.log(`Connecting to ${address}:${port}`);
|
|
109
34
|
let webSocket = new ws.WebSocket(`wss://${address}:${port}`, {
|
|
110
|
-
|
|
111
|
-
key,
|
|
112
|
-
rejectUnauthorized,
|
|
113
|
-
ca: tls.rootCertificates.concat(getTrustedUserCertificates()),
|
|
35
|
+
ca: tls.rootCertificates.concat(getTrustedCertificates()),
|
|
114
36
|
});
|
|
115
37
|
let result = Object.assign(webSocket, { socket: undefined as tls.TLSSocket | undefined });
|
|
116
38
|
webSocket.once("upgrade", e => {
|
package/src/webSocketServer.ts
CHANGED
|
@@ -3,16 +3,20 @@ import http from "http";
|
|
|
3
3
|
import net from "net";
|
|
4
4
|
import tls from "tls";
|
|
5
5
|
import * as ws from "ws";
|
|
6
|
-
import { getCertKeyPair, getNodeIdFromCert } from "./nodeAuthentication";
|
|
7
6
|
import { getNodeIdsFromRequest, httpCallHandler } from "./callHTTPHandler";
|
|
8
7
|
import { SocketFunction } from "../SocketFunction";
|
|
9
|
-
import {
|
|
8
|
+
import { getTrustedCertificates, watchTrustedCertificates } from "./certStore";
|
|
10
9
|
import { createCallFactory } from "./CallFactory";
|
|
11
10
|
import { parseSNIExtension, parseTLSHello, SNIType } from "./tlsParsing";
|
|
12
11
|
import debugbreak from "debugbreak";
|
|
13
12
|
|
|
14
13
|
export type SocketServerConfig = (
|
|
15
14
|
https.ServerOptions & {
|
|
15
|
+
nodeId?: string;
|
|
16
|
+
|
|
17
|
+
key: string | Buffer;
|
|
18
|
+
cert: string | Buffer;
|
|
19
|
+
|
|
16
20
|
port: number;
|
|
17
21
|
|
|
18
22
|
// public sets ip to "0.0.0.0", otherwise it defaults to "127.0.0.1", which
|
|
@@ -20,9 +24,7 @@ export type SocketServerConfig = (
|
|
|
20
24
|
public?: boolean;
|
|
21
25
|
ip?: string;
|
|
22
26
|
|
|
23
|
-
/** If the SNI matches this domain, we use a different key/cert.
|
|
24
|
-
* - Also requestCert may be specified (otherwise it defaults to true)
|
|
25
|
-
*/
|
|
27
|
+
/** If the SNI matches this domain, we use a different key/cert. */
|
|
26
28
|
SNICerts?: {
|
|
27
29
|
[domain: string]: https.ServerOptions;
|
|
28
30
|
};
|
|
@@ -31,25 +33,16 @@ export type SocketServerConfig = (
|
|
|
31
33
|
|
|
32
34
|
export async function startSocketServer(
|
|
33
35
|
config: SocketServerConfig
|
|
34
|
-
): Promise<
|
|
35
|
-
let isSecure = "cert" in config || "key" in config || "pfx" in config;
|
|
36
|
-
if (!isSecure) {
|
|
37
|
-
let { key, cert } = getCertKeyPair();
|
|
38
|
-
config.key = key;
|
|
39
|
-
config.cert = cert;
|
|
40
|
-
}
|
|
41
|
-
|
|
36
|
+
): Promise<void> {
|
|
42
37
|
|
|
43
38
|
const webSocketServer = new ws.Server({
|
|
44
39
|
noServer: true,
|
|
45
40
|
});
|
|
46
41
|
|
|
47
|
-
await loadTrustedUserCertificates();
|
|
48
|
-
|
|
49
42
|
function setupHTTPSServer(options: https.ServerOptions) {
|
|
50
43
|
let httpsServer = https.createServer(options);
|
|
51
|
-
|
|
52
|
-
options.ca =
|
|
44
|
+
watchTrustedCertificates(() => {
|
|
45
|
+
options.ca = getTrustedCertificates();
|
|
53
46
|
httpsServer.setSecureContext(options);
|
|
54
47
|
});
|
|
55
48
|
|
|
@@ -102,8 +95,6 @@ export async function startSocketServer(
|
|
|
102
95
|
// TODO: Only allow unauthorized for ip certificates, and then for domains use the domain as the nodeId,
|
|
103
96
|
// so it is easy to read, and consistent.
|
|
104
97
|
let options: https.ServerOptions = {
|
|
105
|
-
rejectUnauthorized: SocketFunction.rejectUnauthorized,
|
|
106
|
-
requestCert: true,
|
|
107
98
|
...config,
|
|
108
99
|
};
|
|
109
100
|
|
|
@@ -137,8 +128,6 @@ export async function startSocketServer(
|
|
|
137
128
|
if (buffer[0] !== 22) {
|
|
138
129
|
server = httpServer;
|
|
139
130
|
} else {
|
|
140
|
-
debugbreak(1);
|
|
141
|
-
debugger;
|
|
142
131
|
let data = parseTLSHello(buffer);
|
|
143
132
|
let sni = data.extensions.filter(x => x.type === SNIType).flatMap(x => parseSNIExtension(x.data))[0];
|
|
144
133
|
server = sniServers.get(sni) || mainHTTPSServer;
|
|
@@ -176,11 +165,5 @@ export async function startSocketServer(
|
|
|
176
165
|
|
|
177
166
|
let port = (realServer.address() as net.AddressInfo).port;
|
|
178
167
|
|
|
179
|
-
console.log(`Started Listening on ${host}:${port}`);
|
|
180
|
-
|
|
181
|
-
let serverNodeId = getNodeIdFromCert({ raw: config.cert as Buffer | string }, port);
|
|
182
|
-
if (!serverNodeId) {
|
|
183
|
-
throw new Error(`Something is wrong with our cert, we don't have a nodeId?`);
|
|
184
|
-
}
|
|
185
|
-
return serverNodeId;
|
|
168
|
+
console.log(`Started Listening on ${config.nodeId || host}:${port}`);
|
|
186
169
|
}
|