diff --git a/.github/workflows/build-rust.yml b/.github/workflows/build-rust.yml index 4c3782a..0993ec2 100644 --- a/.github/workflows/build-rust.yml +++ b/.github/workflows/build-rust.yml @@ -54,10 +54,6 @@ jobs: run: | sudo apt-get update sudo apt-get install -y ${{ join(matrix.packages, ' ') }} - - name: Install Windows Deps - if: matrix.os == 'windows-2022' - shell: bash - run: echo "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\Llvm\x64\bin" >> $GITHUB_PATH - name: Install Rust uses: dtolnay/rust-toolchain@stable with: diff --git a/Apple/NetworkExtension/DataTypes.swift b/Apple/NetworkExtension/DataTypes.swift index f4ca082..f7ba572 100644 --- a/Apple/NetworkExtension/DataTypes.swift +++ b/Apple/NetworkExtension/DataTypes.swift @@ -7,10 +7,10 @@ enum BurrowError: Error { case resultIsNone } -protocol Request: Codable where CommandT: Codable { - associatedtype CommandT +protocol Request: Codable where T: Codable{ + associatedtype T var id: UInt { get set } - var command: CommandT { get set } + var command: T { get set } } struct BurrowSingleCommand: Request { @@ -18,30 +18,27 @@ struct BurrowSingleCommand: Request { var command: String } -struct BurrowRequest: Request where T: Codable { +struct BurrowRequest: Request where T: Codable{ var id: UInt var command: T } struct BurrowStartRequest: Codable { - struct TunOptions: Codable { + struct TunOptions: Codable{ let name: String? let no_pi: Bool let tun_excl: Bool let tun_retrieve: Bool let address: String? } - struct StartOptions: Codable { + struct StartOptions: Codable{ let tun: TunOptions } let Start: StartOptions } func start_req_fd(id: UInt) -> BurrowRequest { - let command = BurrowStartRequest(Start: BurrowStartRequest.StartOptions( - tun: BurrowStartRequest.TunOptions(name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: nil) - )) - return BurrowRequest(id: id, command: command) + return BurrowRequest(id: id, command: BurrowStartRequest(Start: BurrowStartRequest.StartOptions(tun: BurrowStartRequest.TunOptions(name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: nil)))) } struct Response: Decodable where T: Decodable { diff --git a/Apple/NetworkExtension/PacketTunnelProvider.swift b/Apple/NetworkExtension/PacketTunnelProvider.swift index 19fa760..711f6de 100644 --- a/Apple/NetworkExtension/PacketTunnelProvider.swift +++ b/Apple/NetworkExtension/PacketTunnelProvider.swift @@ -6,7 +6,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { let logger = Logger(subsystem: "com.hackclub.burrow", category: "frontend") var client: BurrowIpc? var osInitialized = false - override func startTunnel(options: [String: NSObject]? = nil) async throws { + override func startTunnel(options: [String : NSObject]? = nil) async throws { logger.log("Starting tunnel") if !osInitialized { libburrow.initialize_oslog() @@ -34,13 +34,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider { // let tunFd = self.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int; // self.logger.info("Found File Descriptor: \(tunFd)") - let startCommand = start_req_fd(id: 1) - guard let data = try await client?.request(startCommand, type: Response>.self) + let start_command = start_req_fd(id: 1) + guard let data = try await client?.request(start_command, type: Response>.self) else { throw BurrowError.cantParseResult } - let encodedStartRes = try JSONEncoder().encode(data.result) - self.logger.log("Received start server response: \(String(decoding: encodedStartRes, as: UTF8.self))") + let encoded_startres = try JSONEncoder().encode(data.result) + self.logger.log("Received start server response: \(String(decoding: encoded_startres, as: UTF8.self))") } catch { self.logger.error("An error occurred: \(error)") throw error @@ -58,12 +58,15 @@ class PacketTunnelProvider: NEPacketTunnelProvider { return nst } override func stopTunnel(with reason: NEProviderStopReason) async { + } override func handleAppMessage(_ messageData: Data) async -> Data? { messageData } override func sleep() async { + } override func wake() { + } } diff --git a/Cargo.lock b/Cargo.lock index cc8d3b3..54a0a53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,15 +110,24 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-channel" -version = "2.1.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", - "event-listener-strategy", "futures-core", - "pin-project-lite", +] + +[[package]] +name = "async-trait" +version = "0.1.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", ] [[package]] @@ -242,6 +251,7 @@ dependencies = [ "aead", "anyhow", "async-channel", + "async-trait", "base64", "blake2", "caps", @@ -629,24 +639,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "4.0.0" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener", - "pin-project-lite", -] +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" @@ -1395,12 +1390,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1461,9 +1450,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1638,16 +1627,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.16.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ "cc", - "getrandom", "libc", + "once_cell", "spin", "untrusted", - "windows-sys 0.48.0", + "web-sys", + "winapi", ] [[package]] @@ -1907,9 +1897,9 @@ dependencies = [ [[package]] name = "spin" -version = "0.9.8" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "ssri" @@ -2276,9 +2266,9 @@ dependencies = [ [[package]] name = "untrusted" -version = "0.9.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" diff --git a/burrow/Cargo.toml b/burrow/Cargo.toml index f263cc6..684bbb4 100644 --- a/burrow/Cargo.toml +++ b/burrow/Cargo.toml @@ -28,7 +28,7 @@ rand = "0.8.5" rand_core = "0.6.4" aead = "0.5.2" x25519-dalek = { version = "2.0.0", features = ["reusable_secrets", "static_secrets"] } -ring = "0.17.7" +ring = "0.16.20" parking_lot = "0.12.1" hmac = "0.12" ipnet = { version = "2.8.0", features = ["serde"] } @@ -36,7 +36,8 @@ base64 = "0.21.4" fehler = "1.0.0" ip_network_table = "0.2.0" ip_network = "0.4.0" -async-channel = "2.1.1" +async-trait = "0.1.74" +async-channel = "1.9" schemars = "0.8" futures = "0.3.28" uuid = { version = "1.6.1", features = ["v4"] } diff --git a/burrow/src/daemon/instance.rs b/burrow/src/daemon/instance.rs index 34e9878..7866fb5 100644 --- a/burrow/src/daemon/instance.rs +++ b/burrow/src/daemon/instance.rs @@ -41,6 +41,10 @@ impl DaemonInstance { } } + pub fn set_tun_interface(&mut self, tun_interface: Arc>) { + self.tun_interface = Some(tun_interface); + } + async fn proc_command(&mut self, command: DaemonCommand) -> Result { info!("Daemon got command: {:?}", command); match command { @@ -107,6 +111,7 @@ impl DaemonInstance { } pub async fn run(&mut self) -> Result<()> { + tracing::info!("BEGIN"); while let Ok(command) = self.rx.recv().await { let response = self.proc_command(command).await; info!("Daemon response: {:?}", response); diff --git a/burrow/src/daemon/mod.rs b/burrow/src/daemon/mod.rs index 9f60e2f..3768e62 100644 --- a/burrow/src/daemon/mod.rs +++ b/burrow/src/daemon/mod.rs @@ -1,24 +1,52 @@ -use std::sync::Arc; +use std::net::ToSocketAddrs; +use std::{ + net::{IpAddr, Ipv4Addr, SocketAddr}, + sync::Arc, +}; mod command; mod instance; mod net; mod response; -use anyhow::Result; +use anyhow::{anyhow, Error, Result}; +use base64::{engine::general_purpose, Engine as _}; pub use command::{DaemonCommand, DaemonStartOptions}; +use fehler::throws; use instance::DaemonInstance; +use ip_network::{IpNetwork, Ipv4Network}; #[cfg(target_vendor = "apple")] pub use net::start_srv; pub use net::DaemonClient; pub use response::{DaemonResponse, DaemonResponseData, ServerInfo}; use tokio::sync::RwLock; +use crate::wireguard::Config; use crate::{ daemon::net::listen, - wireguard::{Config, Interface}, + wireguard::{Interface, Peer, PublicKey, StaticSecret}, }; +#[throws] +fn parse_key(string: &str) -> [u8; 32] { + let value = general_purpose::STANDARD.decode(string)?; + let mut key = [0u8; 32]; + key.copy_from_slice(&value[..]); + key +} + +#[throws] +fn parse_secret_key(string: &str) -> StaticSecret { + let key = parse_key(string)?; + StaticSecret::from(key) +} + +#[throws] +fn parse_public_key(string: &str) -> PublicKey { + let key = parse_key(string)?; + PublicKey::from(key) +} + pub async fn daemon_main() -> Result<()> { let (commands_tx, commands_rx) = async_channel::unbounded(); let (response_tx, response_rx) = async_channel::unbounded(); @@ -45,7 +73,6 @@ pub async fn daemon_main() -> Result<()> { } }); - tokio::try_join!(inst_job, listen_job) - .map(|_| ()) - .map_err(|e| e.into()) + tokio::try_join!(inst_job, listen_job).map(|_| ()); + Ok(()) } diff --git a/burrow/src/daemon/net/apple.rs b/burrow/src/daemon/net/apple.rs index 8a2aadc..b84ec08 100644 --- a/burrow/src/daemon/net/apple.rs +++ b/burrow/src/daemon/net/apple.rs @@ -7,7 +7,7 @@ use crate::daemon::{daemon_main, DaemonClient}; #[no_mangle] pub extern "C" fn start_srv() { - info!("Starting server"); + info!("Rust: Starting server"); let _handle = thread::spawn(move || { let rt = Runtime::new().unwrap(); rt.block_on(async { @@ -20,11 +20,10 @@ pub extern "C" fn start_srv() { rt.block_on(async { loop { match DaemonClient::new().await { - Ok(..) => { - info!("Server successfully started"); - break + Ok(_) => break, + Err(_e) => { + // error!("Error when connecting to daemon: {}", e) } - Err(e) => error!("Could not connect to server: {}", e), } } }); diff --git a/burrow/src/daemon/net/systemd.rs b/burrow/src/daemon/net/systemd.rs index 80fe41c..e619c04 100644 --- a/burrow/src/daemon/net/systemd.rs +++ b/burrow/src/daemon/net/systemd.rs @@ -1,9 +1,7 @@ -use std::os::fd::IntoRawFd; - -use anyhow::Result; - use super::*; use crate::daemon::DaemonResponse; +use anyhow::Result; +use std::os::fd::IntoRawFd; pub async fn listen( cmd_tx: async_channel::Sender, diff --git a/burrow/src/daemon/net/unix.rs b/burrow/src/daemon/net/unix.rs index e2ae16f..cd8fb83 100644 --- a/burrow/src/daemon/net/unix.rs +++ b/burrow/src/daemon/net/unix.rs @@ -6,16 +6,16 @@ use std::{ }, path::{Path, PathBuf}, }; +use tracing::info; +use crate::daemon::{DaemonCommand, DaemonResponse, DaemonResponseData}; use anyhow::{anyhow, Result}; use tokio::{ io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, net::{UnixListener, UnixStream}, }; -use tracing::{debug, info}; - +use tracing::debug; use super::*; -use crate::daemon::{DaemonCommand, DaemonResponse, DaemonResponseData}; #[cfg(not(target_vendor = "apple"))] const UNIX_SOCKET_PATH: &str = "/run/burrow.sock"; @@ -36,7 +36,7 @@ fn fetch_socket_path() -> Option { for path in tries { let path = PathBuf::from(path); if path.exists() { - return Some(path) + return Some(path); } } None diff --git a/burrow/src/daemon/net/windows.rs b/burrow/src/daemon/net/windows.rs index c4a1d71..c734689 100644 --- a/burrow/src/daemon/net/windows.rs +++ b/burrow/src/daemon/net/windows.rs @@ -1,7 +1,4 @@ -use anyhow::Result; - use super::*; -use crate::daemon::DaemonResponse; pub async fn listen( _cmd_tx: async_channel::Sender, diff --git a/burrow/src/daemon/response.rs b/burrow/src/daemon/response.rs index 386da46..4bebe14 100644 --- a/burrow/src/daemon/response.rs +++ b/burrow/src/daemon/response.rs @@ -18,9 +18,9 @@ impl DaemonResponse { } } -impl From for DaemonResponse { - fn from(val: DaemonResponseData) -> Self { - DaemonResponse::new(Ok::(val)) +impl Into for DaemonResponseData { + fn into(self) -> DaemonResponse { + DaemonResponse::new(Ok::(self)) } } diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap index 0eb9096..289851f 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap @@ -1,5 +1,5 @@ --- source: burrow/src/daemon/command.rs -expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions {\n tun: TunOptions { ..TunOptions::default() },\n })).unwrap()" +expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions {\n tun: TunOptions { seek_utun: true, ..TunOptions::default() },\n })).unwrap()" --- -{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":null}}} +{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"seek_utun":true,"address":null}}} diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap index bfd5117..ff32838 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap @@ -2,4 +2,4 @@ source: burrow/src/daemon/command.rs expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions::default())).unwrap()" --- -{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":null}}} +{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"seek_utun":false,"address":null}}} diff --git a/burrow/src/lib.rs b/burrow/src/lib.rs index 3dfc4ac..8bccc30 100644 --- a/burrow/src/lib.rs +++ b/burrow/src/lib.rs @@ -1,16 +1,8 @@ -#[cfg(any(target_os = "linux", target_vendor = "apple"))] pub mod wireguard; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] mod daemon; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] pub use daemon::{ - DaemonClient, - DaemonCommand, - DaemonResponse, - DaemonResponseData, - DaemonStartOptions, - ServerInfo, + DaemonClient, DaemonCommand, DaemonResponse, DaemonResponseData, DaemonStartOptions, ServerInfo, }; #[cfg(target_vendor = "apple")] diff --git a/burrow/src/main.rs b/burrow/src/main.rs index db4602f..645ed5b 100644 --- a/burrow/src/main.rs +++ b/burrow/src/main.rs @@ -1,4 +1,5 @@ use anyhow::{Context, Result}; +#[cfg(any(target_os = "linux", target_vendor = "apple"))] use clap::{Args, Parser, Subcommand}; use tracing::instrument; use tracing_log::LogTracer; @@ -7,16 +8,12 @@ use tracing_subscriber::{prelude::*, EnvFilter, FmtSubscriber}; #[cfg(any(target_os = "linux", target_vendor = "apple"))] use tun::TunInterface; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] mod daemon; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] mod wireguard; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] use daemon::{DaemonClient, DaemonCommand, DaemonStartOptions}; use tun::TunOptions; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] use crate::daemon::DaemonResponseData; #[derive(Parser)] @@ -187,7 +184,6 @@ async fn try_serverinfo() -> Result<()> { async fn try_serverconfig() -> Result<()> { Ok(()) } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { initialize_tracing().await?; @@ -230,8 +226,3 @@ fn system_log() -> Result> { fn system_log() -> Result> { Ok(Some(OsLogger::new("com.hackclub.burrow", "burrow-cli"))) } - -#[cfg(not(any(target_os = "linux", target_vendor = "apple")))] -pub fn main() { - eprintln!("This platform is not supported currently.") -} diff --git a/burrow/src/wireguard/config.rs b/burrow/src/wireguard/config.rs index d86486e..a2599d4 100644 --- a/burrow/src/wireguard/config.rs +++ b/burrow/src/wireguard/config.rs @@ -1,13 +1,13 @@ -use std::{net::ToSocketAddrs, str::FromStr}; - +use crate::wireguard::{Interface as WgInterface, Peer as WgPeer}; use anyhow::{anyhow, Error, Result}; -use base64::{engine::general_purpose, Engine}; +use base64::engine::general_purpose; +use base64::Engine; use fehler::throws; use ip_network::IpNetwork; +use std::net::ToSocketAddrs; +use std::str::FromStr; use x25519_dalek::{PublicKey, StaticSecret}; -use crate::wireguard::{Interface as WgInterface, Peer as WgPeer}; - #[throws] fn parse_key(string: &str) -> [u8; 32] { let value = general_purpose::STANDARD.decode(string)?; @@ -68,11 +68,12 @@ impl TryFrom for WgInterface { endpoint: p .endpoint .to_socket_addrs()? - .find(|sock| sock.is_ipv4()) + .filter(|sock| sock.is_ipv4()) + .next() .ok_or(anyhow!("DNS Lookup Fails!"))?, preshared_key: match &p.preshared_key { None => Ok(None), - Some(k) => parse_key(k).map(Some), + Some(k) => parse_key(k).map(|res| Some(res)), }?, allowed_ips: p .allowed_ips @@ -85,28 +86,29 @@ impl TryFrom for WgInterface { }) }) .collect::>>()?; - WgInterface::new(wg_peers) + Ok(WgInterface::new(wg_peers)?) } } + impl Default for Config { fn default() -> Self { - Self { - interface: Interface { + Self{ + interface: Interface{ private_key: "GNqIAOCRxjl/cicZyvkvpTklgQuUmGUIEkH7IXF/sEE=".into(), address: "10.13.13.2/24".into(), listen_port: 51820, dns: Default::default(), - mtu: Default::default(), + mtu: Default::default() }, - peers: vec![Peer { + peers: vec![Peer{ endpoint: "wg.burrow.rs:51820".into(), allowed_ips: vec!["8.8.8.8/32".into()], public_key: "uy75leriJay0+oHLhRMpV+A5xAQ0hCJ+q7Ww81AOvT4=".into(), preshared_key: Some("s7lx/mg+reVEMnGnqeyYOQkzD86n2+gYnx1M9ygi08k=".into()), persistent_keepalive: Default::default(), - name: Default::default(), - }], + name: Default::default() + }] } } -} +} \ No newline at end of file diff --git a/burrow/src/wireguard/iface.rs b/burrow/src/wireguard/iface.rs index 281cc4a..4e86114 100755 --- a/burrow/src/wireguard/iface.rs +++ b/burrow/src/wireguard/iface.rs @@ -1,15 +1,33 @@ -use std::{net::IpAddr, sync::Arc}; +use std::{net::IpAddr, sync::Arc, time::Duration}; use anyhow::Error; +use async_trait::async_trait; use fehler::throws; -use futures::future::join_all; +use futures::{future::join_all, FutureExt}; use ip_network_table::IpNetworkTable; -use tokio::sync::RwLock; +use tokio::{sync::RwLock, task::JoinHandle, time::timeout}; use tracing::{debug, error}; use tun::tokio::TunInterface; use super::{noise::Tunnel, Peer, PeerPcb}; +#[async_trait] +pub trait PacketInterface { + async fn recv(&mut self, buf: &mut [u8]) -> Result; + async fn send(&mut self, buf: &[u8]) -> Result; +} + +#[async_trait] +impl PacketInterface for tun::tokio::TunInterface { + async fn recv(&mut self, buf: &mut [u8]) -> Result { + self.recv(buf).await + } + + async fn send(&mut self, buf: &[u8]) -> Result { + self.send(buf).await + } +} + struct IndexedPcbs { pcbs: Vec>, allowed_ips: IpNetworkTable, @@ -26,7 +44,7 @@ impl IndexedPcbs { pub fn insert(&mut self, pcb: PeerPcb) { let idx: usize = self.pcbs.len(); for allowed_ip in pcb.allowed_ips.iter() { - self.allowed_ips.insert(*allowed_ip, idx); + self.allowed_ips.insert(allowed_ip.clone(), idx); } self.pcbs.insert(idx, Arc::new(pcb)); } @@ -35,6 +53,10 @@ impl IndexedPcbs { let (_, &idx) = self.allowed_ips.longest_match(addr)?; Some(idx) } + + pub async fn connect(&self, idx: usize, handle: JoinHandle<()>) { + self.pcbs[idx].handle.write().await.replace(handle); + } } impl FromIterator for IndexedPcbs { @@ -56,7 +78,7 @@ impl Interface { pub fn new>(peers: I) -> Self { let pcbs: IndexedPcbs = peers .into_iter() - .map(PeerPcb::new) + .map(|peer| PeerPcb::new(peer)) .collect::>()?; let pcbs = Arc::new(pcbs); @@ -68,53 +90,63 @@ impl Interface { } pub async fn run(&self) -> anyhow::Result<()> { + debug!("RUN: starting interface"); let pcbs = self.pcbs.clone(); let tun = self .tun .clone() .ok_or(anyhow::anyhow!("tun interface does not exist"))?; - log::info!("Starting interface"); + log::info!("starting interface"); let outgoing = async move { loop { + // tracing::debug!("starting loop..."); let mut buf = [0u8; 3000]; let src = { - let src = match tun.read().await.recv(&mut buf[..]).await { - Ok(len) => &buf[..len], - Err(e) => { - error!("Failed to read from interface: {}", e); - continue + let src = match timeout( + Duration::from_millis(10), + tun.read().await.recv(&mut buf[..]), + ) + .await + { + Ok(Ok(len)) => &buf[..len], + Ok(Err(e)) => { + error!("failed to read from interface: {}", e); + continue; } + Err(_would_block) => continue, }; - debug!("Read {} bytes from interface", src.len()); + debug!("read {} bytes from interface", src.len()); + debug!("bytes: {:?}", src); src }; let dst_addr = match Tunnel::dst_address(src) { Some(addr) => addr, None => { - debug!("No destination found"); - continue + tracing::debug!("no destination found"); + continue; } }; - debug!("Routing packet to {}", dst_addr); + tracing::debug!("dst_addr: {}", dst_addr); + debug!("src_addr: {}", Tunnel::src_address(src).unwrap()); let Some(idx) = pcbs.find(dst_addr) else { continue }; - debug!("Found peer:{}", idx); + tracing::debug!("found peer:{}", idx); match pcbs.pcbs[idx].send(src).await { Ok(..) => { let addr = pcbs.pcbs[idx].endpoint; - debug!("Sent packet to peer {}", addr); + tracing::debug!("sent packet to peer {}", addr); } Err(e) => { - log::error!("Failed to send packet {}", e); - continue + log::error!("failed to send packet {}", e); + continue; } }; } @@ -138,13 +170,14 @@ impl Interface { let tsk = async move { if let Err(e) = pcb.open_if_closed().await { log::error!("failed to open pcb: {}", e); - return + return; } let r2 = pcb.run(tun).await; if let Err(e) = r2 { log::error!("failed to run pcb: {}", e); + return; } else { - debug!("pcb ran successfully"); + tracing::debug!("pcb ran successfully"); } }; debug!("task made.."); diff --git a/burrow/src/wireguard/mod.rs b/burrow/src/wireguard/mod.rs index b2e7b54..c181a83 100755 --- a/burrow/src/wireguard/mod.rs +++ b/burrow/src/wireguard/mod.rs @@ -4,8 +4,21 @@ mod noise; mod pcb; mod peer; -pub use config::Config; pub use iface::Interface; pub use pcb::PeerPcb; pub use peer::Peer; pub use x25519_dalek::{PublicKey, StaticSecret}; +pub use config::Config; + +const WIREGUARD_CONFIG: &str = r#" +[Interface] +# Device: Gentle Tomcat +PrivateKey = sIxpokQPnWctJKNaQ3DRdcQbL2S5OMbUrvr4bbsvTHw= +Address = 10.68.136.199/32,fc00:bbbb:bbbb:bb01::5:88c6/128 +DNS = 10.64.0.1 + +[Peer] +public_key = EKZXvHlSDeqAjfC/m9aQR0oXfQ6Idgffa9L0DH5yaCo= +AllowedIPs = 0.0.0.0/0,::0/0 +Endpoint = 146.70.173.66:51820 +"#; diff --git a/burrow/src/wireguard/noise/errors.rs b/burrow/src/wireguard/noise/errors.rs index e196635..10513ae 100755 --- a/burrow/src/wireguard/noise/errors.rs +++ b/burrow/src/wireguard/noise/errors.rs @@ -4,7 +4,9 @@ #[derive(Debug)] pub enum WireGuardError { DestinationBufferTooSmall, + IncorrectPacketLength, UnexpectedPacket, + WrongPacketType, WrongIndex, WrongKey, InvalidTai64nTimestamp, @@ -15,6 +17,7 @@ pub enum WireGuardError { DuplicateCounter, InvalidPacket, NoCurrentSession, + LockFailed, ConnectionExpired, UnderLoad, } diff --git a/burrow/src/wireguard/noise/handshake.rs b/burrow/src/wireguard/noise/handshake.rs index 2ec0c6a..08a4faa 100755 --- a/burrow/src/wireguard/noise/handshake.rs +++ b/burrow/src/wireguard/noise/handshake.rs @@ -9,20 +9,14 @@ use std::{ use aead::{Aead, Payload}; use blake2::{ digest::{FixedOutput, KeyInit}, - Blake2s256, - Blake2sMac, - Digest, + Blake2s256, Blake2sMac, Digest, }; use chacha20poly1305::XChaCha20Poly1305; use rand_core::OsRng; use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; use super::{ - errors::WireGuardError, - session::Session, - x25519, - HandshakeInit, - HandshakeResponse, + errors::WireGuardError, session::Session, x25519, HandshakeInit, HandshakeResponse, PacketCookieReply, }; @@ -209,7 +203,7 @@ impl Tai64N { /// Parse a timestamp from a 12 byte u8 slice fn parse(buf: &[u8; 12]) -> Result { if buf.len() < 12 { - return Err(WireGuardError::InvalidTai64nTimestamp) + return Err(WireGuardError::InvalidTai64nTimestamp); } let (sec_bytes, nano_bytes) = buf.split_at(std::mem::size_of::()); @@ -556,19 +550,22 @@ impl Handshake { let timestamp = Tai64N::parse(×tamp)?; if !timestamp.after(&self.last_handshake_timestamp) { // Possibly a replay - return Err(WireGuardError::WrongTai64nTimestamp) + return Err(WireGuardError::WrongTai64nTimestamp); } self.last_handshake_timestamp = timestamp; // initiator.hash = HASH(initiator.hash || msg.encrypted_timestamp) hash = b2s_hash(&hash, packet.encrypted_timestamp); - self.previous = std::mem::replace(&mut self.state, HandshakeState::InitReceived { - chaining_key, - hash, - peer_ephemeral_public, - peer_index, - }); + self.previous = std::mem::replace( + &mut self.state, + HandshakeState::InitReceived { + chaining_key, + hash, + peer_ephemeral_public, + peer_index, + }, + ); self.format_handshake_response(dst) } @@ -669,7 +666,7 @@ impl Handshake { let local_index = self.cookies.index; if packet.receiver_idx != local_index { - return Err(WireGuardError::WrongIndex) + return Err(WireGuardError::WrongIndex); } // msg.encrypted_cookie = XAEAD(HASH(LABEL_COOKIE || responder.static_public), // msg.nonce, cookie, last_received_msg.mac1) @@ -725,7 +722,7 @@ impl Handshake { dst: &'a mut [u8], ) -> Result<&'a mut [u8], WireGuardError> { if dst.len() < super::HANDSHAKE_INIT_SZ { - return Err(WireGuardError::DestinationBufferTooSmall) + return Err(WireGuardError::DestinationBufferTooSmall); } let (message_type, rest) = dst.split_at_mut(4); @@ -808,7 +805,7 @@ impl Handshake { dst: &'a mut [u8], ) -> Result<(&'a mut [u8], Session), WireGuardError> { if dst.len() < super::HANDSHAKE_RESP_SZ { - return Err(WireGuardError::DestinationBufferTooSmall) + return Err(WireGuardError::DestinationBufferTooSmall); } let state = std::mem::replace(&mut self.state, HandshakeState::None); diff --git a/burrow/src/wireguard/noise/mod.rs b/burrow/src/wireguard/noise/mod.rs index 6ece759..b366775 100755 --- a/burrow/src/wireguard/noise/mod.rs +++ b/burrow/src/wireguard/noise/mod.rs @@ -45,11 +45,7 @@ const N_SESSIONS: usize = 8; pub mod x25519 { pub use x25519_dalek::{ - EphemeralSecret, - PublicKey, - ReusableSecret, - SharedSecret, - StaticSecret, + EphemeralSecret, PublicKey, ReusableSecret, SharedSecret, StaticSecret, }; } @@ -133,15 +129,15 @@ pub struct PacketData<'a> { pub enum Packet<'a> { HandshakeInit(HandshakeInit<'a>), HandshakeResponse(HandshakeResponse<'a>), - CookieReply(PacketCookieReply<'a>), - Data(PacketData<'a>), + PacketCookieReply(PacketCookieReply<'a>), + PacketData(PacketData<'a>), } impl Tunnel { #[inline(always)] pub fn parse_incoming_packet(src: &[u8]) -> Result { if src.len() < 4 { - return Err(WireGuardError::InvalidPacket) + return Err(WireGuardError::InvalidPacket); } // Checks the type, as well as the reserved zero fields @@ -163,12 +159,12 @@ impl Tunnel { .expect("length already checked above"), encrypted_nothing: &src[44..60], }), - (COOKIE_REPLY, COOKIE_REPLY_SZ) => Packet::CookieReply(PacketCookieReply { + (COOKIE_REPLY, COOKIE_REPLY_SZ) => Packet::PacketCookieReply(PacketCookieReply { receiver_idx: u32::from_le_bytes(src[4..8].try_into().unwrap()), nonce: &src[8..32], encrypted_cookie: &src[32..64], }), - (DATA, DATA_OVERHEAD_SZ..=std::usize::MAX) => Packet::Data(PacketData { + (DATA, DATA_OVERHEAD_SZ..=std::usize::MAX) => Packet::PacketData(PacketData { receiver_idx: u32::from_le_bytes(src[4..8].try_into().unwrap()), counter: u64::from_le_bytes(src[8..16].try_into().unwrap()), encrypted_encapsulated_packet: &src[16..], @@ -183,7 +179,7 @@ impl Tunnel { pub fn dst_address(packet: &[u8]) -> Option { if packet.is_empty() { - return None + return None; } match packet[0] >> 4 { @@ -207,7 +203,7 @@ impl Tunnel { pub fn src_address(packet: &[u8]) -> Option { if packet.is_empty() { - return None + return None; } match packet[0] >> 4 { @@ -302,7 +298,7 @@ impl Tunnel { self.timer_tick(TimerName::TimeLastDataPacketSent); } self.tx_bytes += src.len(); - return TunnResult::WriteToNetwork(packet) + return TunnResult::WriteToNetwork(packet); } // If there is no session, queue the packet for future retry @@ -326,7 +322,7 @@ impl Tunnel { ) -> TunnResult<'a> { if datagram.is_empty() { // Indicates a repeated call - return self.send_queued_packet(dst) + return self.send_queued_packet(dst); } let mut cookie = [0u8; COOKIE_REPLY_SZ]; @@ -337,7 +333,7 @@ impl Tunnel { Ok(packet) => packet, Err(TunnResult::WriteToNetwork(cookie)) => { dst[..cookie.len()].copy_from_slice(cookie); - return TunnResult::WriteToNetwork(&mut dst[..cookie.len()]) + return TunnResult::WriteToNetwork(&mut dst[..cookie.len()]); } Err(TunnResult::Err(e)) => return TunnResult::Err(e), _ => unreachable!(), @@ -354,8 +350,8 @@ impl Tunnel { match packet { Packet::HandshakeInit(p) => self.handle_handshake_init(p, dst), Packet::HandshakeResponse(p) => self.handle_handshake_response(p, dst), - Packet::CookieReply(p) => self.handle_cookie_reply(p), - Packet::Data(p) => self.handle_data(p, dst), + Packet::PacketCookieReply(p) => self.handle_cookie_reply(p), + Packet::PacketData(p) => self.handle_data(p, dst), } .unwrap_or_else(TunnResult::from) } @@ -437,7 +433,7 @@ impl Tunnel { let cur_idx = self.current; if cur_idx == new_idx { // There is nothing to do, already using this session, this is the common case - return + return; } if self.sessions[cur_idx % N_SESSIONS].is_none() || self.timers.session_timers[new_idx % N_SESSIONS] @@ -483,7 +479,7 @@ impl Tunnel { force_resend: bool, ) -> TunnResult<'a> { if self.handshake.is_in_progress() && !force_resend { - return TunnResult::Done + return TunnResult::Done; } if self.handshake.is_expired() { @@ -542,7 +538,7 @@ impl Tunnel { }; if computed_len > packet.len() { - return TunnResult::Err(WireGuardError::InvalidPacket) + return TunnResult::Err(WireGuardError::InvalidPacket); } self.timer_tick(TimerName::TimeLastDataPacketReceived); diff --git a/burrow/src/wireguard/noise/rate_limiter.rs b/burrow/src/wireguard/noise/rate_limiter.rs index ff19efd..826414b 100755 --- a/burrow/src/wireguard/noise/rate_limiter.rs +++ b/burrow/src/wireguard/noise/rate_limiter.rs @@ -12,19 +12,9 @@ use ring::constant_time::verify_slices_are_equal; use super::{ handshake::{ - b2s_hash, - b2s_keyed_mac_16, - b2s_keyed_mac_16_2, - b2s_mac_24, - LABEL_COOKIE, - LABEL_MAC1, + b2s_hash, b2s_keyed_mac_16, b2s_keyed_mac_16_2, b2s_mac_24, LABEL_COOKIE, LABEL_MAC1, }, - HandshakeInit, - HandshakeResponse, - Packet, - TunnResult, - Tunnel, - WireGuardError, + HandshakeInit, HandshakeResponse, Packet, TunnResult, Tunnel, WireGuardError, }; const COOKIE_REFRESH: u64 = 128; // Use 128 and not 120 so the compiler can optimize out the division @@ -136,7 +126,7 @@ impl RateLimiter { dst: &'a mut [u8], ) -> Result<&'a mut [u8], WireGuardError> { if dst.len() < super::COOKIE_REPLY_SZ { - return Err(WireGuardError::DestinationBufferTooSmall) + return Err(WireGuardError::DestinationBufferTooSmall); } let (message_type, rest) = dst.split_at_mut(4); @@ -202,7 +192,7 @@ impl RateLimiter { let cookie_packet = self .format_cookie_reply(sender_idx, cookie, mac1, dst) .map_err(TunnResult::Err)?; - return Err(TunnResult::WriteToNetwork(cookie_packet)) + return Err(TunnResult::WriteToNetwork(cookie_packet)); } } } diff --git a/burrow/src/wireguard/noise/session.rs b/burrow/src/wireguard/noise/session.rs index 8988728..14c191b 100755 --- a/burrow/src/wireguard/noise/session.rs +++ b/burrow/src/wireguard/noise/session.rs @@ -88,11 +88,11 @@ impl ReceivingKeyCounterValidator { fn will_accept(&self, counter: u64) -> Result<(), WireGuardError> { if counter >= self.next { // As long as the counter is growing no replay took place for sure - return Ok(()) + return Ok(()); } if counter + N_BITS < self.next { // Drop if too far back - return Err(WireGuardError::InvalidCounter) + return Err(WireGuardError::InvalidCounter); } if !self.check_bit(counter) { Ok(()) @@ -107,22 +107,22 @@ impl ReceivingKeyCounterValidator { fn mark_did_receive(&mut self, counter: u64) -> Result<(), WireGuardError> { if counter + N_BITS < self.next { // Drop if too far back - return Err(WireGuardError::InvalidCounter) + return Err(WireGuardError::InvalidCounter); } if counter == self.next { // Usually the packets arrive in order, in that case we simply mark the bit and // increment the counter self.set_bit(counter); self.next += 1; - return Ok(()) + return Ok(()); } if counter < self.next { // A packet arrived out of order, check if it is valid, and mark if self.check_bit(counter) { - return Err(WireGuardError::InvalidCounter) + return Err(WireGuardError::InvalidCounter); } self.set_bit(counter); - return Ok(()) + return Ok(()); } // Packets where dropped, or maybe reordered, skip them and mark unused if counter - self.next >= N_BITS { @@ -247,7 +247,7 @@ impl Session { panic!("The destination buffer is too small"); } if packet.receiver_idx != self.receiving_index { - return Err(WireGuardError::WrongIndex) + return Err(WireGuardError::WrongIndex); } // Don't reuse counters, in case this is a replay attack we want to quickly // check the counter without running expensive decryption diff --git a/burrow/src/wireguard/noise/timers.rs b/burrow/src/wireguard/noise/timers.rs index 1d0cf1f..f713e6f 100755 --- a/burrow/src/wireguard/noise/timers.rs +++ b/burrow/src/wireguard/noise/timers.rs @@ -190,7 +190,7 @@ impl Tunnel { { if self.handshake.is_expired() { - return TunnResult::Err(WireGuardError::ConnectionExpired) + return TunnResult::Err(WireGuardError::ConnectionExpired); } // Clear cookie after COOKIE_EXPIRATION_TIME @@ -206,7 +206,7 @@ impl Tunnel { tracing::error!("CONNECTION_EXPIRED(REJECT_AFTER_TIME * 3)"); self.handshake.set_expired(); self.clear_all(); - return TunnResult::Err(WireGuardError::ConnectionExpired) + return TunnResult::Err(WireGuardError::ConnectionExpired); } if let Some(time_init_sent) = self.handshake.timer() { @@ -219,7 +219,7 @@ impl Tunnel { tracing::error!("CONNECTION_EXPIRED(REKEY_ATTEMPT_TIME)"); self.handshake.set_expired(); self.clear_all(); - return TunnResult::Err(WireGuardError::ConnectionExpired) + return TunnResult::Err(WireGuardError::ConnectionExpired); } if time_init_sent.elapsed() >= REKEY_TIMEOUT { @@ -299,11 +299,11 @@ impl Tunnel { } if handshake_initiation_required { - return self.format_handshake_initiation(dst, true) + return self.format_handshake_initiation(dst, true); } if keepalive_required { - return self.encapsulate(&[], dst) + return self.encapsulate(&[], dst); } TunnResult::Done diff --git a/burrow/src/wireguard/pcb.rs b/burrow/src/wireguard/pcb.rs index a781870..27db935 100755 --- a/burrow/src/wireguard/pcb.rs +++ b/burrow/src/wireguard/pcb.rs @@ -1,6 +1,10 @@ -use std::{net::SocketAddr, sync::Arc}; +use std::{ + cell::{Cell, RefCell}, + net::SocketAddr, + sync::Arc, +}; -use anyhow::Error; +use anyhow::{anyhow, Error}; use fehler::throws; use ip_network::IpNetwork; use rand::random; @@ -70,7 +74,7 @@ impl PeerPcb { Ok(l) => l, Err(e) => { log::error!("{}: error reading from socket: {:?}", rid, e); - continue + continue; } }; let mut res_dat = &res_buf[..len]; @@ -86,7 +90,7 @@ impl PeerPcb { TunnResult::Done => break, TunnResult::Err(e) => { tracing::error!(message = "Decapsulate error", error = ?e); - break + break; } TunnResult::WriteToNetwork(packet) => { tracing::debug!("WriteToNetwork: {:?}", packet); @@ -94,17 +98,17 @@ impl PeerPcb { socket.send(packet).await?; tracing::debug!("WriteToNetwork done"); res_dat = &[]; - continue + continue; } TunnResult::WriteToTunnelV4(packet, addr) => { tracing::debug!("WriteToTunnelV4: {:?}, {:?}", packet, addr); tun_interface.read().await.send(packet).await?; - break + break; } TunnResult::WriteToTunnelV6(packet, addr) => { tracing::debug!("WriteToTunnelV6: {:?}, {:?}", packet, addr); tun_interface.read().await.send(packet).await?; - break + break; } } } diff --git a/tun/Cargo.toml b/tun/Cargo.toml index e67e45f..b95c1bf 100644 --- a/tun/Cargo.toml +++ b/tun/Cargo.toml @@ -39,5 +39,5 @@ anyhow = "1.0" bindgen = "0.65" reqwest = { version = "0.11", features = ["native-tls"] } ssri = { version = "9.0", default-features = false } -tokio = { version = "1.28", features = ["rt", "macros"] } +tokio = { version = "1.28", features = ["rt"] } zip = { version = "0.6", features = ["deflate"] } diff --git a/tun/build.rs b/tun/build.rs index 8da8a40..03ee131 100644 --- a/tun/build.rs +++ b/tun/build.rs @@ -26,7 +26,7 @@ async fn generate(out_dir: &std::path::Path) -> anyhow::Result<()> { println!("cargo:rerun-if-changed={}", binary_path.to_str().unwrap()); if let (Ok(..), Ok(..)) = (File::open(&bindings_path), File::open(&binary_path)) { - return Ok(()) + return Ok(()); }; let archive = download(out_dir) diff --git a/tun/src/options.rs b/tun/src/options.rs index 339f71a..f5f6778 100644 --- a/tun/src/options.rs +++ b/tun/src/options.rs @@ -2,8 +2,6 @@ use std::io::Error; use fehler::throws; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] -#[cfg(feature = "tokio")] use super::tokio::TunInterface; #[derive(Debug, Clone, Default)] @@ -49,8 +47,6 @@ impl TunOptions { self } - #[cfg(any(target_os = "linux", target_vendor = "apple"))] - #[cfg(feature = "tokio")] #[throws] pub fn open(self) -> TunInterface { let ti = super::TunInterface::new_with_options(self)?; diff --git a/tun/src/tokio/mod.rs b/tun/src/tokio/mod.rs index 947fb74..3820ba9 100644 --- a/tun/src/tokio/mod.rs +++ b/tun/src/tokio/mod.rs @@ -34,7 +34,7 @@ impl TunInterface { Ok(result) => return result, Err(_would_block) => { tracing::debug!("WouldBlock"); - continue + continue; } } } diff --git a/tun/src/unix/apple/mod.rs b/tun/src/unix/apple/mod.rs index e72fb06..8efed1f 100644 --- a/tun/src/unix/apple/mod.rs +++ b/tun/src/unix/apple/mod.rs @@ -1,6 +1,6 @@ use std::{ io::{Error, IoSlice}, - mem, + mem::{self, ManuallyDrop}, net::{Ipv4Addr, SocketAddrV4}, os::fd::{AsRawFd, FromRawFd, RawFd}, }; diff --git a/tun/src/unix/apple/sys.rs b/tun/src/unix/apple/sys.rs index b4d4a6a..c0ea613 100644 --- a/tun/src/unix/apple/sys.rs +++ b/tun/src/unix/apple/sys.rs @@ -2,20 +2,11 @@ use std::mem; use libc::{c_char, c_int, c_short, c_uint, c_ulong, sockaddr}; pub use libc::{ - c_void, - sockaddr_ctl, - sockaddr_in, - socklen_t, - AF_SYSTEM, - AF_SYS_CONTROL, - IFNAMSIZ, + c_void, sockaddr_ctl, sockaddr_in, socklen_t, AF_SYSTEM, AF_SYS_CONTROL, IFNAMSIZ, SYSPROTO_CONTROL, }; use nix::{ - ioctl_read_bad, - ioctl_readwrite, - ioctl_write_ptr_bad, - request_code_readwrite, + ioctl_read_bad, ioctl_readwrite, ioctl_write_ptr_bad, request_code_readwrite, request_code_write, }; diff --git a/tun/src/unix/linux/mod.rs b/tun/src/unix/linux/mod.rs index 60d6341..e60429f 100644 --- a/tun/src/unix/linux/mod.rs +++ b/tun/src/unix/linux/mod.rs @@ -13,7 +13,6 @@ use fehler::throws; use libc::in6_ifreq; use socket2::{Domain, SockAddr, Socket, Type}; use tracing::{info, instrument}; - use super::{ifname_to_string, string_to_ifname}; use crate::TunOptions; diff --git a/tun/src/unix/mod.rs b/tun/src/unix/mod.rs index ae0b77a..77a1158 100644 --- a/tun/src/unix/mod.rs +++ b/tun/src/unix/mod.rs @@ -1,5 +1,5 @@ use std::{ - io::Error, + io::{Error, Read}, mem::MaybeUninit, os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, }; @@ -51,7 +51,7 @@ impl TunInterface { let mut tmp_buf = [MaybeUninit::uninit(); 1500]; let len = self.socket.recv(&mut tmp_buf)?; let result_buf = unsafe { assume_init(&tmp_buf[4..len]) }; - buf[..len - 4].copy_from_slice(result_buf); + buf[..len - 4].copy_from_slice(&result_buf); len - 4 } diff --git a/tun/tests/packets.rs b/tun/tests/packets.rs index 28090a2..91ebfba 100644 --- a/tun/tests/packets.rs +++ b/tun/tests/packets.rs @@ -11,7 +11,7 @@ fn tst_read() { // This test is interactive, you need to send a packet to any server through // 192.168.1.10 EG. `sudo route add 8.8.8.8 192.168.1.10`, //`dig @8.8.8.8 hackclub.com` - let tun = TunInterface::new()?; + let mut tun = TunInterface::new()?; println!("tun name: {:?}", tun.name()?); tun.set_ipv4_addr(Ipv4Addr::from([192, 168, 1, 10]))?; println!("tun ip: {:?}", tun.ipv4_addr()?);