integrate old code
Some checks are pending
continuous-integration/drone/push Build is running

This commit is contained in:
Shimun 2019-03-31 18:04:01 +02:00
parent fb7d706dae
commit 819eb7d362
6 changed files with 82 additions and 29 deletions

View File

@ -5,7 +5,7 @@ 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;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::{Duration, Instant};
pub struct Userspace(PathBuf); pub struct Userspace(PathBuf);

View File

@ -4,8 +4,8 @@ use std::collections::{HashMap, HashSet};
use std::time; use std::time;
pub(crate) fn gen_events( pub(crate) fn gen_events(
state: &HashMap<String, Peer>, state: &HashMap<ECCKey, Peer>,
prev: &HashMap<String, Peer>, prev: &HashMap<ECCKey, Peer>,
listeners: &Vec<Box<EventListener>>, listeners: &Vec<Box<EventListener>>,
timeout: time::Duration, timeout: time::Duration,
poll_interval: time::Duration, poll_interval: time::Duration,
@ -13,20 +13,22 @@ pub(crate) fn gen_events(
let side_by_side = { let side_by_side = {
state state
.keys() .keys()
.map(String::as_ref) .chain(prev.keys())
.chain(prev.keys().map(String::as_ref)) .collect::<HashSet<&ECCKey>>()
.collect::<HashSet<&str>>()
.iter() .iter()
.map(|p| (*p, (prev.get(*p), state.get(*p)))) .map(|p| (*p, (prev.get(*p), state.get(*p))))
.collect::<HashMap<&str, (Option<&Peer>, Option<&Peer>)>>() .collect::<HashMap<&ECCKey, (Option<&Peer>, Option<&Peer>)>>()
}; };
for (_id, (prev, cur)) in side_by_side { for (_id, (prev, cur)) in side_by_side {
match (prev, cur) { match (prev, cur) {
(Some(prev), Some(cur)) => { (Some(prev), Some(cur)) => {
let timedout = |peer: &Peer| match peer.last_handshake_rel() { let timedout = |peer: &Peer| {
Some(shake) if shake > timeout && shake + poll_interval < timeout => true, peer.last_handshake
Some(_) => false, .map(|shake| {
_ => true, shake.elapsed().unwrap() > timeout
|| shake.elapsed().unwrap() + poll_interval < timeout
})
.unwrap_or(true)
}; };
if let (Some(prev_addr), Some(cur_addr)) = (prev.endpoint, cur.endpoint) { if let (Some(prev_addr), Some(cur_addr)) = (prev.endpoint, cur.endpoint) {

View File

@ -3,6 +3,7 @@ use std::net::SocketAddr;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::thread; use std::thread;
use std::time::SystemTime;
pub trait EventListener { pub trait EventListener {
fn added<'a>(&self, peer: &'a Peer) { fn added<'a>(&self, peer: &'a Peer) {
@ -50,25 +51,25 @@ pub struct LogListener;
impl EventListener for LogListener { impl EventListener for LogListener {
fn connected<'a>(&self, peer: &'a Peer) { fn connected<'a>(&self, peer: &'a Peer) {
println!("{} connected!", peer.public_key); println!("{} connected!", peer.key);
} }
fn disconnected<'a>(&self, peer: &'a Peer) { fn disconnected<'a>(&self, peer: &'a Peer) {
println!("{} disconnected!", peer.public_key); println!("{} disconnected!", peer.key);
} }
fn added<'a>(&self, peer: &'a Peer) { fn added<'a>(&self, peer: &'a Peer) {
println!("{} added!", peer.public_key); println!("{} added!", peer.key);
} }
fn removed<'a>(&self, peer: &'a Peer) { fn removed<'a>(&self, peer: &'a Peer) {
println!("{} removed!", peer.public_key); println!("{} removed!", peer.key);
} }
fn roaming<'a>(&self, peer: &'a Peer, previous_addr: SocketAddr) { fn roaming<'a>(&self, peer: &'a Peer, previous_addr: SocketAddr) {
println!( println!(
"{} roamed {} -> {}!", "{} roamed {} -> {}!",
peer.public_key, peer.key,
previous_addr, previous_addr,
peer.endpoint.unwrap() peer.endpoint.unwrap()
); );
@ -87,7 +88,7 @@ impl ScriptListener {
fn peer_props<'a>(&self, peer: &'a Peer) -> String { fn peer_props<'a>(&self, peer: &'a Peer) -> String {
format!( format!(
"{id} {allowed_ips} {endpoint} {last_handshake} {persistent_keepalive} {traffic}", "{id} {allowed_ips} {endpoint} {last_handshake} {persistent_keepalive} {traffic}",
id = peer.public_key, id = peer.key,
allowed_ips = peer allowed_ips = peer
.allowed_ips .allowed_ips
.iter() .iter()
@ -100,7 +101,7 @@ impl ScriptListener {
.unwrap_or("0".to_owned()), .unwrap_or("0".to_owned()),
last_handshake = peer last_handshake = peer
.last_handshake .last_handshake
.map(|s| s.as_secs() as i64) .map(|s| s.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() as i64)
.unwrap_or(-1), .unwrap_or(-1),
persistent_keepalive = peer persistent_keepalive = peer
.persistent_keepalive .persistent_keepalive

View File

@ -5,31 +5,51 @@ extern crate structopt;
extern crate derive_builder; extern crate derive_builder;
mod controller; mod controller;
mod gen;
mod listener;
mod model; mod model;
mod opts; mod opts;
use crate::gen::gen_events;
use crate::listener::*;
use crate::model::{ECCKey, Peer};
use controller::Userspace; use controller::Userspace;
use model::WireguardController; use model::WireguardController;
use opts::Opts; use opts::Opts;
use std::collections::HashMap;
use std::io; use std::io;
use std::thread::sleep; use std::thread::sleep;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use structopt::StructOpt; use structopt::StructOpt;
fn listeners(opts: &Opts) -> Vec<Box<EventListener>> {
let mut listeners: Vec<Box<EventListener>> = Vec::with_capacity(2);
if let Some(events) = opts.events.clone() {
listeners.push(Box::new(ScriptListener::new(events)))
}
if opts.log {
listeners.push(Box::new(LogListener));
}
listeners
}
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);
let timeout = Duration::from_secs(opts.timeout); let timeout = Duration::from_secs(opts.timeout);
let listeners = listeners(&opts);
println!( println!(
"Polling {} every {:?}", "Polling {} every {:?}",
opts.socket.to_str().unwrap(), opts.socket.to_str().unwrap(),
interval interval
); );
let mut peers_last: Option<HashMap<ECCKey, Peer>> = None;
loop { loop {
let now = Instant::now(); let now = Instant::now();
let peers = controller.peers()?; let peers = controller.peers()?;
println!("Connected peers:"); /*println!("Connected peers:");
for peer in peers { for peer in peers {
let peer = peer?; let peer = peer?;
if peer if peer
@ -37,8 +57,19 @@ fn main() -> io::Result<()> {
.map(|h| h.elapsed().unwrap() < timeout) .map(|h| h.elapsed().unwrap() < timeout)
.unwrap_or(false) .unwrap_or(false)
{ {
println!("{}", peer); println!("/\\{:?} {}",(timeout - peer.last_handshake.unwrap().elapsed().unwrap()), peer);
} }
}*/
let peers = peers
.map(|peer| peer.map(|peer_ok| (peer_ok.key.clone(), peer_ok)))
.collect::<io::Result<HashMap<_, _>>>()?;
if let Some(ref mut peers_last) = peers_last {
gen_events(&peers, &peers_last, &listeners, timeout, interval);
*peers_last = peers;
} else {
peers_last = Some(peers);
} }
let pause = interval - now.elapsed(); let pause = interval - now.elapsed();
dbg!(interval - pause); dbg!(interval - pause);

View File

@ -1,7 +1,7 @@
use base64::{decode, encode}; use base64::{decode, encode};
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::hash::Hash; use std::hash::{Hash, Hasher};
use std::io; use std::io;
use std::net::{IpAddr, SocketAddr}; use std::net::{IpAddr, SocketAddr};
use std::time::Instant; use std::time::Instant;
@ -71,7 +71,7 @@ impl Base64Backed for ECCKey {
} }
impl ECCKey { impl ECCKey {
pub fn extract_public_key(&self) -> Option<ECCKey> { pub fn public_key(&self) -> Option<ECCKey> {
//TODO: Determine whether Self is a private key and only the return public part //TODO: Determine whether Self is a private key and only the return public part
Some(self.clone()) Some(self.clone())
} }
@ -95,14 +95,20 @@ impl Base64Backed for SharedKey {
} }
} }
#[derive(Debug, Builder, PartialEq, Eq, Hash, Clone)] #[derive(Debug, Builder, PartialEq, Eq, Clone)]
pub struct Interface { pub struct Interface {
pub key: ECCKey, pub key: ECCKey,
pub port: usize, pub port: usize,
pub fwmark: Option<String>, pub fwmark: Option<String>,
} }
#[derive(Debug, Builder, PartialEq, Eq, Hash, Clone)] impl Hash for Interface {
fn hash<H: Hasher>(&self, state: &mut H) {
self.key.public_key().hash(state);
}
}
#[derive(Debug, Builder, PartialEq, Eq, Clone)]
pub struct Peer { pub struct Peer {
pub key: ECCKey, pub key: ECCKey,
#[builder(default = "None")] #[builder(default = "None")]
@ -121,10 +127,18 @@ pub struct Peer {
pub parsed: Instant, pub parsed: Instant,
} }
impl Hash for Peer {
fn hash<H: Hasher>(&self, state: &mut H) {
self.key.hash(state);
}
}
impl fmt::Display for Peer { impl fmt::Display for Peer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn dis_opt<'a, T: fmt::Display + 'a>(opt: &Option<T>) -> String { fn dis_opt<'a, T: fmt::Display + 'a>(opt: &Option<T>) -> String {
opt.as_ref().map(|s| s.to_string()).unwrap_or(" ".to_string()) opt.as_ref()
.map(|s| s.to_string())
.unwrap_or(" ".to_string())
} }
write!( write!(
f, f,
@ -132,9 +146,11 @@ impl fmt::Display for Peer {
self.key, self.key,
dis_opt(&self.shared_key), dis_opt(&self.shared_key),
dis_opt(&self.endpoint), dis_opt(&self.endpoint),
self.allowed_ips.iter() self.allowed_ips
.iter()
.map(|(ip, sub)| format!(" {}/{}", ip, sub)) .map(|(ip, sub)| format!(" {}/{}", ip, sub))
.collect::<Vec<_>>().join(",") .collect::<Vec<_>>()
.join(",")
) )
} }
} }

View File

@ -31,6 +31,9 @@ pub struct Opts {
#[structopt(short = "I", long = "ignore-socket-err", env = "WG_IGNORE_SOCKET_ERR")] #[structopt(short = "I", long = "ignore-socket-err", env = "WG_IGNORE_SOCKET_ERR")]
pub ignore_socket_errors: bool, pub ignore_socket_errors: bool,
#[structopt(short = "l", long = "log")]
pub log: bool,
#[structopt(name = "SOCKET", parse(from_os_str), env = "WG_EVENT_SOCKET")] #[structopt(name = "SOCKET", parse(from_os_str), env = "WG_EVENT_SOCKET")]
pub socket: PathBuf, pub socket: PathBuf,
} }