diff --git a/Cargo.lock b/Cargo.lock index f62c125..352380b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,6 +66,30 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b" +version = "0.99.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81ce94c69d161e5588f2ebd67fed9220ede4f7e6a174141a76299a538b2ee90d" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "byteorder" version = "1.4.3" @@ -147,6 +171,16 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "curve25519-dalek" version = "3.2.1" @@ -154,7 +188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" dependencies = [ "byteorder", - "digest", + "digest 0.9.0", "rand_core 0.5.1", "subtle", "zeroize", @@ -169,6 +203,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + [[package]] name = "errno" version = "0.3.0" @@ -421,8 +466,11 @@ dependencies = [ name = "masterproef_v2" version = "0.1.0" dependencies = [ + "blake2", + "blake2b", "bytes", "clap", + "digest 0.10.7", "etherparse", "futures", "getrandom 0.2.9", diff --git a/Cargo.toml b/Cargo.toml index a3048ea..6900062 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,6 @@ getrandom = "0.2.9" rand_core = { version = "0.5.1", features = ["getrandom"] } x25519-dalek = "1.2.0" serde_json = "1.0.96" +blake2b = "0.99.0" +blake2 = "0.10.6" +digest = "0.10.7" diff --git a/src/main.rs b/src/main.rs index 258132e..71b07d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,8 +24,6 @@ const LINK_MTU: usize = 1420; #[derive(Parser)] struct Cli { - #[arg(short = 'a', long = "tun-addr")] - tun_addr: Ipv6Addr, #[arg(short = 'p', long = "peers", num_args = 1..)] static_peers: Vec, } @@ -34,8 +32,14 @@ struct Cli { async fn main() -> Result<(), Box> { let cli = Cli::parse(); + // Generate a new keypair for this node, panic if it fails + let node_keypair = x25519::get_keypair().unwrap(); + + // Generate the node's IPv6 address from its public key + let node_addr = x25519::generate_addr_from_pubkey(&node_keypair.1); + // Create TUN interface and add static route - let node_tun = match node_setup::setup_node(cli.tun_addr).await { + let node_tun = match node_setup::setup_node(node_addr).await { Ok(tun) => { println!("Node setup complete"); tun @@ -45,8 +49,6 @@ async fn main() -> Result<(), Box> { } }; - // Generate a new keypair for this node, panic if it fails - let node_keypair = x25519::get_keypair().unwrap(); println!("Node public key: {:?}", node_keypair.1); @@ -56,7 +58,8 @@ async fn main() -> Result<(), Box> { // Creating a new Router instance let router = match router::Router::new( node_tun.clone(), - vec![StaticRoute::new(cli.tun_addr.into())], + node_addr, + vec![StaticRoute::new(node_addr.into())], node_keypair ) { Ok(router) => { diff --git a/src/node_setup.rs b/src/node_setup.rs index 57636ba..3180f13 100644 --- a/src/node_setup.rs +++ b/src/node_setup.rs @@ -1,16 +1,20 @@ -use futures::stream::TryStreamExt; +use futures::TryStreamExt; use rtnetlink::Handle; -use std::{error::Error, net::{Ipv4Addr, Ipv6Addr}, sync::Arc}; +use x25519_dalek::PublicKey; +use std::{ + net::{IpAddr, Ipv6Addr}, + sync::Arc, +}; use tokio_tun::{Tun, TunBuilder}; pub const TUN_NAME: &str = "tun0"; -pub const TUN_ROUTE_DEST: Ipv6Addr = Ipv6Addr::new(0xfd, 0x00, 0, 0, 0, 0, 0, 0); -pub const TUN_ROUTE_PREFIX: u8 = 16; +pub const TUN_ROUTE_DEST: Ipv6Addr = Ipv6Addr::new(0x200, 0, 0, 0, 0, 0, 0, 0); +pub const TUN_ROUTE_PREFIX: u8 = 7; // Create a TUN interface -pub fn create_tun_interface() -> Result, Box> { +pub fn create_tun_interface() -> Result, Box> { let tun = TunBuilder::new() - .name(TUN_NAME) + .name("tun0") .tap(false) .mtu(1420) .packet_info(false) @@ -20,43 +24,85 @@ pub fn create_tun_interface() -> Result, Box> { Ok(Arc::new(tun)) } -// Add a route to the TUN interface -pub async fn add_route(handle: Handle) -> Result<(), Box> { - let mut link_request = handle - .link() - .get() - .match_name(String::from(TUN_NAME)) - .execute(); - let link_idx = if let Some(link) = link_request.try_next().await? { +pub async fn retrieve_tun_link_index(handle: Handle) -> Result> { + let mut link_req = handle.link().get().match_name(TUN_NAME.to_string()).execute(); + let link_index = if let Some(link) = link_req.try_next().await? { link.header.index } else { - eprintln!("link not found"); panic!("link not found"); }; - let route = handle.route(); - route - .add() - .v4() - .destination_prefix(TUN_ROUTE_DEST, TUN_ROUTE_PREFIX) - .output_interface(link_idx) + Ok(link_index) +} + +// Add address to TUN interface +pub async fn add_address(handle: Handle, addr: Ipv6Addr) -> Result<(), Box> { + let link_index = retrieve_tun_link_index(handle.clone()).await?; + // add address to tun interface + handle + .address() + .add( + link_index, + IpAddr::V6(addr), + 7, + ) .execute() .await?; Ok(()) } -pub async fn setup_node(tun_addr: Ipv6Addr) -> Result, Box> { - let tun = create_tun_interface(tun_addr)?; - println!("Interface '{}' ({}) created", TUN_NAME, tun_addr); + +// Adding route to TUN interface +pub async fn add_route(handle: Handle) -> Result<(), Box> { + let link_index = retrieve_tun_link_index(handle.clone()).await?; + // add route to tun interface + let route = handle.route(); + route + .add() + .v6() + .destination_prefix(Ipv6Addr::new(0x200, 0, 0, 0, 0, 0, 0, 0), 7) + .output_interface(link_index) + .execute() + .await?; + + Ok(()) +} + + +pub async fn setup_node(addr: Ipv6Addr) -> Result, Box> { + + let tun = match create_tun_interface() { + Ok(tun) => { + println!("TUN interface created"); + tun + } + Err(e) => { + panic!("Error creating TUN interface: {}", e); + } + }; let (conn, handle, _) = rtnetlink::new_connection()?; tokio::spawn(conn); - add_route(handle.clone()).await?; + match add_address(handle.clone(), addr).await { + Ok(_) => { + println!("Address added to TUN interface"); + } + Err(e) => { + panic!("Error adding address to TUN interface: {}", e); + } + }; - println!("Static route created"); + match add_route(handle.clone()).await { + Ok(_) => { + println!("Route added to TUN interface"); + } + Err(e) => { + panic!("Error adding route to TUN interface: {}", e); + } + }; Ok(tun) } diff --git a/src/peer_manager.rs b/src/peer_manager.rs index 829ab6c..8465e13 100644 --- a/src/peer_manager.rs +++ b/src/peer_manager.rs @@ -69,16 +69,22 @@ impl PeerManager { ); let mut buf = [0u8; 17]; - match self.router.node_tun_addr() { - IpAddr::V4(tun_addr) => { - buf[0] = 0; - buf[1..5].copy_from_slice(&tun_addr.octets()[..]); - } - IpAddr::V6(tun_addr) => { - buf[0] = 1; - buf[1..].copy_from_slice(&tun_addr.octets()[..]); - } - } + // old: + // match self.router.node_tun_addr() { + // IpAddr::V4(tun_addr) => { + // buf[0] = 0; + // buf[1..5].copy_from_slice(&tun_addr.octets()[..]); + // } + // IpAddr::V6(tun_addr) => { + // buf[0] = 1; + // buf[1..].copy_from_slice(&tun_addr.octets()[..]); + // } + // } + // new: + // only using IPv6 + buf[0] = 1; + buf[1..].copy_from_slice(&self.router.node_tun_addr().octets()[..]); + peer_stream.write_all(&buf).await.unwrap(); let peer_stream_ip = peer_addr.ip(); @@ -125,17 +131,21 @@ impl PeerManager { ); let mut buf = [0u8; 17]; - - match self.router.node_tun_addr() { - IpAddr::V4(tun_addr) => { - buf[0] = 0; - buf[1..5].copy_from_slice(&tun_addr.octets()[..]); - } - IpAddr::V6(tun_addr) => { - buf[0] = 1; - buf[1..].copy_from_slice(&tun_addr.octets()[..]); - } - } + // old: + // match self.router.node_tun_addr() { + // IpAddr::V4(tun_addr) => { + // buf[0] = 0; + // buf[1..5].copy_from_slice(&tun_addr.octets()[..]); + // } + // IpAddr::V6(tun_addr) => { + // buf[0] = 1; + // buf[1..].copy_from_slice(&tun_addr.octets()[..]); + // } + // } + // new: + // only using IPv6 + buf[0] = 1; + buf[1..].copy_from_slice(&self.router.node_tun_addr().octets()[..]); peer_stream.write_all(&buf).await.unwrap(); @@ -183,16 +193,22 @@ impl PeerManager { ); let mut buf = [0u8; 17]; - match self.router.node_tun_addr() { - IpAddr::V4(tun_addr) => { - buf[0] = 0; - buf[1..5].copy_from_slice(&tun_addr.octets()[..]); - } - IpAddr::V6(tun_addr) => { - buf[0] = 1; - buf[1..].copy_from_slice(&tun_addr.octets()[..]); - } - } + // old: + // match self.router.node_tun_addr() { + // IpAddr::V4(tun_addr) => { + // buf[0] = 0; + // buf[1..5].copy_from_slice(&tun_addr.octets()[..]); + // } + // IpAddr::V6(tun_addr) => { + // buf[0] = 1; + // buf[1..].copy_from_slice(&tun_addr.octets()[..]); + // } + // } + // new: + // only using IPv6 + buf[0] = 1; + buf[1..].copy_from_slice(&self.router.node_tun_addr().octets()[..]); + peer_stream.write_all(&buf).await.unwrap(); let peer_stream_ip = peer.ip(); @@ -216,7 +232,7 @@ impl PeerManager { Ok(listener) => loop { match listener.accept().await { Ok((stream, _)) => { - PeerManager::start_reverse_peer_exchange(stream, self.router.clone()).await; + self.start_reverse_peer_exchange(stream).await; } Err(e) => { eprintln!("Error accepting connection: {}", e); @@ -229,23 +245,27 @@ impl PeerManager { } } - async fn start_reverse_peer_exchange(mut stream: TcpStream, router: Router) { + async fn start_reverse_peer_exchange(&self, mut stream: TcpStream) { // Steps: // 1. Send own TUN address over the stream // 2. Read other node's TUN address from the stream let mut buf = [0u8; 17]; - - match router.node_tun_addr() { - IpAddr::V4(tun_addr) => { - buf[0] = 0; - buf[1..5].copy_from_slice(&tun_addr.octets()[..]); - } - IpAddr::V6(tun_addr) => { - buf[0] = 1; - buf[1..].copy_from_slice(&tun_addr.octets()[..]); - } - } + // old: + // match self.router.node_tun_addr() { + // IpAddr::V4(tun_addr) => { + // buf[0] = 0; + // buf[1..5].copy_from_slice(&tun_addr.octets()[..]); + // } + // IpAddr::V6(tun_addr) => { + // buf[0] = 1; + // buf[1..].copy_from_slice(&tun_addr.octets()[..]); + // } + // } + // new: + // only using IPv6 + buf[0] = 1; + buf[1..].copy_from_slice(&self.router.node_tun_addr().octets()[..]); stream.write_all(&buf).await.unwrap(); @@ -267,14 +287,14 @@ impl PeerManager { let peer_stream_ip = stream.peer_addr().unwrap().ip(); let new_peer = Peer::new( peer_stream_ip, - router.router_data_tx(), - router.router_control_tx(), + self.router.router_data_tx(), + self.router.router_control_tx(), stream, received_overlay_ip, ); match new_peer { Ok(new_peer) => { - router.add_peer_interface(new_peer); + self.router.add_peer_interface(new_peer); } Err(e) => { eprintln!("Error creating peer: {}", e); diff --git a/src/router.rs b/src/router.rs index 5b24a37..ddb19cf 100644 --- a/src/router.rs +++ b/src/router.rs @@ -9,7 +9,7 @@ use x25519_dalek::{StaticSecret, PublicKey}; use std::{ error::Error, fmt::Debug, - net::IpAddr, + net::{IpAddr, Ipv6Addr}, sync::{Arc, RwLock}, }; use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; @@ -44,6 +44,7 @@ pub struct Router { impl Router { pub fn new( node_tun: Arc, + node_tun_addr: Ipv6Addr, static_routes: Vec, node_keypair: (StaticSecret, PublicKey), ) -> Result> { @@ -55,6 +56,7 @@ impl Router { let router = Router { inner: Arc::new(RwLock::new(RouterInner::new( node_tun, + node_tun_addr, static_routes, router_data_tx, router_control_tx, @@ -91,8 +93,9 @@ impl Router { self.inner.read().unwrap().router_data_tx.clone() } - pub fn node_tun_addr(&self) -> IpAddr { - IpAddr::V6(self.inner.read().unwrap().node_tun.address().unwrap()) + pub fn node_tun_addr(&self) -> Ipv6Addr { + // IpAddr::V6(self.inner.read().unwrap().node_tun.address().unwrap()) + self.inner.read().unwrap().node_tun_addr } pub fn node_tun(&self) -> Arc { @@ -485,7 +488,7 @@ impl Router { // If destination IP of packet is same as TUN interface IP, send to TUN interface // If destination IP of packet is not same as TUN interface IP, send to peer with matching overlay IP let node_tun = self.node_tun(); - let node_tun_addr = node_tun.address().unwrap(); + let node_tun_addr = self.node_tun_addr(); loop { while let Some(data_packet) = router_data_rx.recv().await { match data_packet.dest_ip { @@ -497,7 +500,7 @@ impl Router { } }, _ => { - let best_route = self.select_best_route(IpAddr::V4(data_packet.dest_ip)); + let best_route = self.select_best_route(IpAddr::V6(data_packet.dest_ip)); match best_route { Some (route_entry) => { let peer = self.peer_by_ip(route_entry.next_hop).unwrap(); @@ -580,6 +583,7 @@ pub struct RouterInner { router_control_tx: UnboundedSender, router_data_tx: UnboundedSender, node_tun: Arc, + node_tun_addr: Ipv6Addr, selected_routing_table: RoutingTable, fallback_routing_table: RoutingTable, source_table: SourceTable, @@ -591,6 +595,7 @@ pub struct RouterInner { impl RouterInner { pub fn new( node_tun: Arc, + node_tun_addr: Ipv6Addr, static_routes: Vec, router_data_tx: UnboundedSender, router_control_tx: UnboundedSender, @@ -608,6 +613,7 @@ impl RouterInner { router_seqno: 0, static_routes: static_routes, node_keypair: node_keypair, + node_tun_addr, }; Ok(router_inner) diff --git a/src/x25519.rs b/src/x25519.rs index fcacf0f..d9d1dd3 100644 --- a/src/x25519.rs +++ b/src/x25519.rs @@ -1,13 +1,17 @@ +use blake2::digest::{Update, VariableOutput}; +use blake2::Blake2bVar; +use rand_core::OsRng; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; use std::path::Path; -use rand_core::OsRng; +use std::{ + net::Ipv6Addr, +}; use x25519_dalek::{PublicKey, StaticSecret, SharedSecret}; - // Read the secret key from a file if it exists, otherwise generate a new one and write it to a file // Returns the secret key and the corresponding public key -pub fn get_keypair() -> Result<(StaticSecret, PublicKey), Box>{ +pub fn get_keypair() -> Result<(StaticSecret, PublicKey), Box> { let path = Path::new("keys.txt"); let (secret_key, public_key) = if path.exists() { @@ -29,7 +33,8 @@ pub fn get_keypair() -> Result<(StaticSecret, PublicKey), Box Result<(StaticSecret, PublicKey), Box SharedSecret { secret.diffie_hellman(&pubkey) -} \ No newline at end of file +} + +pub fn generate_addr_from_pubkey(pubkey: &PublicKey) -> Ipv6Addr { + let mut hasher = Blake2bVar::new(16).unwrap(); // output ipv6 is 16 bytes + hasher.update(pubkey.as_bytes()); + let mut buf = [0u8; 16]; + hasher.finalize_variable(&mut buf).unwrap(); + + let ipv6_bytes: [u8; 16] = [ + 0x20, 0x00, // This prefix ensures the address falls into the 200::/7 range + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], + buf[11], buf[12], buf[13], + ]; + + let addr = Ipv6Addr::from(ipv6_bytes); + println!("output buf : {:?}", addr); + + addr +}