Increase subnet range for IPPR (#4487)

* Increase subnet range for IPPR

* Fix for IPv6

* Fix range

* Add unit test

* Bump version
This commit is contained in:
Bogdan-Ștefan Neacşu
2024-03-21 13:18:43 +02:00
committed by GitHub
parent 6ebe71c8a2
commit c1e67cdc15
3 changed files with 34 additions and 11 deletions
+2 -1
View File
@@ -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 {
@@ -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);
@@ -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<R: rand::Rng>(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<T>(
connected_clients_ipv4: &HashMap<Ipv4Addr, T>,
connected_clients_ipv6: &HashMap<Ipv6Addr, T>,
) -> Option<IpPair> {
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<T>(
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<T>(
}
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));
}
}