diff --git a/performance.md b/performance.md index b861b3d..5ad82be 100644 --- a/performance.md +++ b/performance.md @@ -8,12 +8,14 @@ Sender node: * 8 GiB Ram * Intel 82579LM Gigabit Network * Ubuntu 14.04 (Kernel 3.13.0-65-generic) + * Libsodium 1.0.7 Receiver node: * Intel(R) Core(TM) i5-3450 CPU @ 3.10GHz * 16 GiB Ram * Realtek RTL8111/8168/8411 Gigabit Network * Ubuntu 14.04 (Kernel 3.13.0-63-generic) + * Libsodium 1.0.7 VpnCloud version: `VpnCloud v0.2.0 (with crypto support, protocol version 1)` @@ -54,7 +56,7 @@ The test is run in 3 steps: | -------------------- | ------------- | -------------------- | | Without VpnCloud | 926 Mbits/sec | - | | Unencrypted VpnCloud | 873 Mbits/sec | 80% / 95% | -| Encrypted VpnCloud | 635 Mbits/sec | 100% | +| Encrypted VpnCloud | 770 Mbits/sec | 100% | ### Latency @@ -73,13 +75,13 @@ assumed to be half of the RTT. | Without VpnCloud | 158 µs | 165 µs | 178 µs | | Unencrypted VpnCloud | 210 µs | 216 µs | 237 µs | | Difference | +52 µs | +51 µs | +59 µs | -| Encrypted VpnCloud | 225 µs | 252 µs | 262 µs | -| Difference | +15 µs | +36 µs | +25 µs | +| Encrypted VpnCloud | 218 µs | 230 µs | 257 µs | +| Difference | +8 µs | +14 µs | +20 µs | ### Conclusion * VpnCloud achieves over 850 MBit/s with default MTU settings. -* In encrypted mode, VpnCloud reaches over 600 MBit/s with default MTU settings. +* In encrypted mode, VpnCloud reaches over 750 MBit/s with default MTU settings. * VpnCloud adds about 60µs to the latency. -* Encryption adds an additional latency between 10µs and 35µs depending on the packet size. +* Encryption adds an additional latency up to 20µs depending on the packet size. diff --git a/src/ethernet.rs b/src/ethernet.rs index 1f21fc6..c256c36 100644 --- a/src/ethernet.rs +++ b/src/ethernet.rs @@ -4,7 +4,6 @@ use std::collections::HashMap; use super::types::{Error, Table, Protocol, Address}; use super::util::{now, Time, Duration}; -#[derive(PartialEq)] pub struct Frame; impl Protocol for Frame { diff --git a/src/ip.rs b/src/ip.rs index 3b221cd..cf5185d 100644 --- a/src/ip.rs +++ b/src/ip.rs @@ -16,11 +16,17 @@ impl Protocol for Packet { let version = data[0] >> 4; match version { 4 => { + if data.len() < 20 { + return Err(Error::ParseError("Truncated IPv4 header")); + } let src = try!(Address::read_from_fixed(&data[12..], 4)); let dst = try!(Address::read_from_fixed(&data[16..], 4)); Ok((src, dst)) }, 6 => { + if data.len() < 40 { + return Err(Error::ParseError("Truncated IPv6 header")); + } let src = try!(Address::read_from_fixed(&data[8..], 16)); let dst = try!(Address::read_from_fixed(&data[24..], 16)); Ok((src, dst)) diff --git a/src/tests.rs b/src/tests.rs index 8da499c..8ade9dd 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -9,7 +9,7 @@ use super::crypto::Crypto; #[test] -fn encode_message_packet() { +fn udpmessage_packet() { let mut options = Options::default(); let mut crypto = Crypto::None; let payload = [1,2,3,4,5]; @@ -25,7 +25,7 @@ fn encode_message_packet() { #[cfg(feature = "crypto")] #[test] -fn encode_message_encrypted() { +fn udpmessage_encrypted() { let mut options = Options::default(); let mut crypto = Crypto::from_shared_key("test"); let payload = [1,2,3,4,5]; @@ -40,7 +40,7 @@ fn encode_message_encrypted() { } #[test] -fn encode_message_peers() { +fn udpmessage_peers() { use std::str::FromStr; let mut options = Options::default(); let mut crypto = Crypto::None; @@ -59,7 +59,7 @@ fn encode_message_peers() { } #[test] -fn encode_option_network_id() { +fn udpmessage_option_network_id() { let mut options = Options::default(); options.network_id = Some(134); let mut crypto = Crypto::None; @@ -74,7 +74,7 @@ fn encode_option_network_id() { } #[test] -fn encode_message_init() { +fn udpmessage_init() { use super::types::Address; let mut options = Options::default(); let mut crypto = Crypto::None; @@ -91,7 +91,7 @@ fn encode_message_init() { } #[test] -fn encode_message_close() { +fn udpmessage_close() { let mut options = Options::default(); let mut crypto = Crypto::None; let msg = Message::Close; @@ -104,6 +104,34 @@ fn encode_message_close() { assert_eq!(msg, msg2); } +#[test] +fn udpmessage_invalid() { + let mut crypto = Crypto::None; + assert!(decode(&mut [0x76,0x70,0x6e,1,0,0,0,0], &mut crypto).is_ok()); + // too short + assert!(decode(&mut [], &mut crypto).is_err()); + // invalid protocol + assert!(decode(&mut [0,1,2,0,0,0,0,0], &mut crypto).is_err()); + // invalid version + assert!(decode(&mut [0x76,0x70,0x6e,0xaa,0,0,0,0], &mut crypto).is_err()); + // invalid crypto + assert!(decode(&mut [0x76,0x70,0x6e,1,0xaa,0,0,0], &mut crypto).is_err()); + // invalid msg type + assert!(decode(&mut [0x76,0x70,0x6e,1,0,0,0,0xaa], &mut crypto).is_err()); + // truncated options + assert!(decode(&mut [0x76,0x70,0x6e,1,0,0,1,0], &mut crypto).is_err()); +} + +#[cfg(feature = "crypto")] +#[test] +fn udpmessage_invalid_crypto() { + let mut options = Options::default(); + let mut crypto = Crypto::from_shared_key("test"); + // truncated crypto + assert!(decode(&mut [0x76,0x70,0x6e,1,1,0,0,0], &mut crypto).is_err()); +} + + #[test] fn decode_frame_without_vlan() { let data = [6,5,4,3,2,1,1,2,3,4,5,6,1,2,3,4,5,6,7,8]; @@ -120,6 +148,16 @@ fn decode_frame_with_vlan() { assert_eq!(dst, Address{data: [4,210,6,5,4,3,2,1,0,0,0,0,0,0,0,0], len: 8}); } +#[test] +fn decode_invalid_frame() { + assert!(Frame::parse(&[6,5,4,3,2,1,1,2,3,4,5,6,1,2,3,4,5,6,7,8]).is_ok()); + // truncated frame + assert!(Frame::parse(&[]).is_err()); + // truncated vlan frame + assert!(Frame::parse(&[6,5,4,3,2,1,1,2,3,4,5,6,0x81,0x00]).is_err()); +} + + #[test] fn decode_ipv4_packet() { let data = [0x40,0,0,0,0,0,0,0,0,0,0,0,192,168,1,1,192,168,1,2]; @@ -136,6 +174,21 @@ fn decode_ipv6_packet() { assert_eq!(dst, Address{data: [0,9,8,7,6,5,4,3,2,1,6,5,4,3,2,1], len: 16}); } +#[test] +fn decode_invalid_packet() { + assert!(Packet::parse(&[0x40,0,0,0,0,0,0,0,0,0,0,0,192,168,1,1,192,168,1,2]).is_ok()); + assert!(Packet::parse(&[0x60,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,0,9,8,7,6,5,4,3,2,1,6,5,4,3,2,1]).is_ok()); + // no data + assert!(Packet::parse(&[]).is_err()); + // wrong version + assert!(Packet::parse(&[0x20]).is_err()); + // truncated ipv4 + assert!(Packet::parse(&[0x40,0,0,0,0,0,0,0,0,0,0,0,192,168,1,1,192,168,1]).is_err()); + // truncated ipv6 + assert!(Packet::parse(&[0x60,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,0,9,8,7,6,5,4,3,2,1,6,5,4,3,2]).is_err()); +} + + #[test] fn switch() { let mut table = SwitchTable::new(10);