From df03603c4bbded6415b116180d3bae1532a9d26f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20L=C3=B6nnhager?= Date: Mon, 21 Oct 2024 14:05:23 +0200 Subject: [PATCH] Update to maybenot 2.0.0 on Windows --- Cargo.lock | 90 +++++++++++++++++++++- talpid-wireguard/Cargo.toml | 3 +- talpid-wireguard/src/wireguard_nt/daita.rs | 79 ++++++++++--------- 3 files changed, 132 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 994944c41c72..acec671f715a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "adler32" version = "1.2.0" @@ -280,7 +286,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.2", "object", "rustc-demangle", ] @@ -309,6 +315,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -960,6 +975,26 @@ dependencies = [ "syn 2.0.60", ] +[[package]] +name = "enum-map" +version = "2.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" +dependencies = [ + "enum-map-derive", +] + +[[package]] +name = "enum-map-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "env_logger" version = "0.7.1" @@ -1076,6 +1111,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2198,13 +2243,30 @@ dependencies = [ "simple-error", ] +[[package]] +name = "maybenot" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecece6a2196032ddf262a3a35f3dbcb1aac5d1cd9a848fab9aeaf00b99ed658c" +dependencies = [ + "base64 0.22.0", + "bincode", + "enum-map", + "flate2", + "rand 0.8.5", + "rand_core 0.6.4", + "rand_distr", + "serde", + "sha256", +] + [[package]] name = "maybenot-ffi" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12a95dd874046b87f98b3a54e6beed8a63db6354088efd0ae7dc23c0f23931ce" dependencies = [ - "maybenot", + "maybenot 1.1.2", ] [[package]] @@ -2256,6 +2318,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "0.8.11" @@ -3804,6 +3875,18 @@ dependencies = [ "digest", ] +[[package]] +name = "sha256" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0" +dependencies = [ + "async-trait", + "bytes", + "hex", + "sha2", +] + [[package]] name = "sha3" version = "0.10.8" @@ -4385,7 +4468,7 @@ dependencies = [ "ipnetwork", "libc", "log", - "maybenot", + "maybenot 2.0.0", "netlink-packet-core", "netlink-packet-route", "netlink-packet-utils", @@ -4395,6 +4478,7 @@ dependencies = [ "parking_lot", "proptest", "rand 0.8.5", + "rand_chacha 0.3.1", "rtnetlink", "socket2", "surge-ping", diff --git a/talpid-wireguard/Cargo.toml b/talpid-wireguard/Cargo.toml index b4b5e1148121..e02bf874d253 100644 --- a/talpid-wireguard/Cargo.toml +++ b/talpid-wireguard/Cargo.toml @@ -28,6 +28,7 @@ tokio = { workspace = true, features = ["process", "rt-multi-thread", "fs"] } tunnel-obfuscation = { path = "../tunnel-obfuscation" } rand = "0.8.5" surge-ping = "0.8.0" +rand_chacha = "0.3.1" [target.'cfg(not(windows))'.dependencies] wireguard-go-rs = { path = "../wireguard-go-rs"} @@ -60,7 +61,7 @@ talpid-dbus = { path = "../talpid-dbus" } bitflags = "1.2" talpid-windows = { path = "../talpid-windows" } widestring = "1.0" -maybenot = "1.1.2" +maybenot = "2.0.0" # TODO: Figure out which features are needed and which are not [target.'cfg(windows)'.dependencies.windows-sys] diff --git a/talpid-wireguard/src/wireguard_nt/daita.rs b/talpid-wireguard/src/wireguard_nt/daita.rs index a088ba712812..215167866c72 100644 --- a/talpid-wireguard/src/wireguard_nt/daita.rs +++ b/talpid-wireguard/src/wireguard_nt/daita.rs @@ -1,6 +1,10 @@ use super::WIREGUARD_KEY_LENGTH; -use maybenot::framework::MachineId; +use maybenot::{MachineId, Timer}; use once_cell::sync::OnceCell; +use rand::{ + rngs::{adapter::ReseedingRng, OsRng}, + SeedableRng, +}; use std::{ collections::HashMap, fs, io, os::windows::prelude::RawHandle, path::Path, sync::Arc, time::Duration, @@ -12,6 +16,9 @@ use windows_sys::Win32::{ System::Threading::{WaitForMultipleObjects, WaitForSingleObject, INFINITE}, }; +type Rng = ReseedingRng; +const RNG_RESEED_THRESHOLD: u64 = 1024 * 64; // 64 KiB + #[derive(Debug, thiserror::Error)] pub enum Error { /// Failed to find maybenot machines @@ -162,21 +169,12 @@ impl Session { fn maybenot_event_from_event( event: &Event, machine_ids: &MachineMap, - override_size: Option, -) -> Option { - let xmit_bytes = override_size.unwrap_or(event.xmit_bytes); +) -> Option { match event.event_type { - EventType::PaddingReceived => Some(maybenot::framework::TriggerEvent::PaddingRecv { - bytes_recv: xmit_bytes, - }), - EventType::NonpaddingSent => Some(maybenot::framework::TriggerEvent::NonPaddingSent { - bytes_sent: xmit_bytes, - }), - EventType::NonpaddingReceived => Some(maybenot::framework::TriggerEvent::NonPaddingRecv { - bytes_recv: xmit_bytes, - }), - EventType::PaddingSent => Some(maybenot::framework::TriggerEvent::PaddingSent { - bytes_sent: xmit_bytes, + EventType::PaddingReceived => Some(maybenot::TriggerEvent::PaddingRecv), + EventType::NonpaddingSent => Some(maybenot::TriggerEvent::NormalSent), + EventType::NonpaddingReceived => Some(maybenot::TriggerEvent::NormalRecv), + EventType::PaddingSent => Some(maybenot::TriggerEvent::PaddingSent { machine: machine_ids.get_machine_id(event.user_context)?.to_owned(), }), } @@ -208,7 +206,7 @@ pub struct Machinist { tokio_handle: tokio::runtime::Handle, quit_event: talpid_windows::sync::Event, peer: PublicKey, - override_size: Option, + mtu: u16, } // TODO: This is silly. Let me use the raw ID of MachineId, please. @@ -250,7 +248,7 @@ impl Machinist { const MAX_PADDING_BYTES: f64 = 0.0; const MAX_BLOCKING_BYTES: f64 = 0.0; - static MAYBENOT_MACHINES: OnceCell> = OnceCell::new(); + static MAYBENOT_MACHINES: OnceCell> = OnceCell::new(); let machines = MAYBENOT_MACHINES.get_or_try_init(|| { let path = resource_dir.join("maybenot_machines"); @@ -266,7 +264,7 @@ impl Machinist { log::debug!("Adding maybenot machine: {machine_str}"); machines.push( machine_str - .parse::() + .parse::() .map_err(|_error| Error::InvalidMachine(machine_str.to_owned()))?, ); } @@ -277,12 +275,16 @@ impl Machinist { talpid_windows::sync::Event::new(true, false).map_err(Error::InitializeQuitEvent)?; let handle = MachinistHandle::new(&quit_event).map_err(Error::InitializeHandle)?; - let framework = maybenot::framework::Framework::new( + let framework = maybenot::Framework::new( machines.clone(), MAX_PADDING_BYTES, MAX_BLOCKING_BYTES, - mtu, std::time::Instant::now(), + Rng::new( + rand_chacha::ChaCha12Core::from_entropy(), + RNG_RESEED_THRESHOLD, + OsRng, + ), ) .map_err(|error| Error::InitializeMaybenot(error.to_string()))?; @@ -297,8 +299,7 @@ impl Machinist { tokio_handle, quit_event, peer, - // TODO: We're assuming that constant packet size is always enabled here - override_size: Some(mtu), + mtu, } .event_loop(framework); }); @@ -306,10 +307,7 @@ impl Machinist { Ok(handle) } - fn event_loop( - mut self, - mut framework: maybenot::framework::Framework>, - ) { + fn event_loop(mut self, mut framework: maybenot::Framework, Rng>) { use windows_sys::Win32::Foundation::WAIT_OBJECT_0; loop { @@ -338,9 +336,12 @@ impl Machinist { log::debug!("Stopped DAITA event loop"); } - fn handle_action(&mut self, action: &maybenot::framework::Action) { + fn handle_action(&mut self, action: &maybenot::action::TriggerAction) { match *action { - maybenot::framework::Action::Cancel { machine } => { + maybenot::action::TriggerAction::Cancel { machine, timer } => { + debug_assert_ne!(timer, Timer::Internal, "machine timers not implemented"); + + // TODO: cancel only the supported timer let raw_id = self.machine_ids.get_or_create_raw_id(machine); // Drop all scheduled actions for a given machine @@ -348,9 +349,8 @@ impl Machinist { task.abort(); } } - maybenot::framework::Action::InjectPadding { + maybenot::action::TriggerAction::SendPadding { timeout, - size, machine, replace, .. @@ -366,7 +366,7 @@ impl Machinist { user_context: raw_id, payload: ActionPayload { padding: PaddingAction { - byte_count: size, + byte_count: self.mtu, replace: if replace { 1 } else { 0 }, }, }, @@ -391,7 +391,16 @@ impl Machinist { self.machine_tasks.insert(raw_id, task); } } - maybenot::framework::Action::BlockOutgoing { .. } => {} + maybenot::action::TriggerAction::BlockOutgoing { .. } => { + if cfg!(debug_assertions) { + unimplemented!("received BlockOutgoing action"); + } + } + maybenot::action::TriggerAction::UpdateTimer { .. } => { + if cfg!(debug_assertions) { + unimplemented!("received UpdateTimer action"); + } + } } } @@ -399,7 +408,7 @@ impl Machinist { /// If there are no events available, wait for events to arrive. /// Otherwise, break and return a non-zero number of events to be processed. /// If the quit event was signaled, this returns an empty vector. - fn wait_for_events(&mut self) -> io::Result> { + fn wait_for_events(&mut self) -> io::Result> { use windows_sys::Win32::Foundation::WAIT_OBJECT_0; let wait_events = [ @@ -415,9 +424,7 @@ impl Machinist { let converted_events: Vec<_> = events .iter() .filter(|event| &event.peer == self.peer.as_bytes()) - .filter_map(|event| { - maybenot_event_from_event(event, &self.machine_ids, self.override_size) - }) + .filter_map(|event| maybenot_event_from_event(event, &self.machine_ids)) .collect(); if !converted_events.is_empty() { return Ok(converted_events);