priorize LAN endpoint if available
This commit is contained in:
parent
b7a1b4d454
commit
b969c9ada6
1 changed files with 63 additions and 40 deletions
81
src/main.rs
81
src/main.rs
|
@ -141,11 +141,14 @@ struct Daemon {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeerInfo {
|
struct PeerInfo {
|
||||||
endpoint: Option<SocketAddr>,
|
// Info known from config
|
||||||
lan_endpoint: Option<(SocketAddr, u64)>,
|
|
||||||
last_seen: u64,
|
|
||||||
gossip_ip: IpAddr,
|
gossip_ip: IpAddr,
|
||||||
gossip_prio: u64,
|
gossip_prio: u64,
|
||||||
|
// Info retrieved from wireguard
|
||||||
|
endpoint: Option<SocketAddr>,
|
||||||
|
last_seen: u64,
|
||||||
|
// Info received by LAN broadcast
|
||||||
|
lan_endpoint: Option<(SocketAddr, u64)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
@ -158,7 +161,7 @@ enum Gossip {
|
||||||
LanBroadcast {
|
LanBroadcast {
|
||||||
pubkey: Pubkey,
|
pubkey: Pubkey,
|
||||||
listen_port: u16,
|
listen_port: u16,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Daemon {
|
impl Daemon {
|
||||||
|
@ -267,10 +270,14 @@ impl Daemon {
|
||||||
self.socket.send_to(&packet, from)?;
|
self.socket.send_to(&packet, from)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Gossip::LanBroadcast{ pubkey, listen_port } => {
|
Gossip::LanBroadcast {
|
||||||
|
pubkey,
|
||||||
|
listen_port,
|
||||||
|
} => {
|
||||||
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((SocketAddr::new(from.ip(), listen_port), time()));
|
let addr = SocketAddr::new(from.ip(), listen_port);
|
||||||
|
peer.lan_endpoint = Some((addr, time()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,43 +471,59 @@ impl State {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_wg_peers(&self, daemon: &Daemon, i: usize) -> Result<()> {
|
fn setup_wg_peers(&mut self, daemon: &Daemon, i: usize) -> Result<()> {
|
||||||
let now = time();
|
let now = time();
|
||||||
for peer in daemon.config.peers.iter() {
|
for peer_cfg in daemon.config.peers.iter() {
|
||||||
// Skip ourself
|
// Skip ourself
|
||||||
if peer.pubkey == daemon.our_pubkey {
|
if peer_cfg.pubkey == daemon.our_pubkey {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// If peer is connected, use higher keepalive and then skip reconfiguring it
|
|
||||||
if self
|
if let Some(peer) = self.peers.get_mut(&peer_cfg.pubkey) {
|
||||||
.peers
|
// remove LAN endpoint info if it is obsolete
|
||||||
.get(&peer.pubkey)
|
if matches!(peer.lan_endpoint, Some((_, t)) if now > t + TIMEOUT.as_secs()) {
|
||||||
.map(|x| now < x.last_seen + TIMEOUT.as_secs())
|
peer.lan_endpoint = None;
|
||||||
.unwrap_or(false)
|
}
|
||||||
{
|
|
||||||
|
// make sure we aren't skipping this peer (see below) if we can switch to LAN
|
||||||
|
// endpoint instead of currently connected one
|
||||||
|
let bad_endpoint = match (&peer.lan_endpoint, &peer.endpoint) {
|
||||||
|
(Some((addr1, _)), Some(addr2)) => addr1 != addr2,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// if peer is connected and endpoint is the correct one,
|
||||||
|
// set higher keepalive and then skip reconfiguring it
|
||||||
|
if !bad_endpoint && now < peer.last_seen + TIMEOUT.as_secs() {
|
||||||
Command::new("wg")
|
Command::new("wg")
|
||||||
.args([
|
.args([
|
||||||
"set",
|
"set",
|
||||||
&daemon.config.interface,
|
&daemon.config.interface,
|
||||||
"peer",
|
"peer",
|
||||||
&peer.pubkey,
|
&peer_cfg.pubkey,
|
||||||
"persistent-keepalive",
|
"persistent-keepalive",
|
||||||
"30",
|
"30",
|
||||||
])
|
])
|
||||||
.output()?;
|
.output()?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For disconnected peers, cycle through the IP addresses that we know of
|
// For disconnected peers, cycle through the endpoint addresses that we know of
|
||||||
let lan_endpoint = self.peers.get(&peer.pubkey)
|
let lan_endpoint = self
|
||||||
.and_then(|peer| peer.lan_endpoint)
|
.peers
|
||||||
.filter(|(_, t)| time() < t + TIMEOUT.as_secs());
|
.get(&peer_cfg.pubkey)
|
||||||
|
.and_then(|peer| peer.lan_endpoint);
|
||||||
|
|
||||||
let endpoints = match lan_endpoint {
|
let endpoints = match lan_endpoint {
|
||||||
Some(endpoint) => vec![endpoint],
|
Some(endpoint) => vec![endpoint],
|
||||||
None => {
|
None => {
|
||||||
let mut endpoints = self.gossip.get(&peer.pubkey).cloned().unwrap_or_default();
|
let mut endpoints = self
|
||||||
if let Some(endpoint) = &peer.endpoint {
|
.gossip
|
||||||
|
.get(&peer_cfg.pubkey)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default();
|
||||||
|
if let Some(endpoint) = &peer_cfg.endpoint {
|
||||||
match endpoint.to_socket_addrs() {
|
match endpoint.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) => {
|
||||||
|
@ -517,31 +540,31 @@ impl State {
|
||||||
|
|
||||||
if !endpoints.is_empty() {
|
if !endpoints.is_empty() {
|
||||||
let endpoint = endpoints[i % endpoints.len()];
|
let endpoint = endpoints[i % endpoints.len()];
|
||||||
info!("Configure {} with endpoint {}", peer.pubkey, endpoint.0);
|
info!("Configure {} with endpoint {}", peer_cfg.pubkey, endpoint.0);
|
||||||
Command::new("wg")
|
Command::new("wg")
|
||||||
.args([
|
.args([
|
||||||
"set",
|
"set",
|
||||||
&daemon.config.interface,
|
&daemon.config.interface,
|
||||||
"peer",
|
"peer",
|
||||||
&peer.pubkey,
|
&peer_cfg.pubkey,
|
||||||
"endpoint",
|
"endpoint",
|
||||||
&endpoint.0.to_string(),
|
&endpoint.0.to_string(),
|
||||||
"persistent-keepalive",
|
"persistent-keepalive",
|
||||||
"10",
|
"10",
|
||||||
"allowed-ips",
|
"allowed-ips",
|
||||||
&format!("{}/32", peer.address),
|
&format!("{}/32", peer_cfg.address),
|
||||||
])
|
])
|
||||||
.output()?;
|
.output()?;
|
||||||
} else {
|
} else {
|
||||||
info!("Configure {} with no known endpoint", peer.pubkey);
|
info!("Configure {} with no known endpoint", peer_cfg.pubkey);
|
||||||
Command::new("wg")
|
Command::new("wg")
|
||||||
.args([
|
.args([
|
||||||
"set",
|
"set",
|
||||||
&daemon.config.interface,
|
&daemon.config.interface,
|
||||||
"peer",
|
"peer",
|
||||||
&peer.pubkey,
|
&peer_cfg.pubkey,
|
||||||
"allowed-ips",
|
"allowed-ips",
|
||||||
&format!("{}/32", peer.address),
|
&format!("{}/32", peer_cfg.address),
|
||||||
])
|
])
|
||||||
.output()?;
|
.output()?;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue