@dsh-remote/relay 3.1.0 → 3.1.2
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/dist/bundle/main.js +57 -16
- package/package.json +1 -1
package/dist/bundle/main.js
CHANGED
|
@@ -2279,7 +2279,7 @@ var require_websocket = __commonJS({
|
|
|
2279
2279
|
var http = __require("http");
|
|
2280
2280
|
var net = __require("net");
|
|
2281
2281
|
var tls = __require("tls");
|
|
2282
|
-
var { randomBytes:
|
|
2282
|
+
var { randomBytes: randomBytes3, createHash } = __require("crypto");
|
|
2283
2283
|
var { Duplex, Readable } = __require("stream");
|
|
2284
2284
|
var { URL: URL2 } = __require("url");
|
|
2285
2285
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -2830,7 +2830,7 @@ var require_websocket = __commonJS({
|
|
|
2830
2830
|
}
|
|
2831
2831
|
}
|
|
2832
2832
|
const defaultPort = isSecure ? 443 : 80;
|
|
2833
|
-
const key =
|
|
2833
|
+
const key = randomBytes3(16).toString("base64");
|
|
2834
2834
|
const request = isSecure ? https.request : http.request;
|
|
2835
2835
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
2836
2836
|
let perMessageDeflate;
|
|
@@ -23394,7 +23394,7 @@ function date4(params) {
|
|
|
23394
23394
|
return _coercedDate(ZodDate, params);
|
|
23395
23395
|
}
|
|
23396
23396
|
|
|
23397
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
23397
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/wire/limits.js
|
|
23398
23398
|
var MAX_RELAY_MESSAGE_BYTES = 1024 * 1024;
|
|
23399
23399
|
var MAX_CIPHERTEXT_BYTES = MAX_RELAY_MESSAGE_BYTES - 8 * 1024;
|
|
23400
23400
|
var MAX_IMAGE_ATTACHMENTS = 4;
|
|
@@ -23403,7 +23403,7 @@ var MAX_ATTACHMENT_BYTES = 512 * 1024;
|
|
|
23403
23403
|
var MAX_ATTACHMENT_TOTAL_BYTES = 512 * 1024;
|
|
23404
23404
|
var IDEMPOTENCY_WINDOW_MS = 5 * 60 * 1e3;
|
|
23405
23405
|
|
|
23406
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
23406
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/wire/frames.js
|
|
23407
23407
|
var PROTOCOL_VERSION = 1;
|
|
23408
23408
|
var MIN_SUPPORTED_PROTOCOL = 1;
|
|
23409
23409
|
var PAIRING_TOKEN_RE = /^\d{6}$/;
|
|
@@ -23855,7 +23855,7 @@ function loadConfig(env, version2) {
|
|
|
23855
23855
|
|
|
23856
23856
|
// src/server.ts
|
|
23857
23857
|
import { createServer } from "node:http";
|
|
23858
|
-
import { randomUUID as randomUUID2, timingSafeEqual } from "node:crypto";
|
|
23858
|
+
import { randomBytes as randomBytes2, randomUUID as randomUUID2, timingSafeEqual } from "node:crypto";
|
|
23859
23859
|
|
|
23860
23860
|
// node_modules/.pnpm/ws@8.22.0/node_modules/ws/wrapper.mjs
|
|
23861
23861
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -23867,7 +23867,7 @@ var import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
|
23867
23867
|
var import_websocket = __toESM(require_websocket(), 1);
|
|
23868
23868
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
23869
23869
|
|
|
23870
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
23870
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/identity/ids.js
|
|
23871
23871
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
23872
23872
|
var CONVERSATION_ID_PREFIX = "c_";
|
|
23873
23873
|
function newConversationId() {
|
|
@@ -23877,10 +23877,10 @@ function newHostId() {
|
|
|
23877
23877
|
return randomBytes(4).toString("hex");
|
|
23878
23878
|
}
|
|
23879
23879
|
|
|
23880
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
23880
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/platform/sleep.js
|
|
23881
23881
|
var SLEEP_BACKENDS = ["caffeinate", "systemd-inhibit", "unsupported"];
|
|
23882
23882
|
|
|
23883
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
23883
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/wire/payloads.js
|
|
23884
23884
|
var SESSION_STATES = [
|
|
23885
23885
|
"idle",
|
|
23886
23886
|
"running",
|
|
@@ -24291,7 +24291,7 @@ var PAYLOAD_TYPES = {
|
|
|
24291
24291
|
evSessionHistory: "ev.session_history"
|
|
24292
24292
|
};
|
|
24293
24293
|
|
|
24294
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
24294
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/wire/registry.js
|
|
24295
24295
|
var ENDPOINT_FRAME_NAMES = [
|
|
24296
24296
|
"hello",
|
|
24297
24297
|
"pair-begin",
|
|
@@ -24383,7 +24383,7 @@ var CAPABILITY_IDS = [
|
|
|
24383
24383
|
];
|
|
24384
24384
|
var CAPABILITY_SET = new Set(CAPABILITY_IDS);
|
|
24385
24385
|
|
|
24386
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
24386
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/wire/negotiate.js
|
|
24387
24387
|
function negotiateProtocol(peerProtocol, own2 = PROTOCOL_VERSION, min = MIN_SUPPORTED_PROTOCOL) {
|
|
24388
24388
|
if (peerProtocol === void 0 || peerProtocol === null) {
|
|
24389
24389
|
return verdictFor(1, own2, min, true);
|
|
@@ -24423,13 +24423,13 @@ function verdictFor(peer, own2, min, missing) {
|
|
|
24423
24423
|
return { ok: true, version: peer, missing };
|
|
24424
24424
|
}
|
|
24425
24425
|
|
|
24426
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
24426
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/wire/errors.js
|
|
24427
24427
|
var WAIT_HINTABLE = /* @__PURE__ */ new Set(["rate_limited", "pair_table_full"]);
|
|
24428
24428
|
function wantsRetryAfter(code) {
|
|
24429
24429
|
return typeof code === "string" && WAIT_HINTABLE.has(code);
|
|
24430
24430
|
}
|
|
24431
24431
|
|
|
24432
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
24432
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/wire/outbound.js
|
|
24433
24433
|
function helloOkForClient(clientId, protocol) {
|
|
24434
24434
|
return { t: "hello-ok", role: "client", clientId, ...protocol === void 0 ? {} : { protocol } };
|
|
24435
24435
|
}
|
|
@@ -24507,7 +24507,7 @@ function encBatchToRelay(sessionId, items) {
|
|
|
24507
24507
|
return { t: "enc-batch", sessionId, items: items.map((item) => ({ ...item })) };
|
|
24508
24508
|
}
|
|
24509
24509
|
|
|
24510
|
-
// node_modules/.pnpm/@dsh-remote+protocol@3.0.
|
|
24510
|
+
// node_modules/.pnpm/@dsh-remote+protocol@3.0.6/node_modules/@dsh-remote/protocol/dist/src/wire/classify.js
|
|
24511
24511
|
function frameTypeOf(value) {
|
|
24512
24512
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
24513
24513
|
return void 0;
|
|
@@ -25147,6 +25147,8 @@ function tokenMatches(expected, got) {
|
|
|
25147
25147
|
if (a.length !== b.length) return false;
|
|
25148
25148
|
return timingSafeEqual(a, b);
|
|
25149
25149
|
}
|
|
25150
|
+
var CLAIM_MIN_INTERVAL_MS = 4e3;
|
|
25151
|
+
var CLAIM_TRACK_MAX = 1e4;
|
|
25150
25152
|
function createRelay(config2) {
|
|
25151
25153
|
const log = new Log(config2.logLevel);
|
|
25152
25154
|
const state = new RelayState({ maxPendingPairs: config2.maxPendingPairs });
|
|
@@ -25155,10 +25157,24 @@ function createRelay(config2) {
|
|
|
25155
25157
|
const pairStatusBudget = new Budget(config2.pairStatusBudgetPerSec);
|
|
25156
25158
|
const peers = /* @__PURE__ */ new WeakMap();
|
|
25157
25159
|
let shuttingDown = false;
|
|
25160
|
+
let currentHostToken = config2.hostToken;
|
|
25161
|
+
const lastClaimAt = /* @__PURE__ */ new Map();
|
|
25158
25162
|
let sweepTimer;
|
|
25159
25163
|
let pingTimer;
|
|
25160
25164
|
let lastPingAt = 0;
|
|
25161
25165
|
let lastCountersAt = 0;
|
|
25166
|
+
function rotateHostToken() {
|
|
25167
|
+
currentHostToken = randomBytes2(24).toString("hex");
|
|
25168
|
+
if (lastClaimAt.size >= CLAIM_TRACK_MAX) {
|
|
25169
|
+
const drop = lastClaimAt.size - CLAIM_TRACK_MAX + 1;
|
|
25170
|
+
let i = 0;
|
|
25171
|
+
for (const key of lastClaimAt.keys()) {
|
|
25172
|
+
lastClaimAt.delete(key);
|
|
25173
|
+
if (++i >= drop) break;
|
|
25174
|
+
}
|
|
25175
|
+
}
|
|
25176
|
+
return currentHostToken;
|
|
25177
|
+
}
|
|
25162
25178
|
const persistence = { enabled: config2.stateFile !== "", restored: 0, savedAt: 0, writes: 0, failures: 0 };
|
|
25163
25179
|
if (persistence.enabled) {
|
|
25164
25180
|
persistence.restored = restoreState(config2.stateFile, state, log, startedAt);
|
|
@@ -25284,12 +25300,12 @@ function createRelay(config2) {
|
|
|
25284
25300
|
}
|
|
25285
25301
|
peer.protocol = frame.protocol;
|
|
25286
25302
|
if (frame.role === "host") {
|
|
25287
|
-
if (!
|
|
25303
|
+
if (!currentHostToken) {
|
|
25288
25304
|
sendError(peer, "internal", "relay has no host token configured");
|
|
25289
25305
|
peer.ws.close(1011);
|
|
25290
25306
|
return;
|
|
25291
25307
|
}
|
|
25292
|
-
if (!frame.token || !tokenMatches(
|
|
25308
|
+
if (!frame.token || !tokenMatches(currentHostToken, frame.token)) {
|
|
25293
25309
|
peer.authAttempts += 1;
|
|
25294
25310
|
log.warn("host auth failed", { attempts: peer.authAttempts });
|
|
25295
25311
|
sendError(peer, "bad_token");
|
|
@@ -25765,6 +25781,31 @@ function createRelay(config2) {
|
|
|
25765
25781
|
res.end(JSON.stringify(health()));
|
|
25766
25782
|
return;
|
|
25767
25783
|
}
|
|
25784
|
+
if (url2.pathname === "/api/claim-token") {
|
|
25785
|
+
if (req.method !== "POST") {
|
|
25786
|
+
res.statusCode = 405;
|
|
25787
|
+
res.end(JSON.stringify({ error: "use POST" }));
|
|
25788
|
+
return;
|
|
25789
|
+
}
|
|
25790
|
+
if (shuttingDown) {
|
|
25791
|
+
res.statusCode = 503;
|
|
25792
|
+
res.end(JSON.stringify({ error: "shutting_down" }));
|
|
25793
|
+
return;
|
|
25794
|
+
}
|
|
25795
|
+
const now = Date.now();
|
|
25796
|
+
const ip = req.socket.remoteAddress ?? "unknown";
|
|
25797
|
+
const last = lastClaimAt.get(ip) ?? 0;
|
|
25798
|
+
if (now - last < CLAIM_MIN_INTERVAL_MS) {
|
|
25799
|
+
res.statusCode = 429;
|
|
25800
|
+
res.end(JSON.stringify({ error: "too_soon", retryAfterMs: CLAIM_MIN_INTERVAL_MS - (now - last) }));
|
|
25801
|
+
return;
|
|
25802
|
+
}
|
|
25803
|
+
lastClaimAt.set(ip, now);
|
|
25804
|
+
const token = rotateHostToken();
|
|
25805
|
+
log.info("host token claimed", { ip });
|
|
25806
|
+
res.end(JSON.stringify({ token, rotatedAt: new Date(now).toISOString() }));
|
|
25807
|
+
return;
|
|
25808
|
+
}
|
|
25768
25809
|
if (url2.pathname === "/api/info") {
|
|
25769
25810
|
res.end(JSON.stringify({ publicUrl: config2.publicUrl, protocol: PROTOCOL_VERSION }));
|
|
25770
25811
|
return;
|
|
@@ -25951,7 +25992,7 @@ function registerSignalHandlers(shutdown) {
|
|
|
25951
25992
|
|
|
25952
25993
|
// src/main.ts
|
|
25953
25994
|
function readVersion() {
|
|
25954
|
-
if ("3.1.
|
|
25995
|
+
if ("3.1.2") return "3.1.2";
|
|
25955
25996
|
try {
|
|
25956
25997
|
const pkg = JSON.parse(readFileSync2(new URL("../../package.json", import.meta.url), "utf8"));
|
|
25957
25998
|
if (typeof pkg.version === "string") return pkg.version;
|