Skip to content

Commit

Permalink
Merge branch 'set-wggo-tun-name'
Browse files Browse the repository at this point in the history
  • Loading branch information
dlon committed Sep 2, 2024
2 parents ce2b4ff + 6df6115 commit d0040f9
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 83 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ Line wrap the file at 100 chars. Th
### Fixed
- macOS and Linux: Fix potential crash when disconnecting with DAITA enabled.

#### Linux
- Set tunnel name to `wg0-mullvad` for userspace WireGuard.

#### macOS
- Exclude programs when executed using a relative path from a shell.
- Reduce packet loss when using split tunneling.
Expand Down
4 changes: 4 additions & 0 deletions talpid-tunnel/src/tun_provider/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ cfg_if! {
/// Configuration for creating a tunnel device.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TunConfig {
/// Interface name to use.
pub name: Option<String>,

/// IP addresses for the tunnel interface.
pub addresses: Vec<IpAddr>,

Expand Down Expand Up @@ -77,6 +80,7 @@ impl TunConfig {
/// Android to route all traffic inside the tunnel.
pub fn blocking_config() -> TunConfig {
TunConfig {
name: None,
addresses: vec![IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))],
mtu: 1380,
ipv4_gateway: Ipv4Addr::new(10, 64, 0, 1),
Expand Down
157 changes: 78 additions & 79 deletions talpid-tunnel/src/tun_provider/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,25 @@ use tun::{platform, Configuration, Device};
/// Errors that can occur while setting up a tunnel device.
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Failure to create a tunnel device.
#[error("Failed to create a tunnel device")]
CreateTunnelDevice(#[source] NetworkInterfaceError),
/// Failed to set IP address
#[error("Failed to set IPv4 address")]
SetIpv4(#[source] tun::Error),

/// Failed to set IP address
#[error("Failed to set IPv6 address")]
SetIpv6(#[source] io::Error),

/// Failure to set a tunnel device IP address.
#[error("Failed to set tunnel IP address: {0}")]
SetIpAddr(IpAddr, #[source] NetworkInterfaceError),
/// Unable to open a tunnel device
#[error("Unable to open a tunnel device")]
CreateDevice(#[source] tun::Error),

/// Failed to apply async flags to tunnel device
#[error("Failed to apply async flags to tunnel device")]
SetDeviceAsync(#[source] nix::Error),

/// Failure to set the tunnel device as up.
#[error("Failed to set the tunnel device as up")]
SetUp(#[source] NetworkInterfaceError),
/// Failed to enable/disable link device
#[error("Failed to enable/disable link device")]
ToggleDevice(#[source] tun::Error),
}

/// Factory of tunnel devices on Unix systems.
Expand All @@ -42,15 +50,23 @@ impl UnixTunProvider {

/// Open a tunnel using the current tunnel config.
pub fn open_tun(&mut self) -> Result<UnixTun, Error> {
let mut tunnel_device = TunnelDevice::new().map_err(Error::CreateTunnelDevice)?;
let mut tunnel_device = {
#[allow(unused_mut)]
let mut builder = TunnelDeviceBuilder::default();
#[cfg(target_os = "linux")]
builder.enable_packet_information();
#[cfg(target_os = "linux")]
if let Some(ref name) = self.config.name {
builder.name(name);
}
builder.create()?
};

for ip in self.config.addresses.iter() {
tunnel_device
.set_ip(*ip)
.map_err(|cause| Error::SetIpAddr(*ip, cause))?;
tunnel_device.set_ip(*ip)?;
}

tunnel_device.set_up(true).map_err(Error::SetUp)?;
tunnel_device.set_up(true)?;

Ok(UnixTun(tunnel_device))
}
Expand All @@ -76,67 +92,55 @@ impl Deref for UnixTun {
}
}

/// Errors that can happen when working with *nix tunnel interfaces.
#[derive(thiserror::Error, Debug)]
pub enum NetworkInterfaceError {
/// Failed to set IP address
#[error("Failed to set IPv4 address")]
SetIpv4(#[source] tun::Error),

/// Failed to set IP address
#[error("Failed to set IPv6 address")]
SetIpv6(#[source] io::Error),

/// Unable to open a tunnel device
#[error("Unable to open a tunnel device")]
CreateDevice(#[source] tun::Error),

/// Failed to apply async flags to tunnel device
#[error("Failed to apply async flags to tunnel device")]
SetDeviceAsync(#[source] nix::Error),

/// Failed to enable/disable link device
#[error("Failed to enable/disable link device")]
ToggleDevice(#[source] tun::Error),
/// A tunnel device
pub struct TunnelDevice {
dev: platform::Device,
}

/// A trait for managing link devices
pub trait NetworkInterface: Sized {
/// Bring a given interface up or down
fn set_up(&mut self, up: bool) -> Result<(), NetworkInterfaceError>;
/// A tunnel device builder.
///
/// Call [`Self::create`] to create [`TunnelDevice`] from the config.
pub struct TunnelDeviceBuilder {
config: Configuration,
}

/// Set host IPs for interface
fn set_ip(&mut self, ip: IpAddr) -> Result<(), NetworkInterfaceError>;
impl TunnelDeviceBuilder {
/// Create a [`TunnelDevice`] from this builder.
pub fn create(self) -> Result<TunnelDevice, Error> {
fn apply_async_flags(fd: RawFd) -> Result<(), nix::Error> {
fcntl::fcntl(fd, fcntl::FcntlArg::F_GETFL)?;
let arg = fcntl::FcntlArg::F_SETFL(fcntl::OFlag::O_RDWR | fcntl::OFlag::O_NONBLOCK);
fcntl::fcntl(fd, arg)?;
Ok(())
}

/// Get name of interface
fn get_name(&self) -> &str;
}
let dev = platform::create(&self.config).map_err(Error::CreateDevice)?;
apply_async_flags(dev.as_raw_fd()).map_err(Error::SetDeviceAsync)?;
Ok(TunnelDevice { dev })
}

fn apply_async_flags(fd: RawFd) -> Result<(), nix::Error> {
fcntl::fcntl(fd, fcntl::FcntlArg::F_GETFL)?;
let arg = fcntl::FcntlArg::F_SETFL(fcntl::OFlag::O_RDWR | fcntl::OFlag::O_NONBLOCK);
fcntl::fcntl(fd, arg)?;
Ok(())
}
/// Set a custom name for this tunnel device.
#[cfg(target_os = "linux")]
pub fn name(&mut self, name: &str) -> &mut Self {
self.config.name(name);
self
}

/// A tunnel device
pub struct TunnelDevice {
dev: platform::Device,
/// Enable packet information.
/// When enabled the first 4 bytes of each packet is a header with flags and protocol type.
#[cfg(target_os = "linux")]
pub fn enable_packet_information(&mut self) -> &mut Self {
self.config.platform(|platform_config| {
platform_config.packet_information(true);
});
self
}
}

impl TunnelDevice {
/// Creates a new Tunnel device
#[allow(unused_mut)]
pub fn new() -> Result<Self, NetworkInterfaceError> {
let mut config = Configuration::default();

#[cfg(target_os = "linux")]
config.platform(|config| {
config.packet_information(true);
});
let mut dev = platform::create(&config).map_err(NetworkInterfaceError::CreateDevice)?;
apply_async_flags(dev.as_raw_fd()).map_err(NetworkInterfaceError::SetDeviceAsync)?;
Ok(Self { dev })
impl Default for TunnelDeviceBuilder {
fn default() -> Self {
let config = Configuration::default();
Self { config }
}
}

Expand All @@ -152,13 +156,10 @@ impl IntoRawFd for TunnelDevice {
}
}

impl NetworkInterface for TunnelDevice {
fn set_ip(&mut self, ip: IpAddr) -> Result<(), NetworkInterfaceError> {
impl TunnelDevice {
fn set_ip(&mut self, ip: IpAddr) -> Result<(), Error> {
match ip {
IpAddr::V4(ipv4) => self
.dev
.set_address(ipv4)
.map_err(NetworkInterfaceError::SetIpv4),
IpAddr::V4(ipv4) => self.dev.set_address(ipv4).map_err(Error::SetIpv4),
IpAddr::V6(ipv6) => {
#[cfg(target_os = "linux")]
{
Expand All @@ -173,7 +174,7 @@ impl NetworkInterface for TunnelDevice {
)
.run()
.map(|_| ())
.map_err(NetworkInterfaceError::SetIpv6)
.map_err(Error::SetIpv6)
}
#[cfg(target_os = "macos")]
{
Expand All @@ -186,16 +187,14 @@ impl NetworkInterface for TunnelDevice {
)
.run()
.map(|_| ())
.map_err(NetworkInterfaceError::SetIpv6)
.map_err(Error::SetIpv6)
}
}
}
}

fn set_up(&mut self, up: bool) -> Result<(), NetworkInterfaceError> {
self.dev
.enabled(up)
.map_err(NetworkInterfaceError::ToggleDevice)
fn set_up(&mut self, up: bool) -> Result<(), Error> {
self.dev.enabled(up).map_err(Error::ToggleDevice)
}

fn get_name(&self) -> &str {
Expand Down
4 changes: 4 additions & 0 deletions talpid-wireguard/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use std::{
};
use talpid_types::net::{obfuscation::ObfuscatorConfig, wireguard, GenericTunnelOptions};

/// Name to use for the tunnel device
#[cfg(target_os = "linux")]
pub(crate) const MULLVAD_INTERFACE_NAME: &str = "wg0-mullvad";

/// Config required to set up a single WireGuard tunnel
#[derive(Debug, Clone)]
pub struct Config {
Expand Down
6 changes: 6 additions & 0 deletions talpid-wireguard/src/wireguard_go/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use super::{
stats::{Stats, StatsMap},
Config, Tunnel, TunnelError,
};
#[cfg(target_os = "linux")]
use crate::config::MULLVAD_INTERFACE_NAME;
use crate::logging::{clean_up_logging, initialize_logging};

const MAX_PREPARE_TUN_ATTEMPTS: usize = 4;
Expand Down Expand Up @@ -130,6 +132,10 @@ impl WgGoTunnel {
let mut tun_provider = tun_provider.lock().unwrap();

let tun_config = tun_provider.config_mut();
#[cfg(target_os = "linux")]
{
tun_config.name = Some(MULLVAD_INTERFACE_NAME.to_string());
}
tun_config.addresses = config.tunnel.addresses.clone();
tun_config.ipv4_gateway = config.ipv4_gateway;
tun_config.ipv6_gateway = config.ipv6_gateway;
Expand Down
2 changes: 0 additions & 2 deletions talpid-wireguard/src/wireguard_kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ pub enum Error {
NetworkManager(#[source] nm_tunnel::Error),
}

pub(crate) const MULLVAD_INTERFACE_NAME: &str = "wg0-mullvad";

#[derive(Debug)]
pub struct Handle {
pub wg_handle: WireguardConnection,
Expand Down
4 changes: 3 additions & 1 deletion talpid-wireguard/src/wireguard_kernel/netlink_tunnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ use std::pin::Pin;

use futures::Future;

use crate::config::MULLVAD_INTERFACE_NAME;

use super::{
super::stats::{Stats, StatsMap},
wg_message::DeviceNla,
Config, Error, Handle, Tunnel, TunnelError, MULLVAD_INTERFACE_NAME,
Config, Error, Handle, Tunnel, TunnelError,
};

pub struct NetlinkTunnel {
Expand Down
4 changes: 3 additions & 1 deletion talpid-wireguard/src/wireguard_kernel/nm_tunnel.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::config::MULLVAD_INTERFACE_NAME;

use super::{
super::stats::{Stats, StatsMap},
Config, Error as WgKernelError, Handle, Tunnel, TunnelError, MULLVAD_INTERFACE_NAME,
Config, Error as WgKernelError, Handle, Tunnel, TunnelError,
};
use futures::Future;
use std::{collections::HashMap, pin::Pin};
Expand Down

0 comments on commit d0040f9

Please sign in to comment.