diff options
-rw-r--r-- | src/configuration/config.rs | 85 | ||||
-rw-r--r-- | src/configuration/mod.rs | 1 | ||||
-rw-r--r-- | src/platform/bind.rs | 6 | ||||
-rw-r--r-- | src/platform/dummy/bind.rs | 10 | ||||
-rw-r--r-- | src/wireguard/router/peer.rs | 6 | ||||
-rw-r--r-- | src/wireguard/router/tests.rs | 8 | ||||
-rw-r--r-- | src/wireguard/tests.rs | 4 | ||||
-rw-r--r-- | src/wireguard/timers.rs | 14 | ||||
-rw-r--r-- | src/wireguard/wireguard.rs | 20 |
9 files changed, 120 insertions, 34 deletions
diff --git a/src/configuration/config.rs b/src/configuration/config.rs index 6aa6a77..d68084c 100644 --- a/src/configuration/config.rs +++ b/src/configuration/config.rs @@ -19,15 +19,9 @@ pub struct PeerState { allowed_ips: Vec<(IpAddr, u32)>, } -struct UDPState<O: bind::Owner> { - fwmark: Option<u32>, - owner: O, - port: u16, -} - pub struct WireguardConfig<T: tun::Tun, B: bind::Platform> { wireguard: Wireguard<T, B>, - network: Mutex<Option<UDPState<B::Owner>>>, + network: Mutex<Option<B::Owner>>, } impl<T: tun::Tun, B: bind::Platform> WireguardConfig<T, B> { @@ -42,6 +36,7 @@ impl<T: tun::Tun, B: bind::Platform> WireguardConfig<T, B> { pub enum ConfigError { NoSuchPeer, NotListening, + FailedToBind, } impl ConfigError { @@ -50,6 +45,7 @@ impl ConfigError { match self { ConfigError::NoSuchPeer => 1, ConfigError::NotListening => 2, + ConfigError::FailedToBind => 3, } } } @@ -77,7 +73,7 @@ pub trait Configuration { /// An integer indicating the protocol version fn get_protocol_version(&self) -> usize; - fn set_listen_port(&self, port: u16) -> Option<ConfigError>; + fn set_listen_port(&self, port: Option<u16>) -> Option<ConfigError>; /// Set the firewall mark (or similar, depending on platform) /// @@ -200,24 +196,39 @@ impl<T: tun::Tun, B: bind::Platform> Configuration for WireguardConfig<T, B> { 1 } - fn set_listen_port(&self, port: u16) -> Option<ConfigError> { - let mut udp = self.network.lock(); + fn set_listen_port(&self, port: Option<u16>) -> Option<ConfigError> { + let mut bind = self.network.lock(); // close the current listener - *udp = None; + *bind = None; + + // bind to new port + if let Some(port) = port { + // create new listener + let (mut readers, writer, owner) = match B::bind(port) { + Ok(r) => r, + Err(_) => { + return Some(ConfigError::FailedToBind); + } + }; + + // add readers/writer to wireguard + self.wireguard.set_writer(writer); + while let Some(reader) = readers.pop() { + self.wireguard.add_reader(reader); + } + + // create new UDP state + *bind = Some(owner); + } None } fn set_fwmark(&self, mark: Option<u32>) -> Option<ConfigError> { match self.network.lock().as_mut() { - Some(mut bind) => { - // there is a active bind - // set the fwmark (the IO operation) - bind.owner.set_fwmark(mark).unwrap(); // TODO: handle - - // update stored value - bind.fwmark = mark; + Some(bind) => { + bind.set_fwmark(mark).unwrap(); // TODO: handle None } None => Some(ConfigError::NotListening), @@ -238,11 +249,21 @@ impl<T: tun::Tun, B: bind::Platform> Configuration for WireguardConfig<T, B> { } fn set_preshared_key(&self, peer: &PublicKey, psk: Option<[u8; 32]>) -> Option<ConfigError> { - None + if self.wireguard.set_psk(*peer, psk) { + None + } else { + Some(ConfigError::NoSuchPeer) + } } fn set_endpoint(&self, peer: &PublicKey, addr: SocketAddr) -> Option<ConfigError> { - None + match self.wireguard.lookup_peer(peer) { + Some(peer) => { + peer.router.set_endpoint(B::Endpoint::from_address(addr)); + None + } + None => Some(ConfigError::NoSuchPeer), + } } fn set_persistent_keepalive_interval( @@ -250,15 +271,33 @@ impl<T: tun::Tun, B: bind::Platform> Configuration for WireguardConfig<T, B> { peer: &PublicKey, interval: usize, ) -> Option<ConfigError> { - None + match self.wireguard.lookup_peer(peer) { + Some(peer) => { + peer.set_persistent_keepalive_interval(interval); + None + } + None => Some(ConfigError::NoSuchPeer), + } } fn replace_allowed_ips(&self, peer: &PublicKey) -> Option<ConfigError> { - None + match self.wireguard.lookup_peer(peer) { + Some(peer) => { + peer.router.remove_allowed_ips(); + None + } + None => Some(ConfigError::NoSuchPeer), + } } fn add_allowed_ip(&self, peer: &PublicKey, ip: IpAddr, masklen: u32) -> Option<ConfigError> { - None + match self.wireguard.lookup_peer(peer) { + Some(peer) => { + peer.router.add_allowed_ip(ip, masklen); + None + } + None => Some(ConfigError::NoSuchPeer), + } } fn get_peers(&self) -> Vec<PeerState> { diff --git a/src/configuration/mod.rs b/src/configuration/mod.rs index 520b397..83419bc 100644 --- a/src/configuration/mod.rs +++ b/src/configuration/mod.rs @@ -1,5 +1,6 @@ mod config; +use super::platform::Endpoint; use super::platform::{bind, tun}; use super::wireguard::Wireguard; diff --git a/src/platform/bind.rs b/src/platform/bind.rs index f22a5d7..1a234c7 100644 --- a/src/platform/bind.rs +++ b/src/platform/bind.rs @@ -28,7 +28,11 @@ pub trait Bind: Send + Sync + 'static { pub trait Owner: Send { type Error: Error; - fn set_fwmark(&self, value: Option<u32>) -> Option<Self::Error>; + fn get_port(&self) -> u16; + + fn get_fwmark(&self) -> Option<u32>; + + fn set_fwmark(&mut self, value: Option<u32>) -> Option<Self::Error>; } /// On some platforms the application can itself bind to a socket. diff --git a/src/platform/dummy/bind.rs b/src/platform/dummy/bind.rs index 3497656..2c30486 100644 --- a/src/platform/dummy/bind.rs +++ b/src/platform/dummy/bind.rs @@ -203,7 +203,15 @@ impl Bind for PairBind { impl Owner for VoidOwner { type Error = BindError; - fn set_fwmark(&self, _value: Option<u32>) -> Option<Self::Error> { + fn set_fwmark(&mut self, _value: Option<u32>) -> Option<Self::Error> { + None + } + + fn get_port(&self) -> u16 { + 0 + } + + fn get_fwmark(&self) -> Option<u32> { None } } diff --git a/src/wireguard/router/peer.rs b/src/wireguard/router/peer.rs index 5467eb7..5522a3e 100644 --- a/src/wireguard/router/peer.rs +++ b/src/wireguard/router/peer.rs @@ -515,7 +515,7 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Peer<E, C, T /// /// If an identical value already exists as part of a prior peer, /// the allowed IP entry will be removed from that peer and added to this peer. - pub fn add_allowed_ips(&self, ip: IpAddr, masklen: u32) { + pub fn add_allowed_ip(&self, ip: IpAddr, masklen: u32) { debug!("peer.add_allowed_ips"); match ip { IpAddr::V4(v4) => { @@ -523,14 +523,14 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Peer<E, C, T .device .ipv4 .write() - .insert(v4, masklen, self.state.clone()) + .insert(v4.mask(masklen), masklen, self.state.clone()) } IpAddr::V6(v6) => { self.state .device .ipv6 .write() - .insert(v6, masklen, self.state.clone()) + .insert(v6.mask(masklen), masklen, self.state.clone()) } }; } diff --git a/src/wireguard/router/tests.rs b/src/wireguard/router/tests.rs index 1b122a8..d5a1133 100644 --- a/src/wireguard/router/tests.rs +++ b/src/wireguard/router/tests.rs @@ -152,7 +152,7 @@ mod tests { let (mask, len, ip) = ("192.168.1.0", 24, "192.168.1.20"); let mask: IpAddr = mask.parse().unwrap(); let ip1: IpAddr = ip.parse().unwrap(); - peer.add_allowed_ips(mask, len); + peer.add_allowed_ip(mask, len); // every iteration sends 10 GB b.iter(|| { @@ -210,7 +210,7 @@ mod tests { } // map subnet to peer - peer.add_allowed_ips(mask, *len); + peer.add_allowed_ip(mask, *len); // create "IP packet" let msg = make_packet_dst_padded(1024, ip.parse().unwrap(), 0); @@ -334,13 +334,13 @@ mod tests { let (mask, len, _ip, _okay) = p1; let peer1 = router1.new_peer(opaq1.clone()); let mask: IpAddr = mask.parse().unwrap(); - peer1.add_allowed_ips(mask, *len); + peer1.add_allowed_ip(mask, *len); peer1.add_keypair(dummy_keypair(false)); let (mask, len, _ip, _okay) = p2; let peer2 = router2.new_peer(opaq2.clone()); let mask: IpAddr = mask.parse().unwrap(); - peer2.add_allowed_ips(mask, *len); + peer2.add_allowed_ip(mask, *len); peer2.set_endpoint(dummy::UnitEndpoint::new()); if *stage { diff --git a/src/wireguard/tests.rs b/src/wireguard/tests.rs index 37dd571..6a02e1f 100644 --- a/src/wireguard/tests.rs +++ b/src/wireguard/tests.rs @@ -133,11 +133,11 @@ fn test_pure_wireguard() { peer1 .router - .add_allowed_ips("192.168.1.0".parse().unwrap(), 24); + .add_allowed_ip("192.168.1.0".parse().unwrap(), 24); peer2 .router - .add_allowed_ips("192.168.2.0".parse().unwrap(), 24); + .add_allowed_ip("192.168.2.0".parse().unwrap(), 24); // set endpoint (the other should be learned dynamically) diff --git a/src/wireguard/timers.rs b/src/wireguard/timers.rs index 485f466..22a0ff1 100644 --- a/src/wireguard/timers.rs +++ b/src/wireguard/timers.rs @@ -124,14 +124,28 @@ impl<B: bind::Bind> PeerInner<B> { self.timers_any_authenticated_packet_sent(); } + + pub fn set_persistent_keepalive_interval(&self, interval: usize) { + self.timers().send_persistent_keepalive.stop(); + self.keepalive.store(interval, Ordering::SeqCst); + if interval > 0 { + self.timers() + .send_persistent_keepalive + .start(Duration::from_secs(interval as u64)); + } + } + fn packet_send_queued_handshake_initiation(&self, is_retry: bool) { if !is_retry { self.timers().handshake_attempts.store(0, Ordering::SeqCst); } self.packet_send_handshake_initiation(); } + + } + impl Timers { pub fn new<T, B>(runner: &Runner, peer: Peer<T, B>) -> Timers where diff --git a/src/wireguard/wireguard.rs b/src/wireguard/wireguard.rs index 674c96f..78f24da 100644 --- a/src/wireguard/wireguard.rs +++ b/src/wireguard/wireguard.rs @@ -148,6 +148,16 @@ impl<B: Bind> PeerInner<B> { self.queue.lock().send(HandshakeJob::New(self.pk)).unwrap(); } } + + pub fn set_persistent_keepalive_interval(&self, interval: usize) { + self.timers().send_persistent_keepalive.stop(); + self.keepalive.store(interval, Ordering::SeqCst); + if interval > 0 { + self.timers() + .send_persistent_keepalive + .start(Duration::from_secs(internal as u64)); + } + } } struct Handshake { @@ -161,6 +171,12 @@ impl<T: Tun, B: Bind> Deref for WireguardHandle<T, B> { &self.inner } } +impl<T: Tun, B: Bind> Deref for Wireguard<T, B> { + type Target = Arc<WireguardInner<T, B>>; + fn deref(&self) -> &Self::Target { + &self.state + } +} pub struct Wireguard<T: Tun, B: Bind> { runner: Runner, @@ -240,6 +256,10 @@ impl<T: Tun, B: Bind> Wireguard<T, B> { } } + pub fn set_psk(&self, pk: PublicKey, psk: Option<[u8; 32]>) -> bool { + self.state.handshake.write().device.set_psk(pk, psk).is_ok() + } + pub fn new_peer(&self, pk: PublicKey) { let mut rng = OsRng::new().unwrap(); let state = Arc::new(PeerInner { |