@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
package/dist/schema.js ADDED
@@ -0,0 +1,124 @@
1
+ import { z } from "zod";
2
+ import * as net from "net";
3
+ const CrlfFreeString = z.string().refine((val) => !/[\r\n]/.test(val), "Contains CR/LF");
4
+ const Ipv4Schema = z.string().refine((ip) => net.isIPv4(ip), "Invalid IPv4");
5
+ const Ipv6Schema = z.string().refine((ip) => net.isIPv6(ip), "Invalid IPv6");
6
+ const HostnameSchema = z.string().max(253).refine((hostname) => {
7
+ const parts = hostname.split(".");
8
+ const hostPattern = /^[a-zA-Z0-9_]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?$/;
9
+ return parts.every((part) => part.length > 0 && part.length <= 63 && hostPattern.test(part));
10
+ }, "Invalid hostname");
11
+ const PortSchema = z.number().int().min(1).max(65535);
12
+ const ARecordSchema = z.object({ type: z.literal("A"), address: Ipv4Schema });
13
+ const AAAARecordSchema = z.object({ type: z.literal("AAAA"), address: Ipv6Schema });
14
+ const CNAMERecordSchema = z.object({ type: z.literal("CNAME"), target: HostnameSchema });
15
+ const TXTRecordSchema = z.object({ type: z.literal("TXT"), data: z.array(z.string().max(255).refine((val) => !/[\r\n]/.test(val), "Contains CR/LF")) });
16
+ const MXRecordSchema = z.object({ type: z.literal("MX"), priority: z.number().int().min(0).max(65535), exchange: HostnameSchema });
17
+ const NSRecordSchema = z.object({ type: z.literal("NS"), target: HostnameSchema });
18
+ const SRVRecordSchema = z.object({ type: z.literal("SRV"), priority: z.number().int().min(0).max(65535), weight: z.number().int().min(0).max(65535), port: PortSchema, target: HostnameSchema });
19
+ const PTRRecordSchema = z.object({ type: z.literal("PTR"), target: HostnameSchema });
20
+ const DnsRecordSchema = z.discriminatedUnion("type", [
21
+ ARecordSchema,
22
+ AAAARecordSchema,
23
+ CNAMERecordSchema,
24
+ TXTRecordSchema,
25
+ MXRecordSchema,
26
+ NSRecordSchema,
27
+ SRVRecordSchema,
28
+ PTRRecordSchema,
29
+ ]);
30
+ const HttpProxySchema = z.object({
31
+ enabled: z.boolean(),
32
+ upstream: CrlfFreeString.optional(),
33
+ headers: z.record(z.string().regex(/^[a-zA-Z0-9\-]+$/), CrlfFreeString).default({}),
34
+ forwardRequestBody: z.boolean().default(false),
35
+ maxRequestBodyBytes: z.number().int().min(0).max(10485760).default(5242880),
36
+ }).refine(data => !data.enabled || !!data.upstream, {
37
+ message: "HTTP proxy requires 'upstream' URL when enabled",
38
+ path: ["upstream"]
39
+ });
40
+ const RedirectSchema = z.object({
41
+ enabled: z.boolean().default(true),
42
+ code: z.union([z.literal(301), z.literal(302), z.literal(303), z.literal(307), z.literal(308)]),
43
+ target: CrlfFreeString,
44
+ });
45
+ const HostConfigSchema = z.object({
46
+ records: z.array(DnsRecordSchema).default([]),
47
+ http_proxy: HttpProxySchema.optional(),
48
+ redirect: RedirectSchema.optional(),
49
+ });
50
+ const FirewallSchema = z.object({
51
+ defaultPolicy: z.enum(["allow", "deny"]).default("deny"),
52
+ allowlist_domains: z.array(z.string().max(253)).default([]),
53
+ blocklist_domains: z.array(z.string().max(253)).default([]),
54
+ allowlist_ranges: z.array(z.string().max(40)).default([]),
55
+ blocklist_ranges: z.array(z.string().max(40)).default([]),
56
+ allowlist_ips: z.array(z.string().max(40)).default([]),
57
+ blocklist_ips: z.array(z.string().max(40)).default([]),
58
+ });
59
+ const ControlPlaneSchema = z.object({
60
+ enabled: z.boolean().default(true).optional(),
61
+ port: z.coerce.number().int().min(1).max(65535).default(8080).optional(),
62
+ apiKey: z.string().optional()
63
+ });
64
+ const ServerConfigSchema = z.object({
65
+ port: z.coerce.number().int().min(1).max(65535).default(53),
66
+ fallbackDns: Ipv4Schema.optional(),
67
+ firewall: FirewallSchema.optional(),
68
+ controlPlane: ControlPlaneSchema.optional(),
69
+ dnsCacheMaxSize: z.coerce.number().int().min(1).max(100000).default(1024),
70
+ dnsCacheTtlMs: z.coerce.number().int().min(0).max(3600000).default(0),
71
+ maxTcpConnections: z.coerce.number().int().min(1).max(10000).default(100),
72
+ tcpIdleTimeoutMs: z.coerce.number().int().min(1000).max(600000).default(30000),
73
+ rateLimitMaxRequests: z.coerce.number().int().min(0).max(100000).default(0),
74
+ rateLimitWindowMs: z.coerce.number().int().min(100).max(60000).default(1000),
75
+ hosts: z.record(z.string(), HostConfigSchema).default({}),
76
+ }).refine(data => {
77
+ for (const key of Object.keys(data.hosts)) {
78
+ const normalized = key.toLowerCase();
79
+ if (normalized === "*")
80
+ continue;
81
+ if (normalized.startsWith("*.")) {
82
+ HostnameSchema.parse(normalized.slice(2));
83
+ }
84
+ else {
85
+ HostnameSchema.parse(normalized);
86
+ }
87
+ }
88
+ return true;
89
+ }, "Contains invalid hostnames in configuration keys");
90
+ export function validateARecord(record) { return ARecordSchema.parse(record); }
91
+ export function validateAAAARecord(record) { return AAAARecordSchema.parse(record); }
92
+ export function validateCNAME(record) { return CNAMERecordSchema.parse(record); }
93
+ export function validateTXT(record) { return TXTRecordSchema.parse(record); }
94
+ export function validateMX(record) { return MXRecordSchema.parse(record); }
95
+ export function validateNS(record) { return NSRecordSchema.parse(record); }
96
+ export function validateSRV(record) { return SRVRecordSchema.parse(record); }
97
+ export function validatePTR(record) { return PTRRecordSchema.parse(record); }
98
+ export function validateRecord(record) {
99
+ if (!record || typeof record !== "object" || !("type" in record)) {
100
+ throw new Error("DNS record must be an object with a 'type' field");
101
+ }
102
+ return DnsRecordSchema.parse(record);
103
+ }
104
+ export function validateHostConfig(config) {
105
+ try {
106
+ return HostConfigSchema.parse(config);
107
+ }
108
+ catch (error) {
109
+ throw new Error(`Host validation error: ${error}`);
110
+ }
111
+ }
112
+ export function validateServerConfig(config) {
113
+ try {
114
+ const parsed = ServerConfigSchema.parse(config);
115
+ const lowercaseHosts = {};
116
+ for (const [key, value] of Object.entries(parsed.hosts)) {
117
+ lowercaseHosts[key.toLowerCase()] = value;
118
+ }
119
+ return { ...parsed, hosts: lowercaseHosts };
120
+ }
121
+ catch (error) {
122
+ throw new Error(`Configuration validation error: ${error}`);
123
+ }
124
+ }
@@ -0,0 +1 @@
1
+ export {};