Skip to content

Commit

Permalink
fixup
Browse files Browse the repository at this point in the history
  • Loading branch information
hulthe committed Dec 17, 2024
1 parent 6f59edc commit 5cbdf5f
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 57 deletions.
30 changes: 28 additions & 2 deletions leak-checker/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::net::IpAddr;
use std::{fmt, net::IpAddr};

pub mod am_i_mullvad;
pub mod traceroute;
Expand All @@ -16,9 +16,35 @@ pub enum LeakInfo {
/// Managed to reach another network node on the physical interface, bypassing firewall rules.
NodeReachableOnInterface {
reachable_nodes: Vec<IpAddr>,
interface: String,
interface: Interface,
},

/// Queried a <https://am.i.mullvad.net>, and was not mullvad.
AmIMullvad { ip: IpAddr },
}

#[derive(Clone)]
pub enum Interface {
Name(String),

#[cfg(target_os = "windows")]
Luid(windows_sys::Win32::NetworkManagement::Ndis::NET_LUID_LH),
}

impl From<String> for Interface {
fn from(name: String) -> Self {
Interface::Name(name)
}
}

impl fmt::Debug for Interface {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Name(arg0) => f.debug_tuple("Name").field(arg0).finish(),

// TODO:
#[cfg(target_os = "windows")]
Self::Luid(arg0) => f.debug_tuple("Luid").field(unsafe { &arg0.Value }).finish(),
}
}
}
4 changes: 2 additions & 2 deletions leak-checker/src/traceroute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use pnet_packet::{
use socket2::{Domain, Protocol, Socket, Type};
use tokio::time::{sleep, timeout};

use crate::LeakStatus;
use crate::{Interface, LeakStatus};

mod platform;

Expand All @@ -34,7 +34,7 @@ use platform::{
pub struct TracerouteOpt {
/// Try to bind to a specific interface
#[clap(short, long)]
pub interface: String,
pub interface: Interface,

/// Destination IP of the probe packets
#[clap(short, long)]
Expand Down
6 changes: 3 additions & 3 deletions leak-checker/src/traceroute/platform/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::net::IpAddr;

use socket2::Socket;

use crate::traceroute::TracerouteOpt;
use crate::{traceroute::TracerouteOpt, Interface};

use super::{linux, linux::TracerouteLinux, unix, Traceroute};

Expand All @@ -12,12 +12,12 @@ impl Traceroute for TracerouteAndroid {
type AsyncIcmpSocket = linux::AsyncIcmpSocketImpl;
type AsyncUdpSocket = unix::AsyncUdpSocketUnix;

fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Result<()> {
fn bind_socket_to_interface(socket: &Socket, interface: &Interface) -> anyhow::Result<()> {
// can't use the same method as desktop-linux here beacuse reasons
super::common::bind_socket_to_interface(socket, interface)
}

fn get_interface_ip(interface: &str) -> anyhow::Result<IpAddr> {
fn get_interface_ip(interface: &Interface) -> anyhow::Result<IpAddr> {
super::unix::get_interface_ip(interface)
}

Expand Down
8 changes: 4 additions & 4 deletions leak-checker/src/traceroute/platform/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ use tokio::{

use crate::{
traceroute::{parse_icmp_time_exceeded, parse_ipv4, RECV_TIMEOUT},
LeakInfo, LeakStatus,
Interface, LeakInfo, LeakStatus,
};

use super::{AsyncIcmpSocket, Impl, Traceroute};

pub fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Result<()> {
pub fn bind_socket_to_interface(socket: &Socket, interface: &Interface) -> anyhow::Result<()> {
let interface_ip = Impl::get_interface_ip(interface)?;

log::info!("Binding socket to {interface_ip} ({interface:?})");
Expand All @@ -33,7 +33,7 @@ pub fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Res

pub async fn recv_ttl_responses(
socket: &impl AsyncIcmpSocket,
interface: &str,
interface: &Interface,
) -> anyhow::Result<LeakStatus> {
// the list of node IP addresses from which we received a response to our probe packets.
let mut reachable_nodes = vec![];
Expand Down Expand Up @@ -68,7 +68,7 @@ pub async fn recv_ttl_responses(
_timeout = timer => {
return Ok(LeakStatus::LeakDetected(LeakInfo::NodeReachableOnInterface {
reachable_nodes,
interface: interface.to_string(),
interface: interface.clone(),
}));
}
};
Expand Down
14 changes: 8 additions & 6 deletions leak-checker/src/traceroute/platform/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use socket2::Socket;
use tokio::time::{sleep, Instant};

use crate::traceroute::{parse_icmp_echo_raw, TracerouteOpt, RECV_TIMEOUT};
use crate::{LeakInfo, LeakStatus};
use crate::{Interface, LeakInfo, LeakStatus};

use super::{unix, AsyncIcmpSocket, Traceroute};

Expand All @@ -26,11 +26,11 @@ impl Traceroute for TracerouteLinux {
type AsyncIcmpSocket = AsyncIcmpSocketImpl;
type AsyncUdpSocket = unix::AsyncUdpSocketUnix;

fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Result<()> {
fn bind_socket_to_interface(socket: &Socket, interface: &Interface) -> anyhow::Result<()> {
bind_socket_to_interface(socket, interface)
}

fn get_interface_ip(interface: &str) -> anyhow::Result<IpAddr> {
fn get_interface_ip(interface: &Interface) -> anyhow::Result<IpAddr> {
super::unix::get_interface_ip(interface)
}

Expand Down Expand Up @@ -70,9 +70,11 @@ impl AsyncIcmpSocket for AsyncIcmpSocketImpl {
}
}

fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Result<()> {
fn bind_socket_to_interface(socket: &Socket, interface: &Interface) -> anyhow::Result<()> {
log::info!("Binding socket to {interface:?}");

let Interface::Name(interface) = interface;

socket
.bind_device(Some(interface.as_bytes()))
.context("Failed to bind socket to interface")?;
Expand All @@ -86,7 +88,7 @@ fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Result<
// TODO: double check if this works on MacOS
async fn recv_ttl_responses(
destination: IpAddr,
interface: &str,
interface: &Interface,
socket: &impl AsRawFd,
) -> anyhow::Result<LeakStatus> {
// the list of node IP addresses from which we received a response to our probe packets.
Expand Down Expand Up @@ -209,7 +211,7 @@ async fn recv_ttl_responses(
Ok(LeakStatus::LeakDetected(
LeakInfo::NodeReachableOnInterface {
reachable_nodes,
interface: interface.to_string(),
interface: interface.clone(),
},
))
}
21 changes: 11 additions & 10 deletions leak-checker/src/traceroute/platform/macos.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::io;
use std::net::IpAddr;
use std::num::NonZero;
use std::os::fd::{FromRawFd, IntoRawFd};

use anyhow::Context;
use anyhow::{anyhow, Context};
use nix::net::if_::if_nametoindex;
use socket2::Socket;

use crate::traceroute::TracerouteOpt;
use crate::LeakStatus;
use crate::{Interface, LeakStatus};

use super::{common, unix, AsyncIcmpSocket, Traceroute};

Expand All @@ -18,12 +20,12 @@ impl Traceroute for TracerouteMacos {
type AsyncIcmpSocket = AsyncIcmpSocketImpl;
type AsyncUdpSocket = unix::AsyncUdpSocketUnix;

fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Result<()> {
fn bind_socket_to_interface(socket: &Socket, interface: &Interface) -> anyhow::Result<()> {
// can't use the same method as desktop-linux here beacuse reasons
bind_socket_to_interface(socket, interface)
}

fn get_interface_ip(interface: &str) -> anyhow::Result<IpAddr> {
fn get_interface_ip(interface: &Interface) -> anyhow::Result<IpAddr> {
super::unix::get_interface_ip(interface)
}

Expand Down Expand Up @@ -66,15 +68,14 @@ impl AsyncIcmpSocket for AsyncIcmpSocketImpl {
}
}

pub fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Result<()> {
use nix::net::if_::if_nametoindex;
use std::num::NonZero;
pub fn bind_socket_to_interface(socket: &Socket, interface: &Interface) -> anyhow::Result<()> {
let Interface::Name(interface) = interface;

log::info!("Binding socket to {interface:?}");

let interface_index = if_nametoindex(interface)
.map_err(anyhow::Report::from)
.and_then(|code| NonZero::new(code).ok_or_anyhow("Non-zero error code"))
let interface_index = if_nametoindex(interface.as_str())
.map_err(anyhow::Error::from)
.and_then(|code| NonZero::new(code).ok_or(anyhow!("Non-zero error code")))
.context("Failed to get interface index")?;

socket.bind_device_by_index_v4(Some(interface_index))?;
Expand Down
9 changes: 6 additions & 3 deletions leak-checker/src/traceroute/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
net::{IpAddr, SocketAddr},
};

use crate::LeakStatus;
use crate::{Interface, LeakStatus};

use super::TracerouteOpt;

Expand Down Expand Up @@ -32,9 +32,12 @@ pub trait Traceroute {
type AsyncIcmpSocket: AsyncIcmpSocket;
type AsyncUdpSocket: AsyncUdpSocket;

fn get_interface_ip(interface: &str) -> anyhow::Result<IpAddr>;
fn get_interface_ip(interface: &Interface) -> anyhow::Result<IpAddr>;

fn bind_socket_to_interface(socket: &socket2::Socket, interface: &str) -> anyhow::Result<()>;
fn bind_socket_to_interface(
socket: &socket2::Socket,
interface: &Interface,
) -> anyhow::Result<()>;

/// Configure an ICMP socket to allow reception of ICMP/TimeExceeded errors.
// TODO: consider moving into AsyncIcmpSocket constructor
Expand Down
8 changes: 6 additions & 2 deletions leak-checker/src/traceroute/platform/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ use std::os::fd::{FromRawFd, IntoRawFd};

use anyhow::Context;

use crate::Interface;

use super::AsyncUdpSocket;

pub fn get_interface_ip(interface: &str) -> anyhow::Result<IpAddr> {
pub fn get_interface_ip(interface: &Interface) -> anyhow::Result<IpAddr> {
let Interface::Name(interface) = interface;

for interface_address in nix::ifaddrs::getifaddrs()? {
if interface_address.interface_name != interface {
if &interface_address.interface_name != interface {
continue;
};
let Some(address) = interface_address.address else {
Expand Down
15 changes: 9 additions & 6 deletions leak-checker/src/traceroute/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ use std::{
ptr::null_mut,
};

use anyhow::{bail, anyhow, Context};
use anyhow::{anyhow, bail, Context};
use socket2::Socket;
use talpid_windows::net::{get_ip_address_for_interface, luid_from_alias, AddressFamily};

use windows_sys::Win32::Networking::WinSock::{
WSAGetLastError, WSAIoctl, SIO_RCVALL, SOCKET, SOCKET_ERROR,
};

use crate::{traceroute::TracerouteOpt, LeakStatus};
use crate::{traceroute::TracerouteOpt, Interface, LeakStatus};

use super::{common, AsyncIcmpSocket, AsyncUdpSocket, Traceroute};

Expand All @@ -28,11 +28,11 @@ impl Traceroute for TracerouteWindows {
type AsyncIcmpSocket = AsyncIcmpSocketImpl;
type AsyncUdpSocket = AsyncUdpSocketWindows;

fn bind_socket_to_interface(socket: &Socket, interface: &str) -> anyhow::Result<()> {
fn bind_socket_to_interface(socket: &Socket, interface: &Interface) -> anyhow::Result<()> {
common::bind_socket_to_interface(socket, interface)
}

fn get_interface_ip(interface: &str) -> anyhow::Result<IpAddr> {
fn get_interface_ip(interface: &Interface) -> anyhow::Result<IpAddr> {
get_interface_ip(interface)
}

Expand Down Expand Up @@ -93,8 +93,11 @@ impl AsyncUdpSocket for AsyncUdpSocketWindows {
}
}

pub fn get_interface_ip(interface: &str) -> anyhow::Result<IpAddr> {
let interface_luid = luid_from_alias(interface)?;
pub fn get_interface_ip(interface: &Interface) -> anyhow::Result<IpAddr> {
let interface_luid = match interface {
Interface::Name(name) => luid_from_alias(name)?,
Interface::Luid(luid) => *luid,
};

// TODO: ipv6
let interface_ip = get_ip_address_for_interface(AddressFamily::Ipv4, interface_luid)?
Expand Down
Loading

0 comments on commit 5cbdf5f

Please sign in to comment.