From c1e67cdc15caa14d440a72a808871c41e268ccfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Thu, 21 Mar 2024 13:18:43 +0200 Subject: [PATCH] Increase subnet range for IPPR (#4487) * Increase subnet range for IPPR * Fix for IPv6 * Fix range * Add unit test * Bump version --- common/ip-packet-requests/src/lib.rs | 3 +- .../ip-packet-router/src/constants.rs | 4 +- .../src/util/generate_new_ip.rs | 38 +++++++++++++++---- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/common/ip-packet-requests/src/lib.rs b/common/ip-packet-requests/src/lib.rs index d0357d0aa4..6991567d7a 100644 --- a/common/ip-packet-requests/src/lib.rs +++ b/common/ip-packet-requests/src/lib.rs @@ -9,7 +9,8 @@ pub mod response; // version 3: initial version // version 4: IPv6 support // version 5: Add severity level to info response -pub const CURRENT_VERSION: u8 = 5; +// version 6: Increase the available IPs +pub const CURRENT_VERSION: u8 = 6; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct IpPair { diff --git a/service-providers/ip-packet-router/src/constants.rs b/service-providers/ip-packet-router/src/constants.rs index eb7874f902..311087ad2a 100644 --- a/service-providers/ip-packet-router/src/constants.rs +++ b/service-providers/ip-packet-router/src/constants.rs @@ -4,10 +4,10 @@ use std::time::Duration; // The interface used to route traffic pub const TUN_BASE_NAME: &str = "nymtun"; pub const TUN_DEVICE_ADDRESS_V4: Ipv4Addr = Ipv4Addr::new(10, 0, 0, 1); -pub const TUN_DEVICE_NETMASK_V4: Ipv4Addr = Ipv4Addr::new(255, 255, 255, 0); +pub const TUN_DEVICE_NETMASK_V4: Ipv4Addr = Ipv4Addr::new(255, 255, 0, 0); pub const TUN_DEVICE_ADDRESS_V6: Ipv6Addr = Ipv6Addr::new(0x2001, 0xdb8, 0xa160, 0, 0, 0, 0, 0x1); // 2001:db8:a160::1 -pub const TUN_DEVICE_NETMASK_V6: &str = "120"; +pub const TUN_DEVICE_NETMASK_V6: &str = "112"; // We routinely check if any clients needs to be disconnected at this interval pub(crate) const DISCONNECT_TIMER_INTERVAL: Duration = Duration::from_secs(10); diff --git a/service-providers/ip-packet-router/src/util/generate_new_ip.rs b/service-providers/ip-packet-router/src/util/generate_new_ip.rs index 71809cac00..2d2848d821 100644 --- a/service-providers/ip-packet-router/src/util/generate_new_ip.rs +++ b/service-providers/ip-packet-router/src/util/generate_new_ip.rs @@ -6,12 +6,13 @@ use crate::constants::{TUN_DEVICE_ADDRESS_V4, TUN_DEVICE_ADDRESS_V6}; // Find an available IP address in self.connected_clients // TODO: make this nicer -fn generate_random_ips_within_subnet() -> IpPair { - let mut rng = rand::thread_rng(); - // Generate a random number in the range 1-254 - let last_octet = rand::Rng::gen_range(&mut rng, 1..=254); - let ipv4 = Ipv4Addr::new(10, 0, 0, last_octet); - let ipv6 = Ipv6Addr::new(0x2001, 0x0db8, 0xa160, 0, 0, 0, 0, last_octet as u16); +fn generate_random_ips_within_subnet(rng: &mut R) -> IpPair { + // Generate a random number in the range 2-65535 + let last_bytes: u16 = rand::Rng::gen_range(rng, 2..=65534); + let before_last_byte = (last_bytes >> 8) as u8; + let last_byte = (last_bytes & 255) as u8; + let ipv4 = Ipv4Addr::new(10, 0, before_last_byte, last_byte); + let ipv6 = Ipv6Addr::new(0x2001, 0x0db8, 0xa160, 0, 0, 0, 0, last_bytes); IpPair::new(ipv4, ipv6) } @@ -32,7 +33,8 @@ pub(crate) fn find_new_ips( connected_clients_ipv4: &HashMap, connected_clients_ipv6: &HashMap, ) -> Option { - let mut new_ips = generate_random_ips_within_subnet(); + let mut rng = rand::thread_rng(); + let mut new_ips = generate_random_ips_within_subnet(&mut rng); let mut tries = 0; let tun_ips = IpPair::new(TUN_DEVICE_ADDRESS_V4, TUN_DEVICE_ADDRESS_V6); @@ -42,7 +44,7 @@ pub(crate) fn find_new_ips( tun_ips, new_ips, ) { - new_ips = generate_random_ips_within_subnet(); + new_ips = generate_random_ips_within_subnet(&mut rng); tries += 1; if tries > 100 { return None; @@ -50,3 +52,23 @@ pub(crate) fn find_new_ips( } Some(new_ips) } + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashSet; + + #[test] + fn verify_ip_generation() { + let mut map = HashSet::with_capacity(65533); + let mut rng = rand::rngs::mock::StepRng::new(0, 65540); + for _ in 2..65535 { + let pair = generate_random_ips_within_subnet(&mut rng); + println!("{:?}", pair); + assert!(!map.contains(&pair)); + map.insert(pair); + } + let pair = generate_random_ips_within_subnet(&mut rng); + assert!(map.contains(&pair)); + } +}