mirror of https://github.com/dswd/vpncloud.git
Implemented beacon support
This commit is contained in:
parent
2c818d7079
commit
537cb55c41
|
@ -5,5 +5,4 @@ vpncloud-oldnodes
|
||||||
deb/vpncloud/vpncloud
|
deb/vpncloud/vpncloud
|
||||||
deb/vpncloud/vpncloud.1*
|
deb/vpncloud/vpncloud.1*
|
||||||
Stats.ods
|
Stats.ods
|
||||||
.sodium-build
|
dist
|
||||||
wiki
|
|
||||||
|
|
|
@ -4,7 +4,9 @@ This project follows [semantic versioning](http://semver.org).
|
||||||
|
|
||||||
### UNRELEASED
|
### UNRELEASED
|
||||||
|
|
||||||
|
- [added] Added ability to publish small beacons for rendezvous
|
||||||
- [changed] Allow to build binary without manpage
|
- [changed] Allow to build binary without manpage
|
||||||
|
- [fixed] Fixed bug that could cause repeated initialization messages
|
||||||
|
|
||||||
### v0.9.1 (2019-02-16)
|
### v0.9.1 (2019-02-16)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
VpnCloud - Peer-to-Peer VPN
|
VpnCloud - Peer-to-Peer VPN
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/dswd/vpncloud.rs.svg?branch=master)](https://travis-ci.org/dswd/vpncloud.rs)
|
[![Build Status](https://travis-ci.org/dswd/vpncloud.svg?branch=master)](https://travis-ci.org/dswd/vpncloud)
|
||||||
[![Coverage Status](https://coveralls.io/repos/dswd/vpncloud.rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/dswd/vpncloud.rs?branch=master)
|
[![Coverage Status](https://coveralls.io/repos/dswd/vpncloud/badge.svg?branch=master&service=github)](https://coveralls.io/github/dswd/vpncloud?branch=master)
|
||||||
|
|
||||||
**VpnCloud** is a simple VPN over UDP. It creates a virtual network interface on
|
**VpnCloud** is a simple VPN over UDP. It creates a virtual network interface on
|
||||||
the host and forwards all received data via UDP to the destination. VpnCloud
|
the host and forwards all received data via UDP to the destination. VpnCloud
|
||||||
|
|
|
@ -1,7 +1,20 @@
|
||||||
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
|
// Copyright (C) 2019-2019 Dennis Schwerdel
|
||||||
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use base_62;
|
use base_62;
|
||||||
use ring::digest;
|
use ring::digest;
|
||||||
|
|
||||||
use std::num::Wrapping;
|
use std::num::Wrapping;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::io::{self, Write, Read};
|
||||||
|
use std::fs::{self, Permissions, File};
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::mem;
|
||||||
|
use std::thread;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
use super::util::{now, Encoder};
|
use super::util::{now, Encoder};
|
||||||
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr, SocketAddrV6, Ipv6Addr};
|
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr, SocketAddrV6, Ipv6Addr};
|
||||||
|
@ -19,16 +32,27 @@ fn now_hour_16() -> u16 {
|
||||||
((now() / 3600) & 0xffff) as u16
|
((now() / 3600) & 0xffff) as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FutureResult<T> {
|
||||||
|
has_result: AtomicBool,
|
||||||
|
result: Mutex<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct BeaconSerializer {
|
pub struct BeaconSerializer {
|
||||||
magic: Vec<u8>,
|
magic: Vec<u8>,
|
||||||
shared_key: Vec<u8>
|
shared_key: Vec<u8>,
|
||||||
|
future_peers: Arc<FutureResult<Vec<SocketAddr>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BeaconSerializer {
|
impl BeaconSerializer {
|
||||||
pub fn new(magic: &[u8], shared_key: &[u8]) -> Self {
|
pub fn new(magic: &[u8], shared_key: &[u8]) -> Self {
|
||||||
BeaconSerializer {
|
BeaconSerializer {
|
||||||
magic: magic.to_owned(),
|
magic: magic.to_owned(),
|
||||||
shared_key: shared_key.to_owned()
|
shared_key: shared_key.to_owned(),
|
||||||
|
future_peers: Arc::new(FutureResult {
|
||||||
|
has_result: AtomicBool::new(false),
|
||||||
|
result: Mutex::new(Vec::new())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +186,35 @@ impl BeaconSerializer {
|
||||||
self.encode_internal(peers, now_hour_16())
|
self.encode_internal(peers, now_hour_16())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_to_file<P: AsRef<Path>>(&self, peers: &[SocketAddr], path: P) -> Result<(), io::Error> {
|
||||||
|
let beacon = self.encode(peers);
|
||||||
|
debug!("Beacon: {}", beacon);
|
||||||
|
let mut f = try!(File::create(&path));
|
||||||
|
try!(writeln!(&mut f, "{}", beacon));
|
||||||
|
try!(fs::set_permissions(&path, Permissions::from_mode(0o644)));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_cmd(&self, peers: &[SocketAddr], cmd: &str) -> Result<(), io::Error> {
|
||||||
|
let begin = self.begin();
|
||||||
|
let data = self.peerlist_encode(peers, now_hour_16());
|
||||||
|
let end = self.end();
|
||||||
|
let beacon = format!("{}{}{}", begin, data, end);
|
||||||
|
debug!("Calling beacon command: {}", cmd);
|
||||||
|
let process = try!(Command::new("sh").args(&["-c", cmd])
|
||||||
|
.env("begin", begin).env("data", data).env("end", end).env("beacon", beacon)
|
||||||
|
.stdout(Stdio::piped()).stderr(Stdio::piped()).spawn());
|
||||||
|
thread::spawn(move || {
|
||||||
|
let output = process.wait_with_output().expect("Failed to wait on child");
|
||||||
|
if !output.status.success() {
|
||||||
|
error!("Beacon command failed: {}", String::from_utf8_lossy(&output.stderr));
|
||||||
|
} else {
|
||||||
|
debug!("Beacon command succeeded");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn decode_internal(&self, data: &str, ttl_hours: Option<u16>, now_hour: u16) -> Vec<SocketAddr> {
|
fn decode_internal(&self, data: &str, ttl_hours: Option<u16>, now_hour: u16) -> Vec<SocketAddr> {
|
||||||
let data = base_62_sanitize(data);
|
let data = base_62_sanitize(data);
|
||||||
let mut peers = Vec::new();
|
let mut peers = Vec::new();
|
||||||
|
@ -185,6 +238,48 @@ impl BeaconSerializer {
|
||||||
pub fn decode(&self, data: &str, ttl_hours: Option<u16>) -> Vec<SocketAddr> {
|
pub fn decode(&self, data: &str, ttl_hours: Option<u16>) -> Vec<SocketAddr> {
|
||||||
self.decode_internal(data, ttl_hours, now_hour_16())
|
self.decode_internal(data, ttl_hours, now_hour_16())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_from_file<P: AsRef<Path>>(&self, path: P, ttl_hours: Option<u16>) -> Result<Vec<SocketAddr>, io::Error> {
|
||||||
|
let mut f = try!(File::open(&path));
|
||||||
|
let mut contents = String::new();
|
||||||
|
try!(f.read_to_string(&mut contents));
|
||||||
|
Ok(self.decode(&contents, ttl_hours))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_from_cmd(&self, cmd: &str, ttl_hours: Option<u16>) -> Result<(), io::Error> {
|
||||||
|
let begin = self.begin();
|
||||||
|
let end = self.end();
|
||||||
|
debug!("Calling beacon command: {}", cmd);
|
||||||
|
let process = try!(Command::new("sh").args(&["-c", cmd])
|
||||||
|
.env("begin", begin).env("end", end)
|
||||||
|
.stdout(Stdio::piped()).stderr(Stdio::piped()).spawn());
|
||||||
|
let this = self.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let output = process.wait_with_output().expect("Failed to wait on child");
|
||||||
|
if output.status.success() {
|
||||||
|
let data = String::from_utf8_lossy(&output.stdout);
|
||||||
|
let mut peers = this.decode(&data, ttl_hours);
|
||||||
|
debug!("Beacon command succeeded with {} peers", peers.len());
|
||||||
|
mem::swap(&mut peers, &mut this.future_peers.result.lock().expect("Lock poisoned"));
|
||||||
|
this.future_peers.has_result.store(true, Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
|
error!("Beacon command failed: {}", String::from_utf8_lossy(&output.stderr));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//TODO: implement
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_cmd_results(&self) -> Option<Vec<SocketAddr>> {
|
||||||
|
if self.future_peers.has_result.load(Ordering::Relaxed) {
|
||||||
|
let mut peers = Vec::new();
|
||||||
|
mem::swap(&mut peers, &mut self.future_peers.result.lock().expect("Lock poisoned"));
|
||||||
|
self.future_peers.has_result.store(false, Ordering::Relaxed);
|
||||||
|
Some(peers)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
113
src/cloud.rs
113
src/cloud.rs
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
|
@ -140,6 +140,7 @@ impl PeerList {
|
||||||
peer.alt_addrs.retain(|i| i != &addr);
|
peer.alt_addrs.retain(|i| i != &addr);
|
||||||
peer.alt_addrs.push(old_addr);
|
peer.alt_addrs.push(old_addr);
|
||||||
self.peers.insert(addr, peer);
|
self.peers.insert(addr, peer);
|
||||||
|
self.addresses.insert(addr, node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -202,6 +203,7 @@ pub struct ReconnectEntry {
|
||||||
|
|
||||||
|
|
||||||
pub struct GenericCloud<P: Protocol, T: Table> {
|
pub struct GenericCloud<P: Protocol, T: Table> {
|
||||||
|
config: Config,
|
||||||
magic: HeaderMagic,
|
magic: HeaderMagic,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
peers: PeerList,
|
peers: PeerList,
|
||||||
|
@ -209,7 +211,7 @@ pub struct GenericCloud<P: Protocol, T: Table> {
|
||||||
learning: bool,
|
learning: bool,
|
||||||
broadcast: bool,
|
broadcast: bool,
|
||||||
reconnect_peers: Vec<ReconnectEntry>,
|
reconnect_peers: Vec<ReconnectEntry>,
|
||||||
blacklist_peers: Vec<SocketAddr>,
|
own_addresses: Vec<SocketAddr>,
|
||||||
table: T,
|
table: T,
|
||||||
socket4: UdpSocket,
|
socket4: UdpSocket,
|
||||||
socket6: UdpSocket,
|
socket6: UdpSocket,
|
||||||
|
@ -220,9 +222,9 @@ pub struct GenericCloud<P: Protocol, T: Table> {
|
||||||
buffer_out: [u8; 64*1024],
|
buffer_out: [u8; 64*1024],
|
||||||
next_housekeep: Time,
|
next_housekeep: Time,
|
||||||
next_stats_out: Time,
|
next_stats_out: Time,
|
||||||
|
next_beacon: Time,
|
||||||
port_forwarding: Option<PortForwarding>,
|
port_forwarding: Option<PortForwarding>,
|
||||||
traffic: TrafficStats,
|
traffic: TrafficStats,
|
||||||
stats_file: Option<String>,
|
|
||||||
beacon_serializer: BeaconSerializer,
|
beacon_serializer: BeaconSerializer,
|
||||||
_dummy_p: PhantomData<P>,
|
_dummy_p: PhantomData<P>,
|
||||||
}
|
}
|
||||||
|
@ -251,7 +253,7 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
learning,
|
learning,
|
||||||
broadcast,
|
broadcast,
|
||||||
reconnect_peers: Vec::new(),
|
reconnect_peers: Vec::new(),
|
||||||
blacklist_peers: Vec::new(),
|
own_addresses: Vec::new(),
|
||||||
table,
|
table,
|
||||||
socket4,
|
socket4,
|
||||||
socket6,
|
socket6,
|
||||||
|
@ -261,11 +263,12 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
buffer_out: [0; 64*1024],
|
buffer_out: [0; 64*1024],
|
||||||
next_housekeep: now(),
|
next_housekeep: now(),
|
||||||
next_stats_out: now() + STATS_INTERVAL,
|
next_stats_out: now() + STATS_INTERVAL,
|
||||||
|
next_beacon: now(),
|
||||||
port_forwarding,
|
port_forwarding,
|
||||||
traffic: TrafficStats::default(),
|
traffic: TrafficStats::default(),
|
||||||
stats_file: config.stats_file.clone(),
|
|
||||||
beacon_serializer: BeaconSerializer::new(&config.get_magic(), crypto.get_key()),
|
beacon_serializer: BeaconSerializer::new(&config.get_magic(), crypto.get_key()),
|
||||||
crypto,
|
crypto,
|
||||||
|
config: config.clone(),
|
||||||
_dummy_p: PhantomData,
|
_dummy_p: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,14 +359,14 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the address is blacklisted
|
/// Returns whether the address is of this node
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns an `Error::SocketError` if the given address is a name that failed to resolve to
|
/// Returns an `Error::SocketError` if the given address is a name that failed to resolve to
|
||||||
/// actual addresses.
|
/// actual addresses.
|
||||||
fn is_blacklisted<Addr: ToSocketAddrs+fmt::Debug>(&self, addr: Addr) -> Result<bool, Error> {
|
fn is_own_address<Addr: ToSocketAddrs+fmt::Debug>(&self, addr: Addr) -> Result<bool, Error> {
|
||||||
for addr in try!(resolve(&addr)) {
|
for addr in try!(resolve(&addr)) {
|
||||||
if self.blacklist_peers.contains(&addr) {
|
if self.own_addresses.contains(&addr) {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +382,7 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// This method returns `Error::NameError` if the address is a name that fails to resolve.
|
/// This method returns `Error::NameError` if the address is a name that fails to resolve.
|
||||||
pub fn connect<Addr: ToSocketAddrs+fmt::Debug+Clone>(&mut self, addr: Addr) -> Result<(), Error> {
|
pub fn connect<Addr: ToSocketAddrs+fmt::Debug+Clone>(&mut self, addr: Addr) -> Result<(), Error> {
|
||||||
if try!(self.peers.is_connected(addr.clone())) || try!(self.is_blacklisted(addr.clone())) {
|
if try!(self.peers.is_connected(addr.clone())) || try!(self.is_own_address(addr.clone())) {
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
debug!("Connecting to {:?}", addr);
|
debug!("Connecting to {:?}", addr);
|
||||||
|
@ -394,6 +397,25 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Connects to a node given by its address
|
||||||
|
///
|
||||||
|
/// This method connects to node by sending a `Message::Init` to it. If `addr` is a name that
|
||||||
|
/// resolves to multiple addresses, one message is sent to each of them.
|
||||||
|
/// If the node is already a connected peer or the address is blacklisted, no message is sent.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This method returns `Error::NameError` if the address is a name that fails to resolve.
|
||||||
|
fn connect_sock(&mut self, addr: SocketAddr) -> Result<(), Error> {
|
||||||
|
if self.peers.contains_addr(&addr) || self.own_addresses.contains(&addr) {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
debug!("Connecting to {:?}", addr);
|
||||||
|
let subnets = self.addresses.clone();
|
||||||
|
let node_id = self.node_id;
|
||||||
|
let mut msg = Message::Init(0, node_id, subnets.clone());
|
||||||
|
self.send_msg(addr, &mut msg)
|
||||||
|
}
|
||||||
|
|
||||||
/// Run all periodic housekeeping tasks
|
/// Run all periodic housekeeping tasks
|
||||||
///
|
///
|
||||||
/// This method executes several tasks:
|
/// This method executes several tasks:
|
||||||
|
@ -426,10 +448,6 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
// ...and send them to all peers
|
// ...and send them to all peers
|
||||||
let mut msg = Message::Peers(peers);
|
let mut msg = Message::Peers(peers);
|
||||||
try!(self.broadcast_msg(&mut msg));
|
try!(self.broadcast_msg(&mut msg));
|
||||||
// Output beacon
|
|
||||||
let beacon = self.beacon_serializer.encode(&self.peers.subset(3));
|
|
||||||
//TODO: publish beacon
|
|
||||||
debug!("Beacon: {}", beacon);
|
|
||||||
// Reschedule for next update
|
// Reschedule for next update
|
||||||
self.next_peerlist = now + Time::from(self.update_freq);
|
self.next_peerlist = now + Time::from(self.update_freq);
|
||||||
}
|
}
|
||||||
|
@ -478,21 +496,65 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
self.next_stats_out = now + STATS_INTERVAL;
|
self.next_stats_out = now + STATS_INTERVAL;
|
||||||
self.traffic.period(Some(60));
|
self.traffic.period(Some(60));
|
||||||
}
|
}
|
||||||
|
if let Some(peers) = self.beacon_serializer.get_cmd_results() {
|
||||||
|
debug!("Loaded beacon with peers: {:?}", peers);
|
||||||
|
for peer in peers {
|
||||||
|
try!(self.connect_sock(peer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.next_beacon < now {
|
||||||
|
try!(self.store_beacon());
|
||||||
|
try!(self.load_beacon());
|
||||||
|
self.next_beacon = now + Time::from(self.config.beacon_interval);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stores the beacon
|
||||||
|
fn store_beacon(&mut self) -> Result<(), Error> {
|
||||||
|
if let Some(ref path) = self.config.beacon_store {
|
||||||
|
let peers: Vec<_> = self.own_addresses.choose_multiple(&mut thread_rng(),3).cloned().collect();
|
||||||
|
if path.starts_with('|') {
|
||||||
|
try!(self.beacon_serializer.write_to_cmd(&peers, &path[1..]).map_err(|e| Error::Beacon("Failed to call beacon command", e)));
|
||||||
|
} else {
|
||||||
|
try!(self.beacon_serializer.write_to_file(&peers, &path).map_err(|e| Error::Beacon("Failed to write beacon to file", e)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads the beacon
|
||||||
|
fn load_beacon(&mut self) -> Result<(), Error> {
|
||||||
|
let peers;
|
||||||
|
if let Some(ref path) = self.config.beacon_load {
|
||||||
|
if path.starts_with('|') {
|
||||||
|
try!(self.beacon_serializer.read_from_cmd(&path[1..], Some(50)).map_err(|e| Error::Beacon("Failed to call beacon command", e)));
|
||||||
|
return Ok(())
|
||||||
|
} else {
|
||||||
|
peers = try!(self.beacon_serializer.read_from_file(&path, Some(50)).map_err(|e| Error::Beacon("Failed to read beacon from file", e)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
debug!("Loaded beacon with peers: {:?}", peers);
|
||||||
|
for peer in peers {
|
||||||
|
try!(self.connect_sock(peer));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates, resets and writes out the statistics to a file
|
/// Calculates, resets and writes out the statistics to a file
|
||||||
fn write_out_stats(&mut self) -> Result<(), io::Error> {
|
fn write_out_stats(&mut self) -> Result<(), io::Error> {
|
||||||
if self.stats_file.is_none() { return Ok(()) }
|
if self.config.stats_file.is_none() { return Ok(()) }
|
||||||
debug!("Writing out stats");
|
debug!("Writing out stats");
|
||||||
let mut f = try!(File::create(self.stats_file.as_ref().unwrap()));
|
let mut f = try!(File::create(self.config.stats_file.as_ref().unwrap()));
|
||||||
try!(self.peers.write_out(&mut f));
|
try!(self.peers.write_out(&mut f));
|
||||||
try!(writeln!(&mut f));
|
try!(writeln!(&mut f));
|
||||||
try!(self.table.write_out(&mut f));
|
try!(self.table.write_out(&mut f));
|
||||||
try!(writeln!(&mut f));
|
try!(writeln!(&mut f));
|
||||||
try!(self.traffic.write_out(&mut f));
|
try!(self.traffic.write_out(&mut f));
|
||||||
try!(writeln!(&mut f));
|
try!(writeln!(&mut f));
|
||||||
try!(fs::set_permissions(self.stats_file.as_ref().unwrap(), Permissions::from_mode(0o644)));
|
try!(fs::set_permissions(self.config.stats_file.as_ref().unwrap(), Permissions::from_mode(0o644)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +587,7 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
// to reconnect.
|
// to reconnect.
|
||||||
warn!("Destination for {} not found in peers: {}", dst, addr);
|
warn!("Destination for {} not found in peers: {}", dst, addr);
|
||||||
self.table.remove(&dst);
|
self.table.remove(&dst);
|
||||||
try!(self.connect(&addr));
|
try!(self.connect_sock(addr));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
@ -594,16 +656,14 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
Message::Peers(peers) => {
|
Message::Peers(peers) => {
|
||||||
// Connect to sender if not connected
|
// Connect to sender if not connected
|
||||||
if !self.peers.contains_addr(&peer) {
|
if !self.peers.contains_addr(&peer) {
|
||||||
try!(self.connect(&peer));
|
try!(self.connect_sock(peer));
|
||||||
}
|
}
|
||||||
if let Some(node_id) = self.peers.get_node_id(&peer) {
|
if let Some(node_id) = self.peers.get_node_id(&peer) {
|
||||||
self.peers.make_primary(node_id, peer);
|
self.peers.make_primary(node_id, peer);
|
||||||
}
|
}
|
||||||
// Connect to all peers in the message
|
// Connect to all peers in the message
|
||||||
for p in &peers {
|
for p in &peers {
|
||||||
if ! self.peers.contains_addr(p) && ! self.blacklist_peers.contains(p) {
|
try!(self.connect_sock(*p));
|
||||||
try!(self.connect(p));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Refresh peer
|
// Refresh peer
|
||||||
self.peers.refresh(&peer);
|
self.peers.refresh(&peer);
|
||||||
|
@ -611,7 +671,7 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
Message::Init(stage, node_id, ranges) => {
|
Message::Init(stage, node_id, ranges) => {
|
||||||
// Avoid connecting to self
|
// Avoid connecting to self
|
||||||
if node_id == self.node_id {
|
if node_id == self.node_id {
|
||||||
self.blacklist_peers.push(peer);
|
self.own_addresses.push(peer);
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
// Add sender as peer or as alternative address to existing peer
|
// Add sender as peer or as alternative address to existing peer
|
||||||
|
@ -647,8 +707,15 @@ impl<P: Protocol, T: Table> GenericCloud<P, T> {
|
||||||
/// `handle_net_message` method. It will also read from the device and call
|
/// `handle_net_message` method. It will also read from the device and call
|
||||||
/// `handle_interface_data` for each packet read.
|
/// `handle_interface_data` for each packet read.
|
||||||
/// Also, this method will call `housekeep` every second.
|
/// Also, this method will call `housekeep` every second.
|
||||||
#[allow(unknown_lints,clippy::cyclomatic_complexity)]
|
#[allow(unknown_lints, clippy::cyclomatic_complexity)]
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
|
match self.address() {
|
||||||
|
Err(err) => error!("Failed to obtain local addresses: {}", err),
|
||||||
|
Ok((v4, v6)) => {
|
||||||
|
self.own_addresses.push(v4);
|
||||||
|
self.own_addresses.push(v6);
|
||||||
|
}
|
||||||
|
}
|
||||||
let dummy_time = Instant::now();
|
let dummy_time = Instant::now();
|
||||||
let trap = Trap::trap(&[Signal::SIGINT, Signal::SIGTERM, Signal::SIGQUIT]);
|
let trap = Trap::trap(&[Signal::SIGINT, Signal::SIGTERM, Signal::SIGQUIT]);
|
||||||
let mut poll_handle = try_fail!(Poll::new(3), "Failed to create poll handle: {}");
|
let mut poll_handle = try_fail!(Poll::new(3), "Failed to create poll handle: {}");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use super::{MAGIC, Args};
|
use super::{MAGIC, Args};
|
||||||
|
@ -30,6 +30,9 @@ pub struct Config {
|
||||||
pub peers: Vec<String>,
|
pub peers: Vec<String>,
|
||||||
pub peer_timeout: Duration,
|
pub peer_timeout: Duration,
|
||||||
pub keepalive: Option<Duration>,
|
pub keepalive: Option<Duration>,
|
||||||
|
pub beacon_store: Option<String>,
|
||||||
|
pub beacon_load: Option<String>,
|
||||||
|
pub beacon_interval: Duration,
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
pub dst_timeout: Duration,
|
pub dst_timeout: Duration,
|
||||||
pub subnets: Vec<String>,
|
pub subnets: Vec<String>,
|
||||||
|
@ -49,6 +52,7 @@ impl Default for Config {
|
||||||
crypto: CryptoMethod::ChaCha20, shared_key: None,
|
crypto: CryptoMethod::ChaCha20, shared_key: None,
|
||||||
magic: None,
|
magic: None,
|
||||||
port: 3210, peers: vec![], peer_timeout: 1800, keepalive: None,
|
port: 3210, peers: vec![], peer_timeout: 1800, keepalive: None,
|
||||||
|
beacon_store: None, beacon_load: None, beacon_interval: 3600,
|
||||||
mode: Mode::Normal, dst_timeout: 300,
|
mode: Mode::Normal, dst_timeout: 300,
|
||||||
subnets: vec![],
|
subnets: vec![],
|
||||||
port_forwarding: true,
|
port_forwarding: true,
|
||||||
|
@ -99,6 +103,15 @@ impl Config {
|
||||||
if let Some(val) = file.keepalive {
|
if let Some(val) = file.keepalive {
|
||||||
self.keepalive = Some(val);
|
self.keepalive = Some(val);
|
||||||
}
|
}
|
||||||
|
if let Some(val) = file.beacon_store {
|
||||||
|
self.beacon_store = Some(val);
|
||||||
|
}
|
||||||
|
if let Some(val) = file.beacon_load {
|
||||||
|
self.beacon_load = Some(val);
|
||||||
|
}
|
||||||
|
if let Some(val) = file.beacon_interval {
|
||||||
|
self.beacon_interval = val;
|
||||||
|
}
|
||||||
if let Some(val) = file.mode {
|
if let Some(val) = file.mode {
|
||||||
self.mode = val;
|
self.mode = val;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +177,15 @@ impl Config {
|
||||||
if let Some(val) = args.flag_keepalive {
|
if let Some(val) = args.flag_keepalive {
|
||||||
self.keepalive = Some(val);
|
self.keepalive = Some(val);
|
||||||
}
|
}
|
||||||
|
if let Some(val) = args.flag_beacon_store {
|
||||||
|
self.beacon_store = Some(val);
|
||||||
|
}
|
||||||
|
if let Some(val) = args.flag_beacon_load {
|
||||||
|
self.beacon_load = Some(val);
|
||||||
|
}
|
||||||
|
if let Some(val) = args.flag_beacon_interval {
|
||||||
|
self.beacon_interval = val;
|
||||||
|
}
|
||||||
if let Some(val) = args.flag_mode {
|
if let Some(val) = args.flag_mode {
|
||||||
self.mode = val;
|
self.mode = val;
|
||||||
}
|
}
|
||||||
|
@ -233,6 +255,9 @@ pub struct ConfigFile {
|
||||||
pub peers: Option<Vec<String>>,
|
pub peers: Option<Vec<String>>,
|
||||||
pub peer_timeout: Option<Duration>,
|
pub peer_timeout: Option<Duration>,
|
||||||
pub keepalive: Option<Duration>,
|
pub keepalive: Option<Duration>,
|
||||||
|
pub beacon_store: Option<String>,
|
||||||
|
pub beacon_load: Option<String>,
|
||||||
|
pub beacon_interval: Option<Duration>,
|
||||||
pub mode: Option<Mode>,
|
pub mode: Option<Mode>,
|
||||||
pub dst_timeout: Option<Duration>,
|
pub dst_timeout: Option<Duration>,
|
||||||
pub subnets: Option<Vec<String>>,
|
pub subnets: Option<Vec<String>>,
|
||||||
|
@ -262,6 +287,9 @@ peers:
|
||||||
peer_timeout: 1800
|
peer_timeout: 1800
|
||||||
keepalive: 840
|
keepalive: 840
|
||||||
dst_timeout: 300
|
dst_timeout: 300
|
||||||
|
beacon_store: /run/vpncloud.beacon.out
|
||||||
|
beacon_load: /run/vpncloud.beacon.in
|
||||||
|
beacon_interval: 3600
|
||||||
mode: normal
|
mode: normal
|
||||||
subnets:
|
subnets:
|
||||||
- 10.0.1.0/24
|
- 10.0.1.0/24
|
||||||
|
@ -284,6 +312,9 @@ stats_file: /var/log/vpncloud.stats
|
||||||
peers: Some(vec!["remote.machine.foo:3210".to_string(), "remote.machine.bar:3210".to_string()]),
|
peers: Some(vec!["remote.machine.foo:3210".to_string(), "remote.machine.bar:3210".to_string()]),
|
||||||
peer_timeout: Some(1800),
|
peer_timeout: Some(1800),
|
||||||
keepalive: Some(840),
|
keepalive: Some(840),
|
||||||
|
beacon_store: Some("/run/vpncloud.beacon.out".to_string()),
|
||||||
|
beacon_load: Some("/run/vpncloud.beacon.in".to_string()),
|
||||||
|
beacon_interval: Some(3600),
|
||||||
mode: Some(Mode::Normal),
|
mode: Some(Mode::Normal),
|
||||||
dst_timeout: Some(300),
|
dst_timeout: Some(300),
|
||||||
subnets: Some(vec!["10.0.1.0/24".to_string()]),
|
subnets: Some(vec!["10.0.1.0/24".to_string()]),
|
||||||
|
@ -311,6 +342,9 @@ fn config_merge() {
|
||||||
peers: Some(vec!["remote.machine.foo:3210".to_string(), "remote.machine.bar:3210".to_string()]),
|
peers: Some(vec!["remote.machine.foo:3210".to_string(), "remote.machine.bar:3210".to_string()]),
|
||||||
peer_timeout: Some(1800),
|
peer_timeout: Some(1800),
|
||||||
keepalive: Some(840),
|
keepalive: Some(840),
|
||||||
|
beacon_store: Some("/run/vpncloud.beacon.out".to_string()),
|
||||||
|
beacon_load: Some("/run/vpncloud.beacon.in".to_string()),
|
||||||
|
beacon_interval: Some(7200),
|
||||||
mode: Some(Mode::Normal),
|
mode: Some(Mode::Normal),
|
||||||
dst_timeout: Some(300),
|
dst_timeout: Some(300),
|
||||||
subnets: Some(vec!["10.0.1.0/24".to_string()]),
|
subnets: Some(vec!["10.0.1.0/24".to_string()]),
|
||||||
|
@ -334,6 +368,9 @@ fn config_merge() {
|
||||||
peer_timeout: 1800,
|
peer_timeout: 1800,
|
||||||
keepalive: Some(840),
|
keepalive: Some(840),
|
||||||
dst_timeout: 300,
|
dst_timeout: 300,
|
||||||
|
beacon_store: Some("/run/vpncloud.beacon.out".to_string()),
|
||||||
|
beacon_load: Some("/run/vpncloud.beacon.in".to_string()),
|
||||||
|
beacon_interval: 7200,
|
||||||
mode: Mode::Normal,
|
mode: Mode::Normal,
|
||||||
port_forwarding: true,
|
port_forwarding: true,
|
||||||
subnets: vec!["10.0.1.0/24".to_string()],
|
subnets: vec!["10.0.1.0/24".to_string()],
|
||||||
|
@ -356,6 +393,9 @@ fn config_merge() {
|
||||||
flag_peer_timeout: Some(1801),
|
flag_peer_timeout: Some(1801),
|
||||||
flag_keepalive: Some(850),
|
flag_keepalive: Some(850),
|
||||||
flag_dst_timeout: Some(301),
|
flag_dst_timeout: Some(301),
|
||||||
|
flag_beacon_store: Some("/run/vpncloud.beacon.out2".to_string()),
|
||||||
|
flag_beacon_load: Some("/run/vpncloud.beacon.in2".to_string()),
|
||||||
|
flag_beacon_interval: Some(3600),
|
||||||
flag_mode: Some(Mode::Switch),
|
flag_mode: Some(Mode::Switch),
|
||||||
flag_subnet: vec![],
|
flag_subnet: vec![],
|
||||||
flag_connect: vec!["another:3210".to_string()],
|
flag_connect: vec!["another:3210".to_string()],
|
||||||
|
@ -381,6 +421,9 @@ fn config_merge() {
|
||||||
peer_timeout: 1801,
|
peer_timeout: 1801,
|
||||||
keepalive: Some(850),
|
keepalive: Some(850),
|
||||||
dst_timeout: 301,
|
dst_timeout: 301,
|
||||||
|
beacon_store: Some("/run/vpncloud.beacon.out2".to_string()),
|
||||||
|
beacon_load: Some("/run/vpncloud.beacon.in2".to_string()),
|
||||||
|
beacon_interval: 3600,
|
||||||
mode: Mode::Switch,
|
mode: Mode::Switch,
|
||||||
port_forwarding: false,
|
port_forwarding: false,
|
||||||
subnets: vec!["10.0.1.0/24".to_string()],
|
subnets: vec!["10.0.1.0/24".to_string()],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
#![cfg_attr(feature = "bench", feature(test))]
|
#![cfg_attr(feature = "bench", feature(test))]
|
||||||
|
@ -82,6 +82,9 @@ pub struct Args {
|
||||||
flag_peer_timeout: Option<Duration>,
|
flag_peer_timeout: Option<Duration>,
|
||||||
flag_keepalive: Option<Duration>,
|
flag_keepalive: Option<Duration>,
|
||||||
flag_dst_timeout: Option<Duration>,
|
flag_dst_timeout: Option<Duration>,
|
||||||
|
flag_beacon_store: Option<String>,
|
||||||
|
flag_beacon_load: Option<String>,
|
||||||
|
flag_beacon_interval: Option<Duration>,
|
||||||
flag_verbose: bool,
|
flag_verbose: bool,
|
||||||
flag_quiet: bool,
|
flag_quiet: bool,
|
||||||
flag_ifup: Option<String>,
|
flag_ifup: Option<String>,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::net::{SocketAddrV4, UdpSocket, SocketAddr};
|
use std::net::{SocketAddrV4, UdpSocket, SocketAddr};
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
|
// Copyright (C) 2018-2019 Dennis Schwerdel
|
||||||
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::net::{SocketAddr, Ipv4Addr, Ipv6Addr};
|
use std::net::{SocketAddr, Ipv4Addr, Ipv6Addr};
|
||||||
|
@ -227,7 +227,8 @@ pub enum Error {
|
||||||
Name(String),
|
Name(String),
|
||||||
TunTapDev(&'static str, io::Error),
|
TunTapDev(&'static str, io::Error),
|
||||||
Crypto(&'static str),
|
Crypto(&'static str),
|
||||||
File(&'static str, io::Error)
|
File(&'static str, io::Error),
|
||||||
|
Beacon(&'static str, io::Error)
|
||||||
}
|
}
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
@ -238,7 +239,8 @@ impl fmt::Display for Error {
|
||||||
Error::Crypto(msg) => write!(formatter, "{}", msg),
|
Error::Crypto(msg) => write!(formatter, "{}", msg),
|
||||||
Error::Name(ref name) => write!(formatter, "failed to resolve name '{}'", name),
|
Error::Name(ref name) => write!(formatter, "failed to resolve name '{}'", name),
|
||||||
Error::WrongHeaderMagic(net) => write!(formatter, "wrong header magic: {}", bytes_to_hex(&net)),
|
Error::WrongHeaderMagic(net) => write!(formatter, "wrong header magic: {}", bytes_to_hex(&net)),
|
||||||
Error::File(msg, ref err) => write!(formatter, "{}: {:?}", msg, err)
|
Error::File(msg, ref err) => write!(formatter, "{}: {:?}", msg, err),
|
||||||
|
Error::Beacon(msg, ref err) => write!(formatter, "{}: {:?}", msg, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
|
@ -23,6 +23,9 @@ Options:
|
||||||
--keepalive <secs> Periodically send message to keep
|
--keepalive <secs> Periodically send message to keep
|
||||||
connections alive.
|
connections alive.
|
||||||
--dst-timeout <secs> Switch table entry timeout in seconds.
|
--dst-timeout <secs> Switch table entry timeout in seconds.
|
||||||
|
--beacon-store <path|command> The file or command to store the beacon.
|
||||||
|
--beacon-load <path|command> The file or command to load the beacon.
|
||||||
|
--beacon-interval <secs> Beacon store/load interval in seconds.
|
||||||
--ifup <command> A command to setup the network interface.
|
--ifup <command> A command to setup the network interface.
|
||||||
--ifdown <command> A command to bring down the network
|
--ifdown <command> A command to bring down the network
|
||||||
interface.
|
interface.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// VpnCloud - Peer-to-Peer VPN
|
// VpnCloud - Peer-to-Peer VPN
|
||||||
// Copyright (C) 2015-2017 Dennis Schwerdel
|
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||||
|
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
|
|
61
vpncloud.md
61
vpncloud.md
|
@ -86,6 +86,32 @@ vpncloud(1) -- Peer-to-peer VPN
|
||||||
mode. Addresses that have not been seen for the given period of time will
|
mode. Addresses that have not been seen for the given period of time will
|
||||||
be forgotten. [default: `300`]
|
be forgotten. [default: `300`]
|
||||||
|
|
||||||
|
* `--beacon-store <path|command>`:
|
||||||
|
|
||||||
|
Periodically store beacons containing the address of this node in the given
|
||||||
|
file or via the given command. If the parameter value starts with a pipe
|
||||||
|
character (`|`), the rest of the value is interpreted as a shell command.
|
||||||
|
Otherwise the value is interpreted as a file to write the beacon to.
|
||||||
|
If this parameter is not given, beacon storage is disabled.
|
||||||
|
Please see the section **BEACONS** for more information.
|
||||||
|
|
||||||
|
* `--beacon-load <path|command>`:
|
||||||
|
|
||||||
|
Periodically load beacons containing the addresses of other nodes from the
|
||||||
|
given file or via the given command. If the parameter value starts with a
|
||||||
|
pipe character (`|`), the rest of the value is interpreted as a shell
|
||||||
|
command. Otherwise the value is interpreted as a file to read the beacon
|
||||||
|
from.
|
||||||
|
If this parameter is not given, beacon loading is disabled.
|
||||||
|
Please see the section **BEACONS** for more information.
|
||||||
|
|
||||||
|
* `--beacon-interval <secs>`:
|
||||||
|
|
||||||
|
Beacon storage/loading interval in seconds. If configured to do so via
|
||||||
|
`--beacon-store` and `--beacon-load`, the node will periodically store its
|
||||||
|
beacon and load beacons of other nodes. This parameter defines the interval
|
||||||
|
in seconds. [default: `3600`]
|
||||||
|
|
||||||
* `--ifup <command>`:
|
* `--ifup <command>`:
|
||||||
|
|
||||||
A command to setup the network interface. The command will be run (as
|
A command to setup the network interface. The command will be run (as
|
||||||
|
@ -283,6 +309,9 @@ detailed descriptions of the options.
|
||||||
* `port`: The port number on which to listen for data. Same as `--listen`
|
* `port`: The port number on which to listen for data. Same as `--listen`
|
||||||
* `peers`: A list of addresses to connect to. See `--connect`
|
* `peers`: A list of addresses to connect to. See `--connect`
|
||||||
* `peer_timeout`: Peer timeout in seconds. Same as`--peer-timeout`
|
* `peer_timeout`: Peer timeout in seconds. Same as`--peer-timeout`
|
||||||
|
* `beacon_store`: Path or command to store beacons. Same as `--beacon-store`
|
||||||
|
* `beacon_load`: Path or command to load beacons. Same as `--beacon-load`
|
||||||
|
* `beacon_interval`: Interval for loading and storing beacons in seconds. Same as `--beacon-interval`
|
||||||
* `mode`: The mode of the VPN. Same as `--mode`
|
* `mode`: The mode of the VPN. Same as `--mode`
|
||||||
* `dst_timeout`: Switch table entry timeout in seconds. Same as `--dst-timeout`
|
* `dst_timeout`: Switch table entry timeout in seconds. Same as `--dst-timeout`
|
||||||
* `subnets`: A list of local subnets to use. See `--subnet`
|
* `subnets`: A list of local subnets to use. See `--subnet`
|
||||||
|
@ -314,6 +343,38 @@ group: nogroup
|
||||||
pid_file: /run/vpncloud.pid
|
pid_file: /run/vpncloud.pid
|
||||||
|
|
||||||
|
|
||||||
|
## BEACONS
|
||||||
|
|
||||||
|
Beacons are short character sequences that contain a timestamp and a list of
|
||||||
|
addresses. They can be published and retrieved by other nodes to find peers
|
||||||
|
without the need for static addresses.
|
||||||
|
|
||||||
|
The beacons are short (less than 100 characters), encrypted and encoded with
|
||||||
|
printable characters to allow publishing them in various places on the
|
||||||
|
internet, e.g.:
|
||||||
|
- On shared drives or synchronized folders (e.g. on Dropbox)
|
||||||
|
- Via a dedicated database
|
||||||
|
- Via a general purpose message board of message service (e.g. Twitter)
|
||||||
|
|
||||||
|
The beacons are very robust. They only consist of alphanumeric characters
|
||||||
|
and can be interleaved with non-alphanumeric characters (e.g. whitespace).
|
||||||
|
Also the beacons contain a prefix and suffix that depends on the configured
|
||||||
|
network magic and secret key (if set) so that all nodes can find beacons in
|
||||||
|
a long text.
|
||||||
|
|
||||||
|
When beacons are stored or loaded via a command (using the pipe character `|`),
|
||||||
|
the command is interpreted using the configured shell `sh`. This command has
|
||||||
|
access to the following environment variables:
|
||||||
|
* `$begin`: The prefix of the beacon.
|
||||||
|
* `$end`: The suffix of the beacon.
|
||||||
|
* `$data` (only on store): The middle part of the beacon. Do not use this
|
||||||
|
without prefix and suffix!
|
||||||
|
* `$beacon` (only on store): The full beacon consisting of prefix, data and
|
||||||
|
suffix.
|
||||||
|
The commands are called in separate threads, so even longer running commands
|
||||||
|
will not block the node.
|
||||||
|
|
||||||
|
|
||||||
## NETWORK PROTOCOL
|
## NETWORK PROTOCOL
|
||||||
|
|
||||||
The protocol of VpnCloud is kept as simple as possible to allow other
|
The protocol of VpnCloud is kept as simple as possible to allow other
|
||||||
|
|
Loading…
Reference in New Issue