Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions anchor/client/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,14 @@ pub struct Node {
)]
pub use_zero_ports: bool,

#[clap(
long,
help = "Disables UPnP support. Setting this will prevent Anchor \
from attempting to automatically establish external port mappings.",
default_value = "false"
)]
pub disable_upnp: bool,

#[clap(
long,
help = "Specify the target number of connected peers",
Expand Down
4 changes: 4 additions & 0 deletions anchor/client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,13 @@ pub fn from_cli(cli_args: &Node, global_config: GlobalConfig) -> Result<Config,

config.network.subscribe_all_subnets = cli_args.subscribe_all_subnets;

// If the flag was set (true), it means we disable upnp so upnp_enabled should be false
config.network.upnp_enabled = !cli_args.disable_upnp;

if let Some(target_peers) = cli_args.target_peers {
config.network.target_peers = target_peers;
}

// Network related - set peer scoring configuration
config.network.disable_gossipsub_peer_scoring = cli_args.disable_gossipsub_peer_scoring;
config.network.disable_gossipsub_topic_scoring = cli_args.disable_gossipsub_topic_scoring;
Expand Down
1 change: 1 addition & 0 deletions anchor/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ libp2p = { workspace = true, default-features = false, features = [
"quic",
"ping",
"request-response",
"upnp",
"dns",
"metrics",
] }
Expand Down
15 changes: 14 additions & 1 deletion anchor/network/src/behaviour.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use std::{hash::Hasher, time::Duration};

use gossipsub::{ConfigBuilderError, MessageAuthenticity, ValidationMode};
use libp2p::{identify, ping, swarm::NetworkBehaviour};
use libp2p::{
identify, ping,
swarm::{NetworkBehaviour, behaviour::toggle::Toggle},
upnp::tokio::Behaviour as Upnp,
};
use prometheus_client::registry::Registry;
use thiserror::Error;
use twox_hash::XxHash64;
Expand Down Expand Up @@ -69,6 +73,8 @@ pub struct AnchorBehaviour {
/// Anchor peer manager, wrapping libp2p behaviours with minimal added logic for peer
/// selection.
pub peer_manager: PeerManager,
/// Libp2p UPnP port mapping.
pub upnp: Toggle<Upnp>,

pub handshake: handshake::Behaviour,
}
Expand Down Expand Up @@ -157,13 +163,20 @@ impl AnchorBehaviour {

let handshake = handshake::create_behaviour(local_keypair);

let upnp = Toggle::from(
network_config
.upnp_enabled
.then(libp2p::upnp::tokio::Behaviour::default),
);

Ok(AnchorBehaviour {
identify,
ping: ping::Behaviour::default(),
gossipsub,
discovery,
peer_manager,
handshake,
upnp,
})
}
}
Expand Down
4 changes: 4 additions & 0 deletions anchor/network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ pub struct Config {
/// Target number of connected peers.
pub target_peers: usize,

/// Attempt to construct external port mappings with UPnP.
pub upnp_enabled: bool,

pub domain_type: DomainType,
}

Expand Down Expand Up @@ -109,6 +112,7 @@ impl Config {
disable_quic_support: false,
subscribe_all_subnets: false,
domain_type: DomainType::default(),
upnp_enabled: true,
}
}
}
46 changes: 46 additions & 0 deletions anchor/network/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use libp2p::{
identity::Keypair,
multiaddr::Protocol,
swarm::{SwarmEvent, dial_opts::DialOpts},
upnp::Event,
};
use message_receiver::{MessageReceiver, Outcome};
use prometheus_client::registry::Registry;
Expand Down Expand Up @@ -235,6 +236,9 @@ impl<R: MessageReceiver> Network<R> {
self.handle_handshake_result(result);
}
}
AnchorBehaviourEvent::Upnp(upnp_event) => {
self.on_upnp_event(upnp_event);
}
AnchorBehaviourEvent::PeerManager(peer_manager::Event::Heartbeat(heartbeat)) => {
if let Some(actions) = heartbeat.connect_actions {
self.handle_connect_actions(actions);
Expand Down Expand Up @@ -542,6 +546,48 @@ impl<R: MessageReceiver> Network<R> {
}
}

fn on_upnp_event(&mut self, event: Event) {
match event {
libp2p::upnp::Event::NewExternalAddr(addr) => {
info!(%addr, "UPnP route established");
let mut iter = addr.iter();
let is_ipv6 = {
let addr = iter.next();
matches!(addr, Some(Protocol::Ip6(_)))
};
match iter.next() {
Some(Protocol::Udp(udp_port)) => match iter.next() {
Some(Protocol::QuicV1) => {
if let Err(e) =
self.discovery().try_update_port(false, is_ipv6, udp_port)
{
warn!(error = e, "Failed to update ENR");
}
}
_ => {
trace!(%addr, "UPnP address mapped multiaddr from unknown transport");
}
},
Some(Protocol::Tcp(tcp_port)) => {
if let Err(e) = self.discovery().try_update_port(true, is_ipv6, tcp_port) {
warn!(error = e, "Failed to update ENR");
}
}
_ => {
trace!(%addr, "UPnP address mapped multiaddr from unknown transport");
}
}
}
libp2p::upnp::Event::ExpiredExternalAddr(addr) => {
info!(%addr, "UPnP route expired");
}
libp2p::upnp::Event::GatewayNotFound => info!("UPnP not available."),
libp2p::upnp::Event::NonRoutableGateway => {
info!("UPnP is available but gateway is not exposed to public network")
}
}
}

fn peer_manager(&mut self) -> &mut PeerManager {
&mut self.swarm.behaviour_mut().peer_manager
}
Expand Down
Loading