Skip to content

Commit

Permalink
Merge branch 'main' into DisconnectWorstPeer
Browse files Browse the repository at this point in the history
  • Loading branch information
pinges authored Jan 31, 2024
2 parents 10efe34 + 79245bb commit 03d27ba
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand Down Expand Up @@ -316,23 +314,38 @@ protected void handleIncomingPacket(final Endpoint sourceEndpoint, final Packet
* @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();
});
}

/**
Expand Down
53 changes: 52 additions & 1 deletion util/src/main/java/org/hyperledger/besu/util/NetworkUtility.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import java.io.IOException;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
Expand All @@ -26,15 +27,24 @@
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;

/** The Network utility. */
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);

Expand Down Expand Up @@ -119,7 +129,20 @@ public static boolean isNetworkInterfaceAvailable(final String ipAddress)
* @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);
}

/**
Expand Down Expand Up @@ -173,4 +196,32 @@ private static boolean isPortAvailableForUdp(final int port) {
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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,33 @@ public void assertPortIsNotAvailable() throws IOException {
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();
}
}

0 comments on commit 03d27ba

Please sign in to comment.