fix(nameservers): fix ip records

This commit is contained in:
Philipp Kunz 2025-05-30 20:11:44 +00:00
parent 74692c4aa5
commit c776dab2c0
4 changed files with 82 additions and 26 deletions

View File

@ -36,6 +36,7 @@
"@push.rocks/smartfile": "^11.2.5",
"@push.rocks/smartlog": "^3.1.8",
"@push.rocks/smartmail": "^2.1.0",
"@push.rocks/smartnetwork": "^4.0.2",
"@push.rocks/smartpath": "^5.0.5",
"@push.rocks/smartpromise": "^4.0.3",
"@push.rocks/smartproxy": "^19.5.4",

13
pnpm-lock.yaml generated
View File

@ -44,6 +44,9 @@ importers:
'@push.rocks/smartmail':
specifier: ^2.1.0
version: 2.1.0
'@push.rocks/smartnetwork':
specifier: ^4.0.2
version: 4.0.2
'@push.rocks/smartpath':
specifier: ^5.0.5
version: 5.0.18
@ -3800,12 +3803,6 @@ packages:
symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
systeminformation@5.25.11:
resolution: {integrity: sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==}
engines: {node: '>=8.0.0'}
os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android]
hasBin: true
systeminformation@5.27.1:
resolution: {integrity: sha512-FgkVpT6GgATtNvADgtEzDxI/SVaBisfnQ4fmgQZhCJ4335noTgt9q6O81ioHwzs9HgnJaaFSdHSEMIkneZ55iA==}
engines: {node: '>=8.0.0'}
@ -5777,7 +5774,7 @@ snapshots:
'@types/default-gateway': 7.2.2
isopen: 1.3.0
public-ip: 7.0.1
systeminformation: 5.25.11
systeminformation: 5.27.1
'@push.rocks/smartnpm@2.0.4':
dependencies:
@ -9530,8 +9527,6 @@ snapshots:
symbol-tree@3.2.4: {}
systeminformation@5.25.11: {}
systeminformation@5.27.1: {}
tar-fs@3.0.9:

View File

@ -54,14 +54,14 @@ export interface IDcRouterOptions {
};
/**
* The nameserver domains (e.g., ['gatewaymain.lossless.directory', 'gatewaymain2.lossless.directory'])
* These must have A records pointing to your server's IP
* The nameserver domains (e.g., ['ns1.example.com', 'ns2.example.com'])
* These will automatically get A records pointing to publicIp or proxyIps[0]
* These are what go in the NS records for ALL domains in dnsScopes
*/
dnsNsDomains?: string[];
/**
* Domains this DNS server is authoritative for (e.g., ['bleu.de', 'mail.social.io'])
* Domains this DNS server is authoritative for (e.g., ['example.com', 'mail.example.org'])
* NS records will be auto-generated for these domains
* Any DNS record outside these scopes will trigger a warning
* Email domains with `internal-dns` mode must be included here
@ -76,6 +76,13 @@ export interface IDcRouterOptions {
*/
proxyIps?: string[];
/**
* Public IP address for nameserver A records (required if proxyIps not set)
* This is the IP that will be used for the nameserver domains (dnsNsDomains)
* If proxyIps is set, the first proxy IP will be used instead
*/
publicIp?: string;
/**
* DNS records to register
* Must be within the defined dnsScopes (or receive warning)
@ -814,7 +821,7 @@ export class DcRouter {
}
// Apply proxy IP replacement if configured
this.applyProxyIpReplacement(allRecords);
await this.applyProxyIpReplacement(allRecords);
// Register all DNS records
if (allRecords.length > 0) {
@ -948,6 +955,52 @@ export class DcRouter {
return records;
}
// Determine the public IP for nameserver A records
let publicIp: string | null = null;
// Use proxy IPs if configured (these should be public IPs)
if (this.options.proxyIps && this.options.proxyIps.length > 0) {
publicIp = this.options.proxyIps[0]; // Use first proxy IP
logger.log('info', `Using proxy IP for nameserver A records: ${publicIp}`);
} else if (this.options.publicIp) {
// Use explicitly configured public IP
publicIp = this.options.publicIp;
logger.log('info', `Using configured public IP for nameserver A records: ${publicIp}`);
} else {
// Auto-discover public IP using smartnetwork
try {
logger.log('info', 'Auto-discovering public IP address...');
const smartNetwork = new plugins.smartnetwork.SmartNetwork();
const publicIps = await smartNetwork.getPublicIps();
if (publicIps.v4) {
publicIp = publicIps.v4;
logger.log('info', `Auto-discovered public IPv4: ${publicIp}`);
} else {
logger.log('warn', 'Could not auto-discover public IPv4 address');
}
} catch (error) {
logger.log('error', `Failed to auto-discover public IP: ${error.message}`);
}
if (!publicIp) {
logger.log('warn', 'No public IP available. Nameserver A records require either proxyIps, publicIp, or successful auto-discovery.');
}
}
// Generate A records for nameservers if we have a public IP
if (publicIp) {
for (const nsDomain of this.options.dnsNsDomains) {
records.push({
name: nsDomain,
type: 'A',
value: publicIp,
ttl: 3600
});
}
logger.log('info', `Generated A records for ${this.options.dnsNsDomains.length} nameservers`);
}
// Generate NS records for each domain in scopes
for (const domain of this.options.dnsScopes) {
// Add NS records for all nameservers
@ -964,7 +1017,7 @@ export class DcRouter {
// with the primaryNameserver configuration option
}
logger.log('info', `Generated ${records.length} NS records for ${this.options.dnsScopes.length} domains`);
logger.log('info', `Generated ${records.length} total records (A + NS) for ${this.options.dnsScopes.length} domains`);
return records;
}
@ -982,14 +1035,13 @@ export class DcRouter {
/**
* Apply proxy IP replacement logic to DNS records
*/
private applyProxyIpReplacement(records: Array<{name: string; type: string; value: string; ttl?: number; useIngressProxy?: boolean}>): void {
private async applyProxyIpReplacement(records: Array<{name: string; type: string; value: string; ttl?: number; useIngressProxy?: boolean}>): Promise<void> {
if (!this.options.proxyIps || this.options.proxyIps.length === 0) {
return; // No proxy IPs configured, skip replacement
}
// Get server's public IP (for now, we'll use a placeholder - in production this would be detected)
// This would normally be detected from network interfaces or external service
const serverIp = this.detectServerPublicIp();
// Get server's public IP
const serverIp = await this.detectServerPublicIp();
if (!serverIp) {
logger.log('warn', 'Could not detect server public IP, skipping proxy IP replacement');
return;
@ -1014,13 +1066,20 @@ export class DcRouter {
/**
* Detect the server's public IP address
*/
private detectServerPublicIp(): string | null {
// In a real implementation, this would:
// 1. Check network interfaces for public IPs
// 2. Or make a request to an external service to get public IP
// For now, return null to skip proxy replacement
// TODO: Implement proper public IP detection
return null;
private async detectServerPublicIp(): Promise<string | null> {
try {
const smartNetwork = new plugins.smartnetwork.SmartNetwork();
const publicIps = await smartNetwork.getPublicIps();
if (publicIps.v4) {
return publicIps.v4;
}
return null;
} catch (error) {
logger.log('warn', `Failed to detect public IP: ${error.message}`);
return null;
}
}
/**

View File

@ -48,6 +48,7 @@ import * as smartdns from '@push.rocks/smartdns';
import * as smartfile from '@push.rocks/smartfile';
import * as smartlog from '@push.rocks/smartlog';
import * as smartmail from '@push.rocks/smartmail';
import * as smartnetwork from '@push.rocks/smartnetwork';
import * as smartpath from '@push.rocks/smartpath';
import * as smartproxy from '@push.rocks/smartproxy';
import * as smartpromise from '@push.rocks/smartpromise';
@ -55,7 +56,7 @@ import * as smartrequest from '@push.rocks/smartrequest';
import * as smartrule from '@push.rocks/smartrule';
import * as smartrx from '@push.rocks/smartrx';
export { projectinfo, qenv, smartacme, smartdata, smartdns, smartfile, smartlog, smartmail, smartpath, smartproxy, smartpromise, smartrequest, smartrule, smartrx };
export { projectinfo, qenv, smartacme, smartdata, smartdns, smartfile, smartlog, smartmail, smartnetwork, smartpath, smartproxy, smartpromise, smartrequest, smartrule, smartrx };
// Define SmartLog types for use in error handling
export type TLogLevel = 'error' | 'warn' | 'info' | 'success' | 'debug';