Initial beacon test

This commit is contained in:
Dennis Schwerdel 2019-02-18 09:40:54 +01:00
parent 9cf0079698
commit c43b1cc37d
5 changed files with 177 additions and 1 deletions

7
Cargo.lock generated
View File

@ -30,6 +30,11 @@ name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bs58"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.1"
@ -625,6 +630,7 @@ name = "vpncloud"
version = "0.9.1"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"docopt 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -694,6 +700,7 @@ dependencies = [
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de79cfb98e7aa9988188784d8664b4b5dad6eaaa0863b91d9a4ed871d4f7a42"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"

View File

@ -28,6 +28,7 @@ igd = "0.6" # Do not update, 0.7 has problems with exit by ctrl-c
siphasher = "0.3"
daemonize = "0.3"
ring = "0.14"
bs58 = "*"
[build-dependencies]
cc = "^1"

164
src/beacon.rs Normal file
View File

@ -0,0 +1,164 @@
use bs58;
use ring::digest;
use std::str::FromStr;
use super::util::{now, Encoder};
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr, SocketAddrV6, Ipv6Addr};
fn base58_encode(data: &[u8]) -> String {
bs58::encode(data).into_string()
}
fn base58_decode(data: &str) -> Vec<u8> {
bs58::decode(data).into_vec().unwrap()
}
fn sha512(data: &[u8]) -> Vec<u8> {
digest::digest(&digest::SHA512, data).as_ref().iter().map(|b| *b).collect()
}
pub struct BeaconSerializer {
magic: Vec<u8>,
shared_key: String
}
impl BeaconSerializer {
pub fn new(magic: &[u8], shared_key: &str) -> Self {
BeaconSerializer {
magic: magic.to_owned(),
shared_key: shared_key.to_string()
}
}
fn seed(&self, key: &str) -> Vec<u8> {
let mut data = Vec::new();
data.extend_from_slice(key.as_bytes());
data.extend_from_slice(&self.magic);
data.extend_from_slice(self.shared_key.as_bytes());
sha512(&data)
}
fn mask_with_seed(&self, data: &[u8], key: &str) -> Vec<u8> {
let mask = self.seed(key);
let mut output = Vec::with_capacity(data.len());
for i in 0..data.len() {
output.push(data[i] ^ mask[i]);
}
output
}
fn begin(&self) -> String {
base58_encode(&self.seed("begin"))[0..5].to_string()
}
fn end(&self) -> String {
base58_encode(&self.seed("end"))[0..5].to_string()
}
fn peerlist_encode(&self, peers: &[SocketAddr]) -> String {
let mut data = Vec::new();
// Add timestamp
data.append(&mut self.mask_with_seed(&(now() as u32).to_be_bytes(), "time"));
// Split addresses into v4 and v6
let mut v4addrs = Vec::new();
let mut v6addrs = Vec::new();
for p in peers {
match *p {
SocketAddr::V4(addr) => v4addrs.push(addr),
SocketAddr::V6(addr) => v6addrs.push(addr)
}
}
// Add count of v4 addresses
data.append(&mut self.mask_with_seed(&[v4addrs.len() as u8], "v4count"));
// Add v4 addresses
for addr in v4addrs {
let mut dat = [0u8; 6];
dat[0..4].copy_from_slice(&addr.ip().octets());
Encoder::write_u16(addr.port(), &mut dat[4..]);
data.append(&mut self.mask_with_seed(&dat, "peer"));
}
// Add v6 addresses
for addr in v6addrs {
let mut dat = [0u8; 18];
let ip = addr.ip().segments();
Encoder::write_u16(ip[0], &mut dat[0..]);
Encoder::write_u16(ip[1], &mut dat[2..]);
Encoder::write_u16(ip[2], &mut dat[4..]);
Encoder::write_u16(ip[3], &mut dat[6..]);
Encoder::write_u16(ip[4], &mut dat[8..]);
Encoder::write_u16(ip[5], &mut dat[10..]);
Encoder::write_u16(ip[6], &mut dat[12..]);
Encoder::write_u16(ip[7], &mut dat[14..]);
Encoder::write_u16(addr.port(), &mut dat[16..]);
data.append(&mut self.mask_with_seed(&dat, "peer"));
}
base58_encode(&data)
}
fn peerlist_decode(&self, data: &str) -> Vec<SocketAddr> {
let data = base58_decode(data);
let mut peers = Vec::new();
//TODO: decode time
let mut pos = 4;
let v4count = self.mask_with_seed(&[data[pos]], "v4count")[0];
pos += 1;
for _ in 0..v4count {
assert!(data.len() >= pos + 6);
let dat = self.mask_with_seed(&data[pos..pos+6], "peer");
pos += 6;
let port = Encoder::read_u16(&dat[4..]);
let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(dat[0], dat[1], dat[2], dat[3]), port));
peers.push(addr);
}
let v6count = (data.len() - pos)/18;
for _ in 0..v6count {
assert!(data.len() >= pos + 18);
let dat = self.mask_with_seed(&data[pos..pos+18], "peer");
pos += 18;
let mut ip = [0u16; 8];
for i in 0..8 {
ip[i] = Encoder::read_u16(&dat[i*2..i*2+2]);
}
let port = Encoder::read_u16(&dat[16..]);
let addr = SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(ip[0], ip[1], ip[2],
ip[3], ip[4], ip[5], ip[6], ip[7]), port, 0, 0));
peers.push(addr);
}
peers
}
fn decode(&self, data: &str) -> Vec<SocketAddr> {
//TODO: remove anything that is not base58
let mut peers = Vec::new();
let begin = self.begin();
let end = self.end();
let mut pos = 0;
while let Some(found) = data[pos..].find(&begin) {
pos += found;
let start_pos = pos + begin.len();
if let Some(found) = data[pos..].find(&end) {
let end_pos = pos + found;
peers.append(&mut self.peerlist_decode(&data[start_pos..end_pos]));
pos = end_pos + end.len();
} else {
pos += begin.len();
}
}
peers
}
}
pub fn test() {
let beacon = BeaconSerializer::new(b"vpnc", "mysecretkey");
let mut peers = Vec::new();
peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap());
peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap());
peers.push(SocketAddr::from_str("[::1]:5678").unwrap());
let string = format!("{}{}{}", beacon.begin(), beacon.peerlist_encode(&peers), beacon.end());
println!("{}", string);
println!("{:?}", beacon.decode(&string));
}

View File

@ -21,6 +21,7 @@ extern crate igd;
extern crate siphasher;
extern crate daemonize;
extern crate ring;
extern crate bs58;
#[cfg(feature = "bench")] extern crate test;
#[macro_use] pub mod util;
@ -35,6 +36,7 @@ pub mod poll;
pub mod config;
pub mod port_forwarding;
pub mod traffic;
pub mod beacon;
#[cfg(test)] mod tests;
#[cfg(feature = "bench")] mod benches;
@ -262,6 +264,8 @@ fn run<P: Protocol> (config: Config) {
}
fn main() {
beacon::test();
return;
let args: Args = Docopt::new(USAGE).and_then(|d| d.deserialize()).unwrap_or_else(|e| e.exit());
if args.flag_version {
Crypto::init();

View File

@ -188,7 +188,7 @@ pub fn encode<'a>(msg: &'a mut Message, mut buf: &'a mut [u8], magic: HeaderMagi
SocketAddr::V4(addr) => v4addrs.push(addr),
SocketAddr::V6(addr) => v6addrs.push(addr)
}
};
}
assert!(v4addrs.len() <= 255);
assert!(v6addrs.len() <= 255);
let mut pos = start;