From 7ee6a719f3adf3684e43d34d4c4529b3cb18e11e Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 15 Jan 2025 17:53:32 +1100 Subject: [PATCH 1/5] Ipv6 dual-stack by default --- Cargo.lock | 42 +++++++++++++++++++- beacon_node/lighthouse_network/Cargo.toml | 1 + beacon_node/lighthouse_network/src/config.rs | 13 ++++++ beacon_node/src/cli.rs | 7 ++++ beacon_node/src/config.rs | 14 +++++++ 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c62e9fbc878..2e03edff9ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4748,9 +4748,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.164" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libflate" @@ -5324,6 +5324,7 @@ dependencies = [ "libp2p", "libp2p-mplex", "lighthouse_version", + "local-ip-address", "logging", "lru", "lru_cache", @@ -5410,6 +5411,18 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "local-ip-address" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3669cf5561f8d27e8fc84cc15e58350e70f557d4d65f70e3154e54cd2f8e1782" +dependencies = [ + "libc", + "neli", + "thiserror 1.0.69", + "windows-sys 0.59.0", +] + [[package]] name = "lock_api" version = "0.4.12" @@ -5806,6 +5819,31 @@ dependencies = [ "tempfile", ] +[[package]] +name = "neli" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93062a0dce6da2517ea35f301dfc88184ce18d3601ec786a727a87bf535deca9" +dependencies = [ + "byteorder", + "libc", + "log", + "neli-proc-macros", +] + +[[package]] +name = "neli-proc-macros" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8034b7fbb6f9455b2a96c19e6edf8dc9fc34c70449938d8ee3b4df363f61fe" +dependencies = [ + "either", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", +] + [[package]] name = "netlink-packet-core" version = "0.7.0" diff --git a/beacon_node/lighthouse_network/Cargo.toml b/beacon_node/lighthouse_network/Cargo.toml index 485f32b37a7..8b7bf119dd0 100644 --- a/beacon_node/lighthouse_network/Cargo.toml +++ b/beacon_node/lighthouse_network/Cargo.toml @@ -19,6 +19,7 @@ fnv = { workspace = true } futures = { workspace = true } gossipsub = { workspace = true } hex = { workspace = true } +local-ip-address = "0.6" itertools = { workspace = true } libp2p-mplex = "0.42" lighthouse_version = { workspace = true } diff --git a/beacon_node/lighthouse_network/src/config.rs b/beacon_node/lighthouse_network/src/config.rs index 8a93b1185db..207c1edf15f 100644 --- a/beacon_node/lighthouse_network/src/config.rs +++ b/beacon_node/lighthouse_network/src/config.rs @@ -6,6 +6,7 @@ use directory::{ DEFAULT_BEACON_NODE_DIR, DEFAULT_HARDCODED_NETWORK, DEFAULT_NETWORK_DIR, DEFAULT_ROOT_DIR, }; use libp2p::Multiaddr; +use local_ip_address::local_ipv6; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::net::{Ipv4Addr, Ipv6Addr}; @@ -265,6 +266,18 @@ impl Config { } } + /// A helper function to check if the local host has a globally routeable IPv6 address. If so, + /// returns true. + pub fn is_ipv6_supported() -> bool { + // If IPv6 is supported + let Ok(std::net::IpAddr::V6(local_ip)) = local_ipv6() else { + return false; + }; + + // If its globally routable, return true + is_global_ipv6(&local_ip) + } + pub fn listen_addrs(&self) -> &ListenAddress { &self.listen_addresses } diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index cecfcee868f..55aaaab9b35 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -224,6 +224,13 @@ pub fn cli_app() -> Command { .action(ArgAction::Set) .display_order(0) ) + .arg( + Arg::new("disable-ipv6") + .long("disable-ipv6") + .help("If 0.0.0.0 is set as the IPv4 listening address and the host has a globally routeable IPv6 address, Lighthouse will listen on :: by default, in dual-stack mode. This flag prevents this.") + .action(ArgAction::SetTrue) + .display_order(0) + ) .arg( Arg::new("target-peers") .long("target-peers") diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index 8d8a44a6fd6..c9f2a44081a 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -899,6 +899,7 @@ pub fn parse_listening_addresses( // parse the possible ips let mut maybe_ipv4 = None; let mut maybe_ipv6 = None; + for addr_str in listen_addresses_str { let addr = addr_str.parse::().map_err(|parse_error| { format!("Failed to parse listen-address ({addr_str}) as an Ip address: {parse_error}") @@ -926,6 +927,19 @@ pub fn parse_listening_addresses( } } + // If we have specified an IPv4 listen address and not an IPv6 address and the + // host has a globally routeable IPv6 address and the CLI doesn't expressly disable IPv6, + // then we also listen on IPv6. + // Note that we will only listen on all interfaces if the IPv4 counterpart is also listening on + // all interfaces, to prevent accidental exposure of ports. + if maybe_ipv4 == Some(Ipv4Addr::UNSPECIFIED) + && maybe_ipv6.is_none() + && !cli_args.get_flag("disable_ipv6") + && NetworkConfig::is_ipv6_supported() + { + maybe_ipv6 = Some(Ipv6Addr::UNSPECIFIED); + } + // parse the possible tcp ports let port = cli_args .get_one::("port") From e664fb8e63ce935c9ef9f32c755c285ca8e732f6 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Mon, 3 Feb 2025 16:41:02 +1100 Subject: [PATCH 2/5] Listen by default if user does not specify --- beacon_node/src/cli.rs | 13 +++---------- beacon_node/src/config.rs | 36 +++++++++++++++++------------------- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 6696f69cf1d..66137da577c 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -156,16 +156,16 @@ pub fn cli_app() -> Command { .long("listen-address") .value_name("ADDRESS") .help("The address lighthouse will listen for UDP and TCP connections. To listen \ - over IpV4 and IpV6 set this flag twice with the different values.\n\ + over IPv4 and IPv6 set this flag twice with the different values.\n\ Examples:\n\ - --listen-address '0.0.0.0' will listen over IPv4.\n\ - --listen-address '::' will listen over IPv6.\n\ - --listen-address '0.0.0.0' --listen-address '::' will listen over both \ IPv4 and IPv6. The order of the given addresses is not relevant. However, \ - multiple IPv4, or multiple IPv6 addresses will not be accepted.") + multiple IPv4, or multiple IPv6 addresses will not be accepted. \ + If omitted, Lighthouse will listen on all interfaces, for both IPv4 and IPv6.") .action(ArgAction::Append) .num_args(0..=2) - .default_value("0.0.0.0") .display_order(0) ) .arg( @@ -224,13 +224,6 @@ pub fn cli_app() -> Command { .action(ArgAction::Set) .display_order(0) ) - .arg( - Arg::new("disable-ipv6") - .long("disable-ipv6") - .help("If 0.0.0.0 is set as the IPv4 listening address and the host has a globally routeable IPv6 address, Lighthouse will listen on :: by default, in dual-stack mode. This flag prevents this.") - .action(ArgAction::SetTrue) - .display_order(0) - ) .arg( Arg::new("target-peers") .long("target-peers") diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index e2e4c272516..be6083f5437 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -913,8 +913,8 @@ pub fn parse_listening_addresses( IpAddr::V4(v4_addr) => match &maybe_ipv4 { Some(first_ipv4_addr) => { return Err(format!( - "When setting the --listen-address option twice, use an IpV4 address and an Ipv6 address. \ - Got two IpV4 addresses {first_ipv4_addr} and {v4_addr}" + "When setting the --listen-address option twice, use an IPv4 address and an IPv6 address. \ + Got two IPv4 addresses {first_ipv4_addr} and {v4_addr}" )); } None => maybe_ipv4 = Some(v4_addr), @@ -922,8 +922,8 @@ pub fn parse_listening_addresses( IpAddr::V6(v6_addr) => match &maybe_ipv6 { Some(first_ipv6_addr) => { return Err(format!( - "When setting the --listen-address option twice, use an IpV4 address and an Ipv6 address. \ - Got two IpV6 addresses {first_ipv6_addr} and {v6_addr}" + "When setting the --listen-address option twice, use an IPv4 address and an IPv6 address. \ + Got two IPv6 addresses {first_ipv6_addr} and {v6_addr}" )); } None => maybe_ipv6 = Some(v6_addr), @@ -931,19 +931,6 @@ pub fn parse_listening_addresses( } } - // If we have specified an IPv4 listen address and not an IPv6 address and the - // host has a globally routeable IPv6 address and the CLI doesn't expressly disable IPv6, - // then we also listen on IPv6. - // Note that we will only listen on all interfaces if the IPv4 counterpart is also listening on - // all interfaces, to prevent accidental exposure of ports. - if maybe_ipv4 == Some(Ipv4Addr::UNSPECIFIED) - && maybe_ipv6.is_none() - && !cli_args.get_flag("disable_ipv6") - && NetworkConfig::is_ipv6_supported() - { - maybe_ipv6 = Some(Ipv6Addr::UNSPECIFIED); - } - // parse the possible tcp ports let port = cli_args .get_one::("port") @@ -991,11 +978,22 @@ pub fn parse_listening_addresses( format!("Failed to parse --quic6-port as an integer: {parse_error}") })?; + // Here we specify the default listening addresses for Lighthouse. + // By default, we listen on 0.0.0.0. + // + // IF the host supports a globally routable IPv6 address, we also listen on ::. + if matches!((maybe_ipv4, maybe_ipv6), (None, None)) { + maybe_ipv4 = Some(Ipv4Addr::UNSPECIFIED); + + if NetworkConfig::is_ipv6_supported() { + maybe_ipv6 = Some(Ipv6Addr::UNSPECIFIED); + } + } + // Now put everything together let listening_addresses = match (maybe_ipv4, maybe_ipv6) { (None, None) => { - // This should never happen unless clap is broken - return Err("No listening addresses provided".into()); + unreachable!("This path is handled above this match statement"); } (None, Some(ipv6)) => { // A single ipv6 address was provided. Set the ports From 02ac4afe1dc44ce317c4a36684f881c36f4dc1d8 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Mon, 3 Feb 2025 16:47:47 +1100 Subject: [PATCH 3/5] Appease cargo sort --- beacon_node/lighthouse_network/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_node/lighthouse_network/Cargo.toml b/beacon_node/lighthouse_network/Cargo.toml index fba6d05e155..b16ccc2a8ca 100644 --- a/beacon_node/lighthouse_network/Cargo.toml +++ b/beacon_node/lighthouse_network/Cargo.toml @@ -19,10 +19,10 @@ fnv = { workspace = true } futures = { workspace = true } gossipsub = { workspace = true } hex = { workspace = true } -local-ip-address = "0.6" itertools = { workspace = true } libp2p-mplex = "0.43" lighthouse_version = { workspace = true } +local-ip-address = "0.6" lru = { workspace = true } lru_cache = { workspace = true } metrics = { workspace = true } From 7571d1a31a814d33ea515ae311849c0fa17106f1 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Tue, 4 Feb 2025 11:12:00 +1100 Subject: [PATCH 4/5] Handle default CLI --- beacon_node/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index be6083f5437..48601a201ee 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -897,7 +897,7 @@ pub fn parse_listening_addresses( ) -> Result { let listen_addresses_str = cli_args .get_many::("listen-address") - .expect("--listen_addresses has a default value"); + .unwrap_or_default(); let use_zero_ports = parse_flag(cli_args, "zero-ports"); // parse the possible ips From 66a9375fc49a5a5c8cf162a562d67441c868aa17 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Tue, 4 Feb 2025 11:16:41 +1100 Subject: [PATCH 5/5] Fix CLI md --- book/src/help_bn.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/book/src/help_bn.md b/book/src/help_bn.md index 2d12010094c..c99d5c7a5ae 100644 --- a/book/src/help_bn.md +++ b/book/src/help_bn.md @@ -230,7 +230,7 @@ Options: peer without an ENR. --listen-address [
...] The address lighthouse will listen for UDP and TCP connections. To - listen over IpV4 and IpV6 set this flag twice with the different + listen over IPv4 and IPv6 set this flag twice with the different values. Examples: - --listen-address '0.0.0.0' will listen over IPv4. @@ -238,7 +238,8 @@ Options: - --listen-address '0.0.0.0' --listen-address '::' will listen over both IPv4 and IPv6. The order of the given addresses is not relevant. However, multiple IPv4, or multiple IPv6 addresses will not be - accepted. [default: 0.0.0.0] + accepted. If omitted, Lighthouse will listen on all interfaces, for + both IPv4 and IPv6. --log-format Specifies the log format used when emitting logs to the terminal. [possible values: JSON]