@opensecurity/zonzon-core 0.1.1 → 0.1.3

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.
Files changed (71) hide show
  1. package/dist/audit.d.ts +10 -0
  2. package/dist/audit.js +39 -0
  3. package/dist/cache-layer.test.d.ts +1 -0
  4. package/dist/cache-layer.test.js +205 -0
  5. package/dist/cache-multi-question.test.d.ts +1 -0
  6. package/dist/cache-multi-question.test.js +187 -0
  7. package/dist/dns-handler.d.ts +27 -0
  8. package/dist/dns-handler.js +323 -0
  9. package/dist/dns-service.d.ts +45 -0
  10. package/dist/dns-service.js +546 -0
  11. package/dist/dns-service.test.d.ts +1 -0
  12. package/dist/dns-service.test.js +306 -0
  13. package/dist/dns-wireformat.test.d.ts +1 -0
  14. package/dist/dns-wireformat.test.js +669 -0
  15. package/dist/firewall.d.ts +9 -0
  16. package/dist/firewall.js +62 -0
  17. package/dist/http-body-forwarding-integration.test.d.ts +1 -0
  18. package/dist/http-body-forwarding-integration.test.js +318 -0
  19. package/dist/http-body-forwarding.test.d.ts +1 -0
  20. package/dist/http-body-forwarding.test.js +84 -0
  21. package/dist/http-handler.d.ts +21 -0
  22. package/dist/http-handler.js +429 -0
  23. package/dist/http-proxy.d.ts +14 -0
  24. package/dist/http-proxy.js +135 -0
  25. package/dist/http-proxy.test.d.ts +1 -0
  26. package/dist/http-proxy.test.js +375 -0
  27. package/{src/index.ts → dist/index.d.ts} +1 -1
  28. package/dist/index.js +10 -0
  29. package/dist/rate-limiter.d.ts +11 -0
  30. package/dist/rate-limiter.js +33 -0
  31. package/dist/rate-limiter.test.d.ts +1 -0
  32. package/dist/rate-limiter.test.js +149 -0
  33. package/dist/schema.d.ts +12 -0
  34. package/dist/schema.js +124 -0
  35. package/dist/schema.test.d.ts +1 -0
  36. package/dist/schema.test.js +586 -0
  37. package/dist/sni-proxy.d.ts +12 -0
  38. package/dist/sni-proxy.js +141 -0
  39. package/dist/srv-record.test.d.ts +1 -0
  40. package/dist/srv-record.test.js +186 -0
  41. package/dist/tcp-connection-limit.test.d.ts +1 -0
  42. package/dist/tcp-connection-limit.test.js +89 -0
  43. package/dist/types.d.ts +145 -0
  44. package/dist/types.js +34 -0
  45. package/dist/wildcard-matching.test.d.ts +1 -0
  46. package/dist/wildcard-matching.test.js +162 -0
  47. package/package.json +4 -1
  48. package/src/audit.ts +0 -43
  49. package/src/cache-layer.test.ts +0 -236
  50. package/src/cache-multi-question.test.ts +0 -263
  51. package/src/dns-handler.ts +0 -355
  52. package/src/dns-service.test.ts +0 -371
  53. package/src/dns-service.ts +0 -655
  54. package/src/dns-wireformat.test.ts +0 -771
  55. package/src/env.d.ts +0 -1
  56. package/src/firewall.ts +0 -66
  57. package/src/http-body-forwarding-integration.test.ts +0 -357
  58. package/src/http-body-forwarding.test.ts +0 -101
  59. package/src/http-handler.ts +0 -489
  60. package/src/http-proxy.test.ts +0 -440
  61. package/src/http-proxy.ts +0 -148
  62. package/src/rate-limiter.test.ts +0 -144
  63. package/src/rate-limiter.ts +0 -50
  64. package/src/schema.test.ts +0 -685
  65. package/src/schema.ts +0 -137
  66. package/src/sni-proxy.ts +0 -164
  67. package/src/srv-record.test.ts +0 -211
  68. package/src/tcp-connection-limit.test.ts +0 -110
  69. package/src/types.ts +0 -168
  70. package/src/wildcard-matching.test.ts +0 -196
  71. package/tsconfig.json +0 -9
@@ -1,144 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import assert from "assert";
3
- import * as net from "net";
4
-
5
- let PORT_BASE = 65000;
6
- function nextPort(): number { return PORT_BASE++; }
7
-
8
- describe("TCP Rate Limiting", () => {
9
- function buildTcpDnsQuery(name: string): Buffer {
10
- const encoder = new (class {
11
- buf = Buffer.alloc(256); offset = 0;
12
- writeUint16(v: number) { this.buf.writeUInt16BE(v, this.offset); this.offset += 2; }
13
- writeUint8(v: number) { this.buf.writeUInt8(v, this.offset); this.offset += 1; }
14
- writeDomainName(nm: string) {
15
- for (const label of nm.split(".")) { if (!label.length) continue; this.writeUint8(label.length); Buffer.from(label).copy(this.buf, this.offset); this.offset += label.length; }
16
- this.writeUint8(0);
17
- }
18
- finish(): Buffer { return this.buf.subarray(0, this.offset); }
19
- })();
20
- encoder.writeUint16(0xDEAD); encoder.writeUint16(0x0100); encoder.writeUint16(1);
21
- encoder.writeUint16(0); encoder.writeUint16(0); encoder.writeUint16(0);
22
- encoder.writeDomainName(name); encoder.writeUint16(1); encoder.writeUint16(1);
23
- const query = encoder.finish();
24
- const prefixed = Buffer.alloc(2 + query.length);
25
- prefixed.writeUInt16BE(query.length, 0); query.copy(prefixed, 2);
26
- return prefixed;
27
- }
28
-
29
- it("TCP queries are rate limited when configured", async () => {
30
- const port = nextPort();
31
- const { DnsHandler } = await import("./dns-handler.js");
32
- const { DevDnsServer } = await import("./dns-service.js");
33
- const config: any = { port, hosts: { "test.loop": { records: [{ type: "A", address: "5.6.7.8" }] } }, rateLimitMaxRequests: 3, rateLimitWindowMs: 1000 };
34
-
35
- const dnsServer = new DevDnsServer(config);
36
- const handler = new DnsHandler(dnsServer, config);
37
- await handler.start();
38
-
39
- try {
40
- await new Promise<void>((r) => setTimeout(r, 150));
41
-
42
- const results: number[] = [];
43
- for (let i = 0; i < 3; i++) {
44
- let responses = 0;
45
- await new Promise<void>((resolve) => {
46
- const socket = net.createConnection(port, "127.0.0.1", () => {
47
- socket.write(buildTcpDnsQuery("test.loop"));
48
- socket.on("data", (data: Buffer) => {
49
- let off = 0;
50
- while (off + 2 <= data.length) {
51
- const len = data.readUInt16BE(off);
52
- if (len === 0 || off + 2 + len > data.length) break;
53
- responses++; off += 2 + len;
54
- }
55
- });
56
- setTimeout(() => { socket.destroy(); resolve(); }, 1000);
57
- });
58
- });
59
- results.push(responses);
60
- }
61
-
62
- assert.ok(results.every((r) => r > 0));
63
- } finally {
64
- await handler.stop();
65
- }
66
- });
67
-
68
- it("TCP connection is terminated when source IP exceeds rate limit", async () => {
69
- const port = nextPort();
70
- const { DnsHandler } = await import("./dns-handler.js");
71
- const { DevDnsServer } = await import("./dns-service.js");
72
- const config: any = { port, hosts: { "test.loop": { records: [{ type: "A", address: "9.8.7.6" }] } }, rateLimitMaxRequests: 1, rateLimitWindowMs: 5000 };
73
-
74
- const dnsServer = new DevDnsServer(config);
75
- const handler = new DnsHandler(dnsServer, config);
76
- await handler.start();
77
-
78
- try {
79
- await new Promise<void>((r) => setTimeout(r, 150));
80
-
81
- let r1Responses = 0;
82
- await new Promise<void>((resolve) => {
83
- const socket = net.createConnection(port, "127.0.0.1", () => {
84
- socket.write(buildTcpDnsQuery("test.loop"));
85
- socket.on("data", (data: Buffer) => {
86
- let off = 0;
87
- while (off + 2 <= data.length) {
88
- const len = data.readUInt16BE(off);
89
- if (len === 0 || off + 2 + len > data.length) break;
90
- r1Responses++; off += 2 + len;
91
- }
92
- });
93
- setTimeout(() => { socket.destroy(); resolve(); }, 1000);
94
- });
95
- });
96
- assert.ok(r1Responses > 0);
97
-
98
- let r2Destroyed = false;
99
- await new Promise<void>((resolve) => {
100
- const socket = net.createConnection(port, "127.0.0.1", () => {
101
- setTimeout(() => { socket.destroy(); resolve(); }, 1500);
102
- });
103
- socket.on("error", () => { r2Destroyed = true; });
104
- socket.on("close", () => { if (!r2Destroyed) r2Destroyed = true; });
105
- });
106
-
107
- assert.strictEqual(r2Destroyed, true);
108
- } finally {
109
- await handler.stop();
110
- }
111
- });
112
-
113
- it("TCP queries work when rate limiting is disabled", async () => {
114
- const port = nextPort();
115
- const { DnsHandler } = await import("./dns-handler.js");
116
- const { DevDnsServer } = await import("./dns-service.js");
117
- const config: any = { port, hosts: { "test.loop": { records: [{ type: "A", address: "1.2.3.4" }] } }, rateLimitMaxRequests: 0 };
118
-
119
- const dnsServer = new DevDnsServer(config);
120
- const handler = new DnsHandler(dnsServer, config);
121
- await handler.start();
122
-
123
- try {
124
- await new Promise<void>((r) => setTimeout(r, 150));
125
-
126
- let successes = 0;
127
- for (let i = 0; i < 5; i++) {
128
- let gotResponse = false;
129
- await new Promise<void>((resolve) => {
130
- const socket = net.createConnection(port, "127.0.0.1", () => {
131
- socket.write(buildTcpDnsQuery("test.loop"));
132
- socket.on("data", () => { gotResponse = true; });
133
- setTimeout(() => { socket.destroy(); resolve(); }, 1000);
134
- });
135
- });
136
- if (gotResponse) successes++;
137
- }
138
-
139
- assert.strictEqual(successes, 5);
140
- } finally {
141
- await handler.stop();
142
- }
143
- });
144
- });
@@ -1,50 +0,0 @@
1
- export interface RateLimiterOptions {
2
- maxRequests: number;
3
- windowMs: number;
4
- }
5
-
6
- interface IpBucket {
7
- timestamps: number[];
8
- }
9
-
10
- export class RateLimiter {
11
- private options: RateLimiterOptions;
12
- private buckets = new Map<string, IpBucket>();
13
-
14
- constructor(options: RateLimiterOptions) {
15
- this.options = options;
16
- }
17
-
18
- allow(ip: string): boolean {
19
- const now = Date.now();
20
- let bucket = this.buckets.get(ip);
21
-
22
- if (!bucket || now - bucket.timestamps[0] > this.options.windowMs) {
23
- bucket = { timestamps: [now] };
24
- this.buckets.set(ip, bucket);
25
- return true;
26
- }
27
-
28
- const windowStart = now - this.options.windowMs;
29
- while (bucket.timestamps.length > 0 && bucket.timestamps[0] < windowStart) {
30
- bucket.timestamps.shift();
31
- }
32
-
33
- if (bucket.timestamps.length >= this.options.maxRequests) {
34
- return false;
35
- }
36
-
37
- bucket.timestamps.push(now);
38
- return true;
39
- }
40
-
41
- getRequestCount(ip: string): number {
42
- const now = Date.now();
43
- const windowStart = now - this.options.windowMs;
44
- const bucket = this.buckets.get(ip);
45
-
46
- if (!bucket) return 0;
47
-
48
- return bucket.timestamps.filter((t) => t >= windowStart).length;
49
- }
50
- }