| 1 | package node |
| 2 | |
| 3 | import ( |
| 4 | "math" |
| 5 | "time" |
| 6 | |
| 7 | "github.com/ipfs/boxo/gateway" |
| 8 | config "github.com/ipfs/kubo/config" |
| 9 | doh "github.com/libp2p/go-doh-resolver" |
| 10 | madns "github.com/multiformats/go-multiaddr-dns" |
| 11 | ) |
| 12 | |
| 13 | // Compile-time interface check: *madns.Resolver (returned by gateway.NewDNSResolver |
| 14 | // and madns.NewResolver) must implement madns.BasicResolver for p2pForgeResolver fallback. |
| 15 | var _ madns.BasicResolver = (*madns.Resolver)(nil) |
| 16 | |
| 17 | func DNSResolver(cfg *config.Config) (*madns.Resolver, error) { |
| 18 | var dohOpts []doh.Option |
| 19 | if !cfg.DNS.MaxCacheTTL.IsDefault() { |
| 20 | dohOpts = append(dohOpts, doh.WithMaxCacheTTL(cfg.DNS.MaxCacheTTL.WithDefault(time.Duration(math.MaxUint32)*time.Second))) |
| 21 | } |
| 22 | |
| 23 | // Replace "auto" DNS resolver placeholders with autoconf values |
| 24 | resolvers := cfg.DNSResolversWithAutoConf() |
| 25 | |
| 26 | // Get base resolver from boxo (handles custom DoH resolvers per eTLD) |
| 27 | baseResolver, err := gateway.NewDNSResolver(resolvers, dohOpts...) |
| 28 | if err != nil { |
| 29 | return nil, err |
| 30 | } |
| 31 | |
| 32 | // Check if we should skip network DNS lookups for p2p-forge domains |
| 33 | skipAutoTLSDNS := cfg.AutoTLS.SkipDNSLookup.WithDefault(config.DefaultAutoTLSSkipDNSLookup) |
| 34 | if !skipAutoTLSDNS { |
| 35 | // Local resolution disabled, use network DNS for everything |
| 36 | return baseResolver, nil |
| 37 | } |
| 38 | |
| 39 | // Build list of p2p-forge domains to resolve locally without network I/O. |
| 40 | // AutoTLS hostnames encode IP addresses directly (e.g., 1-2-3-4.peerID.libp2p.direct), |
| 41 | // so DNS lookups are wasteful. We resolve these in-memory when possible. |
| 42 | forgeDomains := []string{config.DefaultDomainSuffix} |
| 43 | customDomain := cfg.AutoTLS.DomainSuffix.WithDefault(config.DefaultDomainSuffix) |
| 44 | if customDomain != config.DefaultDomainSuffix { |
| 45 | forgeDomains = append(forgeDomains, customDomain) |
| 46 | } |
| 47 | forgeResolver := NewP2PForgeResolver(forgeDomains, baseResolver) |
| 48 | |
| 49 | // Register p2p-forge resolver for each domain, fallback to baseResolver for others |
| 50 | opts := []madns.Option{madns.WithDefaultResolver(baseResolver)} |
| 51 | for _, domain := range forgeDomains { |
| 52 | opts = append(opts, madns.WithDomainResolver(domain+".", forgeResolver)) |
| 53 | } |
| 54 | |
| 55 | return madns.NewResolver(opts...) |
| 56 | } |