progress [CI SKIP]

This commit is contained in:
Shimun 2019-03-30 17:53:27 +01:00
parent a8be702e88
commit a6af494cb9
3 changed files with 97 additions and 48 deletions

View File

@ -1,4 +1,6 @@
use crate::model::{Base64Backed, ECCKey, Interface, Peer, PeerBuilder, SharedKey, WireguardController}; use crate::model::{
Base64Backed, ECCKey, Interface, Peer, PeerBuilder, SharedKey, WireguardController,
};
use std::io::{BufRead, BufReader, Error, ErrorKind, Result, Write}; use std::io::{BufRead, BufReader, Error, ErrorKind, Result, Write};
use std::net::{IpAddr, SocketAddr}; use std::net::{IpAddr, SocketAddr};
use std::os::unix::net::UnixStream; use std::os::unix::net::UnixStream;
@ -46,6 +48,10 @@ impl WireguardController for Userspace {
Ok(()) Ok(())
}; };
match key.as_ref() { match key.as_ref() {
"" => {
//Empty line means end of data
build_peer(&mut peer, builder); //TODO: handle possible actual error case
}
"public_key" => { "public_key" => {
add_key(&mut peer, parse_err(ECCKey::from_base64(value))?)?; add_key(&mut peer, parse_err(ECCKey::from_base64(value))?)?;
} }
@ -64,9 +70,15 @@ impl WireguardController for Userspace {
"last_handshake_time_nsec" => { "last_handshake_time_nsec" => {
builder.add_last_handshake(Duration::from_nanos(value_as_num()?.into())); builder.add_last_handshake(Duration::from_nanos(value_as_num()?.into()));
} }
"persistent_keepalive" => { "persistent_keepalive_interval" => {
builder.persistent_keepalive(Some(Duration::from_secs(value_as_num()?.into()))); builder.persistent_keepalive(Some(Duration::from_secs(value_as_num()?.into())));
} }
"rx_bytes" => {
builder.add_traffic((parse_err(value.parse::<u64>())?, 0));
}
"tx_bytes" => {
builder.add_traffic((0, (parse_err(value.parse::<u64>())?)));
}
"allowed_ip" => { "allowed_ip" => {
let mut parts = value.split("/").into_iter(); let mut parts = value.split("/").into_iter();
let net = match ( let net = match (
@ -89,7 +101,11 @@ impl WireguardController for Userspace {
format!("Returned error code: {}", code), format!("Returned error code: {}", code),
))?, ))?,
}, },
_ => Err(Error::new(ErrorKind::InvalidData, "Unknown key"))?, "listen_port" | "fwmark" | "private_key" => (), //Ignore for now
_ => Err(Error::new(
ErrorKind::InvalidData,
["Unknown key: \"", &key, "\""].join(""),
))?,
} }
Ok(peer) Ok(peer)
} }
@ -100,19 +116,19 @@ impl WireguardController for Userspace {
match build_peer(builder, line) { match build_peer(builder, line) {
Ok(Some(value)) => Some(Some(Ok(value))), Ok(Some(value)) => Some(Some(Ok(value))),
Err(err) => { Err(err) => {
eprintln!("{:?}", err); eprintln!("{:?}", err);
None None
}, //TODO: propagate } //TODO: propagate
_ => Some(None), _ => Some(None),
} }
}) })
.flatten(); .flatten();
Ok(Box::new(peers)) Ok(Box::new(peers))
} }
fn interface(&mut self) -> Result<Interface> { fn interface(&mut self) -> Result<Interface> {
let mut stream = UnixStream::connect(&self.0)?; let mut stream = UnixStream::connect(&self.0)?;
stream.write_all(b"get=1\n")?; stream.write_all(b"get=1\n")?;
unimplemented!("TODO: return iface") unimplemented!("TODO: return iface")
} }

View File

@ -8,28 +8,42 @@ mod controller;
mod model; mod model;
mod opts; mod opts;
use controller::{Userspace}; use controller::Userspace;
use model::WireguardController; use model::WireguardController;
use opts::Opts; use opts::Opts;
use std::io; use std::io;
use structopt::StructOpt;
use std::thread::sleep; use std::thread::sleep;
use std::time::{Duration,Instant}; use std::time::{Duration, Instant};
use structopt::StructOpt;
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let opts = Opts::from_args(); let opts = Opts::from_args();
let mut controller: Box<WireguardController> = Box::new(Userspace::new(opts.socket.clone())); let mut controller: Box<WireguardController> = Box::new(Userspace::new(opts.socket.clone()));
let interval = Duration::from_millis(opts.poll); let interval = Duration::from_millis(opts.poll);
println!("Polling {} every {:?}", opts.socket.to_str().unwrap(), interval); let timeout = Duration::from_secs(opts.timeout);
println!(
"Polling {} every {:?}",
opts.socket.to_str().unwrap(),
interval
);
loop { loop {
let now = Instant::now(); let now = Instant::now();
let peers = controller.peers()?; let peers = controller.peers()?;
for peer in peers { println!("Connected peers:");
dbg!(peer?); for peer in peers {
} let peer = peer?;
let pause = interval - now.elapsed(); dbg!(peer.last_handshake);
dbg!(pause); if peer.last_handshake.map(|h| h < timeout).unwrap_or(false) {
sleep(if pause > interval/2 { pause } else {interval}); println!("{:?}", peer.key);
} }
}
let pause = interval - now.elapsed();
dbg!(pause);
sleep(if pause > interval / 2 {
pause
} else {
interval
});
}
Ok(()) Ok(())
} }

View File

@ -1,19 +1,22 @@
use base64::{decode, encode}; use base64::{decode, encode};
use std::error::Error; use std::error::Error;
use std::hash::Hash;
use std::io; use std::io;
use std::net::{IpAddr, SocketAddr}; use std::net::{IpAddr, SocketAddr};
use std::time::Duration; use std::time::Duration;
use std::time::Instant; use std::time::Instant;
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] const KEY_SIZE: usize = 48; //TODO: use VEC instead of array
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum ECCKey { pub enum ECCKey {
PublicKey([u8; 32]), PublicKey(Vec<u8>),
PrivateKey([u8; 32]), PrivateKey(Vec<u8>),
} }
pub trait Base64Backed { pub trait Base64Backed {
fn from_bytes(bytes: [u8; 32]) -> Self; fn from_bytes(bytes: Vec<u8>) -> Self;
fn bytes(&self) -> &[u8; 32]; fn bytes(&self) -> &Vec<u8>;
fn from_base64<I: AsRef<str>>(key: I) -> io::Result<Self> fn from_base64<I: AsRef<str>>(key: I) -> io::Result<Self>
where where
Self: Sized, Self: Sized,
@ -29,12 +32,17 @@ pub trait Base64Backed {
}; /*.map_err(|err| { }; /*.map_err(|err| {
})?;*/ })?;*/
let mut bytes = [0; 32]; if key.len() != KEY_SIZE {
if key.len() != 32 { return Err(io::Error::new(
return Err(io::Error::new(io::ErrorKind::Other, "Mismatched key size")); io::ErrorKind::Other,
format!(
"Mismatched key size. Expected: {}, Got {}",
KEY_SIZE,
key.len()
),
));
} }
bytes.copy_from_slice(&key); Ok(Self::from_bytes(key))
Ok(Self::from_bytes(bytes))
} }
fn as_base64(&self) -> io::Result<String> { fn as_base64(&self) -> io::Result<String> {
@ -43,14 +51,14 @@ pub trait Base64Backed {
} }
impl Base64Backed for ECCKey { impl Base64Backed for ECCKey {
fn bytes(&self) -> &[u8; 32] { fn bytes(&self) -> &Vec<u8> {
match self { match self {
ECCKey::PublicKey(bytes) => &bytes, ECCKey::PublicKey(bytes) => &bytes,
ECCKey::PrivateKey(bytes) => &bytes, ECCKey::PrivateKey(bytes) => &bytes,
} }
} }
fn from_bytes(bytes: [u8; 32]) -> ECCKey { fn from_bytes(bytes: Vec<u8>) -> ECCKey {
ECCKey::PublicKey(bytes) ECCKey::PublicKey(bytes)
} }
} }
@ -62,40 +70,42 @@ impl ECCKey {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct SharedKey([u8; 32]); pub struct SharedKey(Vec<u8>);
impl Base64Backed for SharedKey { impl Base64Backed for SharedKey {
fn bytes(&self) -> &[u8; 32] { fn bytes(&self) -> &Vec<u8> {
&self.0 &self.0
} }
fn from_bytes(bytes: [u8; 32]) -> SharedKey { fn from_bytes(bytes: Vec<u8>) -> SharedKey {
SharedKey(bytes) SharedKey(bytes)
} }
} }
#[derive(Debug, Builder, PartialEq, Eq, Hash, Clone)] #[derive(Debug, Builder, PartialEq, Eq, Hash, Clone)]
pub struct Interface { pub struct Interface {
key: ECCKey, pub key: ECCKey,
port: usize, pub port: usize,
fwmark: Option<String> pub fwmark: Option<String>,
} }
#[derive(Debug, Builder, PartialEq, Eq, Hash, Clone)] #[derive(Debug, Builder, PartialEq, Eq, Hash, Clone)]
pub struct Peer { pub struct Peer {
key: ECCKey, pub key: ECCKey,
#[builder(default = "None")] #[builder(default = "None")]
shared_key: Option<SharedKey>, pub shared_key: Option<SharedKey>,
#[builder(default = "None")] #[builder(default = "None")]
endpoint: Option<SocketAddr>, pub endpoint: Option<SocketAddr>,
allowed_ips: Vec<(IpAddr, u8)>, #[builder(default = "Vec::new()")]
last_handshake: Option<Duration>, pub allowed_ips: Vec<(IpAddr, u8)>,
#[builder(default = "None")] #[builder(default = "None")]
persistent_keepalive: Option<Duration>, pub last_handshake: Option<Duration>,
#[builder(default = "None")]
pub persistent_keepalive: Option<Duration>,
#[builder(default = "(0u64,0u64)")] #[builder(default = "(0u64,0u64)")]
traffic: (u64, u64), pub traffic: (u64, u64),
#[builder(default = "Instant::now()")] #[builder(default = "Instant::now()")]
parsed: Instant, pub parsed: Instant,
} }
impl PeerBuilder { impl PeerBuilder {
@ -128,6 +138,15 @@ impl PeerBuilder {
.map(|shake| shake.map(|shake| shake + d)); .map(|shake| shake.map(|shake| shake + d));
} }
} }
pub fn add_traffic(&mut self, txrx: (u64, u64)) {
if let Some(ref mut traffic) = &mut self.traffic {
traffic.0 += txrx.0;
traffic.1 += txrx.1;
} else {
self.traffic = Some(txrx);
}
}
} }
pub trait WireguardController { pub trait WireguardController {