mirror of https://github.com/dswd/vpncloud.git
Compare commits
2 Commits
58ce003cb6
...
2fcf2c1e01
Author | SHA1 | Date |
---|---|---|
Dennis Schwerdel | 2fcf2c1e01 | |
Dennis Schwerdel | 86223fb4f9 |
|
@ -8,7 +8,10 @@ This project follows [semantic versioning](http://semver.org).
|
|||
- [added] Added crypto option AES128
|
||||
- [added] Default port for peers
|
||||
- [changed] Updated dependencies
|
||||
- [changed] Removed C code, now 100% Rust
|
||||
- [fixed] Fixed keepalive for small timeouts
|
||||
- [fixed] Fixed problem with port forwarding
|
||||
- [fixed] Fixed problem with TUN on dynamic host addresses
|
||||
|
||||
### v1.4.0 (2020-06-03)
|
||||
|
||||
|
|
10
src/cloud.rs
10
src/cloud.rs
|
@ -3,7 +3,7 @@
|
|||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||
|
||||
use std::{
|
||||
cmp::{min, max},
|
||||
cmp::{max, min},
|
||||
collections::HashMap,
|
||||
fmt,
|
||||
fs::{self, File},
|
||||
|
@ -109,7 +109,6 @@ impl<TS: TimeSource> PeerList<TS> {
|
|||
self.nodes.contains_key(node_id)
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn add(&mut self, node_id: NodeId, addr: SocketAddr, peer_timeout: u16) {
|
||||
if self.nodes.insert(node_id, addr).is_none() {
|
||||
|
@ -366,7 +365,8 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
/// connect to the peer if it is not already connected.
|
||||
pub fn add_reconnect_peer(&mut self, mut add: String) {
|
||||
let now = TS::now();
|
||||
if add.find(':').unwrap_or(0) <= add.find(']').unwrap_or(0) { // : not present or only in IPv6 address
|
||||
if add.find(':').unwrap_or(0) <= add.find(']').unwrap_or(0) {
|
||||
// : not present or only in IPv6 address
|
||||
add = format!("{}:{}", add, DEFAULT_PORT)
|
||||
}
|
||||
let resolved = match resolve(&add as &str) {
|
||||
|
@ -753,7 +753,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
}
|
||||
if self.learning {
|
||||
// Learn single address
|
||||
self.table.learn(src, None, peer);
|
||||
self.table.learn(src, None, self.node_id, peer);
|
||||
}
|
||||
// Not adding peer in this case to increase performance
|
||||
}
|
||||
|
@ -787,7 +787,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
warn!("Ignoring claimed addresses received from {} in learning mode.", addr_nice(peer));
|
||||
} else {
|
||||
for range in ranges {
|
||||
self.table.learn(range.base, Some(range.prefix_len), peer);
|
||||
self.table.learn(range.base, Some(range.prefix_len), node_id, peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use std::{
|
|||
use fnv::FnvHasher;
|
||||
|
||||
use super::{
|
||||
types::{Address, Error, Protocol, Table},
|
||||
types::{Address, Error, NodeId, Protocol, Table},
|
||||
util::{addr_nice, Duration, Time, TimeSource}
|
||||
};
|
||||
|
||||
|
@ -125,7 +125,7 @@ impl<TS: TimeSource> Table for SwitchTable<TS> {
|
|||
|
||||
/// Learns the given address, inserting it in the hash map
|
||||
#[inline]
|
||||
fn learn(&mut self, key: Address, _prefix_len: Option<u8>, addr: SocketAddr) {
|
||||
fn learn(&mut self, key: Address, _prefix_len: Option<u8>, _: NodeId, addr: SocketAddr) {
|
||||
let deadline = TS::now() + Time::from(self.timeout);
|
||||
match self.table.entry(key) {
|
||||
Entry::Vacant(entry) => {
|
||||
|
@ -212,16 +212,17 @@ fn switch() {
|
|||
MockTimeSource::set_time(1000);
|
||||
let mut table = SwitchTable::<MockTimeSource>::new(10, 1);
|
||||
let addr = Address::from_str("12:34:56:78:90:ab").unwrap();
|
||||
let node_id = [0; 16];
|
||||
let peer = "1.2.3.4:5678".to_socket_addrs().unwrap().next().unwrap();
|
||||
let peer2 = "1.2.3.5:7890".to_socket_addrs().unwrap().next().unwrap();
|
||||
assert!(table.lookup(&addr).is_none());
|
||||
MockTimeSource::set_time(1000);
|
||||
table.learn(addr, None, peer);
|
||||
table.learn(addr, None, node_id, peer);
|
||||
assert_eq!(table.lookup(&addr), Some(peer));
|
||||
MockTimeSource::set_time(1000);
|
||||
table.learn(addr, None, peer2);
|
||||
table.learn(addr, None, node_id, peer2);
|
||||
assert_eq!(table.lookup(&addr), Some(peer));
|
||||
MockTimeSource::set_time(1010);
|
||||
table.learn(addr, None, peer2);
|
||||
table.learn(addr, None, node_id, peer2);
|
||||
assert_eq!(table.lookup(&addr), Some(peer2));
|
||||
}
|
||||
|
|
47
src/ip.rs
47
src/ip.rs
|
@ -12,7 +12,7 @@ use std::{
|
|||
use fnv::FnvHasher;
|
||||
|
||||
use super::{
|
||||
types::{Address, Error, Protocol, Table},
|
||||
types::{Address, Error, NodeId, Protocol, Table},
|
||||
util::addr_nice
|
||||
};
|
||||
|
||||
|
@ -59,6 +59,7 @@ impl Protocol for Packet {
|
|||
|
||||
struct RoutingEntry {
|
||||
address: SocketAddr,
|
||||
node_id: NodeId,
|
||||
bytes: Address,
|
||||
prefix_len: u8
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ impl RoutingTable {
|
|||
|
||||
impl Table for RoutingTable {
|
||||
/// Learns the given address, inserting it in the hash map
|
||||
fn learn(&mut self, addr: Address, prefix_len: Option<u8>, address: SocketAddr) {
|
||||
fn learn(&mut self, addr: Address, prefix_len: Option<u8>, node_id: NodeId, address: SocketAddr) {
|
||||
// If prefix length is not set, treat the whole address as significant
|
||||
let prefix_len = match prefix_len {
|
||||
Some(val) => val,
|
||||
|
@ -96,10 +97,14 @@ impl Table for RoutingTable {
|
|||
let mut group_bytes = [0; 16];
|
||||
group_bytes[..group_len].copy_from_slice(&addr.data[..group_len]);
|
||||
// Create an entry
|
||||
let routing_entry = RoutingEntry { address, bytes: addr, prefix_len };
|
||||
let routing_entry = RoutingEntry { address, bytes: addr, node_id, prefix_len };
|
||||
// Add the entry to the routing table, creating a new list if the prefix group is empty.
|
||||
match self.0.entry(group_bytes) {
|
||||
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry),
|
||||
hash_map::Entry::Occupied(mut entry) => {
|
||||
let list = entry.get_mut();
|
||||
list.retain(|e| e.node_id != routing_entry.node_id || e.address == routing_entry.address);
|
||||
list.push(routing_entry)
|
||||
}
|
||||
hash_map::Entry::Vacant(entry) => {
|
||||
entry.insert(vec![routing_entry]);
|
||||
}
|
||||
|
@ -241,33 +246,36 @@ fn decode_invalid_packet() {
|
|||
fn routing_table_ipv4() {
|
||||
let mut table = RoutingTable::new();
|
||||
let peer1 = "1.2.3.4:1".to_socket_addrs().unwrap().next().unwrap();
|
||||
let node1 = [1; 16];
|
||||
let peer2 = "1.2.3.4:2".to_socket_addrs().unwrap().next().unwrap();
|
||||
let node2 = [2; 16];
|
||||
let peer3 = "1.2.3.4:3".to_socket_addrs().unwrap().next().unwrap();
|
||||
let node3 = [3; 16];
|
||||
assert!(table.lookup(&Address::from_str("192.168.1.1").unwrap()).is_none());
|
||||
table.learn(Address::from_str("192.168.1.1").unwrap(), Some(32), peer1);
|
||||
table.learn(Address::from_str("192.168.1.1").unwrap(), Some(32), node1, peer1);
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1));
|
||||
table.learn(Address::from_str("192.168.1.2").unwrap(), None, peer2);
|
||||
table.learn(Address::from_str("192.168.1.2").unwrap(), None, node2, peer2);
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.2").unwrap()), Some(peer2));
|
||||
table.learn(Address::from_str("192.168.1.0").unwrap(), Some(24), peer3);
|
||||
table.learn(Address::from_str("192.168.1.0").unwrap(), Some(24), node3, peer3);
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.2").unwrap()), Some(peer2));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.3").unwrap()), Some(peer3));
|
||||
table.learn(Address::from_str("192.168.0.0").unwrap(), Some(16), peer1);
|
||||
table.learn(Address::from_str("192.168.0.0").unwrap(), Some(16), node1, peer1);
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.2.1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.2").unwrap()), Some(peer2));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.3").unwrap()), Some(peer3));
|
||||
table.learn(Address::from_str("0.0.0.0").unwrap(), Some(0), peer2);
|
||||
table.learn(Address::from_str("0.0.0.0").unwrap(), Some(0), node2, peer2);
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.2.1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.2").unwrap()), Some(peer2));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.1.3").unwrap()), Some(peer3));
|
||||
assert_eq!(table.lookup(&Address::from_str("1.2.3.4").unwrap()), Some(peer2));
|
||||
table.learn(Address::from_str("192.168.2.0").unwrap(), Some(27), peer3);
|
||||
table.learn(Address::from_str("192.168.2.0").unwrap(), Some(27), node3, peer3);
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.2.31").unwrap()), Some(peer3));
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.2.32").unwrap()), Some(peer1));
|
||||
table.learn(Address::from_str("192.168.2.0").unwrap(), Some(28), peer3);
|
||||
table.learn(Address::from_str("192.168.2.0").unwrap(), Some(28), node3, peer3);
|
||||
assert_eq!(table.lookup(&Address::from_str("192.168.2.1").unwrap()), Some(peer3));
|
||||
}
|
||||
|
||||
|
@ -275,34 +283,37 @@ fn routing_table_ipv4() {
|
|||
fn routing_table_ipv6() {
|
||||
let mut table = RoutingTable::new();
|
||||
let peer1 = "::1:1".to_socket_addrs().unwrap().next().unwrap();
|
||||
let node1 = [1; 16];
|
||||
let peer2 = "::1:2".to_socket_addrs().unwrap().next().unwrap();
|
||||
let node2 = [2; 16];
|
||||
let peer3 = "::1:3".to_socket_addrs().unwrap().next().unwrap();
|
||||
let node3 = [3; 16];
|
||||
assert!(table.lookup(&Address::from_str("::1").unwrap()).is_none());
|
||||
table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap(), Some(128), peer1);
|
||||
table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap(), Some(128), node1, peer1);
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1));
|
||||
table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap(), None, peer2);
|
||||
table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap(), None, node2, peer2);
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap()), Some(peer2));
|
||||
table.learn(Address::from_str("dead:beef:dead:beef::").unwrap(), Some(64), peer3);
|
||||
table.learn(Address::from_str("dead:beef:dead:beef::").unwrap(), Some(64), node3, peer3);
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap()), Some(peer2));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:3").unwrap()), Some(peer3));
|
||||
table.learn(Address::from_str("dead:beef:dead:be00::").unwrap(), Some(56), peer1);
|
||||
table.learn(Address::from_str("dead:beef:dead:be00::").unwrap(), Some(56), node1, peer1);
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:1::").unwrap()), Some(peer3));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:be01::").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap()), Some(peer2));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:3").unwrap()), Some(peer3));
|
||||
table.learn(Address::from_str("::").unwrap(), Some(0), peer2);
|
||||
table.learn(Address::from_str("::").unwrap(), Some(0), node2, peer2);
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:1::").unwrap()), Some(peer3));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:be01::").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:1").unwrap()), Some(peer1));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:2").unwrap()), Some(peer2));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:3").unwrap()), Some(peer3));
|
||||
assert_eq!(table.lookup(&Address::from_str("::1").unwrap()), Some(peer2));
|
||||
table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:be00").unwrap(), Some(123), peer2);
|
||||
table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:be00").unwrap(), Some(123), node2, peer2);
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:be1f").unwrap()), Some(peer2));
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:be20").unwrap()), Some(peer3));
|
||||
table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:be00").unwrap(), Some(124), peer3);
|
||||
table.learn(Address::from_str("dead:beef:dead:beef:dead:beef:dead:be00").unwrap(), Some(124), node3, peer3);
|
||||
assert_eq!(table.lookup(&Address::from_str("dead:beef:dead:beef:dead:beef:dead:be01").unwrap()), Some(peer3));
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ mod internal {
|
|||
if let Ok((port, timeout)) = Self::get_any_forwarding(&gateway, internal_addr, port) {
|
||||
info!("Port-forwarding: external IP is {}", external_ip);
|
||||
let external_addr = SocketAddrV4::new(external_ip, port);
|
||||
info!("Port-forwarding: sucessfully activated port forward on {}, timeout: {}", external_addr, timeout);
|
||||
info!("Port-forwarding: successfully activated port forward on {}, timeout: {}", external_addr, timeout);
|
||||
let next_extension =
|
||||
if timeout > 0 { Some(SystemTimeSource::now() + Time::from(timeout) - 60) } else { None };
|
||||
Some(PortForwarding { internal_addr, external_addr, gateway, next_extension })
|
||||
|
@ -101,6 +101,7 @@ mod internal {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
gateway.remove_port(PortMappingProtocol::UDP, port).ok();
|
||||
match gateway.add_port(PortMappingProtocol::UDP, port, addr, LEASE_TIME, DESCRIPTION) {
|
||||
Ok(()) => Ok((port, LEASE_TIME)),
|
||||
Err(AddPortError::OnlyPermanentLeasesSupported) => {
|
||||
|
|
|
@ -221,7 +221,7 @@ impl FromStr for Mode {
|
|||
}
|
||||
|
||||
pub trait Table {
|
||||
fn learn(&mut self, _: Address, _: Option<u8>, _: SocketAddr);
|
||||
fn learn(&mut self, _: Address, _: Option<u8>, _: NodeId, _: SocketAddr);
|
||||
fn lookup(&mut self, _: &Address) -> Option<SocketAddr>;
|
||||
fn housekeep(&mut self);
|
||||
fn write_out<W: Write>(&self, out: &mut W) -> Result<(), io::Error>;
|
||||
|
|
Loading…
Reference in New Issue