12 Commits

Author SHA1 Message Date
shimunn
34a081c6d6 basic handler [CI SKIP] 2019-01-19 23:04:06 +01:00
shimunn
678987fbbd updated .service [CI SKIP] 2019-01-19 23:03:21 +01:00
shimunn
fa84103e8a added feature to Cargo.toml
Some checks are pending
continuous-integration/drone/push Build is failing
2019-01-19 22:47:23 +01:00
shimunn
8300e94414 added structopt
Some checks are pending
continuous-integration/drone/push Build encountered an error
2019-01-19 19:36:56 +01:00
shimunn
5835ca7ad6 fix drone
Some checks are pending
continuous-integration/drone/push Build is passing
2019-01-19 17:27:27 +01:00
shimunn
46c10a69da cleanup
Some checks are pending
continuous-integration/drone/push Build was killed
2019-01-19 16:53:34 +01:00
shimunn
5f997ca191 supply more info
Some checks are pending
continuous-integration/drone/push Build was killed
2019-01-19 16:44:05 +01:00
shimunn
32a86b45ab more reliable events 2019-01-19 15:43:55 +01:00
Drone CI
215cb7ec8f proper hash
Some checks are pending
continuous-integration/drone/push Build is failing
2019-01-18 19:03:27 +01:00
Drone CI
5526084882 use debug build
Some checks are pending
continuous-integration/drone/push Build is failing
2019-01-18 18:54:00 +01:00
Drone CI
a96c557b45 target alpine
Some checks are pending
continuous-integration/drone/push Build is failing
2019-01-18 10:37:16 +01:00
Drone CI
fa757372cb verify working binary
Some checks are pending
continuous-integration/drone/push Build is failing
2019-01-18 10:27:42 +01:00
11 changed files with 443 additions and 115 deletions

View File

@@ -4,34 +4,42 @@ name: default
steps:
- name: event-gen
image: plugins/docker
repo: repo.shimun.net/shimun/wireguard-user::build-event-gen
registry: repo.shimun.net
cache_from: ["repo.shimun.net/shimun/wireguard-user:build-event-gen"]
target: eventbuild
username:
from_secret: docker_username
password:
from_secret: docker_password
settings:
repo: repo.shimun.net/shimun/wireguard-user
tag: build-event-gen
registry: repo.shimun.net
cache_from: ["repo.shimun.net/shimun/wireguard-user:build-event-gen"]
storage_path: "/drone/docker"
target: eventbuild
username:
from_secret: docker_username
password:
from_secret: docker_password
- name: git-modules
image: alpine/git
commands:
- git submodule update --recursive --remote --init
- name: wireguard-go
image: plugins/docker
repo: repo.shimun.net/shimun/wireguard-user:build-wireguard-go
registry: repo.shimun.net
cache-from: ["repo.shimun.net/shimun/wireguard-user:build-wireguard-go", "repo.shimun.net/shimun/wireguard-user:build-event-gen"]
target: build
username:
from_secret: docker_username
password:
from_secret: docker_password
settings:
repo: repo.shimun.net/shimun/wireguard-user
tag: build-wireguard-go
registry: repo.shimun.net
cache_from: ["repo.shimun.net/shimun/wireguard-user:build-wireguard-go", "repo.shimun.net/shimun/wireguard-user:build-event-gen"]
storage_path: "/drone/docker"
target: build
username:
from_secret: docker_username
password:
from_secret: docker_password
- name: package
image: plugins/docker
repo: repo.shimun.net/shimun/wireguard-user
registry: repo.shimun.net
cache-from: ["repo.shimun.net/shimun/wireguard-user:build-wireguard-go", "repo.shimun.net/shimun/wireguard-user:build-event-gen", "repo.shimun.net/shimun/wireguard-user"]
username:
from_secret: docker_username
password:
from_secret: docker_password
settings:
repo: repo.shimun.net/shimun/wireguard-user
registry: repo.shimun.net
cache_from: ["repo.shimun.net/shimun/wireguard-user:build-wireguard-go", "repo.shimun.net/shimun/wireguard-user:build-event-gen", "repo.shimun.net/shimun/wireguard-user"]
storage_path: "/drone/docker"
username:
from_secret: docker_username
password:
from_secret: docker_password

View File

@@ -4,11 +4,19 @@ WORKDIR /build
COPY wg-event-gen/Cargo.* /build/
RUN mkdir -p src && echo "fn main() {}" > src/main.rs && cargo build --release
RUN rustup target add x86_64-unknown-linux-musl
RUN mkdir -p src && echo "fn main() {}" > src/main.rs && cargo build --release --target x86_64-unknown-linux-musl
COPY wg-event-gen/ /build
RUN cargo build --release
RUN cargo build --target x86_64-unknown-linux-musl
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 golang AS build
@@ -28,7 +36,7 @@ ENV WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1
COPY --from=build /go/bin/wireguard /usr/bin/wireguard-go
COPY --from=eventbuild /build/target/release/wg-event-gen /usr/bin/
COPY --from=eventbuild /build/target/x86_64-unknown-linux-musl/debug/wg-event-gen /usr/bin/
COPY init.sh /init.sh

34
handler.sh Normal file
View File

@@ -0,0 +1,34 @@
#!/bin/bash
#{event} {id} {allowed_ips} {endpoint} {last_handshake} {persistent_keepalive} {traffic}
EVENT=$1
PUB_KEY=$2
IFS=',' read -ra ALLOWED_IPS <<< "$3"
ENDPOINT=$4
LAST_HSHAKE=$5
KEEPALIVE=$6
IFS=',' read -ra TRAFFIC <<< "$7"
TX_BYTES=${TRAFFIC[0]}
RX_BYTES=${TRAFFIC[1]}
echo "Caught event $EVENT for $PUB_KEY with IP $ALLOWED_IPS last shaked: $LAST_HSHAKE" > /tmp/log
case "$EVENT" in
"connected")
;;
"disconnected")
;;
"roaming")
PREV_ENDPOINT=$8
;;
"added")
;;
"removed")
;;
*)
exit 1
;;
esac

View File

@@ -47,7 +47,8 @@ setup_iptables "A"
sleep 3
if [ -e "/usr/bin/wg-event-gen" ]; then
sleep 3 && /usr/bin/wg-event-gen /var/run/wireguard/$WG_IF.sock 3000
export WG_EVENT_SOCKET=/var/run/wireguard/$WG_IF.sock
/usr/bin/wg-event-gen
else
while [ -e "/sys/class/net/$WG_IF/operstate" ]; do
sleep 10

162
wg-event-gen/Cargo.lock generated
View File

@@ -1,3 +1,21 @@
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.10.0"
@@ -6,11 +24,38 @@ dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clap"
version = "2.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hex"
version = "0.3.2"
@@ -21,11 +66,88 @@ name = "libc"
version = "0.2.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "structopt"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "structopt-derive"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.15.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termion"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.42"
@@ -36,12 +158,34 @@ dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-segmentation"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-width"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wg-event-gen"
version = "0.1.0"
dependencies = [
"base64 0.10.0 (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-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -65,12 +209,30 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
"checksum libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)" = "48450664a984b25d5b479554c29cc04e3150c97aa4c01da5604a2d4ed9151476"
"checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d"
"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_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3"
"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04"
"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 textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"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-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@@ -8,6 +8,12 @@ edition = "2018"
hex = "0.3.2"
base64 = "0.10.0"
time = "0.1.42"
structopt = "0.2.14"
structopt-derive = "0.2.14"
[profile.release]
lto = false
lto = true
[features]
addrem = []

View File

@@ -16,6 +16,7 @@ pub(crate) fn gen_events(
prev: &HashMap<String, Peer>,
listeners: &Vec<Box<EventListener>>,
timeout: time::Duration,
poll_interval: time::Duration,
) {
let side_by_side = {
state
@@ -24,36 +25,35 @@ pub(crate) fn gen_events(
.chain(prev.keys().map(String::as_ref))
.collect::<HashSet<&str>>()
.iter()
.map(|p| (p.to_owned(), (prev.get(*p), state.get(*p))))
.map(|p| (*p, (prev.get(*p), state.get(*p))))
.collect::<HashMap<&str, (Option<&Peer>, Option<&Peer>)>>()
};
for (_id, (prev, cur)) in side_by_side {
match (prev, cur) {
(Some(prev), Some(cur)) if prev.endpoint != cur.endpoint => {
if let (Some(prev_addr), Some(_)) = (prev.endpoint, cur.endpoint) {
listeners.roaming(&cur, prev_addr);
}
}
(Some(prev), Some(cur)) => {
let timedout = |peer: &Peer| match peer.last_handshake_rel() {
Some(shake) if shake < timeout => false,
Some(shake) if shake > timeout && shake + poll_interval < timeout => true,
Some(_) => false,
_ => true,
};
//if _id == "HhRgEL2xsnEIqThSTUKLGaTXusorM1MFdjSSYvzBynY=" { dbg!((cur.last_handshake_rel(),timedout(&prev) , timedout(&cur))); }
if let (Some(prev_addr), Some(cur_addr)) = (prev.endpoint, cur.endpoint) {
if prev_addr != cur_addr {
listeners.roaming(&cur, prev_addr);
}
}
if !timedout(&prev) && timedout(&cur) {
listeners.disconnected(&cur);
continue;
}
if timedout(&prev) && !timedout(&cur) {
listeners.connected(&cur);
}
}
(None, Some(cur)) => (), //listeners.added(&cur),
(Some(prev), None) => (), //listeners.removed(&prev),
(None, Some(_cur)) => (),
(Some(_prev), None) => (),
(None, Some(cur)) => listeners.added(&cur),
(Some(prev), None) => listeners.removed(&prev),
fail => {
println!("{:?}", fail);
unreachable!()
@@ -165,19 +165,38 @@ mod test {
let mut cur: HashMap<String, Peer> = HashMap::new();
cur.insert(peer_cur.public_key.clone(), peer_cur.clone());
let (listener, calls) = listeners();
gen_events(&cur, &prev, &listener, time::Duration::from_secs(3));
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));
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));
gen_events(
&prev,
&cur,
&listener,
time::Duration::from_secs(10),
interval,
);
assert_eq!(
vec![["rem", &peer.public_key].join(" ")],
calls.borrow().clone()
@@ -193,13 +212,19 @@ mod test {
prev.insert(peer_prev.public_key.clone(), peer_prev.clone());
gen_events(&prev, &cur, &listener, time::Duration::from_secs(10));
assert_eq!(
vec![["rom", &peer.public_key].join(" ")],
calls.borrow().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 mut peer_prev = peer.clone();
@@ -209,7 +234,13 @@ mod test {
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));
gen_events(
&cur,
&prev,
&listener,
time::Duration::from_secs(10),
interval,
);
assert_eq!(
vec![["con", &peer.public_key].join(" ")],
@@ -219,7 +250,13 @@ mod test {
calls.borrow_mut().clear();
//Other way around should be a disconnect
gen_events(&prev, &cur, &listener, time::Duration::from_secs(3));
gen_events(
&prev,
&cur,
&listener,
time::Duration::from_secs(3),
interval,
);
assert_eq!(
vec![["dis", &peer.public_key].join(" ")],

View File

@@ -22,7 +22,9 @@ pub trait EventListener {
impl EventListener for Vec<Box<EventListener>> {
fn added<'a>(&self, peer: &'a Peer) {
self.iter().for_each(|l| l.added(&peer));
if cfg!(feature = "addrem") || cfg!(test) {
self.iter().for_each(|l| l.added(&peer));
}
}
fn connected<'a>(&self, peer: &'a Peer) {
@@ -34,7 +36,9 @@ impl EventListener for Vec<Box<EventListener>> {
}
fn removed<'a>(&self, peer: &'a Peer) {
self.iter().for_each(|l| l.removed(&peer));
if cfg!(feature = "addrem") || cfg!(test) {
self.iter().for_each(|l| l.removed(&peer));
}
}
fn roaming<'a>(&self, peer: &'a Peer, previous_addr: SocketAddr) {
@@ -80,10 +84,43 @@ impl ScriptListener {
ScriptListener { script }
}
fn peer_props<'a>(&self,peer: &'a Peer) -> String {
format!(
"{id} {allowed_ips} {endpoint} {last_handshake} {persistent_keepalive} {traffic}",
id = peer.public_key,
allowed_ips = peer
.allowed_ips
.iter()
.map(|(addr, mask)| [addr.to_string(), mask.to_string()].join("/"))
.collect::<Vec<String>>()
.join(","),
endpoint = peer
.endpoint
.map(|e| e.to_string())
.unwrap_or("0".to_owned()),
last_handshake = peer
.last_handshake
.map(|s| s.as_secs() as i64)
.unwrap_or(-1),
persistent_keepalive = peer
.persistent_keepalive
.map(|k| k.as_secs() as i64)
.unwrap_or(-1),
traffic = {
let (rx, tx) = peer.traffic;
[rx.to_string(), tx.to_string()].join(",")
}
)
}
fn mkcmd<'a>(&self, args: Vec<&'a str>) -> Command {
let mut cmd = Command::new("/bin/sh");
cmd.arg("-c");
cmd.arg(format!("{} {}",(&self.script).to_str().unwrap(), args.join(" ")));
cmd.arg(format!(
"{} {}",
(&self.script).to_str().unwrap(),
args.join(" ")
));
cmd
}
@@ -97,27 +134,26 @@ impl ScriptListener {
impl EventListener for ScriptListener {
fn connected<'a>(&self, peer: &'a Peer) {
self.call_sub(vec!["connected", &peer.public_key]);
self.call_sub(vec!["connected", &self.peer_props(peer)]);
}
fn disconnected<'a>(&self, peer: &'a Peer) {
self.call_sub(vec!["disconnected", &peer.public_key]);
self.call_sub(vec!["disconnected", &self.peer_props(peer)]);
}
fn added<'a>(&self, peer: &'a Peer) {
self.call_sub(vec!["added", &peer.public_key]);
self.call_sub(vec!["added", &self.peer_props(peer)]);
}
fn removed<'a>(&self, peer: &'a Peer) {
self.call_sub(vec!["removed", &peer.public_key]);
self.call_sub(vec!["removed", &self.peer_props(peer)]);
}
fn roaming<'a>(&self, peer: &'a Peer, previous_addr: SocketAddr) {
self.call_sub(vec![
"roaming",
&peer.public_key,
&self.peer_props(peer),
&previous_addr.to_string(),
&peer.endpoint.unwrap().to_string(),
]);
}
}

View File

@@ -1,22 +1,29 @@
#[macro_use]
extern crate structopt;
mod gen;
mod listener;
mod opts;
use crate::gen::*;
use crate::listener::*;
use base64;
use hex;
use opts::Opts;
use std::collections::HashMap;
use std::env;
use std::fmt;
use std::io::prelude::*;
use std::io::{BufRead, BufReader, Error, ErrorKind, Result};
use std::net::SocketAddr;
use std::net::{IpAddr, SocketAddr};
use std::os::unix::net::UnixStream;
use std::path::PathBuf;
use time;
use std::thread;
use std::time::Duration;
use structopt::StructOpt;
use time;
pub type KV = (String, String);
@@ -30,8 +37,10 @@ enum State {
pub struct Peer {
public_key: String,
endpoint: Option<SocketAddr>,
allowed_ips: Vec<(IpAddr, u8)>,
last_handshake: Option<Duration>,
persistent_keepalive: Option<Duration>,
traffic: (u64, u64),
parsed: time::Timespec,
}
@@ -53,37 +62,58 @@ impl Peer {
.filter(|(key, _)| key == &"endpoint")
.map(|(_, value)| value.parse::<SocketAddr>().unwrap())
.next(),
allowed_ips: entries
.iter()
.filter(|(key, _)| key == &"allowed_ip")
.map(|(_, value)| {
let mut parts = value.split("/").into_iter();
match (
parts.next().and_then(|addr| addr.parse::<IpAddr>().ok()),
parts.next().and_then(|mask| mask.parse::<u8>().ok()),
) {
(Some(addr), Some(mask)) => Some((addr, mask)),
(Some(addr), None) if addr.is_ipv6() => Some((addr, 128)),
(Some(addr), None) => Some((addr, 32)),
_ => None,
}
})
.filter_map(|net| net)
.collect::<Vec<(IpAddr, u8)>>(),
last_handshake: entries
.iter()
.filter_map(|(key, value)| {
let value = || value.parse::<u64>().unwrap();
match key.as_ref() {
"last_handshake_time_sec" if value() != 0 => Some(Duration::new(value(), 0)),
"last_handshake_time_nsec" if value() != 0 => Some(Duration::from_nanos(value())),
_ => None
}
let value = || value.parse::<u64>().unwrap();
match key.as_ref() {
"last_handshake_time_sec" if value() != 0 => {
Some(Duration::new(value(), 0))
}
"last_handshake_time_nsec" if value() != 0 => {
Some(Duration::from_nanos(value()))
}
_ => None,
}
})
.fold(None, |acc, add| {
if let Some(dur) = acc {
Some(dur + add)
} else {
Some(add)
}
if let Some(dur) = acc {
Some(dur + add)
} else {
Some(add)
}
}),
persistent_keepalive: entries
.iter()
.filter(|(key, _)| key == &"persistent_keepalive")
.map(|(_, value)| Duration::from_secs(value.parse::<u64>().unwrap()))
.next(),
parsed: time::get_time(),
traffic: (0, 0),
parsed: time::get_time(),
})
}
pub fn last_handshake_rel(&self) -> Option<Duration> {
let time = self.parsed;
Some(Duration::new(time.sec as u64, time.nsec as u32) - self.last_handshake?)
let time = self.parsed;
Some(Duration::new(time.sec as u64, time.nsec as u32) - self.last_handshake?)
}
}
impl State {
@@ -216,48 +246,33 @@ impl Socket {
}
fn main() {
let mut args = env::args();
args.next(); //Ignore program name
let path = args
.next()
.map(PathBuf::from)
.filter(|p| p.as_path().exists());
let interval = args
.next()
.map(|i| {
i.parse::<u64>()
.expect("[interval] has to be a positive int")
})
.unwrap_or(1000);
let opts = Opts::from_args();
let timeout = Duration::from_secs(opts.timeout);
let interval = Duration::from_secs(opts.poll);
let events = opts.events;
let path = opts.socket;
let mut listeners: Vec<Box<EventListener>> = vec![Box::new(LogListener)];
let events: PathBuf = "/etc/wireguard/events.sh".into();
if events.exists() {
if let Some(events) = events {
listeners.push(Box::new(ScriptListener::new(events)))
}
let timeout = env::vars().collect::<HashMap<String,String>>().get("WG_EVENT_GEN_TIMEOUT").map(|timeout| Duration::from_secs(timeout.parse::<u64>().expect(&format!("Can't parse {} as timeout", timeout)))).unwrap_or(Duration::from_secs(30));
if let Some(path) = path {
let sock = Socket { path };
let mut prev_state: Option<HashMap<String, Peer>> = None;
loop {
let state = match sock.get_peers() {
Ok(state) => state,
Err(err) => {
eprintln!("Failed to read from socket: {}", err);
continue;
}
};
if let Some(prev_state) = prev_state {
gen::gen_events(&state, &prev_state, &listeners, timeout);
let sock = Socket { path };
let mut prev_state: Option<HashMap<String, Peer>> = None;
loop {
let state = match sock.get_peers() {
Ok(state) => state,
Err(err) => {
eprintln!("Failed to read from socket: {}", err);
continue;
}
prev_state = Some(state);
thread::sleep(Duration::from_millis(interval));
};
if let Some(prev_state) = prev_state {
gen::gen_events(&state, &prev_state, &listeners, timeout, interval);
}
} else {
println!("<path> does not exist");
prev_state = Some(state);
thread::sleep(interval);
}
}

18
wg-event-gen/src/opts.rs Normal file
View File

@@ -0,0 +1,18 @@
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(name = "event-gen")]
pub struct Opts {
#[structopt(short = "t", long = "timeout", default_value = "120", env = "WG_EVENT_TIMEOUT")]
pub timeout: u64,
#[structopt(short = "p", long = "poll-interval", default_value = "3000", env = "WG_EVENT_INTERVAL")]
pub poll: u64,
#[structopt(short = "e", long = "event-handler", parse(from_os_str), env = "WG_EVENT_HANDLER")]
pub events: Option<PathBuf>,
#[structopt(name = "SOCKET", parse(from_os_str), env = "WG_EVENT_SOCKET")]
pub socket: PathBuf,
}

View File

@@ -30,6 +30,9 @@ ExecStartPre=/bin/mkdir -p $ROOT_DIR
ExecStart=/usr/bin/rkt --insecure-options=image run --uuid-file-save=${ROOT_DIR}/container.uuid --inherit-env --dns 8.8.8.8 --dns 9.9.9.9 --dns 1.1.1.1 \
--volume dev-net,kind=host,source=/dev/net/tun --volume volume-etc-wireguard,kind=host,source=${ROOT_DIR},readOnly=false \
--port 51820-udp:51820 repo.shimun.net/shimun/wireguard-user --mount volume=dev-net,target=/dev/net/tun --caps-retain=${WG_CAPS}
ExecStop=-/usr/bin/rkt enter --app=wireguard-user $(cat ${ROOT_DIR}/container.uuid) /bin/wg-save
TimeoutStopSec=5
ExecStopPost=-/usr/bin/rkt rm --uuid-file=${ROOT_DIR}/container.uuid
KillMode=mixed