diff --git a/shared/services/config/rocket-pool-config.go b/shared/services/config/rocket-pool-config.go index ba6849f89..e39a4236f 100644 --- a/shared/services/config/rocket-pool-config.go +++ b/shared/services/config/rocket-pool-config.go @@ -149,11 +149,10 @@ type RocketPoolConfig struct { RescueNode addontypes.SmartnodeAddon `yaml:"addon-rescue-node,omitempty"` } -// Get the external IP address. Try finding an IPv4 address first to: -// * Improve peer discovery and node performance -// * Avoid unnecessary container restarts caused by switching between IPv4 and IPv6 +// Get the external IPv4 address. IPv6 is reported separately by GetExternalIpv6 +// so EXTERNAL_IP stays IPv4-or-blank and does not flip families (which would +// recreate containers). func getExternalIP() (net.IP, error) { - // Try IPv4 first consensusConfig := externalip.ConsensusConfig{Timeout: 3 * time.Second} ip4Consensus := externalip.DefaultConsensus(&consensusConfig, nil) err := ip4Consensus.UseIPProtocol(4) @@ -161,18 +160,7 @@ func getExternalIP() (net.IP, error) { // Only panics if the IP protocol isn't one of 0, 4, or 6 panic(err) } - if ip, err := ip4Consensus.ExternalIP(); err == nil { - return ip, nil - } - - // Try IPv6 as fallback - ip6Consensus := externalip.DefaultConsensus(nil, nil) - err = ip6Consensus.UseIPProtocol(6) - if err != nil { - // Only panics if the IP protocol isn't one of 0, 4, or 6 - panic(err) - } - return ip6Consensus.ExternalIP() + return ip4Consensus.ExternalIP() } // Load configuration settings from a file @@ -1478,21 +1466,24 @@ func (cfg *RocketPoolConfig) IsIPv6Enabled() bool { return cfg.EnableIPv6.Value.(bool) } -// Used by text/template to format eth1.yml +// Used by text/template to format eth1.yml and eth2.yml. +// Returns the external IPv4 address, or empty string if IPv4 is unavailable. func (cfg *RocketPoolConfig) GetExternalIp() string { - // Get the external IP address ip, err := getExternalIP() if err != nil { fmt.Println("Warning: couldn't get external IP address; if you're using Nimbus or Besu, it may have trouble finding peers:") fmt.Println(err.Error()) + if !cfg.IsIPv6Enabled() && cfg.GetExternalIpv6() != "" { + fmt.Println("Warning: your external IP address is IPv6. If you haven't enabled IPv6 support in your configuration, your node may have trouble finding peers. Run 'rocketpool service config' and enable IPv6 under 'Smart Node and TX Fees'.") + } return "" } - if ip.To4() == nil && !cfg.IsIPv6Enabled() { - fmt.Println("Warning: your external IP address is IPv6. If you haven't enabled IPv6 support in your configuration, your node may have trouble finding peers. Run 'rocketpool service config' and enable IPv6 under 'Smart Node and TX Fees'.") + v4 := ip.To4() + if v4 == nil { + return "" } - - return ip.String() + return v4.String() } // Used by text/template to format eth2.yml when IPv6 is enabled. diff --git a/shared/services/rocketpool/assets/install/scripts/start-bn.sh b/shared/services/rocketpool/assets/install/scripts/start-bn.sh index e249ad76a..c19ecd3c4 100755 --- a/shared/services/rocketpool/assets/install/scripts/start-bn.sh +++ b/shared/services/rocketpool/assets/install/scripts/start-bn.sh @@ -141,11 +141,7 @@ if [ "$CC_CLIENT" = "lodestar" ]; then fi if [ ! -z "$EXTERNAL_IP" ]; then - if expr "$EXTERNAL_IP" : '.*:' >/dev/null; then - CMD="$CMD --enr.ip6 $EXTERNAL_IP --nat" - else - CMD="$CMD --enr.ip $EXTERNAL_IP --nat" - fi + CMD="$CMD --enr.ip $EXTERNAL_IP --nat" fi if [ "$ENABLE_IPV6" = "true" ]; then @@ -327,7 +323,7 @@ if [ "$CC_CLIENT" = "teku" ]; then if [ "$ENABLE_IPV6" = "true" ]; then CMD="$CMD --p2p-interface=0.0.0.0,:: --p2p-port-ipv6=$BN_IPV6_P2P_PORT --p2p-quic-port-ipv6=$BN_IPV6_QUIC_P2P_PORT" if [ ! -z "$EXTERNAL_IP6" ]; then - if [ ! -z "$EXTERNAL_IP" ] && ! expr "$EXTERNAL_IP" : '.*:' >/dev/null; then + if [ ! -z "$EXTERNAL_IP" ]; then CMD="$CMD --p2p-advertised-ips $EXTERNAL_IP,$EXTERNAL_IP6 --p2p-advertised-port-ipv6=$BN_IPV6_P2P_PORT" else CMD="$CMD --p2p-advertised-ips $EXTERNAL_IP6 --p2p-advertised-port-ipv6=$BN_IPV6_P2P_PORT" diff --git a/shared/services/rocketpool/assets/install/scripts/start-ec.sh b/shared/services/rocketpool/assets/install/scripts/start-ec.sh index d64e7c0be..2a3b7bb2c 100755 --- a/shared/services/rocketpool/assets/install/scripts/start-ec.sh +++ b/shared/services/rocketpool/assets/install/scripts/start-ec.sh @@ -345,6 +345,16 @@ if [ "$CLIENT" = "besu" ]; then CMD="$CMD --p2p-host=$EXTERNAL_IP" fi + if [ "$ENABLE_IPV6" = "true" ]; then + CMD="$CMD --discovery-mode=V5 --p2p-ipv6-outbound-enabled --p2p-interface-ipv6=::" + if [ ! -z "$EC_P2P_PORT" ]; then + CMD="$CMD --p2p-port-ipv6=$EC_P2P_PORT" + fi + if [ ! -z "$EXTERNAL_IP6" ]; then + CMD="$CMD --p2p-host-ipv6=$EXTERNAL_IP6" + fi + fi + if [ ! -z "$EC_SUGGESTED_BLOCK_GAS_LIMIT" ]; then CMD="$CMD --target-gas-limit=$EC_SUGGESTED_BLOCK_GAS_LIMIT" fi diff --git a/shared/services/rocketpool/assets/install/templates/eth1.tmpl b/shared/services/rocketpool/assets/install/templates/eth1.tmpl index c1476193a..f440ecf55 100644 --- a/shared/services/rocketpool/assets/install/templates/eth1.tmpl +++ b/shared/services/rocketpool/assets/install/templates/eth1.tmpl @@ -15,7 +15,7 @@ services: stop_grace_period: 15m {{- $p2p := (or .ExecutionCommon.P2pPort.Value "30303")}} {{- $torrent := (or .Erigon.TorrentPort.Value "42069")}} - ports: [ "{{$p2p}}:{{$p2p}}/udp", "{{$p2p}}:{{$p2p}}/tcp"{{if eq .ExecutionClient.String "erigon"}}, "{{$torrent}}:{{$torrent}}/udp", "{{$torrent}}:{{$torrent}}/tcp"{{end}}{{.GetECOpenAPIPorts}} ] + ports: [ "{{if .IsIPv6Enabled}}[::]:{{end}}{{$p2p}}:{{$p2p}}/udp", "{{if .IsIPv6Enabled}}[::]:{{end}}{{$p2p}}:{{$p2p}}/tcp"{{if eq .ExecutionClient.String "erigon"}}, "{{$torrent}}:{{$torrent}}/udp", "{{$torrent}}:{{$torrent}}/tcp"{{end}}{{.GetECOpenAPIPorts}} ] volumes: - eth1clientdata:/ethclient - {{.RocketPoolDirectory}}/scripts:/setup:ro @@ -38,6 +38,10 @@ services: - EC_WS_PORT={{.ExecutionCommon.WsPort}} - EC_ENGINE_PORT={{.ExecutionCommon.EnginePort}} - EXTERNAL_IP={{.GetExternalIp}} + {{- if .IsIPv6Enabled}} + - EXTERNAL_IP6={{.GetExternalIpv6}} + {{- end}} + - ENABLE_IPV6={{.IsIPv6Enabled}} - ENABLE_METRICS={{.EnableMetrics}} - EC_METRICS_PORT={{.EcMetricsPort}} {{- /* Client-specific values */}}