Skip to content

Commit 81d5c0c

Browse files
swarm: fix recursive resolving of DNS multiaddrs (#2564)
* swarm: fix recursive resolving of DNS multiaddrs * add a test case
1 parent c463bcd commit 81d5c0c

File tree

3 files changed

+59
-45
lines changed

3 files changed

+59
-45
lines changed

p2p/net/swarm/swarm_dial.go

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -301,27 +301,8 @@ func (s *Swarm) addrsForDial(ctx context.Context, p peer.ID) (goodAddrs []ma.Mul
301301
return nil, nil, ErrNoAddresses
302302
}
303303

304-
peerAddrsAfterTransportResolved := make([]ma.Multiaddr, 0, len(peerAddrs))
305-
for _, a := range peerAddrs {
306-
tpt := s.TransportForDialing(a)
307-
resolver, ok := tpt.(transport.Resolver)
308-
if ok {
309-
resolvedAddrs, err := resolver.Resolve(ctx, a)
310-
if err != nil {
311-
log.Warnf("Failed to resolve multiaddr %s by transport %v: %v", a, tpt, err)
312-
continue
313-
}
314-
peerAddrsAfterTransportResolved = append(peerAddrsAfterTransportResolved, resolvedAddrs...)
315-
} else {
316-
peerAddrsAfterTransportResolved = append(peerAddrsAfterTransportResolved, a)
317-
}
318-
}
319-
320304
// Resolve dns or dnsaddrs
321-
resolved, err := s.resolveAddrs(ctx, peer.AddrInfo{
322-
ID: p,
323-
Addrs: peerAddrsAfterTransportResolved,
324-
})
305+
resolved, err := s.resolveAddrs(ctx, peer.AddrInfo{ID: p, Addrs: peerAddrs})
325306
if err != nil {
326307
return nil, nil, err
327308
}
@@ -342,21 +323,19 @@ func (s *Swarm) addrsForDial(ctx context.Context, p peer.ID) (goodAddrs []ma.Mul
342323
}
343324

344325
func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multiaddr, error) {
345-
proto := ma.ProtocolWithCode(ma.P_P2P).Name
346-
p2paddr, err := ma.NewMultiaddr("/" + proto + "/" + pi.ID.String())
326+
p2paddr, err := ma.NewMultiaddr("/" + ma.ProtocolWithCode(ma.P_P2P).Name + "/" + pi.ID.String())
347327
if err != nil {
348328
return nil, err
349329
}
350330

351-
resolveSteps := 0
352-
331+
var resolveSteps int
353332
// Recursively resolve all addrs.
354333
//
355334
// While the toResolve list is non-empty:
356335
// * Pop an address off.
357336
// * If the address is fully resolved, add it to the resolved list.
358337
// * Otherwise, resolve it and add the results to the "to resolve" list.
359-
toResolve := append(([]ma.Multiaddr)(nil), pi.Addrs...)
338+
toResolve := append([]ma.Multiaddr{}, pi.Addrs...)
360339
resolved := make([]ma.Multiaddr, 0, len(pi.Addrs))
361340
for len(toResolve) > 0 {
362341
// pop the last addr off.
@@ -383,6 +362,26 @@ func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multia
383362
continue
384363
}
385364

365+
tpt := s.TransportForDialing(addr)
366+
resolver, ok := tpt.(transport.Resolver)
367+
if ok {
368+
resolvedAddrs, err := resolver.Resolve(ctx, addr)
369+
if err != nil {
370+
log.Warnf("Failed to resolve multiaddr %s by transport %v: %v", addr, tpt, err)
371+
continue
372+
}
373+
var added bool
374+
for _, a := range resolvedAddrs {
375+
if !addr.Equal(a) {
376+
toResolve = append(toResolve, a)
377+
added = true
378+
}
379+
}
380+
if added {
381+
continue
382+
}
383+
}
384+
386385
// otherwise, resolve it
387386
reqaddr := addr.Encapsulate(p2paddr)
388387
resaddrs, err := s.maResolver.Resolve(ctx, reqaddr)

p2p/net/swarm/swarm_dial_test.go

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,9 @@ func TestAddrResolution(t *testing.T) {
197197
}
198198

199199
func TestAddrResolutionRecursive(t *testing.T) {
200-
ctx := context.Background()
200+
p1 := test.RandPeerIDFatal(t)
201+
p2 := test.RandPeerIDFatal(t)
201202

202-
p1, err := test.RandPeerID()
203-
if err != nil {
204-
t.Error(err)
205-
}
206-
p2, err := test.RandPeerID()
207-
if err != nil {
208-
t.Error(err)
209-
}
210203
addr1 := ma.StringCast("/dnsaddr/example.com")
211204
addr2 := ma.StringCast("/ip4/192.0.2.1/tcp/123")
212205
p2paddr1 := ma.StringCast("/dnsaddr/example.com/p2p/" + p1.String())
@@ -221,25 +214,19 @@ func TestAddrResolutionRecursive(t *testing.T) {
221214
"dnsaddr=" + p2paddr1i.String(),
222215
"dnsaddr=" + p2paddr2i.String(),
223216
},
224-
"_dnsaddr.foo.example.com": {
225-
"dnsaddr=" + p2paddr1f.String(),
226-
},
227-
"_dnsaddr.bar.example.com": {
228-
"dnsaddr=" + p2paddr2i.String(),
229-
},
217+
"_dnsaddr.foo.example.com": {"dnsaddr=" + p2paddr1f.String()},
218+
"_dnsaddr.bar.example.com": {"dnsaddr=" + p2paddr2i.String()},
230219
},
231220
}
232221
resolver, err := madns.NewResolver(madns.WithDefaultResolver(backend))
233-
if err != nil {
234-
t.Fatal(err)
235-
}
222+
require.NoError(t, err)
236223

237224
s := newTestSwarmWithResolver(t, resolver)
238225

239226
pi1, err := peer.AddrInfoFromP2pAddr(p2paddr1)
240227
require.NoError(t, err)
241228

242-
tctx, cancel := context.WithTimeout(ctx, time.Millisecond*100)
229+
tctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
243230
defer cancel()
244231
s.Peerstore().AddAddrs(pi1.ID, pi1.Addrs, peerstore.TempAddrTTL)
245232
_, _, err = s.addrsForDial(tctx, p1)
@@ -263,6 +250,34 @@ func TestAddrResolutionRecursive(t *testing.T) {
263250
require.Contains(t, addrs2, addr1)
264251
}
265252

253+
// see https://github.com/libp2p/go-libp2p/issues/2562
254+
func TestAddrResolutionRecursiveTransportSpecific(t *testing.T) {
255+
p := test.RandPeerIDFatal(t)
256+
257+
backend := &madns.MockResolver{
258+
IP: map[string][]net.IPAddr{
259+
"sub.example.com": {net.IPAddr{IP: net.IPv4(1, 2, 3, 4)}},
260+
},
261+
TXT: map[string][]string{
262+
"_dnsaddr.example.com": {"dnsaddr=/dns4/sub.example.com/tcp/443/wss/p2p/" + p.String()},
263+
},
264+
}
265+
resolver, err := madns.NewResolver(madns.WithDefaultResolver(backend))
266+
require.NoError(t, err)
267+
268+
s := newTestSwarmWithResolver(t, resolver)
269+
pi1, err := peer.AddrInfoFromP2pAddr(ma.StringCast("/dnsaddr/example.com/p2p/" + p.String()))
270+
require.NoError(t, err)
271+
272+
tctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
273+
defer cancel()
274+
s.Peerstore().AddAddrs(pi1.ID, pi1.Addrs, peerstore.TempAddrTTL)
275+
addrs, _, err := s.addrsForDial(tctx, p)
276+
require.NoError(t, err)
277+
require.Len(t, addrs, 1)
278+
require.Equal(t, addrs[0].String(), "/ip4/1.2.3.4/tcp/443/tls/sni/sub.example.com/ws")
279+
}
280+
266281
func TestAddrsForDialFiltering(t *testing.T) {
267282
q1 := ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1")
268283
q1v1 := ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1")

p2p/transport/websocket/websocket.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func (t *WebsocketTransport) Proxy() bool {
120120
return false
121121
}
122122

123-
func (t *WebsocketTransport) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
123+
func (t *WebsocketTransport) Resolve(_ context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
124124
parsed, err := parseWebsocketMultiaddr(maddr)
125125
if err != nil {
126126
return nil, err

0 commit comments

Comments
 (0)