From 9f2c42510679dce5544a0ab60f2c3bef561ec600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogdan-=C8=98tefan=20Neac=C5=9Fu?= Date: Fri, 24 Nov 2023 18:13:41 +0100 Subject: [PATCH] Test wg crate --- Cargo.lock | 79 ++++++++++++++++++++++++++++-- common/wireguard/Cargo.toml | 1 + common/wireguard/src/lib.rs | 92 ++++++++++------------------------- common/wireguard/src/setup.rs | 2 +- gateway/Cargo.toml | 6 ++- gateway/src/node/mod.rs | 18 +++---- 6 files changed, 116 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c545037965..b13f180a08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2337,6 +2337,25 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "defguard_wireguard_rs" +version = "0.3.0" +source = "git+https://github.com/DefGuard/wireguard-rs?rev=d40df5c4e598918253682c42c4aa189d0ec2499a#d40df5c4e598918253682c42c4aa189d0ec2499a" +dependencies = [ + "base64 0.21.4", + "libc", + "log", + "netlink-packet-core 0.7.0", + "netlink-packet-generic", + "netlink-packet-route 0.17.1", + "netlink-packet-utils", + "netlink-packet-wireguard", + "netlink-sys", + "nix 0.27.1", + "serde", + "thiserror", +] + [[package]] name = "der" version = "0.6.1" @@ -5694,6 +5713,29 @@ dependencies = [ "netlink-packet-utils", ] +[[package]] +name = "netlink-packet-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-generic" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd7eb8ad331c84c6b8cb7f685b448133e5ad82e1ffd5acafac374af4a5a308b" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-core 0.7.0", + "netlink-packet-utils", +] + [[package]] name = "netlink-packet-route" version = "0.12.0" @@ -5704,7 +5746,21 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "libc", - "netlink-packet-core", + "netlink-packet-core 0.4.2", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core 0.7.0", "netlink-packet-utils", ] @@ -5720,6 +5776,20 @@ dependencies = [ "thiserror", ] +[[package]] +name = "netlink-packet-wireguard" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b25b050ff1f6a1e23c6777b72db22790fe5b6b5ccfd3858672587a79876c8f" +dependencies = [ + "anyhow", + "byteorder", + "libc", + "log", + "netlink-packet-generic", + "netlink-packet-utils", +] + [[package]] name = "netlink-proto" version = "0.10.0" @@ -5729,7 +5799,7 @@ dependencies = [ "bytes", "futures", "log", - "netlink-packet-core", + "netlink-packet-core 0.4.2", "netlink-sys", "thiserror", "tokio", @@ -5781,6 +5851,7 @@ dependencies = [ "bitflags 2.4.1", "cfg-if", "libc", + "memoffset 0.9.0", ] [[package]] @@ -6482,6 +6553,7 @@ dependencies = [ "clap 4.4.7", "colored", "dashmap", + "defguard_wireguard_rs", "dirs 4.0.0", "dotenvy", "futures", @@ -7557,6 +7629,7 @@ dependencies = [ "boringtun", "bytes", "dashmap", + "defguard_wireguard_rs", "etherparse", "futures", "ip_network", @@ -9220,7 +9293,7 @@ checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" dependencies = [ "futures", "log", - "netlink-packet-route", + "netlink-packet-route 0.12.0", "netlink-proto", "nix 0.24.3", "thiserror", diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml index 461282833d..09b3fcc5cf 100644 --- a/common/wireguard/Cargo.toml +++ b/common/wireguard/Cargo.toml @@ -20,6 +20,7 @@ bincode = "1.3.3" #boringtun = "0.6.0" boringtun = { workspace = true } bytes = "1.5.0" +defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs", rev = "d40df5c4e598918253682c42c4aa189d0ec2499a" } dashmap = "5.5.3" etherparse = "0.13.0" futures = "0.3.28" diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs index fe51636a05..426a5e7ca0 100644 --- a/common/wireguard/src/lib.rs +++ b/common/wireguard/src/lib.rs @@ -17,74 +17,34 @@ use std::sync::Arc; #[cfg(target_os = "linux")] use nym_tun::tun_device; +use defguard_wireguard_rs::{host::Peer, InterfaceConfiguration, WGApi, WireguardInterfaceApi}; +use nym_network_defaults::{WG_PORT, WG_TUN_DEVICE_ADDRESS}; use nym_tun::tun_task_channel; +use setup::PRIVATE_KEY; -/// Start wireguard UDP listener and TUN device -/// -/// # Errors -/// -/// This function will return an error if either the UDP listener of the TUN device fails to start. -#[cfg(target_os = "linux")] +/// Start wireguard device pub async fn start_wireguard( - task_client: nym_task::TaskClient, - gateway_client_registry: Arc, -) -> Result<(), Box> { - // TODO: make this configurable - - // We can optionally index peers by their IP like standard wireguard. If we don't then we do - // plain NAT where we match incoming destination IP with outgoing source IP. - - use nym_wireguard_types::tun_common::network_table::NetworkTable; - let peers_by_ip = Arc::new(tokio::sync::Mutex::new(NetworkTable::new())); - - // Alternative 1: - let routing_mode = tun_device::RoutingMode::new_allowed_ips(peers_by_ip.clone()); - // Alternative 2: - //let routing_mode = tun_device::RoutingMode::new_nat(); - - // Start the tun device that is used to relay traffic outbound - let config = tun_device::TunDeviceConfig { - base_name: nym_network_defaults::WG_TUN_BASE_NAME.to_string(), - ip: nym_network_defaults::WG_TUN_DEVICE_ADDRESS.parse().unwrap(), - netmask: nym_network_defaults::WG_TUN_DEVICE_NETMASK.parse().unwrap(), - }; - let (tun, tun_task_tx, tun_task_response_rx) = tun_device::TunDevice::new(routing_mode, config); - tun.start(); - - // We also index peers by a tag - let peers_by_tag = Arc::new(tokio::sync::Mutex::new(wg_tunnel::PeersByTag::new())); - - // If we want to have the tun device on a separate host, it's the tun_task and - // tun_task_response channels that needs to be sent over the network to the host where the tun - // device is running. - - // The packet relayer's responsibility is to route packets between the correct tunnel and the - // tun device. The tun device may or may not be on a separate host, which is why we can't do - // this routing in the tun device itself. - let (packet_relayer, packet_tx) = packet_relayer::PacketRelayer::new( - tun_task_tx.clone(), - tun_task_response_rx, - peers_by_tag.clone(), - ); - packet_relayer.start(); - - // Start the UDP listener that clients connect to - let udp_listener = udp_listener::WgUdpListener::new( - packet_tx, - peers_by_ip, - peers_by_tag, - Arc::clone(&gateway_client_registry), - ) - .await?; - udp_listener.start(task_client); - - Ok(()) -} - -#[cfg(not(target_os = "linux"))] -pub async fn start_wireguard( - _task_client: nym_task::TaskClient, + mut task_client: nym_task::TaskClient, _gateway_client_registry: Arc, -) -> Result<(), Box> { - todo!("WireGuard is currently only supported on Linux") +) -> Result> { + let ifname = String::from("wg0"); + let wgapi = WGApi::new(ifname.clone(), false)?; + wgapi.create_interface()?; + let interface_config = InterfaceConfiguration { + name: ifname.clone(), + prvkey: PRIVATE_KEY.to_string(), + address: WG_TUN_DEVICE_ADDRESS.to_string(), + port: WG_PORT as u32, + peers: vec![], + }; + wgapi.configure_interface(&interface_config)?; + let peer = std::env::var("NYM_PEER_PUBLIC_KEY").expect("NYM_PEER_PUBLIC_KEY must be set"); + let mut peer = Peer::new(peer.as_str().try_into().unwrap()); + peer.set_allowed_ips(vec!["10.1.0.2".parse().unwrap()]); + wgapi.configure_peer(&peer)?; + wgapi.configure_peer_routing(&vec![peer.clone()])?; + + tokio::spawn(async move { task_client.recv().await }); + + Ok(wgapi) } diff --git a/common/wireguard/src/setup.rs b/common/wireguard/src/setup.rs index 779554a6eb..501ec15483 100644 --- a/common/wireguard/src/setup.rs +++ b/common/wireguard/src/setup.rs @@ -9,7 +9,7 @@ pub const WG_ADDRESS: &str = "0.0.0.0"; // The private key of the listener // Corresponding public key: "WM8s8bYegwMa0TJ+xIwhk+dImk2IpDUKslDBCZPizlE=" -const PRIVATE_KEY: &str = "AEqXrLFT4qjYq3wmX0456iv94uM6nDj5ugp6Jedcflg="; +pub(crate) const PRIVATE_KEY: &str = "AEqXrLFT4qjYq3wmX0456iv94uM6nDj5ugp6Jedcflg="; // The AllowedIPs for the connected peer, which is one a single IP and the same as the IP that the // peer has configured on their side. diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index ffaf439c7f..cb013578ba 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -77,9 +77,11 @@ nym-statistics-common = { path = "../common/statistics" } nym-task = { path = "../common/task" } nym-types = { path = "../common/types" } nym-validator-client = { path = "../common/client-libs/validator-client" } -nym-wireguard = { path = "../common/wireguard", optional = true } nym-ip-packet-router = { path = "../service-providers/ip-packet-router" } +nym-wireguard = { path = "../common/wireguard", optional = true } +defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs", rev = "d40df5c4e598918253682c42c4aa189d0ec2499a", optional = true } + [dev-dependencies] tower = "0.4.13" rand = "0.8.5" @@ -95,4 +97,4 @@ sqlx = { version = "0.5", features = [ ] } [features] -wireguard = ["nym-wireguard"] +wireguard = ["nym-wireguard", "defguard_wireguard_rs"] diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index b61628d432..0b26c5c4b8 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -22,6 +22,7 @@ use crate::node::statistics::collector::GatewayStatisticsCollector; use crate::node::storage::Storage; use anyhow::bail; use dashmap::DashMap; +use defguard_wireguard_rs::{WGApi, WireguardInterfaceApi}; use futures::channel::{mpsc, oneshot}; use log::*; use nym_crypto::asymmetric::{encryption, identity}; @@ -200,11 +201,10 @@ impl Gateway { mixnet_handling::Listener::new(listening_address, shutdown).start(connection_handler); } - #[cfg(feature = "wireguard")] async fn start_wireguard( &self, shutdown: TaskClient, - ) -> Result<(), Box> { + ) -> Result> { // TODO: possibly we should start the UDP listener and TUN device explicitly here nym_wireguard::start_wireguard(shutdown, Arc::clone(&self.client_registry)).await } @@ -520,16 +520,10 @@ impl Gateway { Arc::new(coconut_verifier), ); - // Once this is a bit more mature, make this a commandline flag instead of a compile time - // flag - #[cfg(feature = "wireguard")] - if let Err(err) = self + let wg_api = self .start_wireguard(shutdown.subscribe().named("wireguard")) .await - { - // that's a nasty workaround, but anyhow errors are generally nicer, especially on exit - bail!("{err}") - } + .expect("Could not start wireguard"); info!("Finished nym gateway startup procedure - it should now be able to receive mix and client traffic!"); @@ -537,6 +531,10 @@ impl Gateway { // that's a nasty workaround, but anyhow errors are generally nicer, especially on exit bail!("{err}") } + let host = wg_api.read_interface_data()?; + for peer in host.peers.values() { + wg_api.remove_peer(&peer.public_key)?; + } Ok(()) } }