summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2024-08-26 21:40:30 +0200
committerDavid Lönnhager <david.l@mullvad.net>2024-08-29 14:38:32 +0200
commit31637ab8b58a7e1ab00acdf32d5ee5ddbd08c458 (patch)
tree88971e2ce7e8cf0f5dc4d07f19eb17af6e04e10f /test
parentf1d9dd3bf9dab8bd9e08daac7f36980b3c332dfb (diff)
downloadmullvadvpn-31637ab8b58a7e1ab00acdf32d5ee5ddbd08c458.tar.xz
mullvadvpn-31637ab8b58a7e1ab00acdf32d5ee5ddbd08c458.zip
Fix test_split_tunnel
Raw ICMP isn't allowed on all platforms for unprivileged users. Instead: * Use SOCK_DGRAM, where possible * Use 'ping' command, since SOCK_DGRAM isn't allowed on some older Linux distros.
Diffstat (limited to 'test')
-rw-r--r--test/connection-checker/src/cli.rs8
-rw-r--r--test/connection-checker/src/main.rs2
-rw-r--r--test/connection-checker/src/net.rs58
-rw-r--r--test/scripts/ssh-setup.sh3
-rw-r--r--test/test-manager/src/tests/helpers.rs18
5 files changed, 72 insertions, 17 deletions
diff --git a/test/connection-checker/src/cli.rs b/test/connection-checker/src/cli.rs
index ecc33dd7e9..97240cf974 100644
--- a/test/connection-checker/src/cli.rs
+++ b/test/connection-checker/src/cli.rs
@@ -10,8 +10,8 @@ pub struct Opt {
#[clap(short, long)]
pub interactive: bool,
- /// Timeout for network connection to am.i.mullvad (in millis).
- #[clap(short, long, default_value = "3000")]
+ /// Timeout for network connection to am.i.mullvad (in seconds).
+ #[clap(short, long, default_value = "3")]
pub timeout: u64,
/// Try to send some junk data over TCP to <leak>.
@@ -30,8 +30,8 @@ pub struct Opt {
#[clap(long)]
pub leak: Option<SocketAddr>,
- /// Timeout for leak check network connections (in millis).
- #[clap(long, default_value = "1000")]
+ /// Timeout for leak check network connections (in seconds).
+ #[clap(long, default_value = "1")]
pub leak_timeout: u64,
/// Junk data for each UDP and TCP packet
diff --git a/test/connection-checker/src/main.rs b/test/connection-checker/src/main.rs
index 16050f322e..c56d8b31da 100644
--- a/test/connection-checker/src/main.rs
+++ b/test/connection-checker/src/main.rs
@@ -54,7 +54,7 @@ fn am_i_mullvad(opt: &Opt) -> eyre::Result<bool> {
let client = Client::new();
let response: Response = client
.get(url)
- .timeout(Duration::from_millis(opt.timeout))
+ .timeout(Duration::from_secs(opt.timeout))
.send()
.and_then(|r| r.json())
.wrap_err_with(|| eyre!("Failed to GET {url}"))?;
diff --git a/test/connection-checker/src/net.rs b/test/connection-checker/src/net.rs
index 40db99e8b5..0ac19f3ca5 100644
--- a/test/connection-checker/src/net.rs
+++ b/test/connection-checker/src/net.rs
@@ -22,7 +22,7 @@ pub fn send_tcp(opt: &Opt, destination: SocketAddr) -> eyre::Result<()> {
sock.bind(&socket2::SockAddr::from(bind_addr))
.wrap_err(eyre!("Failed to bind TCP socket to {bind_addr}"))?;
- let timeout = Duration::from_millis(opt.leak_timeout);
+ let timeout = Duration::from_secs(opt.leak_timeout);
sock.set_write_timeout(Some(timeout))?;
sock.set_read_timeout(Some(timeout))?;
@@ -60,12 +60,13 @@ pub fn send_udp(opt: &Opt, destination: SocketAddr) -> Result<(), eyre::Error> {
Ok(())
}
+#[cfg(target_os = "windows")]
pub fn send_ping(opt: &Opt, destination: IpAddr) -> eyre::Result<()> {
- eprintln!("Leaking IMCP packets to {destination}");
+ eprintln!("Leaking ICMP packets to {destination}");
ping::ping(
destination,
- Some(Duration::from_millis(opt.leak_timeout)),
+ Some(Duration::from_secs(opt.leak_timeout)),
None,
None,
None,
@@ -74,3 +75,54 @@ pub fn send_ping(opt: &Opt, destination: IpAddr) -> eyre::Result<()> {
Ok(())
}
+
+#[cfg(target_os = "macos")]
+pub fn send_ping(opt: &Opt, destination: IpAddr) -> eyre::Result<()> {
+ eprintln!("Leaking ICMP packets to {destination}");
+
+ // On macOS, use dgramsock (SOCK_DGRAM) instead of the default sock type (SOCK_RAW),
+ // so that we don't need root privileges. Naturally, this does not work for Windows.
+ ping::dgramsock::ping(
+ destination,
+ Some(Duration::from_secs(opt.leak_timeout)),
+ None,
+ None,
+ None,
+ None,
+ )?;
+
+ Ok(())
+}
+
+// Older Linux distributions don't allow unprivileged users to send ICMP packets, even for
+// SOCK_DGRAM sockets. We use the ping command (which has capabilities/setuid set) to get around
+// that.
+#[cfg(target_os = "linux")]
+pub fn send_ping(opt: &Opt, destination: IpAddr) -> eyre::Result<()> {
+ eprintln!("Leaking ICMP packets to {destination}");
+
+ let mut cmd = std::process::Command::new("ping");
+
+ let timeout_sec = opt.leak_timeout.to_string();
+
+ cmd.args(["-c", "1", "-W", &timeout_sec, &destination.to_string()]);
+
+ let output = cmd.output().wrap_err(eyre!(
+ "Failed to execute ping for destination {destination}"
+ ))?;
+
+ if !output.status.success() {
+ eprintln!(
+ "ping stdout:\n\n{}",
+ std::str::from_utf8(&output.stdout).unwrap_or("invalid utf8")
+ );
+ eprintln!(
+ "ping stderr:\n\n{}",
+ std::str::from_utf8(&output.stderr).unwrap_or("invalid utf8")
+ );
+
+ return Err(eyre!("ping for destination {destination} failed"));
+ }
+
+ Ok(())
+}
diff --git a/test/scripts/ssh-setup.sh b/test/scripts/ssh-setup.sh
index 5ac5dea15e..0bbea4f0b9 100644
--- a/test/scripts/ssh-setup.sh
+++ b/test/scripts/ssh-setup.sh
@@ -128,6 +128,9 @@ function install_packages_apt {
echo "Installing required apt packages"
apt update
apt install -yf xvfb wireguard-tools curl
+ if ! which ping &>/dev/null; then
+ apt install -yf iputils-ping
+ fi
curl -fsSL https://get.docker.com | sh
}
diff --git a/test/test-manager/src/tests/helpers.rs b/test/test-manager/src/tests/helpers.rs
index 4c9da00a16..542cf0c8a4 100644
--- a/test/test-manager/src/tests/helpers.rs
+++ b/test/test-manager/src/tests/helpers.rs
@@ -44,15 +44,15 @@ pub const THROTTLE_RETRY_DELAY: Duration = Duration::from_secs(120);
const CHECKER_FILENAME_WINDOWS: &str = "connection-checker.exe";
const CHECKER_FILENAME_UNIX: &str = "connection-checker";
-const AM_I_MULLVAD_TIMEOUT_MS: u64 = 10000;
-const LEAK_TIMEOUT_MS: u64 = 500;
+const AM_I_MULLVAD_TIMEOUT_S: u64 = 10;
+const LEAK_TIMEOUT_S: u64 = 1;
/// Timeout of [ConnCheckerHandle::check_connection].
-const CONN_CHECKER_TIMEOUT: Duration = Duration::from_millis(
- AM_I_MULLVAD_TIMEOUT_MS // https://am.i.mullvad.net timeout
- + LEAK_TIMEOUT_MS // leak-tcp timeout
- + LEAK_TIMEOUT_MS // leak-icmp timeout
- + 1000, // plus some extra grace time
+const CONN_CHECKER_TIMEOUT: Duration = Duration::from_secs(
+ AM_I_MULLVAD_TIMEOUT_S // https://am.i.mullvad.net timeout
+ + LEAK_TIMEOUT_S // leak-tcp timeout
+ + LEAK_TIMEOUT_S // leak-icmp timeout
+ + 1, // plus some extra grace time
);
#[macro_export]
@@ -957,12 +957,12 @@ impl ConnChecker {
let mut args = [
"--interactive",
"--timeout",
- &AM_I_MULLVAD_TIMEOUT_MS.to_string(),
+ &AM_I_MULLVAD_TIMEOUT_S.to_string(),
// try to leak traffic to LEAK_DESTINATION
"--leak",
&self.leak_destination.to_string(),
"--leak-timeout",
- &LEAK_TIMEOUT_MS.to_string(),
+ &LEAK_TIMEOUT_S.to_string(),
"--leak-tcp",
"--leak-udp",
"--leak-icmp",