2 Commits

Author SHA1 Message Date
shimunn
f3717ce132 Streamlined Dockerfile [CI SKIP] 2019-04-03 01:42:23 +02:00
shimunn
aff9648e00 Streamlined Dockerfile 2019-04-03 01:42:05 +02:00
12 changed files with 181 additions and 287 deletions

View File

@@ -2,37 +2,36 @@ FROM rust:1.33-slim AS rustbuild
FROM rustbuild AS eventbuild FROM rustbuild AS eventbuild
ARG MODE=--release
WORKDIR /build WORKDIR /build
RUN rustup target add x86_64-unknown-linux-musl RUN rustup target add x86_64-unknown-linux-musl
COPY wg-event-gen/Cargo.* /build/ COPY wg-event-gen/Cargo.* /build/
RUN mkdir -p src && echo "fn main() {}" > src/main.rs && cargo build --release --target x86_64-unknown-linux-musl RUN mkdir -p src && echo "fn main() {}" > src/main.rs && cargo build $MODE --target x86_64-unknown-linux-musl
COPY wg-event-gen/ /build COPY wg-event-gen/ /build
RUN cargo build --target x86_64-unknown-linux-musl RUN cargo build --target x86_64-unknown-linux-musl $MODE
FROM frolvlad/alpine-glibc AS test
COPY --from=eventbuild /build/target/x86_64-unknown-linux-musl/debug/wg-event-gen /usr/bin/
RUN echo "d41d8cd98f00b204e9800998ecf8427e -" > test.md5 && wg-event-gen | md5sum -c test.md5
FROM rustbuild AS boringbuild FROM rustbuild AS boringbuild
ARG MODE=--release
WORKDIR /build WORKDIR /build
RUN rustup target add x86_64-unknown-linux-musl RUN rustup target add x86_64-unknown-linux-musl
COPY boringtun/Cargo.* /build/ COPY boringtun/Cargo.* /build/
RUN mkdir -p src && echo "fn main() {}" > src/main.rs && touch src/lib.rs && cargo build --release #--target x86_64-unknown-linux-musl #Ring won't compile https://github.com/briansmith/ring/issues/713 RUN mkdir -p src && echo "fn main() {}" > src/main.rs && touch src/lib.rs && cargo build $MODE #--target x86_64-unknown-linux-musl #Ring won't compile https://github.com/briansmith/ring/issues/713
COPY boringtun/ /build COPY boringtun/ /build
RUN cargo build --release #--target x86_64-unknown-linux-musl RUN cargo build $MODE #--target x86_64-unknown-linux-musl
FROM frolvlad/alpine-glibc FROM frolvlad/alpine-glibc
@@ -41,9 +40,11 @@ RUN echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories
ENV WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1 ENV WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1
COPY --from=eventbuild /build/target/x86_64-unknown-linux-musl/debug/wg-event-gen /usr/bin/ ARG MODE=--release
COPY --from=boringbuild /build/target/release/boringtun /usr/bin/ COPY --from=eventbuild /build/target/x86_64-unknown-linux-musl/*/wg-event-gen /usr/bin/
COPY --from=boringbuild /build/target/*/boringtun /usr/bin/
COPY init.sh /init.sh COPY init.sh /init.sh

View File

@@ -3,11 +3,10 @@ REPO := repo.shimun.net/shimun/wireguard-user
build: build:
docker build . -t ${REPO} docker build . -t ${REPO}
.ONESHELL:
update:
cd boringtun
git checkout master
git pull
push: build push: build
docker push ${REPO} docker push ${REPO}
pull:
docker pull ${REPO}
docker pull ${REPO}:build-event-gen
docker pull ${REPO}:build-boringtun

View File

@@ -1,5 +1,3 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]] [[package]]
name = "ansi_term" name = "ansi_term"
version = "0.11.0" version = "0.11.0"
@@ -132,14 +130,6 @@ name = "libc"
version = "0.2.47" version = "0.2.47"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.4.27" version = "0.4.27"
@@ -222,14 +212,6 @@ dependencies = [
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "threadpool"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.42" version = "0.1.42"
@@ -269,7 +251,6 @@ dependencies = [
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -309,7 +290,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" "checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
"checksum libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)" = "48450664a984b25d5b479554c29cc04e3150c97aa4c01da5604a2d4ed9151476" "checksum libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)" = "48450664a984b25d5b479554c29cc04e3150c97aa4c01da5604a2d4ed9151476"
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" "checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2"
@@ -320,7 +300,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"

View File

@@ -11,7 +11,6 @@ time = "0.1.42"
structopt = "0.2.14" structopt = "0.2.14"
structopt-derive = "0.2.14" structopt-derive = "0.2.14"
derive_builder = "0.7.1" derive_builder = "0.7.1"
threadpool = "1.7.1"
[profile.release] [profile.release]
lto = true lto = true

View File

@@ -1,5 +1,5 @@
use crate::model::{ use crate::model::{
ECCKey, HexBackend, Interface, Peer, PeerBuilder, SharedKey, WireguardController, 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};
@@ -33,12 +33,9 @@ impl WireguardController for Userspace {
let value_as_num = || parse_err(value.parse::<u64>()); let value_as_num = || parse_err(value.parse::<u64>());
let mut peer: Option<Peer> = None; let mut peer: Option<Peer> = None;
let build_peer = |peer: &mut Option<Peer>, builder: &mut PeerBuilder| -> Result<()> { let build_peer = |peer: &mut Option<Peer>, builder: &mut PeerBuilder| -> Result<()> {
if builder.has_key() { let built: Result<Peer> = parse_err(builder.build());
//Threat as uninitialized otherwise *peer = Some(built?);
let built: Result<Peer> = parse_err(builder.build()); *builder = PeerBuilder::default();
*peer = Some(built?);
*builder = PeerBuilder::default();
}
Ok(()) Ok(())
}; };
let mut add_key = |peer: &mut Option<Peer>, key: ECCKey| -> Result<()> { let mut add_key = |peer: &mut Option<Peer>, key: ECCKey| -> Result<()> {
@@ -53,24 +50,16 @@ impl WireguardController for Userspace {
match key.as_ref() { match key.as_ref() {
"" => { "" => {
//Empty line means end of data //Empty line means end of data
build_peer(&mut peer, builder).map_err(|err| { build_peer(&mut peer, builder)?; //TODO: handle possible actual error case
Error::new(
ErrorKind::InvalidData,
format!(
"Protocol error, wireguard supplied insufficent data: {}",
err
),
)
})?; //TODO: handle possible actual error case
} }
"public_key" => { "public_key" => {
add_key(&mut peer, parse_err(ECCKey::from_hex(value))?)?; add_key(&mut peer, parse_err(ECCKey::from_base64(value))?)?;
} }
"private_key" => { "private_key" => {
add_key(&mut peer, ECCKey::from_hex(value)?)?; add_key(&mut peer, ECCKey::from_base64(value)?)?;
} }
"preshared_key" => { "preshared_key" => {
builder.shared_key(Some(SharedKey::from_hex(value)?)); builder.shared_key(Some(SharedKey::from_base64(value)?));
} }
"endpoint" => { "endpoint" => {
builder.endpoint(Some(parse_err(value.parse::<SocketAddr>())?)); builder.endpoint(Some(parse_err(value.parse::<SocketAddr>())?));

View File

@@ -19,39 +19,31 @@ pub(crate) fn gen_events(
.map(|p| (*p, (prev.get(*p), state.get(*p)))) .map(|p| (*p, (prev.get(*p), state.get(*p))))
.collect::<HashMap<&ECCKey, (Option<&Peer>, Option<&Peer>)>>() .collect::<HashMap<&ECCKey, (Option<&Peer>, Option<&Peer>)>>()
}; };
let d_zero = Duration::from_secs(0);
let h_ms = Duration::from_millis(100);
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| {
peer.last_handshake
.map(|shake| {
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) {
if prev_addr != cur_addr { if prev_addr != cur_addr {
listeners.roaming(&cur, prev_addr); listeners.roaming(&cur, prev_addr);
} }
} }
let timedout_now = || { if !timedout(&prev) && timedout(&cur) {
if let Some(shake) = cur.last_handshake { listeners.disconnected(&cur);
if let Ok(el) = shake.elapsed() { continue;
return el > timeout && el + poll_interval < timeout; }
}
}
true
};
let timedout_prev = || { if timedout(&prev) && !timedout(&cur) {
if let Some(shake) = prev.last_handshake { listeners.connected(&cur);
if let Ok(el) = shake.elapsed().map(|el| el - poll_interval) {
return el > timeout && el < timeout + poll_interval;
}
}
true
};
match (timedout_prev(), timedout_now()) {
(false, true) => listeners.disconnected(&cur),
(true, false) => listeners.connected(&cur),
other => (),
} }
} }
(None, Some(cur)) => listeners.added(&cur), (None, Some(cur)) => listeners.added(&cur),
@@ -64,7 +56,6 @@ pub(crate) fn gen_events(
} }
} }
/*
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@@ -97,31 +88,31 @@ mod test {
fn added<'a>(&self, peer: &'a Peer) { fn added<'a>(&self, peer: &'a Peer) {
self.calls self.calls
.borrow_mut() .borrow_mut()
.push(format!("add {}", peer.key)); .push(format!("add {}", peer.public_key));
} }
fn connected<'a>(&self, peer: &'a Peer) { fn connected<'a>(&self, peer: &'a Peer) {
self.calls self.calls
.borrow_mut() .borrow_mut()
.push(format!("con {}", peer.key)); .push(format!("con {}", peer.public_key));
} }
fn disconnected<'a>(&self, peer: &'a Peer) { fn disconnected<'a>(&self, peer: &'a Peer) {
self.calls self.calls
.borrow_mut() .borrow_mut()
.push(format!("dis {}", peer.key)); .push(format!("dis {}", peer.public_key));
} }
fn removed<'a>(&self, peer: &'a Peer) { fn removed<'a>(&self, peer: &'a Peer) {
self.calls self.calls
.borrow_mut() .borrow_mut()
.push(format!("rem {}", peer.key)); .push(format!("rem {}", peer.public_key));
} }
fn roaming<'a>(&self, peer: &'a Peer, _previous_addr: SocketAddr) { fn roaming<'a>(&self, peer: &'a Peer, _previous_addr: SocketAddr) {
self.calls self.calls
.borrow_mut() .borrow_mut()
.push(format!("rom {}", peer.key)); .push(format!("rom {}", peer.public_key));
} }
} }
@@ -137,7 +128,7 @@ mod test {
let peer = peer(); let peer = peer();
listeners.connected(&peer); listeners.connected(&peer);
assert_eq!( assert_eq!(
vec![["con", &peer.key].join(" ")], vec![["con", &peer.public_key].join(" ")],
calls.borrow().clone() calls.borrow().clone()
); );
} }
@@ -150,121 +141,121 @@ mod test {
let bkey = "HhRgEL2xsnEIqThSTUKLGaTXusorM1MFdjSSYvzBynY="; let bkey = "HhRgEL2xsnEIqThSTUKLGaTXusorM1MFdjSSYvzBynY=";
let key = b2h(bkey); let key = b2h(bkey);
Peer::from_kv(&vec![ Peer::from_kv(&vec![
("key".to_string(), key.clone()), ("public_key".to_string(), key.clone()),
/*( /*(
"last_handshake_time_nsec".to_string(), "last_handshake_time_nsec".to_string(),
(1000 * 1000 * 1).to_string(), (1000 * 1000 * 1).to_string(),
),*/ ),*/
("endpoint".to_string(), "1.1.1.1:22222".to_string()), ("endpoint".to_string(), "1.1.1.1:22222".to_string()),
]) ])
.unwrap() .unwrap()
}
#[test]
fn connected() {
let peer = peer();
let mut peer_cur = peer.clone();
let mut prev: HashMap<String, Peer> = HashMap::new();
let mut cur: HashMap<String, Peer> = HashMap::new();
cur.insert(peer_cur.public_key.clone(), peer_cur.clone());
let (listener, calls) = listeners();
let interval = time::Duration::from_secs(3);
gen_events(
&cur,
&prev,
&listener,
time::Duration::from_secs(3),
interval,
);
assert_eq!(
vec![["add", &peer_cur.public_key].join(" ")],
calls.borrow().clone()
);
gen_events(
&cur,
&cur,
&listener,
time::Duration::from_secs(3),
interval,
);
//Shouldn't gen any new events
assert!(calls.borrow().len() == 1);
let (listener, calls) = listeners();
gen_events(
&prev,
&cur,
&listener,
time::Duration::from_secs(10),
interval,
);
assert_eq!(
vec![["rem", &peer.public_key].join(" ")],
calls.borrow().clone()
);
calls.borrow_mut().clear();
let mut peer_prev = peer.clone();
peer_prev.endpoint = Some("2.2.2.2:33333".parse::<SocketAddr>().unwrap());
peer_prev.last_handshake = Some(time::Duration::from_secs(1000));
prev.insert(peer_prev.public_key.clone(), peer_prev.clone());
gen_events(
&prev,
&cur,
&listener,
time::Duration::from_secs(10),
interval,
);
assert!(calls
.borrow()
.clone()
.contains(&["rom", &peer.public_key].join(" ")));
calls.borrow_mut().clear();
let peer_prev = peer.clone();
peer_cur.last_handshake = Some(time::Duration::from_secs(5));
cur.insert(peer_cur.public_key.clone(), peer_cur.clone());
prev.insert(peer_prev.public_key.clone(), peer_prev.clone());
gen_events(
&cur,
&prev,
&listener,
time::Duration::from_secs(10),
interval,
);
assert_eq!(
vec![["con", &peer.public_key].join(" ")],
calls.borrow().clone()
);
calls.borrow_mut().clear();
//Other way around should be a disconnect
gen_events(
&prev,
&cur,
&listener,
time::Duration::from_secs(3),
interval,
);
assert_eq!(
vec![["dis", &peer.public_key].join(" ")],
calls.borrow().clone()
);
}
} }
#[test]
fn connected() {
let peer = peer();
let mut peer_cur = peer.clone();
let mut prev: HashMap<String, Peer> = HashMap::new();
let mut cur: HashMap<String, Peer> = HashMap::new();
cur.insert(peer_cur.key.clone(), peer_cur.clone());
let (listener, calls) = listeners();
let interval = time::Duration::from_secs(3);
gen_events(
&cur,
&prev,
&listener,
time::Duration::from_secs(3),
interval,
);
assert_eq!(
vec![["add", &peer_cur.key].join(" ")],
calls.borrow().clone()
);
gen_events(
&cur,
&cur,
&listener,
time::Duration::from_secs(3),
interval,
);
//Shouldn't gen any new events
assert!(calls.borrow().len() == 1);
let (listener, calls) = listeners();
gen_events(
&prev,
&cur,
&listener,
time::Duration::from_secs(10),
interval,
);
assert_eq!(
vec![["rem", &peer.key].join(" ")],
calls.borrow().clone()
);
calls.borrow_mut().clear();
let mut peer_prev = peer.clone();
peer_prev.endpoint = Some("2.2.2.2:33333".parse::<SocketAddr>().unwrap());
peer_prev.last_handshake = Some(time::Duration::from_secs(1000));
prev.insert(peer_prev.key.clone(), peer_prev.clone());
gen_events(
&prev,
&cur,
&listener,
time::Duration::from_secs(10),
interval,
);
assert!(calls
.borrow()
.clone()
.contains(&["rom", &peer.key].join(" ")));
calls.borrow_mut().clear();
let peer_prev = peer.clone();
peer_cur.last_handshake = Some(time::Duration::from_secs(5));
cur.insert(peer_cur.key.clone(), peer_cur.clone());
prev.insert(peer_prev.key.clone(), peer_prev.clone());
gen_events(
&cur,
&prev,
&listener,
time::Duration::from_secs(10),
interval,
);
assert_eq!(
vec![["con", &peer.key].join(" ")],
calls.borrow().clone()
);
calls.borrow_mut().clear();
//Other way around should be a disconnect
gen_events(
&prev,
&cur,
&listener,
time::Duration::from_secs(3),
interval,
);
assert_eq!(
vec![["dis", &peer.key].join(" ")],
calls.borrow().clone()
);
}
}*/

View File

@@ -4,11 +4,8 @@ use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::thread; use std::thread;
use std::time::SystemTime; use std::time::SystemTime;
use threadpool::ThreadPool;
pub trait EventListener { pub trait EventListener {
fn name(&self) -> &'static str;
fn added<'a>(&self, peer: &'a Peer) { fn added<'a>(&self, peer: &'a Peer) {
self.connected(peer); self.connected(peer);
} }
@@ -25,10 +22,6 @@ pub trait EventListener {
} }
impl EventListener for Vec<Box<EventListener>> { impl EventListener for Vec<Box<EventListener>> {
fn name(&self) -> &'static str {
"List of Listeners"
}
fn added<'a>(&self, peer: &'a Peer) { fn added<'a>(&self, peer: &'a Peer) {
if cfg!(feature = "addrem") || cfg!(test) { if cfg!(feature = "addrem") || cfg!(test) {
self.iter().for_each(|l| l.added(&peer)); self.iter().for_each(|l| l.added(&peer));
@@ -57,9 +50,6 @@ impl EventListener for Vec<Box<EventListener>> {
pub struct LogListener; pub struct LogListener;
impl EventListener for LogListener { impl EventListener for LogListener {
fn name(&self) -> &'static str {
"Log"
}
fn connected<'a>(&self, peer: &'a Peer) { fn connected<'a>(&self, peer: &'a Peer) {
println!("{} connected!", peer.key); println!("{} connected!", peer.key);
} }
@@ -88,13 +78,11 @@ impl EventListener for LogListener {
pub struct ScriptListener { pub struct ScriptListener {
pub script: PathBuf, pub script: PathBuf,
pub pool: ThreadPool,
} }
impl ScriptListener { impl ScriptListener {
pub fn new(script: PathBuf) -> ScriptListener { pub fn new(script: PathBuf) -> ScriptListener {
let pool = ThreadPool::new(4); ScriptListener { script }
ScriptListener { script, pool }
} }
fn peer_props<'a>(&self, peer: &'a Peer) -> String { fn peer_props<'a>(&self, peer: &'a Peer) -> String {
@@ -139,16 +127,13 @@ impl ScriptListener {
fn call_sub<'a>(&self, args: Vec<&'a str>) { fn call_sub<'a>(&self, args: Vec<&'a str>) {
let mut cmd = self.mkcmd(args); let mut cmd = self.mkcmd(args);
self.pool.execute(move || { thread::spawn(move || {
cmd.spawn().expect("Failed to call Script hooḱ!"); cmd.spawn().expect("Failed to call Script hooḱ!");
}); });
} }
} }
impl EventListener for ScriptListener { impl EventListener for ScriptListener {
fn name(&self) -> &'static str {
"Script"
}
fn connected<'a>(&self, peer: &'a Peer) { fn connected<'a>(&self, peer: &'a Peer) {
self.call_sub(vec!["connected", &self.peer_props(peer)]); self.call_sub(vec!["connected", &self.peer_props(peer)]);
} }

View File

@@ -17,10 +17,9 @@ use controller::Userspace;
use model::WireguardController; use model::WireguardController;
use opts::Opts; use opts::Opts;
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error;
use std::io; use std::io;
use std::thread::sleep; use std::thread::sleep;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use std::time::{Duration, Instant};
use structopt::StructOpt; use structopt::StructOpt;
fn listeners(opts: &Opts) -> Vec<Box<EventListener>> { fn listeners(opts: &Opts) -> Vec<Box<EventListener>> {
@@ -31,7 +30,6 @@ fn listeners(opts: &Opts) -> Vec<Box<EventListener>> {
if opts.log { if opts.log {
listeners.push(Box::new(LogListener)); listeners.push(Box::new(LogListener));
} }
println!("Enabled handlers: {}", (&listeners.iter().map(|l| l.name()).collect::<Vec<_>>()).join(", "));
listeners listeners
} }
@@ -50,30 +48,31 @@ fn main() -> io::Result<()> {
let mut peers_last: Option<HashMap<ECCKey, Peer>> = None; let mut peers_last: Option<HashMap<ECCKey, Peer>> = None;
loop { loop {
let now = Instant::now(); let now = Instant::now();
let peers = match controller.peers() { let peers = controller.peers()?;
Err(ref err) if opts.ignore_socket_errors => { /*println!("Connected peers:");
eprintln!( for peer in peers {
"Encountered error while querying Wireguard: {}", let peer = peer?;
err.description() if peer
); .last_handshake
sleep(interval); .map(|h| h.elapsed().unwrap() < timeout)
continue; .unwrap_or(false)
{
println!("/\\{:?} {}",(timeout - peer.last_handshake.unwrap().elapsed().unwrap()), peer);
} }
res => res?, }*/
};
let peers = peers let peers = peers
.map(|peer| peer.map(|peer_ok| (peer_ok.key.clone(), peer_ok))) .map(|peer| peer.map(|peer_ok| (peer_ok.key.clone(), peer_ok)))
.collect::<io::Result<HashMap<_, _>>>()?; .collect::<io::Result<HashMap<_, _>>>()?;
if let Some(ref mut peers_last) = peers_last { if let Some(ref mut peers_last) = peers_last {
gen_events(&peers, &peers_last, &listeners, timeout, interval);
gen_events(&peers, &peers_last, &listeners, timeout, interval);
*peers_last = peers; *peers_last = peers;
} else { } else {
peers_last = Some(peers); peers_last = Some(peers);
} }
let pause = interval - now.elapsed(); let pause = interval - now.elapsed();
//dbg!(interval - pause);
sleep(if pause > interval / 2 { sleep(if pause > interval / 2 {
pause pause
} else { } else {

View File

@@ -1,5 +1,4 @@
use base64::{decode, encode}; use base64::{decode, encode};
use hex;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
@@ -22,31 +21,6 @@ impl fmt::Display for ECCKey {
} }
} }
pub trait HexBackend {
fn from_bytes(bytes: Vec<u8>) -> Self;
fn bytes(&self) -> &Vec<u8>;
fn from_hex<I: AsRef<str>>(key: I) -> io::Result<Self>
where
Self: Sized,
{
Ok(Self::from_bytes(hex::decode(key.as_ref()).map_err(
|_| io::Error::new(io::ErrorKind::InvalidData, "Failed to decode hexstring"),
)?))
}
fn as_hex(&self) -> io::Result<String> {
Ok(hex::encode(&self.bytes()))
}
}
impl<T: Base64Backed> HexBackend for T {
fn from_bytes(bytes: Vec<u8>) -> Self {
<Self as Base64Backed>::from_bytes(bytes)
}
fn bytes(&self) -> &Vec<u8> {
<Self as Base64Backed>::bytes(self)
}
}
pub trait Base64Backed { pub trait Base64Backed {
fn from_bytes(bytes: Vec<u8>) -> Self; fn from_bytes(bytes: Vec<u8>) -> Self;
fn bytes(&self) -> &Vec<u8>; fn bytes(&self) -> &Vec<u8>;
@@ -60,7 +34,7 @@ pub trait Base64Backed {
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::InvalidData, io::ErrorKind::InvalidData,
"Failed to decode base64", "Failed to decode base64",
)); ))
} }
}; /*.map_err(|err| { }; /*.map_err(|err| {
@@ -194,10 +168,6 @@ impl PeerBuilder {
self.validate().is_ok() self.validate().is_ok()
} }
pub fn has_key(&self) -> bool {
self.key.is_some()
}
pub fn add_allowed_ip(&mut self, ip: (IpAddr, u8)) { pub fn add_allowed_ip(&mut self, ip: (IpAddr, u8)) {
if let Some(ref mut ips) = &mut self.allowed_ips { if let Some(ref mut ips) = &mut self.allowed_ips {
ips.push(ip); ips.push(ip);
@@ -233,15 +203,3 @@ pub trait WireguardController {
fn update_peer(&mut self, peer: &Peer) -> io::Result<()>; fn update_peer(&mut self, peer: &Peer) -> io::Result<()>;
} }
#[cfg(test)]
mod test {
use super::*;
#[test]
fn key_encoding() {
let key_encoded = "08df3bebd54217eb769d607f8673e1c3c53bb55d6ac689348a9227c8c4dd8857";
let key = ECCKey::from_hex(key_encoded).unwrap();
assert_eq!(&key.as_hex().unwrap(), key_encoded);
}
}

View File

@@ -4,16 +4,14 @@ use structopt::StructOpt;
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
#[structopt(name = "event-gen")] #[structopt(name = "event-gen")]
pub struct Opts { pub struct Opts {
///Time after which a client is considered as offline
#[structopt( #[structopt(
short = "t", short = "t",
long = "timeout", long = "timeout",
default_value = "115", default_value = "120",
env = "WG_EVENT_TIMEOUT" env = "WG_EVENT_TIMEOUT"
)] )]
pub timeout: u64, pub timeout: u64,
///Interval after which Wireguard will be polled for updates
#[structopt( #[structopt(
short = "p", short = "p",
long = "poll-interval", long = "poll-interval",
@@ -22,7 +20,6 @@ pub struct Opts {
)] )]
pub poll: u64, pub poll: u64,
///Programm to run when an event has fired
#[structopt( #[structopt(
short = "e", short = "e",
long = "event-handler", long = "event-handler",
@@ -31,15 +28,12 @@ pub struct Opts {
)] )]
pub events: Option<PathBuf>, pub events: Option<PathBuf>,
///Don't exit on API errors
#[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,
///Log all events to Stdout
#[structopt(short = "l", long = "log", env = "WG_LOG_EVENTS")] #[structopt(short = "l", long = "log", env = "WG_LOG_EVENTS")]
pub log: bool, pub log: bool,
///Socket for the userspace implementation to poll
#[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,
} }

View File

@@ -1 +1 @@
cargo +nightly build && cat target/release/wg-event-gen | ssh core@ks1 "sudo bash -c 'rm -f /srv/vpn/wireguard/event-gen; cat > /srv/vpn/wireguard/event-gen; chmod +x /srv/vpn/wireguard/event-gen'" cargo build --release && cat target/release/wg-event-gen | ssh core@ks1 "sudo bash -c 'cat > /srv/vpn/wireguard/event-gen'"