summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2024-11-13 13:49:51 +0100
committerMarkus Pettersson <markus.pettersson@mullvad.net>2024-11-15 09:58:51 +0100
commita427c100eb1f462897f1efbb7b2ee8ead322bc21 (patch)
treeb112ff4e82b1c8c43dff73c1d88057bb9b179c33 /test
parentf56bae181c477fbb4fc46ca832d72e41af2d3416 (diff)
downloadmullvadvpn-a427c100eb1f462897f1efbb7b2ee8ead322bc21.tar.xz
mullvadvpn-a427c100eb1f462897f1efbb7b2ee8ead322bc21.zip
Move end-to-end tests for audit issues to separate module
Diffstat (limited to 'test')
-rw-r--r--test/test-manager/src/tests/audits/cve_2019_14899.rs (renamed from test/test-manager/src/tests/cve_2019_14899.rs)28
-rw-r--r--test/test-manager/src/tests/audits/mod.rs3
-rw-r--r--test/test-manager/src/tests/audits/mul_02_002.rs98
-rw-r--r--test/test-manager/src/tests/mod.rs2
-rw-r--r--test/test-manager/src/tests/tunnel.rs91
5 files changed, 118 insertions, 104 deletions
diff --git a/test/test-manager/src/tests/cve_2019_14899.rs b/test/test-manager/src/tests/audits/cve_2019_14899.rs
index 79687b646a..71872c0716 100644
--- a/test/test-manager/src/tests/cve_2019_14899.rs
+++ b/test/test-manager/src/tests/audits/cve_2019_14899.rs
@@ -1,4 +1,16 @@
#![cfg(target_os = "linux")]
+//! Test mitigation for cve-2019-14899
+//!
+//! The vulnerability allowed a malicious router to learn the victims private mullvad tunnel IP.
+//! It is performed by sending a TCP packet to the victim with SYN and ACK flags set.
+//!
+//! If the destination_addr of the packet was the same as the private IP, the victims computer
+//! would respond to the packet with the RST flag set.
+//!
+//! This test simply gets the private tunnel IP from the test runner and sends the SYN/ACK packet
+//! targeted to that address. If the guest does not respond, the test passes.
+//!
+//! Note that only linux was susceptible to this vulnerability.
use std::{
convert::Infallible,
@@ -30,27 +42,13 @@ use test_rpc::ServiceClient;
use tokio::{task::yield_now, time::sleep};
use crate::{
- tests::helpers,
+ tests::{helpers, TestContext},
vm::network::{linux::TAP_NAME, NON_TUN_GATEWAY},
};
-use super::TestContext;
-
/// The port number we set in the malicious packet.
const MALICIOUS_PACKET_PORT: u16 = 12345;
-/// Test mitigation for cve-2019-14899.
-///
-/// The vulnerability allowed a malicious router to learn the victims private mullvad tunnel IP.
-/// It is performed by sending a TCP packet to the victim with SYN and ACK flags set.
-///
-/// If the destination_addr of the packet was the same as the private IP, the victims computer
-/// would respond to the packet with the RST flag set.
-///
-/// This test simply gets the private tunnel IP from the test runner and sends the SYN/ACK packet
-/// targeted to that address. If the guest does not respond, the test passes.
-///
-/// Note that only linux was susceptible to this vulnerability.
#[test_function(target_os = "linux")]
pub async fn test_cve_2019_14899_mitigation(
_: TestContext,
diff --git a/test/test-manager/src/tests/audits/mod.rs b/test/test-manager/src/tests/audits/mod.rs
new file mode 100644
index 0000000000..b34257c71f
--- /dev/null
+++ b/test/test-manager/src/tests/audits/mod.rs
@@ -0,0 +1,3 @@
+//! This module collects tests for old audit issues to prevent any potential regression.
+pub mod cve_2019_14899;
+pub mod mul_02_002;
diff --git a/test/test-manager/src/tests/audits/mul_02_002.rs b/test/test-manager/src/tests/audits/mul_02_002.rs
new file mode 100644
index 0000000000..c0571eaacc
--- /dev/null
+++ b/test/test-manager/src/tests/audits/mul_02_002.rs
@@ -0,0 +1,98 @@
+//! Test mitigation for MUL-02-002-WP2
+//!
+//! Fail to leak traffic to verify that mitigation "Firewall allows deanonymization by eavesdropper" works.
+//!
+//! # Vulnerability
+//! 1. Connect to a relay on port 443. Record this relay's IP address (the new gateway of the
+//! client)
+//! 2. Start listening for unencrypted traffic on the outbound network interface
+//! (Choose some human-readable, identifiable payload to look for in the outgoing TCP packets)
+//! 3. Start a rogue program which performs a GET request\* containing the payload defined in step 2
+//! 4. The network snooper started in step 2 should now be able to observe the network request
+//! containing the identifiable payload being sent unencrypted over the wire
+//!
+//! \* or something similar, as long as it generates some traffic containing UDP and/or TCP packets
+//! with the correct payload.
+
+use anyhow::{bail, ensure};
+use mullvad_management_interface::MullvadProxyClient;
+use mullvad_relay_selector::query::builder::{RelayQueryBuilder, TransportProtocol};
+use mullvad_types::states::TunnelState;
+use test_macro::test_function;
+use test_rpc::ServiceClient;
+
+use crate::network_monitor::{start_packet_monitor, MonitorOptions, ParsedPacket};
+use crate::tests::helpers::{
+ connect_and_wait, constrain_to_relay, disconnect_and_wait, ConnChecker,
+};
+use crate::tests::TestContext;
+
+#[test_function]
+pub async fn test_mul_02_002(
+ _: TestContext,
+ rpc: ServiceClient,
+ mut mullvad_client: MullvadProxyClient,
+) -> anyhow::Result<()> {
+ // Step 1 - Choose a relay
+ constrain_to_relay(
+ &mut mullvad_client,
+ RelayQueryBuilder::new()
+ .openvpn()
+ .transport_protocol(TransportProtocol::Tcp)
+ .port(443)
+ .build(),
+ )
+ .await?;
+
+ // Step 1.5 - Temporarily connect to the relay to get the target endpoint
+ let tunnel_state = connect_and_wait(&mut mullvad_client).await?;
+ let TunnelState::Connected { endpoint, .. } = tunnel_state else {
+ bail!("Expected tunnel state to be `Connected` - instead it was {tunnel_state:?}");
+ };
+ disconnect_and_wait(&mut mullvad_client).await?;
+ let target_endpoint = endpoint.endpoint.address;
+
+ // Step 2 - Start a network monitor snooping the outbound network interface for some
+ // identifiable payload
+ let unique_identifier = "Hello there!";
+ let identify_rogue_packet = move |packet: &ParsedPacket| {
+ packet
+ .payload
+ .windows(unique_identifier.len())
+ .any(|window| window == unique_identifier.as_bytes())
+ };
+ let rogue_packet_monitor =
+ start_packet_monitor(identify_rogue_packet, MonitorOptions::default()).await;
+
+ // Step 3 - Start the rogue program which will try to leak the unique identifier payload
+ // to the chosen relay endpoint
+ let mut checker = ConnChecker::new(rpc.clone(), mullvad_client.clone(), target_endpoint);
+ checker.payload(unique_identifier);
+ let mut conn_artist = checker.spawn().await?;
+ // Before proceeding, assert that the method of detecting identifiable packets work.
+ conn_artist.check_connection().await?;
+ let monitor_result = rogue_packet_monitor.into_result().await?;
+
+ log::info!("Checking that the identifiable payload was detectable without encryption");
+ ensure!(
+ !monitor_result.packets.is_empty(),
+ "Did not observe rogue packets! The method seems to be broken"
+ );
+ log::info!("The identifiable payload was detected! (that's good)");
+
+ // Step 4 - Finally, connect to a tunnel and assert that no outgoing traffic contains the
+ // payload in plain text.
+ connect_and_wait(&mut mullvad_client).await?;
+ let rogue_packet_monitor =
+ start_packet_monitor(identify_rogue_packet, MonitorOptions::default()).await;
+ conn_artist.check_connection().await?;
+ let monitor_result = rogue_packet_monitor.into_result().await?;
+
+ log::info!("Checking that the identifiable payload was not detected");
+ ensure!(
+ monitor_result.packets.is_empty(),
+ "Observed rogue packets! The tunnel seems to be leaking traffic"
+ );
+
+ Ok(())
+}
diff --git a/test/test-manager/src/tests/mod.rs b/test/test-manager/src/tests/mod.rs
index 14c2a1e3a5..ca24cd63bf 100644
--- a/test/test-manager/src/tests/mod.rs
+++ b/test/test-manager/src/tests/mod.rs
@@ -1,7 +1,7 @@
mod access_methods;
mod account;
+mod audits;
pub mod config;
-mod cve_2019_14899;
mod daita;
mod dns;
mod helpers;
diff --git a/test/test-manager/src/tests/tunnel.rs b/test/test-manager/src/tests/tunnel.rs
index fde8c73049..d1b6e65585 100644
--- a/test/test-manager/src/tests/tunnel.rs
+++ b/test/test-manager/src/tests/tunnel.rs
@@ -7,11 +7,11 @@ use super::{
Error, TestContext,
};
use crate::{
- network_monitor::{start_packet_monitor, MonitorOptions, ParsedPacket},
- tests::helpers::{login_with_retries, ConnChecker},
+ network_monitor::{start_packet_monitor, MonitorOptions},
+ tests::helpers::login_with_retries,
};
-use anyhow::{bail, ensure, Context};
+use anyhow::Context;
use mullvad_management_interface::MullvadProxyClient;
use mullvad_relay_selector::query::builder::RelayQueryBuilder;
use mullvad_types::{
@@ -20,7 +20,6 @@ use mullvad_types::{
self, BridgeConstraints, BridgeSettings, BridgeType, OpenVpnConstraints, RelayConstraints,
RelaySettings, TransportPort, WireguardConstraints,
},
- states::TunnelState,
wireguard,
};
use std::net::SocketAddr;
@@ -833,87 +832,3 @@ pub async fn test_establish_tunnel_without_api(
// Profit
Ok(())
}
-
-/// Fail to leak traffic to verify that mitigation for MUL-02-002-WP2
-/// ("Firewall allows deanonymization by eavesdropper") works.
-///
-/// # Vulnerability
-/// 1. Connect to a relay on port 443. Record this relay's IP address (the new gateway of the
-/// client)
-/// 2. Start listening for unencrypted traffic on the outbound network interface
-/// (Choose some human-readable, identifiable payload to look for in the outgoing TCP packets)
-/// 3. Start a rogue program which performs a GET request* containing the payload defined in step 2
-/// 4. The network snooper started in step 2 should now be able to observe the network request
-/// containing the identifiable payload being sent unencrypted over the wire
-///
-/// * or something similiar, as long as it generates some traffic containing UDP and/or TCP packets
-/// with the correct payload.
-#[test_function]
-pub async fn test_mul_02_002(
- _: TestContext,
- rpc: ServiceClient,
- mut mullvad_client: MullvadProxyClient,
-) -> anyhow::Result<()> {
- // Step 1 - Choose a relay
- helpers::constrain_to_relay(
- &mut mullvad_client,
- RelayQueryBuilder::new()
- .openvpn()
- .transport_protocol(TransportProtocol::Tcp)
- .port(443)
- .build(),
- )
- .await?;
-
- // Step 1.5 - Temporarily connect to the relay to get the target endpoint
- let tunnel_state = helpers::connect_and_wait(&mut mullvad_client).await?;
- let TunnelState::Connected { endpoint, .. } = tunnel_state else {
- bail!("Expected tunnel state to be `Connected` - instead it was {tunnel_state:?}");
- };
- helpers::disconnect_and_wait(&mut mullvad_client).await?;
- let target_endpoint = endpoint.endpoint.address;
-
- // Step 2 - Start a network monitor snooping the outbound network interface for some
- // identifiable payload
- let unique_identifier = "Hello there!";
- let identify_rogue_packet = move |packet: &ParsedPacket| {
- packet
- .payload
- .windows(unique_identifier.len())
- .any(|window| window == unique_identifier.as_bytes())
- };
- let rogue_packet_monitor =
- start_packet_monitor(identify_rogue_packet, MonitorOptions::default()).await;
-
- // Step 3 - Start the rogue program which will try to leak the unique identifier payload
- // to the chosen relay endpoint
- let mut checker = ConnChecker::new(rpc.clone(), mullvad_client.clone(), target_endpoint);
- checker.payload(unique_identifier);
- let mut conn_artist = checker.spawn().await?;
- // Before proceeding, assert that the method of detecting identifiable packets work.
- conn_artist.check_connection().await?;
- let monitor_result = rogue_packet_monitor.into_result().await?;
-
- log::info!("Checking that the identifiable payload was detectable without encryption");
- ensure!(
- !monitor_result.packets.is_empty(),
- "Did not observe rogue packets! The method seems to be broken"
- );
- log::info!("The identifiable payload was detected! (that's good)");
-
- // Step 4 - Finally, connect to a tunnel and assert that no outgoing traffic contains the
- // payload in plain text.
- helpers::connect_and_wait(&mut mullvad_client).await?;
- let rogue_packet_monitor =
- start_packet_monitor(identify_rogue_packet, MonitorOptions::default()).await;
- conn_artist.check_connection().await?;
- let monitor_result = rogue_packet_monitor.into_result().await?;
-
- log::info!("Checking that the identifiable payload was not detected");
- ensure!(
- monitor_result.packets.is_empty(),
- "Observed rogue packets! The tunnel seems to be leaking traffic"
- );
-
- Ok(())
-}