diff --git a/.gitignore b/.gitignore index b113591..083b50a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target nodeconfig.toml +keys.txt diff --git a/Cargo.lock b/Cargo.lock index 2436585..f62c125 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -380,6 +380,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + [[package]] name = "libc" version = "0.2.141" @@ -419,9 +425,12 @@ dependencies = [ "clap", "etherparse", "futures", + "getrandom 0.2.9", "rand", + "rand_core 0.5.1", "rtnetlink", "serde", + "serde_json", "tokio", "tokio-tun", "tokio-util", @@ -698,6 +707,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + [[package]] name = "scopeguard" version = "1.1.0" @@ -724,6 +739,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_spanned" version = "0.6.1" diff --git a/Cargo.toml b/Cargo.toml index a47e6b5..a3048ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,4 +17,7 @@ serde = { version = "1.0.158", features = ["derive"] } rand = "0.8.5" bytes = "1.4.0" etherparse = "0.13.0" -x25519-dalek = "1.2.0" +getrandom = "0.2.9" +rand_core = { version = "0.5.1", features = ["getrandom"] } +x25519-dalek = "1.2.0" +serde_json = "1.0.96" diff --git a/keys.txt b/keys.txt new file mode 100644 index 0000000..d2aa7b7 --- /dev/null +++ b/keys.txt @@ -0,0 +1 @@ +!);KZmv7@9Z/hlG \ No newline at end of file diff --git a/src/codec.rs b/src/codec.rs index 7830429..d91b3bf 100644 --- a/src/codec.rs +++ b/src/codec.rs @@ -201,7 +201,7 @@ impl Encoder for DataPacketCodec { type Error = std::io::Error; fn encode(&mut self, item: DataPacket, dst: &mut BytesMut) -> Result<(), Self::Error> { - dst.reserve(item.raw_data.len() + 6); + dst.reserve(item.raw_data.len() + 6 + 32); // Write the length of the data dst.put_u16(item.raw_data.len() as u16); // Write the destination IP @@ -304,7 +304,7 @@ impl Decoder for ControlPacketCodec { // based on the remaining bytes (ip + router_id) we can check if it's IPv4 or v6 let prefix = match ae { 0 => { - // 4 bytes IP + 8 bytes router_id + // 4 bytes IP + 4 bytes router_id IpAddr::V4(Ipv4Addr::new( buf.get_u8(), buf.get_u8(), @@ -313,7 +313,7 @@ impl Decoder for ControlPacketCodec { )) } 1 => { - // 16 bytes IP + 8 bytes router_id + // 16 bytes IP + 4 bytes router_id IpAddr::V6(Ipv6Addr::new( buf.get_u16(), buf.get_u16(), @@ -332,7 +332,13 @@ impl Decoder for ControlPacketCodec { )) } }; - let router_id = buf.get_u64(); + + let mut router_id_bytes = [0u8; 32]; + router_id_bytes.copy_from_slice(&buf[..32]); + buf.advance(32); + + let router_id = PublicKey::from(router_id_bytes); + BabelPacketBody { tlv_type, @@ -421,8 +427,9 @@ impl Encoder for ControlPacketCodec { buf.put_u16(_ipv6.segments()[7]); } } - buf.put_u64(router_id); - } // Add encoding logic for other TLV types. + + buf.put_slice(&router_id.to_bytes()); + } } Ok(()) diff --git a/src/main.rs b/src/main.rs index 7f38da2..70cbd81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ mod peer_manager; mod router; mod routing_table; mod source_table; +mod x25519; const LINK_MTU: usize = 1420; @@ -44,15 +45,22 @@ 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); + let static_peers = cli.static_peers; // Creating a new Router instance let router = match router::Router::new( node_tun.clone(), vec![StaticRoute::new(cli.tun_addr.into())], + node_keypair ) { Ok(router) => { - println!("Router created. ID: {}", router.router_id()); + println!("Router created. Pubkey: {:?}", router.node_public_key()); router } Err(e) => { @@ -102,26 +110,21 @@ async fn main() -> Result<(), Box> { continue; }; - // read the next 32 bytes from the buffer to obtain the pubkey - let pubkey_bytes = &buf[20..52]; - if pubkey_bytes.len() >= 32 { - let pubkey_bytes_32: [u8; 32] = pubkey_bytes[..32].try_into().unwrap(); - let pubkey = PublicKey::from(pubkey_bytes_32); + // inject own pubkey - let data_packet = DataPacket { - dest_ip: dest_addr, - pubkey, - raw_data: buf.to_vec(), - }; + // and fix this + /* + let data_packet = DataPacket { + dest_ip: dest_addr, + pubkey, + raw_data: buf.to_vec(), // this needs to be encrypted + }; + - if router.router_data_tx().send(data_packet).is_err() { - eprintln!("Failed to send data_packet"); - } - - } else { - // Handle the case where pubkey_bytes is less than 32 bytes. - eprintln!("pubkey_bytes is less than 32 bytes"); + if router.router_data_tx().send(data_packet).is_err() { + eprintln!("Failed to send data_packet"); } + */ } }); } diff --git a/src/packet.rs b/src/packet.rs index 7540d74..feb4790 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -108,7 +108,7 @@ impl ControlPacket { seqno: u16, metric: u16, prefix: IpAddr, - router_id: u64, + router_id: PublicKey, ) -> Self { let uses_ipv6 = prefix.is_ipv6(); let header_length = (BabelTLVType::Update.get_tlv_length(uses_ipv6) + 2) as u16; @@ -201,6 +201,6 @@ pub enum BabelTLV { seqno: u16, metric: u16, prefix: IpAddr, - router_id: u64, + router_id: PublicKey, }, } diff --git a/src/router.rs b/src/router.rs index 46780c7..d8a2a5e 100644 --- a/src/router.rs +++ b/src/router.rs @@ -5,6 +5,7 @@ use crate::{ source_table::{self, FeasibilityDistance, SourceKey, SourceTable}, }; use rand::Rng; +use x25519_dalek::{StaticSecret, PublicKey}; use std::{ error::Error, fmt::Debug, @@ -44,6 +45,7 @@ impl Router { pub fn new( node_tun: Arc, static_routes: Vec, + node_keypair: (StaticSecret, PublicKey), ) -> Result> { // Tx is passed onto each new peer instance. This enables peers to send control packets to the router. let (router_control_tx, router_control_rx) = mpsc::unbounded_channel::(); @@ -56,6 +58,7 @@ impl Router { static_routes, router_data_tx, router_control_tx, + node_keypair, )?)), }; @@ -76,8 +79,8 @@ impl Router { Ok(router) } - pub fn router_id(&self) -> u64 { - self.inner.read().unwrap().router_id + pub fn router_id(&self) -> PublicKey { + self.node_public_key() } pub fn router_control_tx(&self) -> UnboundedSender { @@ -137,6 +140,9 @@ impl Router { matching_peer.map(Clone::clone) } + pub fn node_public_key(&self) -> PublicKey { + self.inner.read().unwrap().node_keypair.1 + } pub fn print_selected_routes(&self) { let inner = self.inner.read().unwrap(); @@ -484,6 +490,7 @@ impl Router { while let Some(data_packet) = router_data_rx.recv().await { match data_packet.dest_ip { x if x == node_tun_addr => match node_tun.send(&data_packet.raw_data).await { + // als packet voor onzelf is, decrypt uw raw-data en stuur naar tun interface Ok(_) => {} Err(e) => { eprintln!("Error sending data packet to TUN interface: {:?}", e) @@ -568,7 +575,7 @@ impl Router { } pub struct RouterInner { - pub router_id: u64, + pub router_id: PublicKey, peer_interfaces: Vec, router_control_tx: UnboundedSender, router_data_tx: UnboundedSender, @@ -578,6 +585,7 @@ pub struct RouterInner { source_table: SourceTable, router_seqno: u16, static_routes: Vec, + node_keypair: (StaticSecret, PublicKey), } impl RouterInner { @@ -586,9 +594,10 @@ impl RouterInner { static_routes: Vec, router_data_tx: UnboundedSender, router_control_tx: UnboundedSender, + node_keypair: (StaticSecret, PublicKey), ) -> Result> { let router_inner = RouterInner { - router_id: rand::thread_rng().gen(), + router_id: node_keypair.1, peer_interfaces: Vec::new(), router_control_tx, router_data_tx, @@ -598,6 +607,7 @@ impl RouterInner { source_table: SourceTable::new(), router_seqno: 0, static_routes: static_routes, + node_keypair: node_keypair, }; Ok(router_inner) diff --git a/src/routing_table.rs b/src/routing_table.rs index 728edf5..013c929 100644 --- a/src/routing_table.rs +++ b/src/routing_table.rs @@ -1,3 +1,5 @@ +use x25519_dalek::PublicKey; + use crate::{peer::Peer, source_table::SourceKey}; use std::{collections::BTreeMap, net::IpAddr}; @@ -55,7 +57,7 @@ impl RouteEntry { self.seqno = seqno; } - pub fn update_router_id(&mut self, router_id: u64) { + pub fn update_router_id(&mut self, router_id: PublicKey) { self.source.router_id = router_id; } } diff --git a/src/source_table.rs b/src/source_table.rs index 2486a0d..8ba549e 100644 --- a/src/source_table.rs +++ b/src/source_table.rs @@ -1,10 +1,12 @@ use std::{collections::HashMap, net::IpAddr}; +use x25519_dalek::PublicKey; + #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] pub struct SourceKey { pub prefix: IpAddr, pub plen: u8, - pub router_id: u64, // We temporarily use 100 for all router IDs + pub router_id: PublicKey, } #[derive(Debug, Clone, Copy)] @@ -20,7 +22,6 @@ impl FeasibilityDistance { } // Store (prefix, plen, router_id) -> feasibility distance mapping - #[derive(Debug)] pub struct SourceTable { pub table: HashMap, diff --git a/src/x25519.rs b/src/x25519.rs index e69de29..2522943 100644 --- a/src/x25519.rs +++ b/src/x25519.rs @@ -0,0 +1,38 @@ +use std::fs::{File, OpenOptions}; +use std::io::{Read, Write}; +use std::path::Path; +use rand_core::OsRng; +use x25519_dalek::{PublicKey, StaticSecret}; + + +// 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>{ + let path = Path::new("keys.txt"); + + let (secret_key, public_key) = if path.exists() { + let mut file = File::open(&path).expect("Failed to open file"); + let mut secret_bytes = [0u8; 32]; + file.read(&mut secret_bytes).expect("Failed to read file"); + + let secret_key = StaticSecret::from(secret_bytes); + let public_key = PublicKey::from(&secret_key); + + (secret_key, public_key) + } else { + let secret_key = StaticSecret::new(OsRng); + let public_key = PublicKey::from(&secret_key); + + let mut file = OpenOptions::new() + .write(true) + .create_new(true) + .open(&path) + .expect("Failed to open file"); + + file.write_all(secret_key.to_bytes().as_ref()).expect("Failed to write to file"); + + (secret_key, public_key) + }; + + Ok((secret_key, public_key)) +} \ No newline at end of file