fix(dns): register separate handlers for each DNS record to serve multiple records

The previous implementation grouped records by domain and only returned the first
matching record. This prevented serving multiple NS records for a domain, which
caused GoDaddy to reject the nameservers.

Changes:
- Modified registerDnsRecords to register a separate handler for each record
- This works around smartdns limitation where it breaks after first handler match
- Now all NS records are properly served in DNS responses
- Added readme.smartdns.md documenting the underlying issue in smartdns module

The root cause is in smartdns DnsServer which breaks after finding the first
matching handler, preventing multiple records of the same type from being served.
This commit is contained in:
2025-05-30 16:44:10 +00:00
parent ae73de19b2
commit 71183b35c0
2 changed files with 138 additions and 25 deletions

View File

@ -693,40 +693,27 @@ export class DcRouter {
private registerDnsRecords(records: Array<{name: string; type: string; value: string; ttl?: number}>): void {
if (!this.dnsServer) return;
// Group records by domain pattern
const recordsByDomain = new Map<string, typeof records>();
// Register a separate handler for each record
// This ensures multiple records of the same type (like NS records) are all served
for (const record of records) {
// Use exact domain name for registration - no automatic wildcard prefix
const pattern = record.name;
if (!recordsByDomain.has(pattern)) {
recordsByDomain.set(pattern, []);
}
recordsByDomain.get(pattern)!.push(record);
}
// Register handlers for each domain pattern
for (const [domainPattern, domainRecords] of recordsByDomain) {
const recordTypes = [...new Set(domainRecords.map(r => r.type))];
this.dnsServer.registerHandler(domainPattern, recordTypes, (question) => {
const matchingRecord = domainRecords.find(
r => r.name === question.name && r.type === question.type
);
if (matchingRecord) {
// Register handler for this specific record
this.dnsServer.registerHandler(record.name, [record.type], (question) => {
// Check if this handler matches the question
if (question.name === record.name && question.type === record.type) {
return {
name: matchingRecord.name,
type: matchingRecord.type,
name: record.name,
type: record.type,
class: 'IN',
ttl: matchingRecord.ttl || 300,
data: this.parseDnsRecordData(matchingRecord.type, matchingRecord.value)
ttl: record.ttl || 300,
data: this.parseDnsRecordData(record.type, record.value)
};
}
return null;
});
}
logger.log('info', `Registered ${records.length} DNS handlers (one per record)`);
}
/**