Standalone dns server

This commit is contained in:
Owen
2026-10-28 15:41:31 -04:00
parent 0be847ce9e
commit 3dd46e48ec
5 changed files with 193 additions and 10 deletions
+19 -8
View File
@@ -36,7 +36,7 @@ import {
import { privateConfig as config } from "#private/lib/config";
import * as dnsResolver from "dns";
import logger from "@server/logger";
import { listExitNodes } from "../exitNodes";
import { listExitNodesAcrossRegions } from "../exitNodes/exitNodes";
import { parseCustomDnsRecordValues } from "@server/routers/customDnsRecord/types";
import {
matchCustomRecords,
@@ -44,7 +44,6 @@ import {
type CustomZoneRecord
} from "./customRecordMatch";
import { rateLimitService } from "../rateLimit";
import license from "#private/license/license";
type DNSRecord = {
id: number;
@@ -89,6 +88,7 @@ export class AuthoritativeDNSServer {
// set refresh and read from memory here.
private isLicensed: boolean = false;
private licenseRefreshInterval: NodeJS.Timeout | null = null;
private requireLicense: boolean;
// Cache for per-queryName zone resolution and SOA records
private authoritativeDomainCache: LocalCache = createLocalCache(
@@ -100,8 +100,9 @@ export class AuthoritativeDNSServer {
DNS_CACHE_TTL_SECONDS
);
constructor(port: number) {
constructor(port: number, options: { requireLicense?: boolean } = {}) {
this.port = port;
this.requireLicense = options.requireLicense ?? true;
this.server = dgram.createSocket("udp4");
this.setupServer();
@@ -965,7 +966,7 @@ export class AuthoritativeDNSServer {
queryType: dns.RecordType
): Promise<DNSRecord[] | null> {
// TODO: EVENTUALLY WE SHOULD PICK THE CLOSEST EXIT NODE TO THE USER BASED ON LATENCY
const exitNodesList = await listExitNodes(orgId, true);
const exitNodesList = await listExitNodesAcrossRegions(orgId, true);
if (!exitNodesList || exitNodesList.length === 0) {
logger.warn(`No exit nodes found for orgId: ${orgId}`);
@@ -1549,6 +1550,12 @@ export class AuthoritativeDNSServer {
private async refreshLicenseStatus(): Promise<void> {
try {
// Imported lazily so the standalone DNS server, which runs
// without a license, never loads the license module (it touches
// the database and starts phoning home as soon as it is imported)
const { default: license } = await import(
"#private/license/license"
);
this.isLicensed = await license.hasTier([
"personal",
"tier2",
@@ -1568,10 +1575,14 @@ export class AuthoritativeDNSServer {
);
}, 60_000);
await this.refreshLicenseStatus();
this.licenseRefreshInterval = setInterval(() => {
this.refreshLicenseStatus();
}, 60_000);
if (this.requireLicense) {
await this.refreshLicenseStatus();
this.licenseRefreshInterval = setInterval(() => {
this.refreshLicenseStatus();
}, 60_000);
} else {
this.isLicensed = true;
}
return new Promise((resolve, reject) => {
this.server.bind(this.port, (err?: Error) => {