Skip to content

Commit

Permalink
Use CIDR for tunnel network settings
Browse files Browse the repository at this point in the history
  • Loading branch information
b123400 committed Dec 15, 2023
1 parent 00b5ed4 commit 052957e
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 57 deletions.
46 changes: 25 additions & 21 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -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<Framed<AsyncDevice, TunPacketCodec>, TunPacket>;
Expand All @@ -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| {
Expand All @@ -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();

Expand Down Expand Up @@ -120,7 +124,7 @@ impl Client {
Client {
tunnels: arc_tunnels.clone(),
remote_receiver,
local_addr: config.driver.local_addr.clone(),
local_addr,
sink,
}
}
Expand Down
15 changes: 2 additions & 13 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,13 @@ pub struct MqttConfig {
pub brokers: Vec<MqttBroker>,
}

#[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 {
Expand All @@ -77,13 +66,13 @@ pub struct ClientTunnel {

#[derive(Deserialize, Debug)]
pub struct ClientConfig {
pub bind_cidr: String,
pub tunnels: Vec<ClientTunnel>,
}

#[derive(Deserialize, Debug)]
pub struct Config {
pub mqtt: MqttConfig,
pub driver: DriverConfig,
pub server: Option<ServerConfig>,
pub client: Option<ClientConfig>,
}
Expand Down
38 changes: 23 additions & 15 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<Framed<AsyncDevice, TunPacketCodec>, TunPacket>;
type IpPool = LookupPool<String, Ipv4Addr, SizedIpv4NetworkIterator>;
Expand All @@ -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| {
Expand Down Expand Up @@ -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,
Expand Down
10 changes: 2 additions & 8 deletions zika_config.sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,18 @@
]
},

"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": "",

"server": {
"// 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",
Expand Down

0 comments on commit 052957e

Please sign in to comment.