fixed regression in NAT traversal (gossip was only exchanging IP info, not ports)

This commit is contained in:
Lyn 2025-01-29 11:41:36 +01:00
parent 7f844a2f5d
commit 7d02510878

View file

@ -206,10 +206,10 @@ struct PeerInfo {
gossip_ip: IpAddr, gossip_ip: IpAddr,
gossip_prio: u64, gossip_prio: u64,
// Info retrieved from wireguard // Info retrieved from wireguard
endpoint: Option<IpAddr>, endpoint: Option<SocketAddr>,
last_seen: u64, last_seen: u64,
// Info received by LAN broadcast // Info received by LAN broadcast
lan_endpoint: Option<(IpAddr, u64)>, lan_endpoint: Option<(SocketAddr, u64)>,
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -218,7 +218,7 @@ enum Gossip {
Pong, Pong,
Announce { Announce {
pubkey: Pubkey, pubkey: Pubkey,
endpoints: Vec<(IpAddr, u64)>, endpoints: Vec<(SocketAddr, u64)>,
}, },
Request, Request,
LanBroadcast { LanBroadcast {
@ -393,7 +393,7 @@ impl Daemon {
Gossip::LanBroadcast { pubkey } => { Gossip::LanBroadcast { pubkey } => {
if self.config.lan_discovery { if self.config.lan_discovery {
if let Some(peer) = state.peers.get_mut(&pubkey) { if let Some(peer) = state.peers.get_mut(&pubkey) {
peer.lan_endpoint = Some((from.ip(), time())); peer.lan_endpoint = Some((from, time()));
} }
} }
} }
@ -551,7 +551,7 @@ impl Daemon {
struct State { struct State {
peers: HashMap<Pubkey, PeerInfo>, peers: HashMap<Pubkey, PeerInfo>,
gossip: HashMap<Pubkey, Vec<(IpAddr, u64)>>, gossip: HashMap<Pubkey, Vec<(SocketAddr, u64)>>,
interfaces: HashMap<String, IfInfo>, interfaces: HashMap<String, IfInfo>,
} }
@ -573,7 +573,7 @@ impl State {
.config .config
.forbidden_nets .forbidden_nets
.iter() .iter()
.any(|net| net.contains(&ep)) .any(|net| net.contains(&ep.ip()))
}) })
.unwrap_or(false); .unwrap_or(false);
seen && endpoint_valid seen && endpoint_valid
@ -595,7 +595,7 @@ impl State {
&mut self, &mut self,
daemon: &Daemon, daemon: &Daemon,
pubkey: Pubkey, pubkey: Pubkey,
mut endpoints: Vec<(IpAddr, u64)>, mut endpoints: Vec<(SocketAddr, u64)>,
) -> Result<()> { ) -> Result<()> {
let propagate = { let propagate = {
match self.gossip.get_mut(&pubkey) { match self.gossip.get_mut(&pubkey) {
@ -647,7 +647,7 @@ impl State {
*ifinfo = wg_dump(&ifname)?; *ifinfo = wg_dump(&ifname)?;
for (pk, endpoint, last_seen) in &mut ifinfo.peers { for (pk, endpoint, last_seen) in &mut ifinfo.peers {
if let Some(i) = self.peers.get_mut(&*pk) { if let Some(i) = self.peers.get_mut(&*pk) {
i.endpoint = endpoint.as_ref().map(SocketAddr::ip); i.endpoint = *endpoint;
i.last_seen = *last_seen; i.last_seen = *last_seen;
} else { } else {
warn!("unknown peer: {}", pk); warn!("unknown peer: {}", pk);
@ -686,7 +686,7 @@ impl State {
.config .config
.forbidden_nets .forbidden_nets
.iter() .iter()
.any(|net| net.contains(&ep)) .any(|net| net.contains(&ep.ip()))
}) })
.unwrap_or(false); .unwrap_or(false);
@ -726,11 +726,12 @@ impl State {
.cloned() .cloned()
.unwrap_or_default(); .unwrap_or_default();
if let Some(endpoint) = &peer_cfg.endpoint { if let Some(endpoint) = &peer_cfg.endpoint {
match format!("{}:0", endpoint).to_socket_addrs() { let port = peer_cfg.port.unwrap_or(0);
match format!("{}:{}", endpoint, port).to_socket_addrs() {
Err(e) => error!("Could not resolve DNS for {}: {}", endpoint, e), Err(e) => error!("Could not resolve DNS for {}: {}", endpoint, e),
Ok(iter) => { Ok(iter) => {
for addr in iter { for addr in iter {
endpoints.push((addr.ip(), 0)); endpoints.push((addr, 0));
} }
} }
} }
@ -743,7 +744,7 @@ impl State {
.config .config
.forbidden_nets .forbidden_nets
.iter() .iter()
.any(|net| net.contains(ep)) .any(|net| net.contains(&ep.ip()))
}) })
.collect(); .collect();
endpoints endpoints
@ -762,33 +763,32 @@ impl State {
// Skip if we are already using that endpoint // Skip if we are already using that endpoint
continue; continue;
} }
if let Some(port) = peer_cfg.port {
info!("Configure {} with endpoint {}", peer_cfg.pubkey, endpoint); info!("Configure {} with endpoint {}", peer_cfg.pubkey, endpoint);
Command::new("wg") Command::new("wg")
.args([ .args([
"set", "set",
&peer_cfg.interface, &peer_cfg.interface,
"peer", "peer",
&peer_cfg.pubkey, &peer_cfg.pubkey,
"endpoint", "endpoint",
&SocketAddr::new(endpoint, port).to_string(), &endpoint.to_string(),
"persistent-keepalive", "persistent-keepalive",
"10", "10",
"allowed-ips", "allowed-ips",
&peer_cfg &peer_cfg
.allowed_ips .allowed_ips
.iter() .iter()
.map(|ip| ip.to_string()) .map(|ip| ip.to_string())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(","), .join(","),
]) ])
.output()?; .output()?;
let packet = daemon.make_packet(&Gossip::Ping)?; let packet = daemon.make_packet(&Gossip::Ping)?;
daemon.socket.send_to( daemon.socket.send_to(
&packet, &packet,
SocketAddr::new(peer_cfg.address, daemon.config.gossip_port), SocketAddr::new(peer_cfg.address, daemon.config.gossip_port),
)?; )?;
}
} else { } else {
info!("Configure {} with no known endpoint", peer_cfg.pubkey); info!("Configure {} with no known endpoint", peer_cfg.pubkey);
Command::new("wg") Command::new("wg")