diff --git a/CHANGELOG.md b/CHANGELOG.md index 27437ad3f..a45b7515b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The full list of changes is below. - The `waku-rln-relay` now supports spam-protection for a specific combination of `pubsubTopic` and `contentTopic` (available under the `rln` compiler flag). - The `waku-rln-relay` protocol in integrated into `chat2` (available under the`rln` compiler flag) +- Added support for resolving dns-based `multiaddrs` ### Changes diff --git a/tests/v2/test_wakunode.nim b/tests/v2/test_wakunode.nim index 2ed780e20..cc4458e3e 100644 --- a/tests/v2/test_wakunode.nim +++ b/tests/v2/test_wakunode.nim @@ -12,6 +12,7 @@ import libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/pubsub/pubsub, libp2p/protocols/pubsub/gossipsub, + libp2p/nameresolving/mockresolver, eth/keys, ../../waku/v2/node/storage/sqlite, ../../waku/v2/node/storage/message/waku_message_store, @@ -468,6 +469,31 @@ procSuite "WakuNode": $(remotePeerInfo.addrs[0][0].tryGet()) == "/ip4/127.0.0.1" $(remotePeerInfo.addrs[0][1].tryGet()) == "/tcp/60002" + # DNS multiaddrs parsing expected cases: + let + dnsPeer = parseRemotePeerInfo("/dns/localhost/tcp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc") + dnsAddrPeer = parseRemotePeerInfo("/dnsaddr/localhost/tcp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc") + dns4Peer = parseRemotePeerInfo("/dns4/localhost/tcp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc") + dns6Peer = parseRemotePeerInfo("/dns6/localhost/tcp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc") + + check: + # /dns + $(dnsPeer.peerId) == "16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc" + $(dnsPeer.addrs[0][0].tryGet()) == "/dns/localhost" + $(dnsPeer.addrs[0][1].tryGet()) == "/tcp/60002" + # /dnsaddr + $(dnsAddrPeer.peerId) == "16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc" + $(dnsAddrPeer.addrs[0][0].tryGet()) == "/dnsaddr/localhost" + $(dnsAddrPeer.addrs[0][1].tryGet()) == "/tcp/60002" + # /dns4 + $(dns4Peer.peerId) == "16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc" + $(dns4Peer.addrs[0][0].tryGet()) == "/dns4/localhost" + $(dns4Peer.addrs[0][1].tryGet()) == "/tcp/60002" + # /dns6 + $(dns6Peer.peerId) == "16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc" + $(dns6Peer.addrs[0][0].tryGet()) == "/dns6/localhost" + $(dns6Peer.addrs[0][1].tryGet()) == "/tcp/60002" + # Now test some common corner cases expect LPError: # gibberish @@ -493,6 +519,34 @@ procSuite "WakuNode": # unsupported transport discard parseRemotePeerInfo("/ip4/127.0.0.1/udp/60002/p2p/16Uuu2HBmAcHvhLqQKwSSbX6BG5JLWUDRcaLVrehUVqpw7fz1hbYc") + asyncTest "resolve and connect to dns multiaddrs": + let resolver = MockResolver.new() + + resolver.ipResponses[("localhost", false)] = @["127.0.0.1"] + + let + nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] + node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), Port(60000), nameResolver = resolver) + nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[] + node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(60002)) + + # Construct DNS multiaddr for node2 + let + node2PeerId = $(node2.switch.peerInfo.peerId) + node2Dns4Addr = "/dns4/localhost/tcp/60002/p2p/" & node2PeerId + + node1.mountRelay() + node2.mountRelay() + + await allFutures([node1.start(), node2.start()]) + + await node1.connectToNodes(@[node2Dns4Addr]) + + check: + node1.switch.connManager.connCount(node2.switch.peerInfo.peerId) == 1 + + await allFutures([node1.stop(), node2.stop()]) + asyncTest "filtering relayed messages using topic validators": ## test scenario: ## node1 and node3 set node2 as their relay node @@ -534,7 +588,6 @@ procSuite "WakuNode": await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) - var completionFutValidatorAcc = newFuture[bool]() var completionFutValidatorRej = newFuture[bool]() @@ -922,6 +975,7 @@ procSuite "WakuNode": await node1.stop() await node2.stop() await node3.stop() + asyncTest "Relay protocol is started correctly": let nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] @@ -1162,7 +1216,7 @@ procSuite "WakuNode": await allFutures([node1.stop(), node2.stop(), node3.stop()]) -asyncTest "Messages are relayed between two websocket nodes": + asyncTest "Messages are relayed between two websocket nodes": let nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), @@ -1207,7 +1261,7 @@ asyncTest "Messages are relayed between two websocket nodes": await node2.stop() -asyncTest "Messages are relayed between nodes with multiple transports (TCP and Websockets)": + asyncTest "Messages are relayed between nodes with multiple transports (TCP and Websockets)": let nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), @@ -1251,7 +1305,7 @@ asyncTest "Messages are relayed between nodes with multiple transports (TCP and await node1.stop() await node2.stop() -asyncTest "Messages relaying fails with non-overlapping transports (TCP or Websockets)": + asyncTest "Messages relaying fails with non-overlapping transports (TCP or Websockets)": let nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), @@ -1299,7 +1353,7 @@ asyncTest "Messages relaying fails with non-overlapping transports (TCP or Webso await node1.stop() await node2.stop() -asyncTest "Messages are relayed between nodes with multiple transports (TCP and secure Websockets)": + asyncTest "Messages are relayed between nodes with multiple transports (TCP and secure Websockets)": let nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), @@ -1343,7 +1397,7 @@ asyncTest "Messages are relayed between nodes with multiple transports (TCP and await node1.stop() await node2.stop() -asyncTest "Messages fails with wrong key path": + asyncTest "Messages fails with wrong key path": let nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] @@ -1352,7 +1406,7 @@ asyncTest "Messages fails with wrong key path": discard WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), bindPort = Port(60000), wsBindPort = Port(8000), wssEnabled = true, secureKey = "../../waku/v2/node/key_dummy.txt") -asyncTest "Messages are relayed between nodes with multiple transports (websocket and secure Websockets)": + asyncTest "Messages are relayed between nodes with multiple transports (websocket and secure Websockets)": let nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[] node1 = WakuNode.new(nodeKey1, ValidIpAddress.init("0.0.0.0"), @@ -1396,36 +1450,36 @@ asyncTest "Messages are relayed between nodes with multiple transports (websocke await node1.stop() await node2.stop() -asyncTest "Peer info updates with correct announced addresses": - let - nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[] - bindIp = ValidIpAddress.init("0.0.0.0") - bindPort = Port(60000) - extIp = some(ValidIpAddress.init("127.0.0.1")) - extPort = some(Port(60002)) - node = WakuNode.new( - nodeKey, - bindIp, bindPort, - extIp, extPort) - - let - bindEndpoint = MultiAddress.init(bindIp, tcpProtocol, bindPort) - announcedEndpoint = MultiAddress.init(extIp.get(), tcpProtocol, extPort.get()) - - check: - # Check that underlying peer info contains only bindIp before starting - node.switch.peerInfo.addrs.len == 1 - node.switch.peerInfo.addrs.contains(bindEndpoint) - - node.announcedAddresses.len == 1 - node.announcedAddresses.contains(announcedEndpoint) + asyncTest "Peer info updates with correct announced addresses": + let + nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[] + bindIp = ValidIpAddress.init("0.0.0.0") + bindPort = Port(60000) + extIp = some(ValidIpAddress.init("127.0.0.1")) + extPort = some(Port(60002)) + node = WakuNode.new( + nodeKey, + bindIp, bindPort, + extIp, extPort) - await node.start() + let + bindEndpoint = MultiAddress.init(bindIp, tcpProtocol, bindPort) + announcedEndpoint = MultiAddress.init(extIp.get(), tcpProtocol, extPort.get()) - check: - # Check that underlying peer info is updated with announced address - node.started - node.switch.peerInfo.addrs.len == 1 - node.switch.peerInfo.addrs.contains(announcedEndpoint) + check: + # Check that underlying peer info contains only bindIp before starting + node.switch.peerInfo.addrs.len == 1 + node.switch.peerInfo.addrs.contains(bindEndpoint) + + node.announcedAddresses.len == 1 + node.announcedAddresses.contains(announcedEndpoint) + + await node.start() - await node.stop() + check: + # Check that underlying peer info is updated with announced address + node.started + node.switch.peerInfo.addrs.len == 1 + node.switch.peerInfo.addrs.contains(announcedEndpoint) + + await node.stop() diff --git a/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool b/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool index b97bec04c..41760c003 100755 --- a/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool +++ b/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool @@ -2,7 +2,7 @@ # libtool - Provide generalized library-building support services. # Generated automatically by config.status (libbacktrace) version-unused -# Libtool was configured on host fv-az272-316: +# Libtool was configured on host fv-az190-599: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, diff --git a/waku/v2/node/config.nim b/waku/v2/node/config.nim index cd6a239bd..c5a3d6acb 100644 --- a/waku/v2/node/config.nim +++ b/waku/v2/node/config.nim @@ -64,6 +64,18 @@ type desc: "Enable message persistence: true|false", defaultValue: false name: "persist-messages" }: bool + + ## DNS addrs config + + dnsAddrs* {. + desc: "Enable resolution of `dnsaddr`, `dns4` or `dns6` multiaddrs" + defaultValue: true + name: "dns-addrs" }: bool + + dnsAddrsNameServers* {. + desc: "DNS name server IPs to query for DNS multiaddrs resolution. Argument may be repeated." + defaultValue: @[ValidIpAddress.init("1.1.1.1"), ValidIpAddress.init("1.0.0.1")] + name: "dns-addrs-name-server" }: seq[ValidIpAddress] ## Relay config diff --git a/waku/v2/node/wakunode2.nim b/waku/v2/node/wakunode2.nim index 6b18cb155..c7812017e 100644 --- a/waku/v2/node/wakunode2.nim +++ b/waku/v2/node/wakunode2.nim @@ -10,7 +10,7 @@ import libp2p/crypto/crypto, libp2p/protocols/ping, libp2p/protocols/pubsub/[gossipsub, rpc/messages], - libp2p/nameresolving/dnsresolver, + libp2p/nameresolving/nameresolver, libp2p/[builders, multihash], libp2p/transports/[transport, tcptransport, wstransport], ../protocol/[waku_relay, waku_message], @@ -159,7 +159,8 @@ proc new*(T: type WakuNode, nodeKey: crypto.PrivateKey, wssEnabled: bool = false, secureKey: string = "", secureCert: string = "", - wakuFlags = none(WakuEnrBitfield) + wakuFlags = none(WakuEnrBitfield), + nameResolver: NameResolver = nil, ): T {.raises: [Defect, LPError, IOError, TLSStreamProtocolError].} = ## Creates a Waku Node. @@ -218,7 +219,8 @@ proc new*(T: type WakuNode, nodeKey: crypto.PrivateKey, maxConnections = maxConnections, wssEnabled = wssEnabled, secureKeyPath = secureKey, - secureCertPath = secureCert) + secureCertPath = secureCert, + nameResolver = nameResolver) let wakuNode = WakuNode( peerManager: PeerManager.new(switch, peerStorage), @@ -926,6 +928,7 @@ when isMainModule: import confutils, system/ansi_c, + libp2p/nameresolving/dnsresolver, ../../common/utils/nat, ./config, ./waku_setup, @@ -997,7 +1000,15 @@ when isMainModule: ## file. Optionally include persistent peer storage. ## No protocols are mounted yet. - + var dnsResolver: DnsResolver + if conf.dnsAddrs: + # Support for DNS multiaddrs + var nameServers: seq[TransportAddress] + for ip in conf.dnsAddrsNameServers: + nameServers.add(initTAddress(ip, Port(53))) # Assume all servers use port 53 + + dnsResolver = DnsResolver.new(nameServers) + let ## `udpPort` is only supplied to satisfy underlying APIs but is not ## actually a supported transport for libp2p traffic. @@ -1020,17 +1031,18 @@ when isMainModule: conf.relay) node = WakuNode.new(conf.nodekey, - conf.listenAddress, Port(uint16(conf.tcpPort) + conf.portsShift), - extIp, extPort, - pStorage, - conf.maxConnections.int, - Port(uint16(conf.websocketPort) + conf.portsShift), - conf.websocketSupport, - conf.websocketSecureSupport, - conf.websocketSecureKeyPath, - conf.websocketSecureCertPath, - some(wakuFlags) - ) + conf.listenAddress, Port(uint16(conf.tcpPort) + conf.portsShift), + extIp, extPort, + pStorage, + conf.maxConnections.int, + Port(uint16(conf.websocketPort) + conf.portsShift), + conf.websocketSupport, + conf.websocketSecureSupport, + conf.websocketSecureKeyPath, + conf.websocketSecureCertPath, + some(wakuFlags), + dnsResolver + ) if conf.discv5Discovery: let discv5UdpPort = Port(uint16(conf.discv5UdpPort) + conf.portsShift) diff --git a/waku/v2/utils/peers.nim b/waku/v2/utils/peers.nim index 6e11d2df2..b49554497 100644 --- a/waku/v2/utils/peers.nim +++ b/waku/v2/utils/peers.nim @@ -69,13 +69,13 @@ proc parseRemotePeerInfo*(address: string): RemotePeerInfo {.raises: [Defect, Va let multiAddr = MultiAddress.init(address).tryGet() var - - ipPart, tcpPart, p2pPart, wsPart, wssPart: MultiAddress + nwPart, tcpPart, p2pPart, wsPart, wssPart: MultiAddress for addrPart in multiAddr.items(): case addrPart[].protoName()[] - of "ip4", "ip6": - ipPart = addrPart.tryGet() + # All protocols listed here: https://github.com/multiformats/multiaddr/blob/b746a7d014e825221cc3aea6e57a92d78419990f/protocols.csv + of "ip4", "ip6", "dns", "dnsaddr", "dns4", "dns6": + nwPart = addrPart.tryGet() of "tcp": tcpPart = addrPart.tryGet() of "p2p": @@ -89,7 +89,7 @@ proc parseRemotePeerInfo*(address: string): RemotePeerInfo {.raises: [Defect, Va let peerIdStr = p2pPart.toString()[].split("/")[^1] - wireAddr = ipPart & tcpPart & wsPart & wssPart + wireAddr = nwPart & tcpPart & wsPart & wssPart if (not wireAddr.validWireAddr()): raise newException(ValueError, "Invalid node multi-address") diff --git a/waku/v2/utils/wakuswitch.nim b/waku/v2/utils/wakuswitch.nim index af84df9ca..65b9bac79 100644 --- a/waku/v2/utils/wakuswitch.nim +++ b/waku/v2/utils/wakuswitch.nim @@ -45,8 +45,6 @@ proc withWssTransport*(b: SwitchBuilder, tlsCertificate = cert, {TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName})) - - proc newWakuSwitch*( privKey = none(crypto.PrivateKey), address = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(),