@opensecurity/zonzon-core 0.1.5 → 0.1.7
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/cache-layer.test.js +1 -1
- package/dist/cache-multi-question.test.js +1 -1
- package/dist/dns-handler.js +1 -1
- package/dist/dns-service.test.js +1 -1
- package/dist/dns-wireformat.test.js +1 -1
- package/dist/doh-dot.test.js +91 -88
- package/dist/firewall.js +1 -1
- package/dist/http-body-forwarding-integration.test.js +1 -1
- package/dist/http-body-forwarding.test.js +1 -1
- package/dist/http-handler.js +4 -4
- package/dist/http-proxy.js +2 -2
- package/dist/rate-limiter.test.js +2 -2
- package/dist/schema.js +1 -1
- package/dist/srv-record.test.js +1 -1
- package/dist/tcp-connection-limit.test.js +2 -2
- package/dist/wildcard-matching.test.js +1 -1
- package/package.json +1 -1
package/dist/cache-layer.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
|
-
import assert from "assert";
|
|
2
|
+
import assert from "node:assert";
|
|
3
3
|
import { DevDnsServer } from "./dns-service.js";
|
|
4
4
|
import { DNS_TYPES, DNS_CLASSES } from "./types.js";
|
|
5
5
|
describe("Multi-Question TTL Cache Rewriting", () => {
|
package/dist/dns-handler.js
CHANGED
package/dist/dns-service.test.js
CHANGED
package/dist/doh-dot.test.js
CHANGED
|
@@ -1,101 +1,104 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
2
|
import assert from "node:assert";
|
|
3
|
-
import { generateKeyPairSync } from "node:crypto";
|
|
4
3
|
import { DnsHandler } from "./dns-handler.js";
|
|
5
4
|
import { DevDnsServer } from "./dns-service.js";
|
|
6
|
-
function
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
function createMockReqRes(method, url, headers = {}) {
|
|
6
|
+
const req = {
|
|
7
|
+
method,
|
|
8
|
+
url,
|
|
9
|
+
headers,
|
|
10
|
+
socket: { remoteAddress: "127.0.0.1" },
|
|
11
|
+
destroy: () => { }
|
|
12
|
+
};
|
|
13
|
+
let statusCode = 0;
|
|
14
|
+
let endData = null;
|
|
15
|
+
const resHeaders = {};
|
|
16
|
+
const res = {
|
|
17
|
+
writeHead: (code, headers) => {
|
|
18
|
+
statusCode = code;
|
|
19
|
+
if (headers)
|
|
20
|
+
Object.assign(resHeaders, headers);
|
|
21
|
+
},
|
|
22
|
+
end: (data) => {
|
|
23
|
+
endData = data;
|
|
21
24
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
encoder.writeUint16(0xDEAD);
|
|
25
|
-
encoder.writeUint16(0x0100);
|
|
26
|
-
encoder.writeUint16(1);
|
|
27
|
-
encoder.writeUint16(0);
|
|
28
|
-
encoder.writeUint16(0);
|
|
29
|
-
encoder.writeUint16(0);
|
|
30
|
-
encoder.writeDomainName(name);
|
|
31
|
-
encoder.writeUint16(type);
|
|
32
|
-
encoder.writeUint16(1);
|
|
33
|
-
return encoder.finish();
|
|
34
|
-
}
|
|
35
|
-
function parseResponseFlags(buf) {
|
|
36
|
-
const flags = buf.readUInt16BE(2);
|
|
37
|
-
const qr = (flags >> 15) & 0x1;
|
|
38
|
-
const rcode = flags & 0xf;
|
|
39
|
-
return { qr, rcode };
|
|
25
|
+
};
|
|
26
|
+
return { req, res, getStatus: () => statusCode, getEndData: () => endData, getHeaders: () => resHeaders };
|
|
40
27
|
}
|
|
41
|
-
describe("Modern DNS Protocols (DoH
|
|
42
|
-
let handler;
|
|
43
|
-
const dotPort = 64853;
|
|
44
|
-
const dohPort = 64443;
|
|
45
|
-
const dnsPort = 64053;
|
|
46
|
-
// Minimal self-signed cert generation for testing boundaries
|
|
47
|
-
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
|
|
48
|
-
modulusLength: 2048,
|
|
49
|
-
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
50
|
-
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
|
|
51
|
-
});
|
|
52
|
-
// Note: For a strictly functional test without full x509 cert generation logic,
|
|
53
|
-
// we mock the TLS block to bypass strict validation in the Node runtime,
|
|
54
|
-
// or use a pre-generated fixture. The handler binds TLS correctly, but
|
|
55
|
-
// client verification needs to be disabled.
|
|
28
|
+
describe("Modern DNS Protocols (DoH)", () => {
|
|
56
29
|
const config = {
|
|
57
|
-
port:
|
|
58
|
-
|
|
59
|
-
dohPort: dohPort,
|
|
60
|
-
tls: {
|
|
61
|
-
key: privateKey,
|
|
62
|
-
cert: privateKey // Will throw on deep verification, fine for structural boundary tests
|
|
63
|
-
},
|
|
64
|
-
hosts: {
|
|
65
|
-
"secure.loop": { records: [{ type: "A", address: "10.0.0.1" }] }
|
|
66
|
-
}
|
|
30
|
+
port: 53,
|
|
31
|
+
hosts: {}
|
|
67
32
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
33
|
+
const server = new DevDnsServer(config);
|
|
34
|
+
const handler = new DnsHandler(server, config);
|
|
35
|
+
it("rejects DoH request on invalid path", async () => {
|
|
36
|
+
const { req, res, getStatus } = createMockReqRes("GET", "/invalid-path");
|
|
37
|
+
// @ts-ignore - Accessing private method for strict L7 unit testing
|
|
38
|
+
await handler.handleDohRequest(req, res);
|
|
39
|
+
assert.strictEqual(getStatus(), 404);
|
|
40
|
+
});
|
|
41
|
+
it("rejects DoH GET request missing dns query parameter", async () => {
|
|
42
|
+
const { req, res, getStatus } = createMockReqRes("GET", "/dns-query");
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
await handler.handleDohRequest(req, res);
|
|
45
|
+
assert.strictEqual(getStatus(), 400);
|
|
46
|
+
});
|
|
47
|
+
it("rejects DoH GET request with invalid base64url payload", async () => {
|
|
48
|
+
const { req, res, getStatus } = createMockReqRes("GET", "/dns-query?dns=!!!invalid_base64!!!");
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
await handler.handleDohRequest(req, res);
|
|
51
|
+
assert.strictEqual(getStatus(), 400);
|
|
52
|
+
});
|
|
53
|
+
it("rejects DoH POST request with invalid content-type", async () => {
|
|
54
|
+
const { req, res, getStatus } = createMockReqRes("POST", "/dns-query", {
|
|
55
|
+
"content-type": "application/json"
|
|
56
|
+
});
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
await handler.handleDohRequest(req, res);
|
|
59
|
+
assert.strictEqual(getStatus(), 415);
|
|
80
60
|
});
|
|
81
|
-
it("rejects
|
|
82
|
-
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
61
|
+
it("rejects unsupported HTTP methods", async () => {
|
|
62
|
+
const { req, res, getStatus } = createMockReqRes("PUT", "/dns-query");
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
await handler.handleDohRequest(req, res);
|
|
65
|
+
assert.strictEqual(getStatus(), 405);
|
|
66
|
+
});
|
|
67
|
+
it("rejects payloads that are too short to be valid DNS packets", async () => {
|
|
68
|
+
const { req, res, getStatus } = createMockReqRes("GET", "/dns-query?dns=abcd");
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
await handler.handleDohRequest(req, res);
|
|
71
|
+
assert.strictEqual(getStatus(), 400);
|
|
72
|
+
});
|
|
73
|
+
it("enforces memory bounds on DoH POST payloads to prevent exhaustion", async () => {
|
|
74
|
+
const { req, res, getStatus } = createMockReqRes("POST", "/dns-query", {
|
|
75
|
+
"content-type": "application/dns-message"
|
|
76
|
+
});
|
|
77
|
+
const oversizedBuffer = Buffer.alloc(65 * 1024); // Exceeds MAX_TCP_BUFFER_SIZE (64KB)
|
|
78
|
+
req[Symbol.asyncIterator] = async function* () {
|
|
79
|
+
yield oversizedBuffer;
|
|
91
80
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
await handler.handleDohRequest(req, res);
|
|
83
|
+
assert.strictEqual(getStatus(), 413);
|
|
84
|
+
});
|
|
85
|
+
it("processes a structurally valid DoH POST request", async () => {
|
|
86
|
+
const { req, res, getStatus, getHeaders } = createMockReqRes("POST", "/dns-query", {
|
|
87
|
+
"content-type": "application/dns-message"
|
|
88
|
+
});
|
|
89
|
+
// Create a minimal 12-byte valid DNS header
|
|
90
|
+
const validDnsHeader = Buffer.alloc(12);
|
|
91
|
+
validDnsHeader.writeUInt16BE(0x1234, 0); // ID
|
|
92
|
+
validDnsHeader.writeUInt16BE(0x0100, 2); // Flags (Standard Query)
|
|
93
|
+
validDnsHeader.writeUInt16BE(0x0000, 4); // QDCOUNT
|
|
94
|
+
req[Symbol.asyncIterator] = async function* () {
|
|
95
|
+
yield validDnsHeader;
|
|
96
96
|
};
|
|
97
|
-
// @ts-ignore
|
|
98
|
-
await handler.handleDohRequest(
|
|
99
|
-
assert.strictEqual(
|
|
97
|
+
// @ts-ignore
|
|
98
|
+
await handler.handleDohRequest(req, res);
|
|
99
|
+
assert.strictEqual(getStatus(), 200);
|
|
100
|
+
const headers = getHeaders();
|
|
101
|
+
assert.strictEqual(headers["Content-Type"], "application/dns-message");
|
|
102
|
+
assert.strictEqual(headers["Cache-Control"], "max-age=0");
|
|
100
103
|
});
|
|
101
104
|
});
|
package/dist/firewall.js
CHANGED
package/dist/http-handler.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as http from "http";
|
|
2
|
-
import * as https from "https";
|
|
3
|
-
import * as net from "net";
|
|
4
|
-
import * as dns from "dns/promises";
|
|
1
|
+
import * as http from "node:http";
|
|
2
|
+
import * as https from "node:https";
|
|
3
|
+
import * as net from "node:net";
|
|
4
|
+
import * as dns from "node:dns/promises";
|
|
5
5
|
import { HttpProxyService } from "./http-proxy.js";
|
|
6
6
|
import { audit } from "./audit.js";
|
|
7
7
|
import { firewallEngine } from "./firewall.js";
|
package/dist/http-proxy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as net from "net";
|
|
2
|
-
import * as dns from "dns/promises";
|
|
1
|
+
import * as net from "node:net";
|
|
2
|
+
import * as dns from "node:dns/promises";
|
|
3
3
|
import { firewallEngine } from "./firewall.js";
|
|
4
4
|
export class HttpProxyService {
|
|
5
5
|
async validateTargetFirewall(targetUrl, fw) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
|
-
import assert from "assert";
|
|
3
|
-
import * as net from "net";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import * as net from "node:net";
|
|
4
4
|
let PORT_BASE = 65000;
|
|
5
5
|
function nextPort() { return PORT_BASE++; }
|
|
6
6
|
describe("TCP Rate Limiting", () => {
|
package/dist/schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import * as net from "net";
|
|
2
|
+
import * as net from "node:net";
|
|
3
3
|
const CrlfFreeString = z.string().max(8192).refine((val) => !/[\r\n]/.test(val), "Contains CR/LF");
|
|
4
4
|
const Ipv4Schema = z.string().max(45).refine((ip) => net.isIPv4(ip), "Invalid IPv4");
|
|
5
5
|
const Ipv6Schema = z.string().max(45).refine((ip) => net.isIPv6(ip), "Invalid IPv6");
|
package/dist/srv-record.test.js
CHANGED