Skip to content

Commit a410065

Browse files
authored
Merge pull request #1015 from rocket-pool/ipv6-stack
Ipv6 stack
2 parents 8ba738c + 7f8ef8f commit a410065

18 files changed

Lines changed: 140 additions & 13 deletions

rocketpool-cli/service/config/settings-native-smartnode.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func NewNativeSmartnodeConfigPage(home *settingsNativeHome) *NativeSmartnodeConf
2323
configPage.page = newPage(
2424
home.homePage,
2525
"settings-native-smartnode",
26-
"Smartnode and TX Fees",
26+
"Smart Node and TX Fees",
2727
"Select this to configure the settings for the Smart Node itself, including the defaults and limits on transaction fees.",
2828
configPage.layout.grid,
2929
)
@@ -43,7 +43,8 @@ func (configPage *NativeSmartnodeConfigPage) createContent() {
4343
layout.setupEscapeReturnHomeHandler(configPage.home.md, configPage.home.homePage)
4444

4545
// Set up the form items
46-
formItems := createParameterizedFormItems(masterConfig.Smartnode.GetParameters(), layout.descriptionBox)
46+
params := append(masterConfig.Smartnode.GetParameters(), &masterConfig.EnableIPv6, &masterConfig.Alertmanager.ShowAlertsOnCLI)
47+
formItems := createParameterizedFormItems(params, layout.descriptionBox)
4748
for _, formItem := range formItems {
4849
if formItem.parameter.ID == config.ProjectNameID {
4950
// Ignore the project name ID since it doesn't apply to native mode

rocketpool-cli/service/config/settings-smartnode.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func NewSmartnodeConfigPage(home *settingsHome) *SmartnodeConfigPage {
2525
configPage.page = newPage(
2626
home.homePage,
2727
"settings-smartnode",
28-
"Smartnode and TX Fees",
28+
"Smart Node and TX Fees",
2929
"Select this to configure the settings for the Smart Node itself, including the defaults and limits on transaction fees.",
3030
configPage.layout.grid,
3131
)
@@ -68,7 +68,8 @@ func (configPage *SmartnodeConfigPage) createContent() {
6868
})
6969

7070
// Set up the form items
71-
formItems := createParameterizedFormItems(masterConfig.Smartnode.GetParameters(), layout.descriptionBox)
71+
params := append(masterConfig.Smartnode.GetParameters(), &masterConfig.EnableIPv6, &masterConfig.Alertmanager.ShowAlertsOnCLI)
72+
formItems := createParameterizedFormItems(params, layout.descriptionBox)
7273
for _, formItem := range formItems {
7374
layout.form.AddFormItem(formItem.item)
7475
layout.parameters[formItem.item] = formItem

rocketpool-cli/service/service.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,12 @@ func configureService(configPath string, isNative, yes bool, composeFiles []stri
328328
})
329329
}
330330

331+
// Warn if IPv6 is enabled but no public IPv6 address is available
332+
if md.Config.IsIPv6Enabled() && md.Config.GetExternalIpv6() == "" {
333+
color.YellowPrintln("Warning: IPv6 is enabled but no public IPv6 address was detected. Your node will not be reachable by IPv6 peers.")
334+
fmt.Println()
335+
}
336+
331337
// Query for service start if this is old and there are containers to change
332338
if len(md.ContainersToRestart) > 0 {
333339
fmt.Println("The following containers must be restarted for the changes to take effect:")
@@ -520,6 +526,12 @@ func startService(params startServiceParams) error {
520526
return fmt.Errorf("No configuration detected. Please run `rocketpool service config` to set up your Smart Node before running it.")
521527
}
522528

529+
// Warn if IPv6 is enabled but no public IPv6 address is available
530+
if cfg.IsIPv6Enabled() && cfg.GetExternalIpv6() == "" {
531+
color.YellowPrintln("Warning: IPv6 is enabled but no public IPv6 address was detected. Your node will not be reachable by IPv6 peers.")
532+
fmt.Println()
533+
}
534+
523535
// Check if this is a new install
524536
isUpdate, err := rp.IsFirstRun()
525537
if err != nil {

shared/services/config/rocket-pool-config.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ type RocketPoolConfig struct {
7676
ConsensusClient config.Parameter `yaml:"consensusClient,omitempty"`
7777
ExternalConsensusClient config.Parameter `yaml:"externalConsensusClient,omitempty"`
7878

79+
// IPv6 networking
80+
EnableIPv6 config.Parameter `yaml:"enableIPv6,omitempty"`
81+
7982
// Metrics settings
8083
EnableMetrics config.Parameter `yaml:"enableMetrics,omitempty"`
8184
EnableODaoMetrics config.Parameter `yaml:"enableODaoMetrics,omitempty"`
@@ -352,6 +355,17 @@ func NewRocketPoolConfig(rpDir string, isNativeMode bool) *RocketPoolConfig {
352355
}},
353356
},
354357

358+
EnableIPv6: config.Parameter{
359+
ID: "enableIPv6",
360+
Name: "Enable IPv6",
361+
Description: "Enables dual-stack (IPv4 + IPv6) networking for the Smart Node. When enabled, your Ethereum clients will listen on both IPv4 and IPv6 and can peer with IPv6 nodes in addition to IPv4. Enable this if your machine has only an IPv6 address, or if you want your node to participate in IPv6 peering.",
362+
Type: config.ParameterType_Bool,
363+
Default: map[config.Network]interface{}{config.Network_All: false},
364+
AffectsContainers: []config.ContainerID{config.ContainerID_Api, config.ContainerID_Node, config.ContainerID_Watchtower, config.ContainerID_Eth1, config.ContainerID_Eth2, config.ContainerID_Validator, config.ContainerID_Grafana, config.ContainerID_Prometheus, config.ContainerID_Alertmanager, config.ContainerID_Exporter, config.ContainerID_MevBoost, config.ContainerID_CommitBoost},
365+
CanBeBlank: false,
366+
OverwriteOnUpgrade: false,
367+
},
368+
355369
EnableMetrics: config.Parameter{
356370
ID: "enableMetrics",
357371
Name: "Enable Metrics",
@@ -573,6 +587,7 @@ func (cfg *RocketPoolConfig) GetParameters() []*config.Parameter {
573587
&cfg.ConsensusClientMode,
574588
&cfg.ConsensusClient,
575589
&cfg.ExternalConsensusClient,
590+
&cfg.EnableIPv6,
576591
&cfg.EnableMetrics,
577592
&cfg.EnableODaoMetrics,
578593
&cfg.EnableBitflyNodeMetrics,
@@ -1327,6 +1342,12 @@ func (cfg *RocketPoolConfig) GetECAdditionalFlags() (string, error) {
13271342
return "", fmt.Errorf("Unknown Execution Client %s", string(cfg.ExecutionClient.Value.(config.ExecutionClient)))
13281343
}
13291344

1345+
// IsIPv6Enabled returns true if IPv6 support is enabled for the Docker network.
1346+
// Used by text/template to conditionally add enable_ipv6 to compose network definitions.
1347+
func (cfg *RocketPoolConfig) IsIPv6Enabled() bool {
1348+
return cfg.EnableIPv6.Value.(bool)
1349+
}
1350+
13301351
// Used by text/template to format eth1.yml
13311352
func (cfg *RocketPoolConfig) GetExternalIp() string {
13321353
// Get the external IP address
@@ -1337,13 +1358,31 @@ func (cfg *RocketPoolConfig) GetExternalIp() string {
13371358
return ""
13381359
}
13391360

1340-
if ip.To4() == nil {
1341-
fmt.Println("Warning: external IP address is v6; if you're using Nimbus or Besu, it may have trouble finding peers:")
1361+
if ip.To4() == nil && !cfg.IsIPv6Enabled() {
1362+
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'.")
13421363
}
13431364

13441365
return ip.String()
13451366
}
13461367

1368+
// Used by text/template to format eth2.yml when IPv6 is enabled.
1369+
// Lodestar requires --enr.ip6 and Teku requires --p2p-advertised-ips to advertise IPv6 in their ENR.
1370+
// Returns the external IPv6 address, or empty string if unavailable.
1371+
func (cfg *RocketPoolConfig) GetExternalIpv6() string {
1372+
consensusConfig := externalip.ConsensusConfig{Timeout: 3 * time.Second}
1373+
ip6Consensus := externalip.DefaultConsensus(&consensusConfig, nil)
1374+
err := ip6Consensus.UseIPProtocol(6)
1375+
if err != nil {
1376+
return ""
1377+
}
1378+
1379+
ip, err := ip6Consensus.ExternalIP()
1380+
if err != nil || ip.To4() != nil {
1381+
return ""
1382+
}
1383+
return ip.String()
1384+
}
1385+
13471386
// Gets the tag of the cc container
13481387
// Used by text/template to format eth2.yml
13491388
func (cfg *RocketPoolConfig) GetBeaconContainerTag() (string, error) {

shared/services/config/teku-config.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import (
77
)
88

99
const (
10-
tekuTagTest string = "consensys/teku:26.4.0"
11-
tekuTagProd string = "consensys/teku:26.4.0"
12-
defaultTekuMaxPeers uint16 = 100
10+
tekuTagTest string = "consensys/teku:26.4.0"
11+
tekuTagProd string = "consensys/teku:26.4.0"
12+
defaultTekuMaxPeers uint16 = 100
13+
defaultTekuP2pIpv6Port uint16 = 9090
1314
)
1415

1516
// Configuration for Teku
@@ -37,6 +38,9 @@ type TekuConfig struct {
3738
// Custom command line flags for the BN
3839
AdditionalBnFlags config.Parameter `yaml:"additionalBnFlags,omitempty"`
3940

41+
// The IPv6 P2P port for Teku (Teku uses a separate port for IPv6)
42+
P2pIpv6Port config.Parameter `yaml:"p2pIpv6Port,omitempty"`
43+
4044
// Custom command line flags for the VC
4145
AdditionalVcFlags config.Parameter `yaml:"additionalVcFlags,omitempty"`
4246
}
@@ -121,6 +125,17 @@ func NewTekuConfig(cfg *RocketPoolConfig) *TekuConfig {
121125
OverwriteOnUpgrade: false,
122126
},
123127

128+
P2pIpv6Port: config.Parameter{
129+
ID: "p2pIpv6Port",
130+
Name: "P2P IPv6 Port",
131+
Description: "The port Teku uses for P2P communication over IPv6. Teku requires a dedicated port for IPv6 (separate from the main P2P port). Only used when IPv6 support is enabled.",
132+
Type: config.ParameterType_Uint16,
133+
Default: map[config.Network]interface{}{config.Network_All: defaultTekuP2pIpv6Port},
134+
AffectsContainers: []config.ContainerID{config.ContainerID_Eth2},
135+
CanBeBlank: false,
136+
OverwriteOnUpgrade: false,
137+
},
138+
124139
AdditionalVcFlags: config.Parameter{
125140
ID: "additionalVcFlags",
126141
Name: "Additional Validator Client Flags",
@@ -143,6 +158,7 @@ func (cfg *TekuConfig) GetParameters() []*config.Parameter {
143158
&cfg.UseSlashingProtection,
144159
&cfg.ContainerTag,
145160
&cfg.AdditionalBnFlags,
161+
&cfg.P2pIpv6Port,
146162
&cfg.AdditionalVcFlags,
147163
}
148164
}

shared/services/connectivity/check-port-connectivity.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ var publicIPResolvers = []struct {
3030
addr string // host:port (IP literal)
3131
hostname string // special hostname that returns the caller's public IP
3232
}{
33-
{"208.67.222.222:53", "myip.opendns.com"}, // OpenDNS primary
34-
{"208.67.220.220:53", "myip.opendns.com"}, // OpenDNS secondary
35-
{"216.239.32.10:53", "o-o.myaddr.l.google.com"}, // Google ns1
33+
{"208.67.222.222:53", "myip.opendns.com"}, // OpenDNS primary (IPv4)
34+
{"208.67.220.220:53", "myip.opendns.com"}, // OpenDNS secondary (IPv4)
35+
{"216.239.32.10:53", "o-o.myaddr.l.google.com"}, // Google ns1 (IPv4)
36+
{"[2620:119:35::35]:53", "myip.opendns.com"}, // OpenDNS primary (IPv6)
37+
{"[2620:119:53::53]:53", "myip.opendns.com"}, // OpenDNS secondary (IPv6)
38+
{"[2001:4860:4860::8888]:53", "o-o.myaddr.l.google.com"}, // Google ns1 (IPv6)
3639
}
3740

3841
// Check port connectivity task

shared/services/rocketpool/assets/install/scripts/start-bn.sh

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ if [ "$CC_CLIENT" = "lighthouse" ]; then
9999
CMD="$CMD --monitoring-endpoint $BITFLY_NODE_METRICS_ENDPOINT?apikey=$BITFLY_NODE_METRICS_SECRET&machine=$BITFLY_NODE_METRICS_MACHINE_NAME"
100100
fi
101101

102+
if [ "$ENABLE_IPV6" = "true" ]; then
103+
CMD="$CMD --listen-address 0.0.0.0 --listen-address :: --port6 $BN_P2P_PORT --enr-udp6-port $BN_P2P_PORT --quic-port6 ${BN_P2P_QUIC_PORT:-8001}"
104+
fi
105+
102106
exec ${CMD}
103107

104108
fi
@@ -142,7 +146,14 @@ if [ "$CC_CLIENT" = "lodestar" ]; then
142146
else
143147
CMD="$CMD --enr.ip $EXTERNAL_IP --nat"
144148
fi
145-
fi
149+
fi
150+
151+
if [ "$ENABLE_IPV6" = "true" ]; then
152+
CMD="$CMD --listenAddress 0.0.0.0 --listenAddress6 :: --port6 $BN_P2P_PORT --quicPort6 ${BN_P2P_QUIC_PORT:-8001}"
153+
if [ ! -z "$EXTERNAL_IP6" ]; then
154+
CMD="$CMD --enr.ip6 $EXTERNAL_IP6"
155+
fi
156+
fi
146157

147158
if [ ! -z "$CHECKPOINT_SYNC_URL" ]; then
148159
CMD="$CMD --checkpointSyncUrl $CHECKPOINT_SYNC_URL"
@@ -313,6 +324,17 @@ if [ "$CC_CLIENT" = "teku" ]; then
313324
CMD="$CMD --metrics-publish-endpoint=$BITFLY_NODE_METRICS_ENDPOINT?apikey=$BITFLY_NODE_METRICS_SECRET&machine=$BITFLY_NODE_METRICS_MACHINE_NAME"
314325
fi
315326

327+
if [ "$ENABLE_IPV6" = "true" ]; then
328+
CMD="$CMD --p2p-interface=0.0.0.0,:: --p2p-port-ipv6=$BN_IPV6_P2P_PORT"
329+
if [ ! -z "$EXTERNAL_IP6" ]; then
330+
if [ ! -z "$EXTERNAL_IP" ] && ! expr "$EXTERNAL_IP" : '.*:' >/dev/null; then
331+
CMD="$CMD --p2p-advertised-ips $EXTERNAL_IP,$EXTERNAL_IP6 --p2p-advertised-port-ipv6=$BN_IPV6_P2P_PORT"
332+
else
333+
CMD="$CMD --p2p-advertised-ips $EXTERNAL_IP6 --p2p-advertised-port-ipv6=$BN_IPV6_P2P_PORT"
334+
fi
335+
fi
336+
fi
337+
316338
if [ "$TEKU_JVM_HEAP_SIZE" -gt "0" ]; then
317339
CMD="env JAVA_OPTS=\"-Xmx${TEKU_JVM_HEAP_SIZE}m\" $CMD"
318340
fi

shared/services/rocketpool/assets/install/templates/alertmanager.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ services:
2121
- net
2222
networks:
2323
net:
24+
enable_ipv6: {{ .IsIPv6Enabled }}
2425
volumes:
2526
alertmanager-data:

shared/services/rocketpool/assets/install/templates/commit-boost.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ services:
2929
- no-new-privileges
3030
networks:
3131
net:
32+
enable_ipv6: {{ .IsIPv6Enabled }}

shared/services/rocketpool/assets/install/templates/eth1.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,6 @@ services:
6666
- no-new-privileges
6767
networks:
6868
net:
69+
enable_ipv6: {{ .IsIPv6Enabled }}
6970
volumes:
7071
eth1clientdata:

0 commit comments

Comments
 (0)