From 052957e4425c4bc17873a66f86bd1afb105622af Mon Sep 17 00:00:00 2001 From: b123400 Date: Fri, 15 Dec 2023 13:42:15 +0900 Subject: [PATCH] Use CIDR for tunnel network settings --- src/client.rs | 46 ++++++++++++++++++++++------------------- src/config.rs | 15 ++------------ src/server.rs | 38 ++++++++++++++++++++-------------- zika_config.sample.json | 10 ++------- 4 files changed, 52 insertions(+), 57 deletions(-) diff --git a/src/client.rs b/src/client.rs index 410a166..b224a31 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,22 +1,20 @@ use base64::{engine::general_purpose, Engine as _}; use bytes::Bytes; use etherparse::Ipv4Header; -use futures::stream::SplitSink; -use futures::stream::StreamExt; +use futures::stream::{SplitSink, StreamExt}; use futures::SinkExt; use ipnetwork::Ipv4Network; -use rand::distributions::Alphanumeric; +use rand::distributions::Standard; use rand::{thread_rng, Rng}; use std::io::{Cursor, Write}; use std::net::Ipv4Addr; use std::sync::Arc; use tokio::{sync::mpsc, task}; use tokio_util::codec::Framed; -use tun::AsyncDevice; -use tun::TunPacketCodec; -use tun::{IntoAddress as _, TunPacket}; +use tun::{AsyncDevice, TunPacket, TunPacketCodec}; use crate::config; +use crate::ip_iter::SizedIpv4NetworkIterator; use crate::remote; type TunSink = SplitSink, TunPacket>; @@ -37,15 +35,29 @@ struct Tunnel { impl Client { pub async fn new(config: &config::Config) -> Self { + let client_config = config + .client + .as_ref() + .expect("Client config to be non-null"); + + let ip_network: Ipv4Network = client_config + .bind_cidr + .parse() + .expect("A proper CIDR for ip network"); + let local_addr = SizedIpv4NetworkIterator::new(ip_network) + .next() + .expect("A subnet large enough to have a local ip"); + log::info!( - "Creating tun at {:?} network {:?}", - config.driver.local_addr, - config.driver.tun.netmask + "Creating tun at {:?} netmask {:?} local {:?}", + ip_network.ip(), + ip_network.mask(), + local_addr ); let mut tun_config = tun::Configuration::default(); - tun_config.address(config.driver.local_addr); - tun_config.destination(config.driver.local_addr); - tun_config.netmask(config.driver.tun.netmask); + tun_config.address(local_addr); + tun_config.destination(local_addr); + tun_config.netmask(ip_network.mask()); #[cfg(target_os = "linux")] tun_config.platform(|tun_config| { @@ -57,18 +69,10 @@ impl Client { let dev = tun::create_as_async(&tun_config).expect("Tunnel"); let (sink, mut stream) = dev.into_framed().split(); - let ip_network = - Ipv4Network::with_netmask(config.driver.local_addr, config.driver.tun.netmask) - .expect("A proper ip network"); let mqtt_options = config.broker_mqtt_options(); let (remote, remote_receiver) = remote::Remote::new(&mqtt_options, Vec::new()); - let client_config = config - .client - .as_ref() - .expect("Client config to be non-null"); - let mut tunnels = Vec::with_capacity(client_config.tunnels.len()); let mut rng = thread_rng(); @@ -120,7 +124,7 @@ impl Client { Client { tunnels: arc_tunnels.clone(), remote_receiver, - local_addr: config.driver.local_addr.clone(), + local_addr, sink, } } diff --git a/src/config.rs b/src/config.rs index 49ff72b..84f88b6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,24 +42,13 @@ pub struct MqttConfig { pub brokers: Vec, } -#[derive(Deserialize, Debug)] -pub struct DriverTun { - pub netmask: Ipv4Addr, -} - -#[derive(Deserialize, Debug)] -pub struct DriverConfig { - pub local_addr: Ipv4Addr, - pub tun: DriverTun, -} - #[derive(Deserialize, Debug)] pub struct ServerConfig { #[serde(default = "default_id_length")] pub id_length: usize, pub topic: String, - pub bind_addr: Ipv4Addr, + pub bind_cidr: String, } fn default_id_length() -> usize { @@ -77,13 +66,13 @@ pub struct ClientTunnel { #[derive(Deserialize, Debug)] pub struct ClientConfig { + pub bind_cidr: String, pub tunnels: Vec, } #[derive(Deserialize, Debug)] pub struct Config { pub mqtt: MqttConfig, - pub driver: DriverConfig, pub server: Option, pub client: Option, } diff --git a/src/server.rs b/src/server.rs index b0f9cc3..4c8226a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -2,6 +2,7 @@ use crate::config; use crate::ip_iter::SizedIpv4NetworkIterator; use crate::lookup_pool::LookupPool; use crate::remote; + use base64::{engine::general_purpose, Engine as _}; use bytes::Bytes; use etherparse::Ipv4Header; @@ -11,10 +12,10 @@ use ipnetwork::Ipv4Network; use std::io::{Cursor, Write}; use std::net::Ipv4Addr; use std::sync::Arc; -use tokio::sync::Mutex; -use tokio::{sync::mpsc, task}; +use tokio::sync::{mpsc, Mutex}; +use tokio::task; use tokio_util::codec::Framed; -use tun::{AsyncDevice, IntoAddress as _, TunPacket, TunPacketCodec}; +use tun::{AsyncDevice, TunPacket, TunPacketCodec}; type TunSink = SplitSink, TunPacket>; type IpPool = LookupPool; @@ -32,22 +33,29 @@ impl Server { pub fn new(config: config::Config) -> Self { let mqtt_options = config.broker_mqtt_options(); let server_config = config.server.expect("Server config to be non-null"); - let (remote, remote_receiver) = remote::Remote::new(&mqtt_options, vec![server_config.topic.clone()]); - let netmask = config.driver.tun.netmask; - let ip_network = Ipv4Network::with_netmask(server_config.bind_addr, netmask) - .expect("A proper ip network"); - let bind_addr = ip_network.ip(); - - log::info!("Binding to {:?} netmask {:?}", bind_addr, netmask); - let ip_iter = SizedIpv4NetworkIterator::new(ip_network); + let ip_network: Ipv4Network = server_config + .bind_cidr + .parse() + .expect("A proper CIDR for ip network"); + let mut ip_iter = SizedIpv4NetworkIterator::new(ip_network); + let local_addr = ip_iter + .next() + .expect("A subnet large enough to have a local ip"); + + log::info!( + "Binding to {:?} netmask {:?} local {:?}", + ip_network.ip(), + ip_network.mask(), + local_addr + ); let mut tun_config = tun::Configuration::default(); - tun_config.address(bind_addr); - tun_config.destination(bind_addr); - tun_config.netmask(netmask); + tun_config.address(local_addr); + tun_config.destination(local_addr); + tun_config.netmask(ip_network.mask()); #[cfg(target_os = "linux")] tun_config.platform(|tun_config| { @@ -80,7 +88,7 @@ impl Server { Self { remote_receiver, topic: server_config.topic, - local_addr: config.driver.local_addr, + local_addr, id_length: server_config.id_length, ip_pool: ip_pool_arc, sink, diff --git a/zika_config.sample.json b/zika_config.sample.json index 8da6f3a..8019485 100644 --- a/zika_config.sample.json +++ b/zika_config.sample.json @@ -24,11 +24,6 @@ ] }, - "driver": { - "local_addr": "172.20.0.1", - "tun": { "netmask": "255.255.255.0" } - }, - "// NOTE: Tunnel ID and MQTT topic are prepended to all IP packets": "", "// Long IDs / topics will add significant overhead to traffic with many small packets": "", @@ -36,12 +31,11 @@ "// In bytes (Optional, default shown, must match client)": "", "id_length": 4, "topic": "zika/OjFcZWEAGy2E3Vkh", - "// The follow ip is used with driver.tun.netmask to create a tunnel":"", - "// please make sure driver.local_addr is within the subnet":"", - "bind_addr": "172.20.0.0", + "bind_cidr": "172.20.0.0/24", }, "client": { + "bind_cidr": "172.20.0.0/24", "tunnels": [ { "topic": "zika/OjFcZWEAGy2E3Vkh",