mirror of
https://github.com/fosrl/pangolin.git
synced 2026-09-11 21:41:41 +02:00
Add dns server
This commit is contained in:
Generated
+30
@@ -61,6 +61,7 @@
|
|||||||
"cors": "2.8.6",
|
"cors": "2.8.6",
|
||||||
"crypto-js": "4.2.0",
|
"crypto-js": "4.2.0",
|
||||||
"d3": "7.9.0",
|
"d3": "7.9.0",
|
||||||
|
"dns-packet": "^5.6.1",
|
||||||
"drizzle-orm": "0.45.2",
|
"drizzle-orm": "0.45.2",
|
||||||
"express": "5.2.1",
|
"express": "5.2.1",
|
||||||
"express-rate-limit": "8.7.0",
|
"express-rate-limit": "8.7.0",
|
||||||
@@ -124,6 +125,7 @@
|
|||||||
"@types/cors": "2.8.19",
|
"@types/cors": "2.8.19",
|
||||||
"@types/crypto-js": "4.2.2",
|
"@types/crypto-js": "4.2.2",
|
||||||
"@types/d3": "7.4.3",
|
"@types/d3": "7.4.3",
|
||||||
|
"@types/dns-packet": "^5.6.5",
|
||||||
"@types/express": "5.0.6",
|
"@types/express": "5.0.6",
|
||||||
"@types/express-session": "1.19.0",
|
"@types/express-session": "1.19.0",
|
||||||
"@types/jmespath": "0.15.2",
|
"@types/jmespath": "0.15.2",
|
||||||
@@ -2445,6 +2447,12 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@leichtgewicht/ip-codec": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@levischuck/tiny-cbor": {
|
"node_modules/@levischuck/tiny-cbor": {
|
||||||
"version": "0.2.11",
|
"version": "0.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz",
|
||||||
@@ -6764,6 +6772,16 @@
|
|||||||
"@types/d3-selection": "*"
|
"@types/d3-selection": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/dns-packet": {
|
||||||
|
"version": "5.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.6.5.tgz",
|
||||||
|
"integrity": "sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/esrecurse": {
|
"node_modules/@types/esrecurse": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
|
||||||
@@ -9261,6 +9279,18 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dns-packet": {
|
||||||
|
"version": "5.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
|
||||||
|
"integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@leichtgewicht/ip-codec": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/doctrine": {
|
"node_modules/doctrine": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
||||||
|
|||||||
@@ -84,6 +84,7 @@
|
|||||||
"cors": "2.8.6",
|
"cors": "2.8.6",
|
||||||
"crypto-js": "4.2.0",
|
"crypto-js": "4.2.0",
|
||||||
"d3": "7.9.0",
|
"d3": "7.9.0",
|
||||||
|
"dns-packet": "^5.6.1",
|
||||||
"drizzle-orm": "0.45.2",
|
"drizzle-orm": "0.45.2",
|
||||||
"express": "5.2.1",
|
"express": "5.2.1",
|
||||||
"express-rate-limit": "8.7.0",
|
"express-rate-limit": "8.7.0",
|
||||||
@@ -147,6 +148,7 @@
|
|||||||
"@types/cors": "2.8.19",
|
"@types/cors": "2.8.19",
|
||||||
"@types/crypto-js": "4.2.2",
|
"@types/crypto-js": "4.2.2",
|
||||||
"@types/d3": "7.4.3",
|
"@types/d3": "7.4.3",
|
||||||
|
"@types/dns-packet": "^5.6.5",
|
||||||
"@types/express": "5.0.6",
|
"@types/express": "5.0.6",
|
||||||
"@types/express-session": "1.19.0",
|
"@types/express-session": "1.19.0",
|
||||||
"@types/jmespath": "0.15.2",
|
"@types/jmespath": "0.15.2",
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export async function startDnsServer() {
|
||||||
|
// No-op: the authoritative DNS server is only available in builds
|
||||||
|
// that include the private/enterprise feature set.
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function stopDnsServer() {
|
||||||
|
// No-op counterpart to startDnsServer.
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ import { setHostMeta } from "@server/lib/hostMeta";
|
|||||||
import { TraefikConfigManager } from "@server/lib/traefik/TraefikConfigManager";
|
import { TraefikConfigManager } from "@server/lib/traefik/TraefikConfigManager";
|
||||||
import { initCleanup } from "#dynamic/cleanup";
|
import { initCleanup } from "#dynamic/cleanup";
|
||||||
import { startSchedulers } from "#dynamic/startSchedulers";
|
import { startSchedulers } from "#dynamic/startSchedulers";
|
||||||
|
import { startDnsServer } from "#dynamic/dns";
|
||||||
import license from "#dynamic/license/license";
|
import license from "#dynamic/license/license";
|
||||||
import { fetchServerIp } from "@server/lib/serverIpService";
|
import { fetchServerIp } from "@server/lib/serverIpService";
|
||||||
import { initAiModelCatalog } from "@server/lib/aiModelCatalog";
|
import { initAiModelCatalog } from "@server/lib/aiModelCatalog";
|
||||||
@@ -45,6 +46,8 @@ async function startServers() {
|
|||||||
|
|
||||||
startSchedulers();
|
startSchedulers();
|
||||||
|
|
||||||
|
await startDnsServer();
|
||||||
|
|
||||||
// Start all servers
|
// Start all servers
|
||||||
const apiServer = createApiServer();
|
const apiServer = createApiServer();
|
||||||
const internalServer = createInternalServer();
|
const internalServer = createInternalServer();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { flushSiteBandwidthToDb } from "@server/routers/gerbil/receiveBandwidth"
|
|||||||
import { stopPingAccumulator } from "@server/routers/newt/pingAccumulator";
|
import { stopPingAccumulator } from "@server/routers/newt/pingAccumulator";
|
||||||
import { shutdownUsageRecorder } from "@server/lib/aiBudgetEnforcement";
|
import { shutdownUsageRecorder } from "@server/lib/aiBudgetEnforcement";
|
||||||
import { shutdownAiSessionLogger } from "@server/routers/aiGateway/logAiSession";
|
import { shutdownAiSessionLogger } from "@server/routers/aiGateway/logAiSession";
|
||||||
|
import { stopDnsServer } from "./dns";
|
||||||
|
|
||||||
async function cleanup() {
|
async function cleanup() {
|
||||||
await stopPingAccumulator();
|
await stopPingAccumulator();
|
||||||
@@ -31,6 +32,7 @@ async function cleanup() {
|
|||||||
await rateLimitService.cleanup();
|
await rateLimitService.cleanup();
|
||||||
await wsCleanup();
|
await wsCleanup();
|
||||||
await logStreamingManager.shutdown();
|
await logStreamingManager.shutdown();
|
||||||
|
await stopDnsServer();
|
||||||
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of a proprietary work.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025-2026 Fossorial, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is licensed under the Fossorial Commercial License.
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
|
||||||
|
*
|
||||||
|
* This file is not licensed under the AGPLv3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { AuthoritativeDNSServer } from "#private/lib/dns";
|
||||||
|
import { privateConfig } from "#private/lib/config";
|
||||||
|
|
||||||
|
let dnsServer: AuthoritativeDNSServer | undefined;
|
||||||
|
|
||||||
|
export async function startDnsServer() {
|
||||||
|
const dnsConfig = privateConfig.getRawPrivateConfig().dns;
|
||||||
|
if (!dnsConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cacheOptions = {
|
||||||
|
stdTTL: 300, // 5 minutes default TTL
|
||||||
|
checkperiod: 60, // Check for expired keys every 60 seconds
|
||||||
|
useClones: false // Better performance
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create DNS server
|
||||||
|
dnsServer = new AuthoritativeDNSServer(
|
||||||
|
dnsConfig.listen_port,
|
||||||
|
cacheOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
await dnsServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function stopDnsServer() {
|
||||||
|
if (!dnsServer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await dnsServer.stop();
|
||||||
|
dnsServer = undefined;
|
||||||
|
}
|
||||||
@@ -152,6 +152,10 @@ export class PrivateConfig {
|
|||||||
return this.rawPrivateConfig;
|
return this.rawPrivateConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getRawConfig() {
|
||||||
|
return this.getRawPrivateConfig();
|
||||||
|
}
|
||||||
|
|
||||||
// `flags.enable_acme_cert_sync`, `flags.disable_private_http_placeholder`,
|
// `flags.enable_acme_cert_sync`, `flags.disable_private_http_placeholder`,
|
||||||
// and `acme` used to live in the private config file. They now live in
|
// and `acme` used to live in the private config file. They now live in
|
||||||
// the public config file. If an operator still has them set in the
|
// the public config file. If an operator still has them set in the
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./server";
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -95,6 +95,69 @@ export const privateConfigSchema = z
|
|||||||
.optional()
|
.optional()
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
dns: z
|
||||||
|
.object({
|
||||||
|
listen_port: z.number(),
|
||||||
|
nameserver_name: z.string(),
|
||||||
|
cname_extension: z.string(),
|
||||||
|
site_extension: z.string(),
|
||||||
|
cname_alternate_extensions: z
|
||||||
|
.array(z.string())
|
||||||
|
.optional()
|
||||||
|
.default([]),
|
||||||
|
alternate_nameservers: z
|
||||||
|
.array(z.string())
|
||||||
|
.optional()
|
||||||
|
.default([]),
|
||||||
|
rate_limit: z
|
||||||
|
.object({
|
||||||
|
enabled: z.boolean().optional().default(true),
|
||||||
|
window_ms: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.min(1000)
|
||||||
|
.max(600000)
|
||||||
|
.optional()
|
||||||
|
.default(60000),
|
||||||
|
max_requests: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.min(50)
|
||||||
|
.max(100000)
|
||||||
|
.optional()
|
||||||
|
.default(1200),
|
||||||
|
max_requests_per_query_type: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.min(10)
|
||||||
|
.max(50000)
|
||||||
|
.optional()
|
||||||
|
.default(600)
|
||||||
|
})
|
||||||
|
.default({
|
||||||
|
enabled: true,
|
||||||
|
window_ms: 60000,
|
||||||
|
max_requests: 1200,
|
||||||
|
max_requests_per_query_type: 600
|
||||||
|
}),
|
||||||
|
static_records: z
|
||||||
|
.array(
|
||||||
|
z.object({
|
||||||
|
domain: z.string(),
|
||||||
|
type: z.enum(["TXT", "CNAME", "A", "NS"]),
|
||||||
|
value: z.string(),
|
||||||
|
ttl: z
|
||||||
|
.number()
|
||||||
|
.int()
|
||||||
|
.positive()
|
||||||
|
.optional()
|
||||||
|
.default(300)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.optional()
|
||||||
|
.default([])
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
gerbil: z
|
gerbil: z
|
||||||
.object({
|
.object({
|
||||||
local_exit_node_reachable_at: z
|
local_exit_node_reachable_at: z
|
||||||
|
|||||||
Reference in New Issue
Block a user