diff --git a/Cargo.lock b/Cargo.lock index 4581fb9ce0..219b6df0d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5432,6 +5432,7 @@ dependencies = [ "libp2p", "libp2p-mplex", "lighthouse_version", + "local-ip-address", "logging", "lru", "lru_cache", @@ -5512,6 +5513,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" @@ -5955,6 +5968,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 3c89ece442..b16ccc2a8c 100644 --- a/beacon_node/lighthouse_network/Cargo.toml +++ b/beacon_node/lighthouse_network/Cargo.toml @@ -22,6 +22,7 @@ hex = { workspace = true } 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 } diff --git a/beacon_node/lighthouse_network/src/config.rs b/beacon_node/lighthouse_network/src/config.rs index 843187d9a7..5a6628439e 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}; @@ -266,6 +267,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 942e2bc33e..4c2daecdd3 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -147,16 +147,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( diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index b6e7dd55f1..24d569bea2 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -905,12 +905,13 @@ 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 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}") @@ -920,8 +921,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), @@ -929,8 +930,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), @@ -984,11 +985,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 diff --git a/book/src/help_bn.md b/book/src/help_bn.md index 2feb2e306b..cbcb1ec5a3 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]