diff --git a/networking/nat/src/main/java/tech/pegasys/teku/networking/nat/NatService.java b/networking/nat/src/main/java/tech/pegasys/teku/networking/nat/NatService.java index bb313377191..718be01f0a8 100644 --- a/networking/nat/src/main/java/tech/pegasys/teku/networking/nat/NatService.java +++ b/networking/nat/src/main/java/tech/pegasys/teku/networking/nat/NatService.java @@ -22,12 +22,15 @@ public class NatService extends Service { private final Optional maybeNatManager; private final boolean isDiscoveryEnabled; private final int p2pPort; + private final Optional p2pPortIpv6; NatService( final int p2pPort, + final Optional p2pPortipv6, final boolean isDiscoveryEnabled, final Optional maybeNatManager) { this.p2pPort = p2pPort; + this.p2pPortIpv6 = p2pPortipv6; this.isDiscoveryEnabled = isDiscoveryEnabled; this.maybeNatManager = maybeNatManager; } @@ -35,9 +38,11 @@ public class NatService extends Service { public NatService( final NatConfiguration natConfiguration, final int p2pPort, + final Optional p2pPortIpv6, final boolean isDiscoveryEnabled) { this( p2pPort, + p2pPortIpv6, isDiscoveryEnabled, natConfiguration.getNatMethod().equals(NatMethod.UPNP) ? Optional.of(new NatManager()) @@ -54,11 +59,8 @@ protected SafeFuture doStart() { .start() .thenRun( () -> { - natManager.requestPortForward(p2pPort, NetworkProtocol.TCP, NatServiceType.TEKU_P2P); - if (isDiscoveryEnabled) { - natManager.requestPortForward( - p2pPort, NetworkProtocol.UDP, NatServiceType.TEKU_DISCOVERY); - } + requestPortForward(natManager, p2pPort); + p2pPortIpv6.ifPresent(port -> requestPortForward(natManager, port)); }); } @@ -66,4 +68,11 @@ protected SafeFuture doStart() { protected SafeFuture doStop() { return maybeNatManager.map(NatManager::stop).orElse(SafeFuture.completedFuture(null)); } + + private void requestPortForward(final NatManager natManager, final int port) { + natManager.requestPortForward(port, NetworkProtocol.TCP, NatServiceType.TEKU_P2P); + if (isDiscoveryEnabled) { + natManager.requestPortForward(port, NetworkProtocol.UDP, NatServiceType.TEKU_DISCOVERY); + } + } } diff --git a/networking/nat/src/test/java/tech/pegasys/teku/networking/nat/NatServiceTest.java b/networking/nat/src/test/java/tech/pegasys/teku/networking/nat/NatServiceTest.java index 4c87c61018f..88b2ff7475b 100644 --- a/networking/nat/src/test/java/tech/pegasys/teku/networking/nat/NatServiceTest.java +++ b/networking/nat/src/test/java/tech/pegasys/teku/networking/nat/NatServiceTest.java @@ -31,18 +31,20 @@ public class NatServiceTest { @Test public void shouldRequestPortsBeMappedOnServiceStart() { - final NatService natService = new NatService(9000, true, maybeNatManager); + final NatService natService = new NatService(9000, Optional.of(9090), true, maybeNatManager); when(natManager.start()).thenReturn(SafeFuture.completedFuture(null)); assertThat(natService.start()).isCompleted(); verify(natManager).start(); verify(natManager).requestPortForward(eq(9000), eq(NetworkProtocol.UDP), any()); verify(natManager).requestPortForward(eq(9000), eq(NetworkProtocol.TCP), any()); + verify(natManager).requestPortForward(eq(9090), eq(NetworkProtocol.UDP), any()); + verify(natManager).requestPortForward(eq(9090), eq(NetworkProtocol.TCP), any()); verifyNoMoreInteractions(natManager); } @Test public void shouldShutdownNatManager() { - final NatService natService = new NatService(9000, true, maybeNatManager); + final NatService natService = new NatService(9000, Optional.empty(), true, maybeNatManager); when(natManager.start()).thenReturn(SafeFuture.completedFuture(null)); assertThat(natService.start()).isCompleted(); diff --git a/teku/src/main/java/tech/pegasys/teku/services/BeaconNodeServiceController.java b/teku/src/main/java/tech/pegasys/teku/services/BeaconNodeServiceController.java index ae948646e9d..0e33d4839dc 100644 --- a/teku/src/main/java/tech/pegasys/teku/services/BeaconNodeServiceController.java +++ b/teku/src/main/java/tech/pegasys/teku/services/BeaconNodeServiceController.java @@ -20,6 +20,7 @@ import tech.pegasys.teku.config.TekuConfiguration; import tech.pegasys.teku.ethereum.executionclient.web3j.ExecutionWeb3jClientProvider; import tech.pegasys.teku.networking.nat.NatService; +import tech.pegasys.teku.networking.p2p.network.config.NetworkConfig; import tech.pegasys.teku.service.serviceutils.ServiceConfig; import tech.pegasys.teku.services.beaconchain.BeaconChainService; import tech.pegasys.teku.services.chainstorage.StorageService; @@ -58,10 +59,15 @@ public BeaconNodeServiceController( final BeaconChainService beaconChainService = new BeaconChainService(serviceConfig, tekuConfig.beaconChain()); services.add(beaconChainService); + final NetworkConfig networkConfig = tekuConfig.network(); services.add( new NatService( tekuConfig.natConfiguration(), - tekuConfig.network().getListenPort(), + networkConfig.getListenPort(), + // // IPv4 and IPv6 (dual-stack) + networkConfig.getNetworkInterfaces().size() == 2 + ? Optional.of(networkConfig.getListenPortIpv6()) + : Optional.empty(), tekuConfig.discovery().isDiscoveryEnabled())); // making it a Supplier ensures that BeaconChainService has been started and RecentChainData has // been initialized when `get()` is called