diff --git a/packages/identity/src/handle/index.ts b/packages/identity/src/handle/index.ts index fa9c016cd99..8780437efa7 100644 --- a/packages/identity/src/handle/index.ts +++ b/packages/identity/src/handle/index.ts @@ -6,9 +6,12 @@ const PREFIX = 'did=' export class HandleResolver { public timeout: number + private backupNameservers: string[] | undefined + private backupNameserverIps: string[] | undefined constructor(opts: HandleResolverOpts = {}) { this.timeout = opts.timeout ?? 3000 + this.backupNameservers = opts.backupNameservers } async resolve(handle: string): Promise { @@ -23,7 +26,11 @@ export class HandleResolver { httpAbort.abort() return dnsRes } - return httpPromise + const res = await httpPromise + if (res) { + return res + } + return this.resolveDnsBackup(handle) } async resolveDns(handle: string): Promise { @@ -33,12 +40,7 @@ export class HandleResolver { } catch (err) { return undefined } - const results = chunkedResults.map((chunks) => chunks.join('')) - const found = results.filter((i) => i.startsWith(PREFIX)) - if (found.length !== 1) { - return undefined - } - return found[0].slice(PREFIX.length) + return this.parseDnsResult(chunkedResults) } async resolveHttp( @@ -57,4 +59,44 @@ export class HandleResolver { return undefined } } + + async resolveDnsBackup(handle: string): Promise { + let chunkedResults: string[][] + try { + const backupIps = await this.getBackupNameserverIps() + if (!backupIps || backupIps.length < 1) return undefined + const resolver = new dns.Resolver() + resolver.setServers(backupIps) + chunkedResults = await resolver.resolveTxt(`${SUBDOMAIN}.${handle}`) + } catch (err) { + return undefined + } + return this.parseDnsResult(chunkedResults) + } + + parseDnsResult(chunkedResults: string[][]): string | undefined { + const results = chunkedResults.map((chunks) => chunks.join('')) + const found = results.filter((i) => i.startsWith(PREFIX)) + if (found.length !== 1) { + return undefined + } + return found[0].slice(PREFIX.length) + } + + private async getBackupNameserverIps(): Promise { + if (!this.backupNameservers) { + return undefined + } else if (!this.backupNameserverIps) { + const responses = await Promise.allSettled( + this.backupNameservers.map((h) => dns.lookup(h)), + ) + for (const res of responses) { + if (res.status === 'fulfilled') { + this.backupNameserverIps ??= [] + this.backupNameserverIps.push(res.value.address) + } + } + } + return this.backupNameserverIps + } } diff --git a/packages/identity/src/types.ts b/packages/identity/src/types.ts index fdb1857f3b5..f1d983e6742 100644 --- a/packages/identity/src/types.ts +++ b/packages/identity/src/types.ts @@ -4,10 +4,12 @@ export type IdentityResolverOpts = { timeout?: number plcUrl?: string didCache?: DidCache + backupNameservers?: string[] } export type HandleResolverOpts = { timeout?: number + backupNameservers?: string[] } export type DidResolverOpts = { diff --git a/packages/pds/src/config.ts b/packages/pds/src/config.ts index b860cb75908..282f7929a10 100644 --- a/packages/pds/src/config.ts +++ b/packages/pds/src/config.ts @@ -35,6 +35,7 @@ export interface ServerConfigValues { databaseLocation?: string availableUserDomains: string[] + handleResolveNameservers?: string[] imgUriSalt: string imgUriKey: string @@ -136,6 +137,10 @@ export class ServerConfig { ? process.env.AVAILABLE_USER_DOMAINS.split(',') : [] + const handleResolveNameservers = process.env.HANDLE_RESOLVE_NAMESERVERS + ? process.env.HANDLE_RESOLVE_NAMESERVERS.split(',') + : [] + const imgUriSalt = process.env.IMG_URI_SALT || '9dd04221f5755bce5f55f47464c27e1e' const imgUriKey = @@ -215,6 +220,7 @@ export class ServerConfig { termsOfServiceUrl, databaseLocation, availableUserDomains, + handleResolveNameservers, imgUriSalt, imgUriKey, imgUriEndpoint, @@ -368,6 +374,10 @@ export class ServerConfig { return this.cfg.availableUserDomains } + get handleResolveNameservers() { + return this.cfg.handleResolveNameservers + } + get imgUriSalt() { return this.cfg.imgUriSalt } diff --git a/packages/pds/src/index.ts b/packages/pds/src/index.ts index a56fa893930..f77b654a069 100644 --- a/packages/pds/src/index.ts +++ b/packages/pds/src/index.ts @@ -96,7 +96,11 @@ export class PDS { config.didCacheStaleTTL, config.didCacheMaxTTL, ) - const idResolver = new IdResolver({ plcUrl: config.didPlcUrl, didCache }) + const idResolver = new IdResolver({ + plcUrl: config.didPlcUrl, + didCache, + backupNameservers: config.handleResolveNameservers, + }) const messageDispatcher = new MessageDispatcher() const sequencer = new Sequencer(db)