Work on configuration interface

This commit is contained in:
Mathias Hall-Andersen
2019-11-02 21:58:04 +01:00
parent 38cbe50223
commit 027d3d24d9
9 changed files with 120 additions and 34 deletions

View File

@@ -19,15 +19,9 @@ pub struct PeerState {
allowed_ips: Vec<(IpAddr, u32)>, 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> { pub struct WireguardConfig<T: tun::Tun, B: bind::Platform> {
wireguard: Wireguard<T, B>, 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> { 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 { pub enum ConfigError {
NoSuchPeer, NoSuchPeer,
NotListening, NotListening,
FailedToBind,
} }
impl ConfigError { impl ConfigError {
@@ -50,6 +45,7 @@ impl ConfigError {
match self { match self {
ConfigError::NoSuchPeer => 1, ConfigError::NoSuchPeer => 1,
ConfigError::NotListening => 2, ConfigError::NotListening => 2,
ConfigError::FailedToBind => 3,
} }
} }
} }
@@ -77,7 +73,7 @@ pub trait Configuration {
/// An integer indicating the protocol version /// An integer indicating the protocol version
fn get_protocol_version(&self) -> usize; 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) /// 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 1
} }
fn set_listen_port(&self, port: u16) -> Option<ConfigError> { fn set_listen_port(&self, port: Option<u16>) -> Option<ConfigError> {
let mut udp = self.network.lock(); let mut bind = self.network.lock();
// close the current listener // 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 None
} }
fn set_fwmark(&self, mark: Option<u32>) -> Option<ConfigError> { fn set_fwmark(&self, mark: Option<u32>) -> Option<ConfigError> {
match self.network.lock().as_mut() { match self.network.lock().as_mut() {
Some(mut bind) => { Some(bind) => {
// there is a active bind bind.set_fwmark(mark).unwrap(); // TODO: handle
// set the fwmark (the IO operation)
bind.owner.set_fwmark(mark).unwrap(); // TODO: handle
// update stored value
bind.fwmark = mark;
None None
} }
None => Some(ConfigError::NotListening), 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> { 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> { 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( fn set_persistent_keepalive_interval(
@@ -250,15 +271,33 @@ impl<T: tun::Tun, B: bind::Platform> Configuration for WireguardConfig<T, B> {
peer: &PublicKey, peer: &PublicKey,
interval: usize, interval: usize,
) -> Option<ConfigError> { ) -> 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> { 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> { 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> { fn get_peers(&self) -> Vec<PeerState> {

View File

@@ -1,5 +1,6 @@
mod config; mod config;
use super::platform::Endpoint;
use super::platform::{bind, tun}; use super::platform::{bind, tun};
use super::wireguard::Wireguard; use super::wireguard::Wireguard;

View File

@@ -28,7 +28,11 @@ pub trait Bind: Send + Sync + 'static {
pub trait Owner: Send { pub trait Owner: Send {
type Error: Error; 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. /// On some platforms the application can itself bind to a socket.

View File

@@ -203,7 +203,15 @@ impl Bind for PairBind {
impl Owner for VoidOwner { impl Owner for VoidOwner {
type Error = BindError; 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 None
} }
} }

View File

@@ -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, /// 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. /// 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"); debug!("peer.add_allowed_ips");
match ip { match ip {
IpAddr::V4(v4) => { IpAddr::V4(v4) => {
@@ -523,14 +523,14 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Peer<E, C, T
.device .device
.ipv4 .ipv4
.write() .write()
.insert(v4, masklen, self.state.clone()) .insert(v4.mask(masklen), masklen, self.state.clone())
} }
IpAddr::V6(v6) => { IpAddr::V6(v6) => {
self.state self.state
.device .device
.ipv6 .ipv6
.write() .write()
.insert(v6, masklen, self.state.clone()) .insert(v6.mask(masklen), masklen, self.state.clone())
} }
}; };
} }

View File

@@ -152,7 +152,7 @@ mod tests {
let (mask, len, ip) = ("192.168.1.0", 24, "192.168.1.20"); let (mask, len, ip) = ("192.168.1.0", 24, "192.168.1.20");
let mask: IpAddr = mask.parse().unwrap(); let mask: IpAddr = mask.parse().unwrap();
let ip1: IpAddr = ip.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 // every iteration sends 10 GB
b.iter(|| { b.iter(|| {
@@ -210,7 +210,7 @@ mod tests {
} }
// map subnet to peer // map subnet to peer
peer.add_allowed_ips(mask, *len); peer.add_allowed_ip(mask, *len);
// create "IP packet" // create "IP packet"
let msg = make_packet_dst_padded(1024, ip.parse().unwrap(), 0); let msg = make_packet_dst_padded(1024, ip.parse().unwrap(), 0);
@@ -334,13 +334,13 @@ mod tests {
let (mask, len, _ip, _okay) = p1; let (mask, len, _ip, _okay) = p1;
let peer1 = router1.new_peer(opaq1.clone()); let peer1 = router1.new_peer(opaq1.clone());
let mask: IpAddr = mask.parse().unwrap(); let mask: IpAddr = mask.parse().unwrap();
peer1.add_allowed_ips(mask, *len); peer1.add_allowed_ip(mask, *len);
peer1.add_keypair(dummy_keypair(false)); peer1.add_keypair(dummy_keypair(false));
let (mask, len, _ip, _okay) = p2; let (mask, len, _ip, _okay) = p2;
let peer2 = router2.new_peer(opaq2.clone()); let peer2 = router2.new_peer(opaq2.clone());
let mask: IpAddr = mask.parse().unwrap(); let mask: IpAddr = mask.parse().unwrap();
peer2.add_allowed_ips(mask, *len); peer2.add_allowed_ip(mask, *len);
peer2.set_endpoint(dummy::UnitEndpoint::new()); peer2.set_endpoint(dummy::UnitEndpoint::new());
if *stage { if *stage {

View File

@@ -133,11 +133,11 @@ fn test_pure_wireguard() {
peer1 peer1
.router .router
.add_allowed_ips("192.168.1.0".parse().unwrap(), 24); .add_allowed_ip("192.168.1.0".parse().unwrap(), 24);
peer2 peer2
.router .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) // set endpoint (the other should be learned dynamically)

View File

@@ -124,14 +124,28 @@ impl<B: bind::Bind> PeerInner<B> {
self.timers_any_authenticated_packet_sent(); 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) { fn packet_send_queued_handshake_initiation(&self, is_retry: bool) {
if !is_retry { if !is_retry {
self.timers().handshake_attempts.store(0, Ordering::SeqCst); self.timers().handshake_attempts.store(0, Ordering::SeqCst);
} }
self.packet_send_handshake_initiation(); self.packet_send_handshake_initiation();
} }
} }
impl Timers { impl Timers {
pub fn new<T, B>(runner: &Runner, peer: Peer<T, B>) -> Timers pub fn new<T, B>(runner: &Runner, peer: Peer<T, B>) -> Timers
where where

View File

@@ -148,6 +148,16 @@ impl<B: Bind> PeerInner<B> {
self.queue.lock().send(HandshakeJob::New(self.pk)).unwrap(); 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 { struct Handshake {
@@ -161,6 +171,12 @@ impl<T: Tun, B: Bind> Deref for WireguardHandle<T, B> {
&self.inner &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> { pub struct Wireguard<T: Tun, B: Bind> {
runner: Runner, 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) { pub fn new_peer(&self, pk: PublicKey) {
let mut rng = OsRng::new().unwrap(); let mut rng = OsRng::new().unwrap();
let state = Arc::new(PeerInner { let state = Arc::new(PeerInner {