From bbf6ad69ef6b33acf23d8d1ba584410e1d3683fc Mon Sep 17 00:00:00 2001 From: ian Date: Wed, 6 Dec 2023 12:45:05 +0000 Subject: [PATCH] Only return public addresses in kademlia queries --- src/main/java/org/peergos/PeerAddresses.java | 11 +++++++ .../peergos/protocol/dht/KademliaEngine.java | 31 ++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/peergos/PeerAddresses.java b/src/main/java/org/peergos/PeerAddresses.java index 5954505e..f2afb379 100644 --- a/src/main/java/org/peergos/PeerAddresses.java +++ b/src/main/java/org/peergos/PeerAddresses.java @@ -13,6 +13,7 @@ import java.io.*; import java.net.*; import java.util.*; +import java.util.function.*; import java.util.stream.*; public class PeerAddresses { @@ -70,6 +71,16 @@ public Dht.Message.Peer toProtobuf() { .build(); } + public Dht.Message.Peer toProtobuf(Predicate filter) { + return Dht.Message.Peer.newBuilder() + .setId(ByteString.copyFrom(peerId.toBytes())) + .addAllAddrs(addresses.stream() + .filter(filter) + .map(a -> ByteString.copyFrom(a.serialize())) + .collect(Collectors.toList())) + .build(); + } + public static PeerAddresses fromHost(Host host) { Multihash peerId = Multihash.deserialize(host.getPeerId().getBytes()); List addrs = host.listenAddresses(); diff --git a/src/main/java/org/peergos/protocol/dht/KademliaEngine.java b/src/main/java/org/peergos/protocol/dht/KademliaEngine.java index 68e5f59d..eaba4464 100644 --- a/src/main/java/org/peergos/protocol/dht/KademliaEngine.java +++ b/src/main/java/org/peergos/protocol/dht/KademliaEngine.java @@ -8,12 +8,15 @@ import io.libp2p.core.*; import io.libp2p.core.Stream; import io.libp2p.core.multiformats.*; +import io.libp2p.core.multiformats.Protocol; import io.prometheus.client.*; import org.peergos.*; import org.peergos.blockstore.*; import org.peergos.protocol.dht.pb.*; import org.peergos.protocol.ipns.*; +import java.io.*; +import java.net.*; import java.time.*; import java.util.*; import java.util.stream.*; @@ -117,7 +120,7 @@ public void receiveRequest(Dht.Message msg, PeerId source, Stream stream) { .setValue(ByteString.copyFrom(ipnsRecord.get().raw)).build()); builder = builder.addAllCloserPeers(getKClosestPeers(msg.getKey().toByteArray()) .stream() - .map(PeerAddresses::toProtobuf) + .map(p -> p.toProtobuf(a -> isPublic(a))) .collect(Collectors.toList())); Dht.Message reply = builder.build(); stream.writeAndFlush(reply); @@ -140,14 +143,17 @@ public void receiveRequest(Dht.Message msg, PeerId source, Stream stream) { if (blocks.hasAny(hash).join()) { providers = new HashSet<>(providers); providers.add(new PeerAddresses(ourPeerId, - new ArrayList<>(addressBook.getAddrs(PeerId.fromBase58(ourPeerId.toBase58())).join())).toProtobuf()); + addressBook.getAddrs(PeerId.fromBase58(ourPeerId.toBase58())).join() + .stream() + .filter(a -> isPublic(a)) + .collect(Collectors.toList())).toProtobuf()); } Dht.Message.Builder builder = msg.toBuilder(); builder = builder.addAllProviderPeers(providers.stream() .collect(Collectors.toList())); builder = builder.addAllCloserPeers(getKClosestPeers(msg.getKey().toByteArray()) .stream() - .map(PeerAddresses::toProtobuf) + .map(p -> p.toProtobuf(a -> isPublic(a))) .collect(Collectors.toList())); Dht.Message reply = builder.build(); stream.writeAndFlush(reply); @@ -162,7 +168,7 @@ public void receiveRequest(Dht.Message msg, PeerId source, Stream stream) { builder = builder.addAllCloserPeers(getKClosestPeers(target) .stream() .filter(p -> ! p.peerId.equals(sourcePeer)) // don't tell a peer about themselves - .map(PeerAddresses::toProtobuf) + .map(p -> p.toProtobuf(a -> isPublic(a))) .collect(Collectors.toList())); Dht.Message reply = builder.build(); stream.writeAndFlush(reply); @@ -174,4 +180,21 @@ public void receiveRequest(Dht.Message msg, PeerId source, Stream stream) { default: throw new IllegalStateException("Unknown message kademlia type: " + msg.getType()); } } + + public static boolean isPublic(Multiaddr addr) { + try { + List parts = addr.getComponents(); + for (MultiaddrComponent part: parts) { + if (part.getProtocol() == Protocol.IP6ZONE) + return true; + if (part.getProtocol() == Protocol.IP4 || part.getProtocol() == Protocol.IP6) { + InetAddress ip = InetAddress.getByName(part.getStringValue()); + if (ip.isLoopbackAddress() || ip.isSiteLocalAddress() || ip.isLinkLocalAddress() || ip.isAnyLocalAddress()) + return false; + return true; + } + } + } catch (IOException e) {} + return false; + } }