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