diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3898e26..db4918b 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,10 +1,18 @@ # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.148.1/containers/rust/.devcontainer/base.Dockerfile -FROM mcr.microsoft.com/vscode/devcontainers/rust:0-1 +FROM mcr.microsoft.com/vscode/devcontainers/rust:1 RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install --no-install-recommends asciidoctor RUN rm /etc/localtime && ln -s /usr/share/zoneinfo/Europe/Berlin /etc/localtime -RUN cargo install cargo-outdated cargo-cache \ No newline at end of file +RUN chown vscode: -R /usr/local/rustup /usr/local/cargo + +USER vscode + +RUN rustup default 1.51.0 \ + && rustup component add clippy rust-src rustfmt + +RUN cargo install cargo-outdated cargo-cache \ + && cargo cache -a \ No newline at end of file diff --git a/.whitesource b/.whitesource deleted file mode 100644 index 55b922e..0000000 --- a/.whitesource +++ /dev/null @@ -1,12 +0,0 @@ -{ - "scanSettings": { - "baseBranches": [] - }, - "checkRunSettings": { - "vulnerableCheckRunConclusionLevel": "failure", - "displayMode": "diff" - }, - "issueSettings": { - "minSeverityLevel": "LOW" - } -} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dd3174..bfb16a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ This project follows [semantic versioning](http://semver.org). -### UNRELEASED +### v2.2.0 (2021-04-06) - [added] Service target file (thanks to mnhauke) - [added] Added interactive configuration wizard @@ -10,7 +10,7 @@ This project follows [semantic versioning](http://semver.org). - [added] Building static binaries - [added] Building i686 rpm - [changed] Restructured example config -- [changed] Changed Rust version to 1.50.0 +- [changed] Changed Rust version to 1.51.0 - [changed] Updated dependencies - [changed] Change permissions of /etc/vpncloud diff --git a/Cargo.lock b/Cargo.lock index 886f628..3ab0283 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1268,7 +1268,7 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "vpncloud" -version = "2.1.0" +version = "2.2.0" dependencies = [ "byteorder", "criterion", diff --git a/Cargo.toml b/Cargo.toml index 9ff0d23..af7d619 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vpncloud" -version = "2.1.0" +version = "2.2.0" authors = ["Dennis Schwerdel "] build = "build.rs" license = "GPL-3.0" @@ -12,7 +12,7 @@ readme = "README.md" edition = "2018" [package.metadata] -toolchain = "1.50.0" +toolchain = "1.51.0" upx_version = "3.96" [dependencies] diff --git a/README.md b/README.md index 64c7417..9666a72 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ peers: - REMOTE_HOST:PORT ``` -For more information, please see the [Website](https://vpncloud.ddswd.de) or the [Forum](https://groups.google.com/forum/#!forum/vpncloud). +For more information, please see the [Website](https://vpncloud.ddswd.de) or the [Discussions group](https://github.com/dswd/vpncloud/discussions). ### Project Status diff --git a/assets/changelog.txt b/assets/changelog.txt index 1ebb0ac..e008230 100644 --- a/assets/changelog.txt +++ b/assets/changelog.txt @@ -1,3 +1,17 @@ +vpncloud (2.2.0) stable; urgency=medium + + * [added] Service target file (thanks to mnhauke) + * [added] Added interactive configuration wizard + * [added] Support for (un-)installation + * [added] Building static binaries + * [added] Building i686 rpm + * [changed] Restructured example config + * [changed] Changed Rust version to 1.51.0 + * [changed] Updated dependencies + * [changed] Change permissions of /etc/vpncloud + + -- Dennis Schwerdel Tue, 06 Apr 2021 12:27:00 +0200 + vpncloud (2.1.0) stable; urgency=medium * [added] Support for websocket proxy mode @@ -9,7 +23,7 @@ vpncloud (2.1.0) stable; urgency=medium * [fixed] Added missing peer address propagation * [fixed] Fixed problem with peer addresses without port - -- Dennis Schwerdel Sat, 06 Feb 2020 13:13:00 +0100 + -- Dennis Schwerdel Sat, 06 Feb 2021 13:13:00 +0100 vpncloud (2.0.1) stable; urgency=medium diff --git a/contrib/asciinema-recorder/Dockerfile b/contrib/asciinema-recorder/Dockerfile index 53c152d..d342c20 100644 --- a/contrib/asciinema-recorder/Dockerfile +++ b/contrib/asciinema-recorder/Dockerfile @@ -1,9 +1,13 @@ FROM ubuntu -RUN apt-get update && apt-get install -y asciinema +RUN apt-get update && apt-get install -y asciinema locales bash iputils-ping +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 RUN mkdir /root/.asciinema RUN mkdir /etc/vpncloud WORKDIR /data ADD config /root/.asciinema/config -RUN echo 'PS1="\[\e[00;34m\]\[\e[01;31m\]\u\[\e[00;01;34m\]@\[\e[00;34m\]node\[\e[01;31m\]:\[\e[00;34m\]\w\[\e[01;31m\]> \[\e[00m\]"' >> /root/.bashrc \ No newline at end of file +RUN echo 'PS1="\[\e[00;34m\]\[\e[01;31m\]\u\[\e[00;01;34m\]@\[\e[00;34m\]node\[\e[01;31m\]:\[\e[00;34m\]\w\[\e[01;31m\]> \[\e[00m\]"' >> /root/.bashrc diff --git a/contrib/asciinema-recorder/config b/contrib/asciinema-recorder/config index 5746cd5..6bfaf0c 100644 --- a/contrib/asciinema-recorder/config +++ b/contrib/asciinema-recorder/config @@ -1,3 +1,3 @@ [record] -command = /usr/bin/bash -l -idle_time_limit = 2.5 \ No newline at end of file +command = bash -l +idle_time_limit = 2.5 diff --git a/contrib/asciinema-recorder/record.sh b/contrib/asciinema-recorder/record.sh deleted file mode 100755 index c9d9da4..0000000 --- a/contrib/asciinema-recorder/record.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -set -e - -docker build -t asciinema-recorder . -docker run -it --rm --network host -v $(pwd)/../../target/release/:/usr/local/bin/ -v $(pwd):/data asciinema-recorder asciinema "$@" \ No newline at end of file diff --git a/contrib/asciinema-recorder/recorder.sh b/contrib/asciinema-recorder/recorder.sh new file mode 100755 index 0000000..9b289b7 --- /dev/null +++ b/contrib/asciinema-recorder/recorder.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +cd $(dirname $0) + +docker build -t asciinema-recorder . +docker run -it --rm --network host \ + -v $(pwd):/data \ + -v /etc/hosts:/etc/hosts \ + asciinema-recorder diff --git a/src/beacon.rs b/src/beacon.rs index 8fdef16..abb5cec 100644 --- a/src/beacon.rs +++ b/src/beacon.rs @@ -15,16 +15,15 @@ use std::{ process::{Command, Stdio}, sync::{ atomic::{AtomicBool, Ordering}, - Arc, Mutex + Arc, Mutex, }, - thread + thread, }; use super::util::{from_base62, to_base62, Encoder, TimeSource}; use smallvec::SmallVec; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; - const TYPE_BEGIN: u8 = 0; const TYPE_END: u8 = 1; const TYPE_DATA: u8 = 2; @@ -40,14 +39,14 @@ fn sha512(data: &[u8]) -> SmallVec<[u8; 64]> { struct FutureResult { has_result: AtomicBool, - result: Mutex + result: Mutex, } #[derive(Clone)] pub struct BeaconSerializer { shared_key: Vec, future_peers: Arc>>, - _dummy_ts: PhantomData + _dummy_ts: PhantomData, } impl BeaconSerializer { @@ -55,7 +54,7 @@ impl BeaconSerializer { Self { shared_key: shared_key.to_owned(), future_peers: Arc::new(FutureResult { has_result: AtomicBool::new(false), result: Mutex::new(Vec::new()) }), - _dummy_ts: PhantomData + _dummy_ts: PhantomData, } } @@ -105,7 +104,7 @@ impl BeaconSerializer { fn decrypt_data(&self, data: &mut Vec) -> bool { if data.is_empty() { - return false + return false; } let seed = data.pop().unwrap() ^ self.get_keystream(TYPE_SEED, 0, 0)[0]; self.mask_with_keystream(data as &mut [u8], TYPE_DATA, seed); @@ -122,7 +121,7 @@ impl BeaconSerializer { for p in peers { match *p { SocketAddr::V4(addr) => v4addrs.push(addr), - SocketAddr::V6(addr) => v6addrs.push(addr) + SocketAddr::V6(addr) => v6addrs.push(addr), } } // Add count of v4 addresses @@ -158,23 +157,23 @@ impl BeaconSerializer { let mut peers = Vec::new(); let mut pos = 0; if data.len() < 4 { - return peers + return peers; } if !self.decrypt_data(&mut data) { - return peers + return peers; } let then = Wrapping(Encoder::read_u16(&data[pos..=pos + 1])); if let Some(ttl) = ttl_hours { let now = Wrapping(Self::now_hour_16()); if now - then > Wrapping(ttl) && then - now > Wrapping(ttl) { - return peers + return peers; } } pos += 2; let v4count = data[pos] as usize; pos += 1; if v4count * 6 > data.len() - pos || (data.len() - pos - v4count * 6) % 18 > 0 { - return peers + return peers; } for _ in 0..v4count { assert!(data.len() >= pos + 6); @@ -198,7 +197,7 @@ impl BeaconSerializer { Ipv6Addr::new(ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]), port, 0, - 0 + 0, )); peers.push(addr); } @@ -262,14 +261,14 @@ impl BeaconSerializer { peers.append(&mut self.peerlist_decode(&data[start_pos..end_pos], ttl_hours)); pos = start_pos } else { - break + break; } } peers } pub fn read_from_file>( - &self, path: P, ttl_hours: Option + &self, path: P, ttl_hours: Option, ) -> Result, io::Error> { let mut f = File::open(&path)?; let mut contents = String::new(); @@ -316,26 +315,22 @@ impl BeaconSerializer { } } - -#[cfg(test)] use crate::util::MockTimeSource; -#[cfg(test)] use std::str::FromStr; -#[cfg(test)] use std::time::Duration; +#[cfg(test)] +use crate::util::MockTimeSource; +#[cfg(test)] +use std::str::FromStr; +#[cfg(test)] +use std::time::Duration; #[test] fn encode() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"mysecretkey"); - let mut peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:53").unwrap() - ]; + let mut peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:53").unwrap()]; assert_eq!("WsHI31EWDMBYxvITiILIrm2k9gEik22E", ser.encode(&peers)); peers.push(SocketAddr::from_str("[::1]:5678").unwrap()); assert_eq!("WsHI3GXKaXCveo6uejmZizZ72kR6Y0L9T7h49TXONp1ugfKvvvEik22E", ser.encode(&peers)); - let peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:54").unwrap() - ]; + let peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:54").unwrap()]; assert_eq!("WsHI32gm9eMSHP3Lm1GXcdP7rD3ik22E", ser.encode(&peers)); } @@ -343,10 +338,7 @@ fn encode() { fn decode() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"mysecretkey"); - let mut peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:53").unwrap() - ]; + let mut peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:53").unwrap()]; assert_eq!(format!("{:?}", peers), format!("{:?}", ser.decode("WsHI31EWDMBYxvITiILIrm2k9gEik22E", None))); peers.push(SocketAddr::from_str("[::1]:5678").unwrap()); assert_eq!( @@ -359,10 +351,7 @@ fn decode() { fn decode_split() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"mysecretkey"); - let peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:53").unwrap() - ]; + let peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:53").unwrap()]; assert_eq!( format!("{:?}", peers), format!("{:?}", ser.decode("WsHI3-1E.WD:MB Yx\tvI\nTi(IL)Ir[m2]k9ügEäik22E", None)) @@ -377,10 +366,7 @@ fn decode_split() { fn decode_offset() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"mysecretkey"); - let peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:53").unwrap() - ]; + let peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:53").unwrap()]; assert_eq!( format!("{:?}", peers), format!("{:?}", ser.decode("Hello World: WsHI31EWDMBYxvITiILIrm2k9gEik22E! End of the World", None)) @@ -391,10 +377,7 @@ fn decode_offset() { fn decode_multiple() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"mysecretkey"); - let peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:53").unwrap() - ]; + let peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:53").unwrap()]; assert_eq!( format!("{:?}", peers), format!("{:?}", ser.decode("WsHI31HVpqxFNMNSPrvik22E WsHI34yOBcZIulKdtn2ik22E", None)) @@ -438,15 +421,11 @@ fn decode_invalid() { assert_eq!(2, ser.decode("WsHI3WsHI31EWDMBYxvITiILIrm2k9gEik22Eik22E", None).len()); } - #[test] fn encode_decode() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"mysecretkey"); - let peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:53").unwrap() - ]; + let peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:53").unwrap()]; let data = ser.encode(&peers); let peers2 = ser.decode(&data, None); assert_eq!(format!("{:?}", peers), format!("{:?}", peers2)); @@ -456,10 +435,7 @@ fn encode_decode() { fn encode_decode_file() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"mysecretkey"); - let peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:53").unwrap() - ]; + let peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:53").unwrap()]; let file = tempfile::NamedTempFile::new().expect("Failed to create temp file"); assert!(ser.write_to_file(&peers, file.path()).is_ok()); let peers2 = ser.read_from_file(file.path(), None); @@ -471,10 +447,7 @@ fn encode_decode_file() { fn encode_decode_cmd() { MockTimeSource::set_time(2000 * 3600); let ser = BeaconSerializer::::new(b"mysecretkey"); - let peers = vec![ - SocketAddr::from_str("1.2.3.4:5678").unwrap(), - SocketAddr::from_str("6.6.6.6:53").unwrap() - ]; + let peers = vec![SocketAddr::from_str("1.2.3.4:5678").unwrap(), SocketAddr::from_str("6.6.6.6:53").unwrap()]; let file = tempfile::NamedTempFile::new().expect("Failed to create temp file"); assert!(ser.write_to_cmd(&peers, &format!("echo $beacon > {}", file.path().display())).is_ok()); thread::sleep(Duration::from_millis(100)); diff --git a/src/cloud.rs b/src/cloud.rs index fa00e24..88e9c22 100644 --- a/src/cloud.rs +++ b/src/cloud.rs @@ -12,7 +12,7 @@ use std::{ marker::PhantomData, net::{SocketAddr, ToSocketAddrs}, path::Path, - str::FromStr + str::FromStr, }; use fnv::FnvHasher; @@ -27,7 +27,7 @@ use crate::{ error::Error, messages::{ AddrList, NodeInfo, PeerInfo, MESSAGE_TYPE_CLOSE, MESSAGE_TYPE_DATA, MESSAGE_TYPE_KEEPALIVE, - MESSAGE_TYPE_NODE_INFO + MESSAGE_TYPE_NODE_INFO, }, net::{mapped_addr, Socket}, payload::Protocol, @@ -36,7 +36,7 @@ use crate::{ table::ClaimTable, traffic::TrafficStats, types::{Address, Mode, NodeId, Range, RangeList}, - util::{addr_nice, bytes_to_hex, resolve, CtrlC, Duration, MsgBuffer, StatsdMsg, Time, TimeSource} + util::{addr_nice, bytes_to_hex, resolve, CtrlC, Duration, MsgBuffer, StatsdMsg, Time, TimeSource}, }; pub type Hash = BuildHasherDefault; @@ -54,7 +54,7 @@ struct PeerData { timeout: Time, peer_timeout: u16, node_id: NodeId, - crypto: PeerCrypto + crypto: PeerCrypto, } #[derive(Clone)] @@ -64,10 +64,9 @@ pub struct ReconnectEntry { tries: u16, timeout: u16, next: Time, - final_timeout: Option