Files
lighthouse/beacon_node/network/src/nat.rs
chonghe 522bd9e9c6 Update Rust Edition to 2024 (#7766)
* #7749

Thanks @dknopik and @michaelsproul for your help!
2025-08-13 03:04:31 +00:00

57 lines
1.8 KiB
Rust

//! This houses various NAT hole punching strategies.
//!
//! Currently supported strategies:
//! - UPnP
use anyhow::{Context, Error, bail};
use igd_next::{PortMappingProtocol, aio::tokio as igd};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::time::Duration;
use tokio::time::sleep;
use tracing::debug;
/// The duration in seconds of a port mapping on the gateway.
const MAPPING_DURATION: u32 = 3600;
/// Renew the Mapping every half of `MAPPING_DURATION` to avoid the port being unmapped.
const MAPPING_TIMEOUT: u64 = MAPPING_DURATION as u64 / 2;
/// Attempts to map Discovery external port mappings with UPnP.
pub async fn construct_upnp_mappings(addr: Ipv4Addr, port: u16) -> Result<(), Error> {
let gateway = igd::search_gateway(Default::default())
.await
.context("Gateway does not support UPnP")?;
let external_address = gateway
.get_external_ip()
.await
.context("Could not access gateway's external ip")?;
let is_private = match external_address {
IpAddr::V4(ipv4) => ipv4.is_private(),
IpAddr::V6(ipv6) => ipv6.is_loopback() || ipv6.is_unspecified(),
};
if is_private {
bail!(
"Gateway's external address is a private address: {}",
external_address
);
}
loop {
gateway
.add_port(
PortMappingProtocol::UDP,
port,
SocketAddr::new(IpAddr::V4(addr), port),
MAPPING_DURATION,
"Lighthouse Discovery port",
)
.await
.with_context(|| format!("Could not UPnP map port: {} on the gateway", port))?;
debug!(%port,"Discovery UPnP port mapped");
sleep(Duration::from_secs(MAPPING_TIMEOUT)).await;
}
}