socket-function 0.75.0 → 0.77.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/SocketFunction.ts +5 -9
- package/package.json +1 -1
- package/src/callHTTPHandler.ts +3 -13
- package/src/misc.ts +11 -0
- package/src/webSocketServer.ts +18 -10
package/SocketFunction.ts
CHANGED
|
@@ -419,8 +419,9 @@ export class SocketFunction {
|
|
|
419
419
|
if (isNode()) {
|
|
420
420
|
throw new Error("Cannot get browser nodeId on server");
|
|
421
421
|
}
|
|
422
|
-
|
|
423
|
-
|
|
422
|
+
let edgeNode = getBootedEdgeNode();
|
|
423
|
+
if (edgeNode) {
|
|
424
|
+
return edgeNode.host;
|
|
424
425
|
}
|
|
425
426
|
return SocketFunction.connect({ address: location.hostname, port: +location.port || 443 });
|
|
426
427
|
}
|
|
@@ -433,14 +434,9 @@ export class SocketFunction {
|
|
|
433
434
|
}
|
|
434
435
|
}
|
|
435
436
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
var BOOTED_EDGE_NODE: EdgeNodeConfig | undefined;
|
|
437
|
+
function getBootedEdgeNode() {
|
|
438
|
+
return (globalThis as any).BOOTED_EDGE_NODE as { host: string } | undefined;
|
|
439
439
|
}
|
|
440
|
-
type EdgeNodeConfig = {
|
|
441
|
-
// EX: 127-0-0-1.example.com:3334
|
|
442
|
-
host: string;
|
|
443
|
-
};
|
|
444
440
|
|
|
445
441
|
|
|
446
442
|
let socketContextSeqNum = 1;
|
package/package.json
CHANGED
package/src/callHTTPHandler.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { isDataImmutable, performLocalCall } from "./callManager";
|
|
|
5
5
|
import { SocketFunction } from "../SocketFunction";
|
|
6
6
|
import { gzip } from "zlib";
|
|
7
7
|
import zlib from "zlib";
|
|
8
|
-
import { formatNumberSuffixed, sha256Hash } from "./misc";
|
|
8
|
+
import { formatNumberSuffixed, getRootDomain, sha256Hash } from "./misc";
|
|
9
9
|
import { getClientNodeId, getNodeId } from "./nodeCache";
|
|
10
10
|
|
|
11
11
|
let defaultHTTPCall: CallType | undefined;
|
|
@@ -79,18 +79,8 @@ export async function httpCallHandler(request: http.IncomingMessage, response: h
|
|
|
79
79
|
if (!host) {
|
|
80
80
|
throw new Error("Missing host in request headers");
|
|
81
81
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
hostname = parts.slice(-2).join(".");
|
|
85
|
-
if (hostname.startsWith("https://")) {
|
|
86
|
-
hostname = hostname.slice("https://".length);
|
|
87
|
-
}
|
|
88
|
-
hostname = hostname.split(":")[0];
|
|
89
|
-
hostname = hostname.split("/")[0];
|
|
90
|
-
return hostname;
|
|
91
|
-
}
|
|
92
|
-
let hostDomain = rootDomain(host);
|
|
93
|
-
let originDomain = rootDomain(origin);
|
|
82
|
+
let hostDomain = getRootDomain(host);
|
|
83
|
+
let originDomain = getRootDomain(origin);
|
|
94
84
|
allowed = hostDomain === originDomain;
|
|
95
85
|
if (!allowed) {
|
|
96
86
|
console.log(`Rejected CORS, hostDomain: ${hostDomain} !== ${originDomain}`);
|
package/src/misc.ts
CHANGED
|
@@ -293,6 +293,17 @@ export function sort<T>(arr: T[], sortKey: (obj: T) => unknown) {
|
|
|
293
293
|
return arr;
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
+
export function getRootDomain(hostname: string) {
|
|
297
|
+
if (hostname.startsWith("https://")) {
|
|
298
|
+
hostname = hostname.slice("https://".length);
|
|
299
|
+
}
|
|
300
|
+
hostname = hostname.split("/")[0];
|
|
301
|
+
let parts = hostname.split(".");
|
|
302
|
+
hostname = parts.slice(-2).join(".");
|
|
303
|
+
hostname = hostname.split(":")[0];
|
|
304
|
+
return hostname;
|
|
305
|
+
}
|
|
306
|
+
|
|
296
307
|
export class QueueLimited<T> {
|
|
297
308
|
private items: T[] = [];
|
|
298
309
|
private nextIndex = 0;
|
package/src/webSocketServer.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { parseSNIExtension, parseTLSHello, SNIType } from "./tlsParsing";
|
|
|
11
11
|
import debugbreak from "debugbreak";
|
|
12
12
|
import { getNodeId } from "./nodeCache";
|
|
13
13
|
import crypto from "crypto";
|
|
14
|
-
import { Watchable, timeInHour, timeInMinute } from "./misc";
|
|
14
|
+
import { Watchable, getRootDomain, timeInHour, timeInMinute } from "./misc";
|
|
15
15
|
import { delay, runInfinitePoll, runInfinitePollCallAtStart } from "./batching";
|
|
16
16
|
import { magenta, red } from "./formatting/logColors";
|
|
17
17
|
import { yellow } from "./formatting/logColors";
|
|
@@ -46,7 +46,9 @@ export type SocketServerConfig = (
|
|
|
46
46
|
// may be, "querysub.com", for example), use ["letx.ca"]
|
|
47
47
|
allowHostnames?: string[];
|
|
48
48
|
|
|
49
|
-
/** If the SNI matches this domain, we use a different key/cert.
|
|
49
|
+
/** If the SNI matches this domain, we use a different key/cert.
|
|
50
|
+
* We remove subdomains until we find a match
|
|
51
|
+
*/
|
|
50
52
|
SNICerts?: {
|
|
51
53
|
[domain: string]: Watchable<https.ServerOptions>;
|
|
52
54
|
};
|
|
@@ -131,12 +133,14 @@ export async function startSocketServer(
|
|
|
131
133
|
let originHeader = request.headers["origin"];
|
|
132
134
|
if (originHeader) {
|
|
133
135
|
try {
|
|
134
|
-
let host = new URL("ws://" + request.headers["host"]).hostname;
|
|
135
|
-
let origin = new URL(originHeader).hostname;
|
|
136
|
+
let host = getRootDomain(new URL("ws://" + request.headers["host"]).hostname);
|
|
137
|
+
let origin = getRootDomain(new URL(originHeader).hostname);
|
|
136
138
|
if (host !== origin && !allowedHostnames.has(origin)) {
|
|
137
139
|
throw new Error(`Invalid cross domain request, ${JSON.stringify(host)} !== ${JSON.stringify(origin)} (also not in config.allowedHostnames ${JSON.stringify(config.allowHostnames)})`);
|
|
138
140
|
}
|
|
139
141
|
} catch (e) {
|
|
142
|
+
// Destroy the socket, so we don't lock up the client
|
|
143
|
+
socket.destroy();
|
|
140
144
|
// NOTE: Just log, because invalid requests are guaranteed to happen, and
|
|
141
145
|
// there's no point wasting time looking at them.
|
|
142
146
|
console.log(e);
|
|
@@ -214,14 +218,18 @@ export async function startSocketServer(
|
|
|
214
218
|
console.warn(`No SNI found in TLS hello from ${debug}, using main server. Packets ${packetCount}`);
|
|
215
219
|
console.log(buffer.toString("base64"));
|
|
216
220
|
}
|
|
221
|
+
let originalSNI = sni;
|
|
222
|
+
if (sni) {
|
|
223
|
+
// Remove subdomains until we can find a domain
|
|
224
|
+
while (!sniServers.has(sni)) {
|
|
225
|
+
let parts = sni.split(".");
|
|
226
|
+
if (parts.length <= 2) break;
|
|
227
|
+
sni = parts.slice(1).join(".");
|
|
228
|
+
}
|
|
229
|
+
}
|
|
217
230
|
|
|
218
231
|
if (!sniServers.has(sni)) {
|
|
219
|
-
|
|
220
|
-
sni = sni.split(".").slice(-2).join(".");
|
|
221
|
-
}
|
|
222
|
-
if (!sniServers.has(sni)) {
|
|
223
|
-
console.warn(`No SNI server found for ${sni}, using main server.`);
|
|
224
|
-
}
|
|
232
|
+
console.warn(`No SNI server found for ${originalSNI}, using main server. SNI candidates ${Array.from(sniServers.keys()).join(", ")}`);
|
|
225
233
|
}
|
|
226
234
|
server = sniServers.get(sni) || mainHTTPSServer;
|
|
227
235
|
}
|