mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-08 20:47:59 -05:00
Filter Discovered peers for ipv6 support (#6498)
* use existing NetworkUtility for PeerDiscoveryAgent pingpacket data filtering, add ipv6 check/fallback * log at debug when we override pingpacket from * use java native address parsing rather than lookup by host Signed-off-by: garyschulte <garyschulte@gmail.com>
This commit is contained in:
@@ -74,9 +74,6 @@ public abstract class PeerDiscoveryAgent {
|
||||
// The devp2p specification says only accept packets up to 1280, but some
|
||||
// clients ignore that, so we add in a little extra padding.
|
||||
private static final int MAX_PACKET_SIZE_BYTES = 1600;
|
||||
private static final List<String> PING_PACKET_SOURCE_IGNORED =
|
||||
List.of("127.0.0.1", "255.255.255.255", "0.0.0.0", "::", "0:0:0:0:0:0:0:0");
|
||||
|
||||
protected final List<DiscoveryPeer> bootstrapPeers;
|
||||
private final List<PeerRequirement> peerRequirements = new CopyOnWriteArrayList<>();
|
||||
private final PeerPermissions peerPermissions;
|
||||
@@ -85,6 +82,7 @@ public abstract class PeerDiscoveryAgent {
|
||||
private final RlpxAgent rlpxAgent;
|
||||
private final ForkIdManager forkIdManager;
|
||||
private final PeerTable peerTable;
|
||||
private static final boolean isIpv6Available = NetworkUtility.isIPv6Available();
|
||||
|
||||
/* The peer controller, which takes care of the state machine of peers. */
|
||||
protected Optional<PeerDiscoveryController> controller = Optional.empty();
|
||||
@@ -316,23 +314,38 @@ public abstract class PeerDiscoveryAgent {
|
||||
* @return host address as string
|
||||
*/
|
||||
static String deriveHost(final Endpoint sourceEndpoint, final Packet packet) {
|
||||
return packet
|
||||
.getPacketData(PingPacketData.class)
|
||||
.flatMap(PingPacketData::getFrom)
|
||||
.map(Endpoint::getHost)
|
||||
.filter(
|
||||
fromAddr ->
|
||||
(!PING_PACKET_SOURCE_IGNORED.contains(fromAddr)
|
||||
&& InetAddresses.isInetAddress(fromAddr)))
|
||||
final Optional<String> pingPacketHost =
|
||||
packet
|
||||
.getPacketData(PingPacketData.class)
|
||||
.flatMap(PingPacketData::getFrom)
|
||||
.map(Endpoint::getHost);
|
||||
|
||||
return pingPacketHost
|
||||
// fall back to source endpoint "from" if ping packet from address does not satisfy filters
|
||||
.filter(InetAddresses::isInetAddress)
|
||||
.filter(h -> !NetworkUtility.isUnspecifiedAddress(h))
|
||||
.filter(h -> !NetworkUtility.isLocalhostAddress(h))
|
||||
.filter(h -> isIpv6Available || !NetworkUtility.isIpV6Address(h))
|
||||
.stream()
|
||||
.peek(
|
||||
h ->
|
||||
LOG.trace(
|
||||
"Using \"From\" endpoint {} specified in ping packet. Ignoring UDP source host {}",
|
||||
h,
|
||||
sourceEndpoint.getHost()))
|
||||
LOG.atTrace()
|
||||
.setMessage(
|
||||
"Using \"From\" endpoint {} specified in ping packet. Ignoring UDP source host {}")
|
||||
.addArgument(h)
|
||||
.addArgument(sourceEndpoint::getHost)
|
||||
.log())
|
||||
.findFirst()
|
||||
.orElseGet(sourceEndpoint::getHost);
|
||||
.orElseGet(
|
||||
() -> {
|
||||
LOG.atTrace()
|
||||
.setMessage(
|
||||
"Ignoring \"From\" endpoint {} in ping packet. Using UDP source host {}")
|
||||
.addArgument(pingPacketHost.orElse("not specified"))
|
||||
.addArgument(sourceEndpoint.getHost())
|
||||
.log();
|
||||
return sourceEndpoint.getHost();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@ package org.hyperledger.besu.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -26,6 +27,7 @@ import java.net.UnknownHostException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -33,8 +35,16 @@ import org.slf4j.LoggerFactory;
|
||||
public class NetworkUtility {
|
||||
/** The constant INADDR_ANY. */
|
||||
public static final String INADDR_ANY = "0.0.0.0";
|
||||
/** The constant INADDR_NONE. */
|
||||
public static final String INADDR_NONE = "255.255.255.255";
|
||||
/** The constant INADDR6_ANY. */
|
||||
public static final String INADDR6_ANY = "0:0:0:0:0:0:0:0";
|
||||
/** The constant INADDR6_NONE. */
|
||||
public static final String INADDR6_NONE = "::";
|
||||
/** The constant INADDR_LOCALHOST. */
|
||||
public static final String INADDR_LOCALHOST = "127.0.0.1";
|
||||
/** The constant INADDR6_LOCALHOST. */
|
||||
public static final String INADDR6_LOCALHOST = "::1";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NetworkUtility.class);
|
||||
|
||||
@@ -119,7 +129,20 @@ public class NetworkUtility {
|
||||
* @return the boolean
|
||||
*/
|
||||
public static boolean isUnspecifiedAddress(final String ipAddress) {
|
||||
return INADDR_ANY.equals(ipAddress) || INADDR6_ANY.equals(ipAddress);
|
||||
return INADDR_ANY.equals(ipAddress)
|
||||
|| INADDR6_ANY.equals(ipAddress)
|
||||
|| INADDR_NONE.equals(ipAddress)
|
||||
|| INADDR6_NONE.equals(ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether host address string is local host address.
|
||||
*
|
||||
* @param ipAddress the host address as a string
|
||||
* @return true if the host address is a local host address
|
||||
*/
|
||||
public static boolean isLocalhostAddress(final String ipAddress) {
|
||||
return INADDR_LOCALHOST.equals(ipAddress) || INADDR6_LOCALHOST.equals(ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,4 +196,32 @@ public class NetworkUtility {
|
||||
public static boolean isPortAvailable(final int port) {
|
||||
return isPortAvailableForTcp(port) && isPortAvailableForUdp(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is hostAddress string an ip v4 address
|
||||
*
|
||||
* @param hostAddress the host address as a string
|
||||
* @return true if the host address is an ip v4 address
|
||||
*/
|
||||
public static boolean isIpV4Address(final String hostAddress) {
|
||||
try {
|
||||
return InetAddresses.forString(hostAddress) instanceof Inet4Address;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is hostAddress string an ip v6 address
|
||||
*
|
||||
* @param hostAddress the host address as a string
|
||||
* @return true if the host address is an ip v6 address
|
||||
*/
|
||||
public static boolean isIpV6Address(final String hostAddress) {
|
||||
try {
|
||||
return InetAddresses.forString(hostAddress) instanceof Inet6Address;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,33 @@ public class NetworkUtilityTest {
|
||||
assertThat(!NetworkUtility.isPortAvailable(8541)).isEqualTo(true);
|
||||
serverSocket.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertLocalhostIdentification() {
|
||||
assertThat(NetworkUtility.isLocalhostAddress("127.0.0.1")).isTrue();
|
||||
assertThat(NetworkUtility.isLocalhostAddress("::1")).isTrue();
|
||||
assertThat(NetworkUtility.isLocalhostAddress("192.168.1.1")).isFalse();
|
||||
assertThat(NetworkUtility.isLocalhostAddress("::ffff:c0a8:101")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertIpV4Address() {
|
||||
assertThat(NetworkUtility.isIpV4Address("127.0.0.1")).isTrue();
|
||||
assertThat(NetworkUtility.isIpV4Address("10.0.0.0")).isTrue();
|
||||
assertThat(NetworkUtility.isIpV4Address("172.16.1.1")).isTrue();
|
||||
assertThat(NetworkUtility.isIpV4Address("127.0.0.")).isFalse();
|
||||
assertThat(NetworkUtility.isIpV4Address("256.256.256.256")).isFalse();
|
||||
// ipv6 compatible ipv4 address
|
||||
assertThat(NetworkUtility.isIpV4Address("::ffff:c0a8:5801")).isTrue();
|
||||
assertThat(NetworkUtility.isIpV4Address("0:0:0:0:0:ffff:c0a8:5801")).isTrue();
|
||||
assertThat(NetworkUtility.isIpV4Address("0000:0000:0000:0000:0000:ffff:c0a8:5801")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertIpV6Address() {
|
||||
assertThat(NetworkUtility.isIpV6Address("::1")).isTrue();
|
||||
assertThat(NetworkUtility.isIpV6Address("::")).isTrue();
|
||||
assertThat(NetworkUtility.isIpV6Address("2001:db8:3333:4444:5555:6666:7777:8888")).isTrue();
|
||||
assertThat(NetworkUtility.isIpV6Address("00:00::00:00::00:00")).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user