Skip to content

Commit 21872f4

Browse files
aschmahmannlidel
andauthored
feat: support custom dnslink resolvers (#224)
* feat: custom dnslink resolvers * docs: RAINBOW_DNSLINK_RESOLVERS including explicit defaults --------- Co-authored-by: Marcin Rataj <[email protected]>
1 parent aca9ee3 commit 21872f4

7 files changed

+70
-9
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ The following emojis are used to highlight certain changes:
1515

1616
### Added
1717

18+
- Add support for custom DNSLink resolvers (e.g. to support TLDs like `.eth`, `.crypto`). It is possible to set custom DoH resolvers by setting `RAINBOW_DNSLINK_RESOLVERS` with the same convention as Kubo's [`DNS.Resolvers`](https://github.com/ipfs/kubo/blob/master/docs/config.md#dnsresolvers) ) [#224](https://github.com/ipfs/rainbow/pull/224)
19+
1820
### Changed
1921

2022
### Fixed

docs/environment-variables.md

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- [`RAINBOW_SEED_INDEX`](#rainbow_seed_index)
1616
- [`RAINBOW_DHT_ROUTING`](#rainbow_dht_routing)
1717
- [`RAINBOW_HTTP_ROUTERS`](#rainbow_http_routers)
18+
- [`RAINBOW_DNSLINK_RESOLVERS`](#rainbow_dnslink_resolvers)
1819
- [Experiments](#experiments)
1920
- [`RAINBOW_SEED_PEERING`](#rainbow_seed_peering)
2021
- [`RAINBOW_SEED_PEERING_MAX_INDEX`](#rainbow_seed_peering_max_index)
@@ -32,6 +33,7 @@
3233
- [`IPFS_NS_MAP`](#ipfs_ns_map)
3334
- [Tracing](#tracing)
3435
- [`RAINBOW_TRACING_AUTH`](#rainbow_tracing_auth)
36+
- [`RAINBOW_SAMPLING_FRACTION`](#rainbow_sampling_fraction)
3537

3638
## Configuration
3739

@@ -148,6 +150,14 @@ HTTP servers with /routing/v1 endpoints to use for delegated routing (comma-sepa
148150

149151
Default: `https://cid.contact`
150152

153+
### `RAINBOW_DNSLINK_RESOLVERS`
154+
155+
DNS-over-HTTPS servers to use for resolving DNSLink on specified TLDs (comma-separated map: `TLD:URL,TLD2:URL2`).
156+
157+
It is possible to override OS resolver by passing root: `. : catch-URL`.
158+
159+
Default: `eth. : https://resolver.cloudflare-eth.com/dns-query, crypto. : https://resolver.cloudflare-eth.com/dns-query`
160+
151161
## Experiments
152162

153163
### `RAINBOW_SEED_PEERING`

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ require (
3333
github.com/mitchellh/go-server-timing v1.0.1
3434
github.com/mr-tron/base58 v1.2.0
3535
github.com/multiformats/go-multiaddr v0.14.0
36+
github.com/multiformats/go-multiaddr-dns v0.4.1
3637
github.com/multiformats/go-multicodec v0.9.0
3738
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
3839
github.com/prometheus/client_golang v1.20.5
@@ -149,7 +150,6 @@ require (
149150
github.com/minio/sha256-simd v1.0.1 // indirect
150151
github.com/multiformats/go-base32 v0.1.0 // indirect
151152
github.com/multiformats/go-base36 v0.2.0 // indirect
152-
github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
153153
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
154154
github.com/multiformats/go-multibase v0.2.0 // indirect
155155
github.com/multiformats/go-multihash v0.2.3 // indirect

main.go

+34
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ import (
1919
"time"
2020

2121
sddaemon "github.com/coreos/go-systemd/v22/daemon"
22+
"github.com/ipfs/boxo/gateway"
2223
logging "github.com/ipfs/go-log/v2"
2324
"github.com/libp2p/go-libp2p/core/crypto"
2425
peer "github.com/libp2p/go-libp2p/core/peer"
26+
madns "github.com/multiformats/go-multiaddr-dns"
2527
"github.com/urfave/cli/v2"
2628
"go.opentelemetry.io/contrib/propagators/autoprop"
2729
"go.opentelemetry.io/otel"
@@ -399,6 +401,12 @@ Generate an identity seed and launch a gateway:
399401
EnvVars: []string{"ROUTING_MAX_TIMEOUT"},
400402
Usage: "Maximum time for routing to find the maximum number of providers",
401403
},
404+
&cli.StringSliceFlag{
405+
Name: "dnslink-resolvers",
406+
Value: cli.NewStringSlice(extraDNSLinkResolvers...),
407+
EnvVars: []string{"RAINBOW_DNSLINK_RESOLVERS"},
408+
Usage: "The DNSLink resolvers to use (comma-separated tuples that each look like `eth. : https://dns.eth.limo/dns-query`)",
409+
},
402410
}
403411

404412
app.Commands = []*cli.Command{
@@ -513,6 +521,12 @@ share the same seed as long as the indexes are different.
513521
}
514522
}
515523

524+
customDNSResolvers := cctx.StringSlice("dnslink-resolvers")
525+
dns, err := parseCustomDNSLinkResolvers(customDNSResolvers)
526+
if err != nil {
527+
return err
528+
}
529+
516530
cfg := Config{
517531
DataDir: ddir,
518532
BlockstoreType: cctx.String("blockstore"),
@@ -546,6 +560,7 @@ share the same seed as long as the indexes are different.
546560
GCThreshold: cctx.Float64("gc-threshold"),
547561
ListenAddrs: cctx.StringSlice("libp2p-listen-addrs"),
548562
TracingAuthToken: cctx.String("tracing-auth"),
563+
DNSLinkResolver: dns,
549564

550565
// Pebble config
551566
BytesPerSync: cctx.Int("pebble-bytes-per-sync"),
@@ -639,6 +654,7 @@ share the same seed as long as the indexes are different.
639654
printIfListConfigured(" RAINBOW_SUBDOMAIN_GATEWAY_DOMAINS = ", cfg.SubdomainGatewayDomains)
640655
printIfListConfigured(" RAINBOW_TRUSTLESS_GATEWAY_DOMAINS = ", cfg.TrustlessGatewayDomains)
641656
printIfListConfigured(" RAINBOW_HTTP_ROUTERS = ", cfg.RoutingV1Endpoints)
657+
printIfListConfigured(" RAINBOW_DNSLINK_RESOLVERS = ", customDNSResolvers)
642658
printIfListConfigured(" RAINBOW_REMOTE_BACKENDS = ", cfg.RemoteBackends)
643659

644660
fmt.Printf("\n")
@@ -766,3 +782,21 @@ func replaceRainbowSeedWithPeer(addr string, seed string) (string, error) {
766782

767783
return strings.Replace(addr, match[0], "/p2p/"+pid.String(), 1), nil
768784
}
785+
786+
func parseCustomDNSLinkResolvers(customDNSResolvers []string) (madns.BasicResolver, error) {
787+
customDNSResolverMap := make(map[string]string)
788+
for _, s := range customDNSResolvers {
789+
split := strings.SplitN(s, ":", 2)
790+
if len(split) != 2 {
791+
return nil, fmt.Errorf("invalid DNS resolver: %s", s)
792+
}
793+
domain := strings.TrimSpace(split[0])
794+
resolverUrl := strings.TrimSpace(split[1])
795+
customDNSResolverMap[domain] = resolverUrl
796+
}
797+
dns, err := gateway.NewDNSResolver(customDNSResolverMap)
798+
if err != nil {
799+
return nil, err
800+
}
801+
return dns, nil
802+
}

main_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99

1010
chunker "github.com/ipfs/boxo/chunker"
11+
"github.com/ipfs/boxo/gateway"
1112
"github.com/ipfs/boxo/ipld/merkledag"
1213
"github.com/ipfs/boxo/ipld/unixfs/importer/balanced"
1314
uih "github.com/ipfs/boxo/ipld/unixfs/importer/helpers"
@@ -63,6 +64,12 @@ func mustTestNodeWithKey(t *testing.T, cfg Config, sk ic.PrivKey) *Node {
6364
_ = cdns.Close()
6465
})
6566

67+
if cfg.DNSLinkResolver == nil {
68+
dnslinkResovler, err := gateway.NewDNSResolver(nil)
69+
require.NoError(t, err)
70+
cfg.DNSLinkResolver = dnslinkResovler
71+
}
72+
6673
nd, err := SetupWithLibp2p(ctx, cfg, sk, cdns)
6774
require.NoError(t, err)
6875
return nd

setup.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
4242
"github.com/libp2p/go-libp2p/p2p/protocol/identify"
4343
"github.com/multiformats/go-multiaddr"
44+
madns "github.com/multiformats/go-multiaddr-dns"
4445
)
4546

4647
func init() {
@@ -53,6 +54,11 @@ const cidContactEndpoint = "https://cid.contact"
5354

5455
var httpRoutersFilterProtocols = []string{"unknown", "transport-bitswap"} // IPIP-484
5556

57+
var extraDNSLinkResolvers = []string{
58+
"eth. : https://resolver.cloudflare-eth.com/dns-query",
59+
"crypto. : https://resolver.cloudflare-eth.com/dns-query",
60+
}
61+
5662
type DHTRouting string
5763

5864
const (
@@ -112,6 +118,8 @@ type Config struct {
112118
IpnsMaxCacheTTL time.Duration
113119
Bitswap bool
114120

121+
DNSLinkResolver madns.BasicResolver
122+
115123
// BitswapWantHaveReplaceSize tells the bitswap server to replace WantHave
116124
// with WantBlock responses when the block size less then or equal to this
117125
// value. Set to zero to disable replacement and avoid block size lookup
@@ -194,7 +202,7 @@ func SetupNoLibp2p(ctx context.Context, cfg Config, dnsCache *cachedDNS) (*Node,
194202
bsrv = nopfsipfs.WrapBlockService(bsrv, blocker)
195203
}
196204

197-
ns, err := setupNamesys(cfg, vs, blocker)
205+
ns, err := setupNamesys(cfg, vs, blocker, cfg.DNSLinkResolver)
198206
if err != nil {
199207
return nil, err
200208
}
@@ -357,7 +365,7 @@ func SetupWithLibp2p(ctx context.Context, cfg Config, key crypto.PrivKey, dnsCac
357365
n.bsrv = bsrv
358366
n.resolver = r
359367

360-
ns, err := setupNamesys(cfg, vs, blocker)
368+
ns, err := setupNamesys(cfg, vs, blocker, cfg.DNSLinkResolver)
361369
if err != nil {
362370
return nil, err
363371
}
@@ -521,12 +529,8 @@ func setupDenylists(cfg Config) ([]*nopfs.HTTPSubscriber, *nopfs.Blocker, error)
521529
return denylists, blocker, nil
522530
}
523531

524-
func setupNamesys(cfg Config, vs routing.ValueStore, blocker *nopfs.Blocker) (namesys.NameSystem, error) {
525-
dns, err := gateway.NewDNSResolver(nil)
526-
if err != nil {
527-
return nil, err
528-
}
529-
nsOptions := []namesys.Option{namesys.WithDNSResolver(dns)}
532+
func setupNamesys(cfg Config, vs routing.ValueStore, blocker *nopfs.Blocker, dnslinkResolver madns.BasicResolver) (namesys.NameSystem, error) {
533+
nsOptions := []namesys.Option{namesys.WithDNSResolver(dnslinkResolver)}
530534
if cfg.IpnsMaxCacheTTL > 0 {
531535
nsOptions = append(nsOptions, namesys.WithMaxCacheTTL(cfg.IpnsMaxCacheTTL))
532536
}

setup_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88
"time"
99

10+
"github.com/ipfs/boxo/gateway"
1011
blocks "github.com/ipfs/go-block-format"
1112
ci "github.com/libp2p/go-libp2p-testing/ci"
1213
ic "github.com/libp2p/go-libp2p/core/crypto"
@@ -173,6 +174,8 @@ func testSeedPeering(t *testing.T, n int, dhtRouting DHTRouting, dhtSharedHost b
173174
nodes := make([]*Node, n)
174175

175176
for i := 0; i < n; i++ {
177+
dnslinkResolver, err := gateway.NewDNSResolver(nil)
178+
require.NoError(t, err)
176179
cfgs[i] = Config{
177180
DataDir: t.TempDir(),
178181
BlockstoreType: "flatfs",
@@ -183,6 +186,7 @@ func testSeedPeering(t *testing.T, n int, dhtRouting DHTRouting, dhtSharedHost b
183186
SeedIndex: i,
184187
SeedPeering: true,
185188
SeedPeeringMaxIndex: n,
189+
DNSLinkResolver: dnslinkResolver,
186190
}
187191

188192
nodes[i], err = SetupWithLibp2p(ctx, cfgs[i], keys[i], cdns)

0 commit comments

Comments
 (0)