serverless-ircd 0.10.0 → 0.11.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/.github/workflows/ci.yml +28 -0
- package/.github/workflows/deploy-cf-tcp.yml +26 -2
- package/.github/workflows/deploy-cf.yml +26 -0
- package/CHANGELOG.md +289 -0
- package/README.md +153 -20
- package/apps/aws-stack/bin/aws.ts +36 -0
- package/apps/aws-stack/package.json +1 -1
- package/apps/aws-stack/src/aws-stack.ts +221 -15
- package/apps/aws-stack/tests/stack.test.ts +450 -16
- package/apps/cf-tcp-container/Dockerfile +37 -5
- package/apps/cf-tcp-container/package.json +7 -2
- package/apps/cf-tcp-container/src/config-loader.ts +113 -2
- package/apps/cf-tcp-container/src/container-server.ts +256 -79
- package/apps/cf-tcp-container/src/main.ts +22 -7
- package/apps/cf-tcp-container/src/proxy-protocol.ts +112 -0
- package/apps/cf-tcp-container/terraform/spectrum.tf +40 -11
- package/apps/cf-tcp-container/tests/config-loader.test.ts +170 -0
- package/apps/cf-tcp-container/tests/container-server-tls.test.ts +382 -0
- package/apps/cf-tcp-container/tests/container-server.test.ts +358 -31
- package/apps/cf-tcp-container/tests/dockerfile.test.ts +110 -0
- package/apps/cf-tcp-container/tests/proxy-protocol.test.ts +187 -0
- package/apps/cf-tcp-container/tests/spectrum-terraform.test.ts +135 -0
- package/apps/cf-tcp-container/tests/tls-e2e.test.ts +5 -1
- package/apps/cf-tcp-container/wrangler.toml +17 -4
- package/apps/cf-worker/package.json +2 -2
- package/apps/cf-worker/src/worker.ts +77 -5
- package/apps/cf-worker/tests/raw-modules.d.ts +11 -0
- package/apps/cf-worker/tests/smoke.test.ts +4 -0
- package/apps/cf-worker/tests/wrangler-config.test.ts +47 -0
- package/apps/cf-worker/tests/ws-admission.test.ts +112 -0
- package/apps/cf-worker/tests/ws-rate-limit.test.ts +133 -0
- package/apps/cf-worker/wrangler.test.toml +15 -1
- package/apps/cf-worker/wrangler.toml +86 -9
- package/apps/local-cli/package.json +1 -1
- package/apps/local-cli/src/config-loader.ts +14 -2
- package/apps/local-cli/src/line-scanner.ts +26 -0
- package/apps/local-cli/src/server.ts +23 -2
- package/apps/local-cli/tests/line-scanner.test.ts +64 -0
- package/apps/local-cli/tests/tcp.test.ts +29 -0
- package/apps/web/package.json +1 -1
- package/docs/AWS-Deployment.md +123 -22
- package/docs/AWS-TCP-Deployment.md +37 -2
- package/docs/Chat-History.md +55 -0
- package/docs/Cloudflare-Deployment-Guide.md +9 -2
- package/docs/Cloudflare-TCP-Deployment.md +135 -52
- package/docs/SASL-EXTERNAL.md +175 -0
- package/package.json +3 -3
- package/packages/aws-adapter/package.json +1 -1
- package/packages/aws-adapter/src/admission.ts +28 -13
- package/packages/aws-adapter/src/aws-runtime.ts +30 -3
- package/packages/aws-adapter/src/cdk-table-defs.ts +34 -6
- package/packages/aws-adapter/src/config-loader.ts +134 -6
- package/packages/aws-adapter/src/dynamo-services-store.ts +12 -0
- package/packages/aws-adapter/src/handlers/connect.ts +47 -1
- package/packages/aws-adapter/src/handlers/default.ts +95 -6
- package/packages/aws-adapter/src/handlers/index.ts +31 -2
- package/packages/aws-adapter/src/handlers/nlb-stream.ts +132 -8
- package/packages/aws-adapter/src/ip-admission.ts +79 -0
- package/packages/aws-adapter/src/serialize.ts +8 -0
- package/packages/aws-adapter/src/tables.ts +9 -0
- package/packages/aws-adapter/tests/admission.test.ts +60 -2
- package/packages/aws-adapter/tests/aws-harness.ts +23 -1
- package/packages/aws-adapter/tests/aws-runtime.test.ts +64 -0
- package/packages/aws-adapter/tests/config-loader.test.ts +151 -0
- package/packages/aws-adapter/tests/connect.test.ts +199 -2
- package/packages/aws-adapter/tests/default-frame-limit.test.ts +231 -0
- package/packages/aws-adapter/tests/default-occ.test.ts +10 -3
- package/packages/aws-adapter/tests/dynamo-services-store-unit.test.ts +123 -1
- package/packages/aws-adapter/tests/handlers.test.ts +57 -1
- package/packages/aws-adapter/tests/nlb-secure.test.ts +362 -0
- package/packages/aws-adapter/tests/nlb-stream.test.ts +628 -9
- package/packages/cf-adapter/package.json +1 -1
- package/packages/cf-adapter/src/cf-runtime.ts +48 -9
- package/packages/cf-adapter/src/config-loader.ts +133 -8
- package/packages/cf-adapter/src/connection-do.ts +154 -21
- package/packages/cf-adapter/src/counter-do.ts +142 -0
- package/packages/cf-adapter/src/d1-services-store.ts +47 -5
- package/packages/cf-adapter/src/env.ts +88 -0
- package/packages/cf-adapter/src/index.ts +17 -1
- package/packages/cf-adapter/src/rate-limit-do.ts +87 -0
- package/packages/cf-adapter/tests/cf-runtime.test.ts +104 -15
- package/packages/cf-adapter/tests/config-loader.test.ts +159 -0
- package/packages/cf-adapter/tests/connection-do-counter.test.ts +165 -0
- package/packages/cf-adapter/tests/connection-do-frame-limit.test.ts +177 -0
- package/packages/cf-adapter/tests/connection-do-pure.test.ts +74 -5
- package/packages/cf-adapter/tests/connection-do-ws-spec-contract.test.ts +7 -4
- package/packages/cf-adapter/tests/counter-do.test.ts +181 -0
- package/packages/cf-adapter/tests/d1-services-store.test.ts +192 -1
- package/packages/cf-adapter/tests/rate-limit-do.test.ts +160 -0
- package/packages/cf-adapter/tests/worker/main.ts +4 -0
- package/packages/cf-adapter/wrangler.test.toml +18 -1
- package/packages/in-memory-runtime/package.json +1 -1
- package/packages/in-memory-runtime/src/in-memory-runtime.ts +25 -0
- package/packages/in-memory-runtime/tests/in-memory-runtime.test.ts +74 -0
- package/packages/irc-core/package.json +1 -1
- package/packages/irc-core/src/caps/capabilities.ts +20 -10
- package/packages/irc-core/src/certfp.ts +178 -0
- package/packages/irc-core/src/commands/cap.ts +10 -2
- package/packages/irc-core/src/commands/chanserv.ts +117 -14
- package/packages/irc-core/src/commands/chathistory.ts +13 -5
- package/packages/irc-core/src/commands/hostserv.ts +84 -8
- package/packages/irc-core/src/commands/index.ts +2 -1
- package/packages/irc-core/src/commands/invite.ts +1 -7
- package/packages/irc-core/src/commands/join.ts +1 -16
- package/packages/irc-core/src/commands/kick.ts +1 -8
- package/packages/irc-core/src/commands/list.ts +1 -8
- package/packages/irc-core/src/commands/mode.ts +1 -8
- package/packages/irc-core/src/commands/multiline.ts +4 -10
- package/packages/irc-core/src/commands/names.ts +53 -13
- package/packages/irc-core/src/commands/nickserv.ts +40 -1
- package/packages/irc-core/src/commands/oper.ts +361 -8
- package/packages/irc-core/src/commands/part.ts +4 -10
- package/packages/irc-core/src/commands/privmsg.ts +8 -4
- package/packages/irc-core/src/commands/registration.ts +146 -2
- package/packages/irc-core/src/commands/sasl.ts +136 -19
- package/packages/irc-core/src/commands/topic.ts +10 -12
- package/packages/irc-core/src/commands/who.ts +1 -8
- package/packages/irc-core/src/config.ts +393 -20
- package/packages/irc-core/src/effects.ts +24 -0
- package/packages/irc-core/src/flood-control.ts +10 -10
- package/packages/irc-core/src/frame-rate-limit.ts +82 -0
- package/packages/irc-core/src/index.ts +8 -0
- package/packages/irc-core/src/oper-hashing.ts +43 -0
- package/packages/irc-core/src/oper-lockout.ts +87 -0
- package/packages/irc-core/src/ports.ts +395 -36
- package/packages/irc-core/src/protocol/bytes.ts +65 -0
- package/packages/irc-core/src/protocol/channel-name.ts +37 -0
- package/packages/irc-core/src/protocol/index.ts +12 -1
- package/packages/irc-core/src/protocol/outbound.ts +43 -10
- package/packages/irc-core/src/protocol/parser.ts +79 -10
- package/packages/irc-core/src/state/connection.ts +13 -0
- package/packages/irc-core/src/types.ts +228 -13
- package/packages/irc-core/src/ws-framing.ts +5 -4
- package/packages/irc-core/tests/bytes.test.ts +89 -0
- package/packages/irc-core/tests/certfp.test.ts +117 -0
- package/packages/irc-core/tests/commands/cap.test.ts +76 -2
- package/packages/irc-core/tests/commands/chanserv.test.ts +166 -0
- package/packages/irc-core/tests/commands/chathistory.test.ts +140 -0
- package/packages/irc-core/tests/commands/hostserv.test.ts +316 -0
- package/packages/irc-core/tests/commands/join.test.ts +78 -1
- package/packages/irc-core/tests/commands/names.test.ts +193 -0
- package/packages/irc-core/tests/commands/nickserv.test.ts +182 -2
- package/packages/irc-core/tests/commands/oper.test.ts +560 -2
- package/packages/irc-core/tests/commands/privmsg.test.ts +16 -0
- package/packages/irc-core/tests/commands/registration.test.ts +463 -1
- package/packages/irc-core/tests/commands/sasl.test.ts +596 -7
- package/packages/irc-core/tests/commands/topic.test.ts +137 -2
- package/packages/irc-core/tests/commands/unified-account.test.ts +2 -0
- package/packages/irc-core/tests/config.test.ts +534 -2
- package/packages/irc-core/tests/effects.test.ts +14 -0
- package/packages/irc-core/tests/flood-control.test.ts +29 -1
- package/packages/irc-core/tests/frame-rate-limit.test.ts +98 -0
- package/packages/irc-core/tests/oper-hashing.test.ts +60 -0
- package/packages/irc-core/tests/oper-lockout.test.ts +74 -0
- package/packages/irc-core/tests/outbound.test.ts +148 -0
- package/packages/irc-core/tests/parser.test.ts +287 -5
- package/packages/irc-core/tests/persistent-services-store.test.ts +141 -0
- package/packages/irc-core/tests/ports.test.ts +99 -7
- package/packages/irc-core/tests/services-store.test.ts +376 -14
- package/packages/irc-core/tests/ws-framing.test.ts +45 -0
- package/packages/irc-server/package.json +1 -1
- package/packages/irc-server/src/actor.ts +123 -8
- package/packages/irc-server/src/dispatch.ts +1 -0
- package/packages/irc-server/src/index.ts +7 -0
- package/packages/irc-server/src/redact.ts +159 -0
- package/packages/irc-server/src/runtime.ts +14 -0
- package/packages/irc-server/src/transport.ts +28 -1
- package/packages/irc-server/tests/actor.test.ts +544 -7
- package/packages/irc-server/tests/dispatch.test.ts +31 -0
- package/packages/irc-server/tests/redact.test.ts +198 -0
- package/packages/irc-server/tests/runtime.test.ts +2 -0
- package/packages/irc-server/tests/transport.test.ts +66 -0
- package/packages/irc-test-support/package.json +1 -1
- package/packages/irc-test-support/src/in-memory-harness.ts +4 -0
- package/scripts/package.json +1 -1
- package/tools/ci-hardening/package.json +2 -2
- package/tools/ci-hardening/src/cf-deploy-cli.ts +3 -0
- package/tools/ci-hardening/src/cf-deploy.ts +118 -0
- package/tools/ci-hardening/src/deploy-hostname.ts +118 -0
- package/tools/ci-hardening/src/env-var-drift.ts +192 -0
- package/tools/ci-hardening/src/hostname-guard.ts +11 -0
- package/tools/ci-hardening/src/index.ts +17 -0
- package/tools/ci-hardening/tests/__wrangler_missing__.toml +2 -0
- package/tools/ci-hardening/tests/__wrangler_placeholder__.toml +3 -0
- package/tools/ci-hardening/tests/__wrangler_real__.toml +3 -0
- package/tools/ci-hardening/tests/cf-deploy.test.ts +200 -0
- package/tools/ci-hardening/tests/deploy-hostname.test.ts +348 -0
- package/tools/ci-hardening/tests/env-var-drift.test.ts +284 -0
- package/tools/ci-hardening/vitest.config.ts +5 -1
- package/tools/hash-oper-cred.ts +85 -0
- package/tools/load-test/package.json +1 -1
- package/tools/tcp-ws-forwarder/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helper for `tools/hash-oper-cred.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Wraps {@link hashAccountCredential}'s scrypt derivation in the
|
|
5
|
+
* `{user, salt, hash}` shape the oper config consumes (see
|
|
6
|
+
* {@link OperCredSchema}). The CLI entry point (arg parsing, console
|
|
7
|
+
* output) lives in the tools script; this helper is side-effect-free
|
|
8
|
+
* and fully unit-testable, mirroring the
|
|
9
|
+
* `account-migration.ts` / `tools/migrate-accounts-to-services.ts`
|
|
10
|
+
* split.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { hashAccountCredential } from './credential-hashing.js';
|
|
14
|
+
import type { OperCredHashed } from './types.js';
|
|
15
|
+
|
|
16
|
+
export type { OperCredHashed };
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Hashes a plaintext oper `{user, password}` pair into the at-rest
|
|
20
|
+
* `{user, salt, hash}` shape operators paste into secrets.
|
|
21
|
+
*
|
|
22
|
+
* The `salt` is cryptographically random by default; pass `{ salt }`
|
|
23
|
+
* for deterministic test scenarios. The `hash` is scrypt-derived via
|
|
24
|
+
* {@link hashAccountCredential} (memory-hard, GPU-resistant) and both
|
|
25
|
+
* `salt` and `hash` are base64 strings safe to embed in JSON / env
|
|
26
|
+
* vars / wrangler secrets.
|
|
27
|
+
*
|
|
28
|
+
* Round-trips via {@link matchOperCred} (the OPER reducer's verify
|
|
29
|
+
* path) — the resulting {@link OperCredHashed} is directly assignable
|
|
30
|
+
* to the {@link OperCredSchema} array on `ServerConfig`.
|
|
31
|
+
*/
|
|
32
|
+
export function hashOperCredential(
|
|
33
|
+
user: string,
|
|
34
|
+
password: string,
|
|
35
|
+
opts?: { salt?: Uint8Array },
|
|
36
|
+
): OperCredHashed {
|
|
37
|
+
const entry = hashAccountCredential(user, password, opts);
|
|
38
|
+
return {
|
|
39
|
+
user: entry.account,
|
|
40
|
+
salt: entry.salt,
|
|
41
|
+
hash: entry.hash,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-IP failed-`OPER` counter — the failed-authentication counterpart of
|
|
3
|
+
* {@link AdmissionStats}.
|
|
4
|
+
*
|
|
5
|
+
* Online brute force against `OPER` is bounded by this sliding-window
|
|
6
|
+
* counter: once a single source host accumulates `oper.maxFailures`
|
|
7
|
+
* credential failures within `oper.failureWindowSeconds`, every further
|
|
8
|
+
* `OPER` from that host is rejected with `491 ERR_NOOPERHOST` before the
|
|
9
|
+
* credential store is consulted (see `commands/oper.ts`).
|
|
10
|
+
*
|
|
11
|
+
* Ownership + injection follows the {@link AdmissionStats} precedent: the
|
|
12
|
+
* runtime (in-memory reference runtime, local CLI) constructs exactly one
|
|
13
|
+
* instance per process and shares it across every connection via the
|
|
14
|
+
* `ctx.operFailures` port, so the counter is per-IP across the whole
|
|
15
|
+
* deployment rather than per-connection. The instance MUST be constructed
|
|
16
|
+
* with the same {@link Clock} the actors use so window arithmetic is
|
|
17
|
+
* coherent.
|
|
18
|
+
*
|
|
19
|
+
* Determinism: same Clock + same call stream → same answers. There are no
|
|
20
|
+
* ambient inputs (never `Date.now`).
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import type { Clock } from './ports.js';
|
|
24
|
+
|
|
25
|
+
/** Per-IP failed-`OPER` counter owned by the runtime (sliding window). */
|
|
26
|
+
export class OperFailureStats {
|
|
27
|
+
private readonly clock: Clock;
|
|
28
|
+
/**
|
|
29
|
+
* Per-IP timestamps of recent OPER credential failures, used by the
|
|
30
|
+
* lockout gate. Stored ascending; entries older than the queried window
|
|
31
|
+
* are pruned lazily (identical bookkeeping to `AdmissionStats`'
|
|
32
|
+
* `perIpAdmitTimes`).
|
|
33
|
+
*/
|
|
34
|
+
private readonly failureTimes = new Map<string, number[]>();
|
|
35
|
+
|
|
36
|
+
constructor(clock: Clock) {
|
|
37
|
+
this.clock = clock;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns the number of `OPER` credential failures recorded for `ip`
|
|
42
|
+
* within the last `windowMs` milliseconds (inclusive of the moment
|
|
43
|
+
* returned by `clock.now()`). Stale entries are pruned as a side effect,
|
|
44
|
+
* so an IP whose every failure has expired drops out of the map
|
|
45
|
+
* entirely.
|
|
46
|
+
*/
|
|
47
|
+
recentFailures(ip: string, windowMs: number): number {
|
|
48
|
+
const times = this.failureTimes.get(ip);
|
|
49
|
+
if (times === undefined) return 0;
|
|
50
|
+
const cutoff = this.clock.now() - windowMs;
|
|
51
|
+
let writeIdx = 0;
|
|
52
|
+
// `times` is dense (only ever appended to via push), so iterating
|
|
53
|
+
// values via for-of avoids the noUncheckedIndexedAccess trap while
|
|
54
|
+
// still allowing in-place compaction of stale entries.
|
|
55
|
+
for (const t of times) {
|
|
56
|
+
if (t >= cutoff) {
|
|
57
|
+
times[writeIdx++] = t;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (writeIdx === 0) {
|
|
61
|
+
this.failureTimes.delete(ip);
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
times.length = writeIdx;
|
|
65
|
+
return writeIdx;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Records one `OPER` credential failure for `ip`, stamped with the
|
|
70
|
+
* injected clock's current time. Called by the OPER reducer on the
|
|
71
|
+
* `464 ERR_PASSWDMISMATCH` path.
|
|
72
|
+
*/
|
|
73
|
+
recordFailure(ip: string): void {
|
|
74
|
+
const times = this.failureTimes.get(ip) ?? [];
|
|
75
|
+
times.push(this.clock.now());
|
|
76
|
+
this.failureTimes.set(ip, times);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Clears every recorded failure for `ip`. Called by the OPER reducer on
|
|
81
|
+
* successful authentication so a legitimate oper's success never
|
|
82
|
+
* contributes to a later lockout.
|
|
83
|
+
*/
|
|
84
|
+
reset(ip: string): void {
|
|
85
|
+
this.failureTimes.delete(ip);
|
|
86
|
+
}
|
|
87
|
+
}
|