Skip to content

Commit

Permalink
Merge branch 'testing-add-socks-bridge-tests'
Browse files Browse the repository at this point in the history
  • Loading branch information
dlon committed Feb 8, 2024
2 parents 7ab32cf + e1a194c commit bc51bf6
Showing 1 changed file with 202 additions and 3 deletions.
205 changes: 202 additions & 3 deletions test/test-manager/src/tests/tunnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ use crate::network_monitor::{start_packet_monitor, MonitorOptions};

use mullvad_management_interface::MullvadProxyClient;
use mullvad_types::relay_constraints::{
self, BridgeSettings, Constraint, OpenVpnConstraints, RelayConstraints, RelaySettings,
SelectedObfuscation, TransportPort, Udp2TcpObfuscationSettings, WireguardConstraints,
self, BridgeConstraints, BridgeSettings, BridgeType, Constraint, OpenVpnConstraints,
RelayConstraints, RelaySettings, SelectedObfuscation, TransportPort,
Udp2TcpObfuscationSettings, WireguardConstraints,
};
use mullvad_types::wireguard;
use talpid_types::net::{TransportProtocol, TunnelType};
use std::net::SocketAddr;
use talpid_types::net::{
proxy::{CustomProxy, Socks5Local, Socks5Remote},
TransportProtocol, TunnelType,
};
use test_macro::test_function;
use test_rpc::meta::Os;
use test_rpc::mullvad_daemon::ServiceStatus;
Expand Down Expand Up @@ -571,3 +576,197 @@ pub async fn test_quantum_resistant_multihop_udp2tcp_tunnel(

Ok(())
}

/// Try to connect to an OpenVPN relay via a remote, passwordless SOCKS5 server.
/// * No outgoing traffic to the bridge/entry relay is observed from the SUT.
/// * The conncheck reports an unexpected exit relay.
#[test_function]
pub async fn test_remote_socks_bridge(
_: TestContext,
rpc: ServiceClient,
mut mullvad_client: MullvadProxyClient,
) -> Result<(), Error> {
mullvad_client
.set_bridge_state(relay_constraints::BridgeState::On)
.await
.expect("failed to enable bridge mode");

mullvad_client
.set_bridge_settings(BridgeSettings {
bridge_type: BridgeType::Custom,
normal: BridgeConstraints::default(),
custom: Some(CustomProxy::Socks5Remote(Socks5Remote::new((
crate::vm::network::NON_TUN_GATEWAY,
crate::vm::network::SOCKS5_PORT,
)))),
})
.await
.expect("failed to update bridge settings");

set_relay_settings(
&mut mullvad_client,
RelaySettings::Normal(RelayConstraints {
tunnel_protocol: Constraint::Only(TunnelType::OpenVpn),
..Default::default()
}),
)
.await
.expect("failed to update relay settings");

//
// Connect to VPN
//

connect_and_wait(&mut mullvad_client).await?;

let (entry, exit) = match mullvad_client.get_tunnel_state().await? {
mullvad_types::states::TunnelState::Connected { endpoint, .. } => {
(endpoint.proxy.unwrap().endpoint, endpoint.endpoint)
}
actual => {
panic!("unexpected tunnel state. Expected `TunnelState::Connected` but got {actual:?}")
}
};

log::info!(
"Selected entry bridge {entry_addr} & exit relay {exit_addr}",
entry_addr = entry.address,
exit_addr = exit.address
);

// Start recording outgoing packets. Their destination will be verified
// against the bridge's IP address later.
let monitor = start_packet_monitor(
move |packet| packet.destination.ip() == entry.address.ip(),
MonitorOptions::default(),
)
.await;

//
// Verify exit IP
//

log::info!("Verifying exit server");

assert!(
helpers::using_mullvad_exit(&rpc).await,
"expected Mullvad exit IP"
);

//
// Verify entry IP
//

log::info!("Verifying entry server");

let monitor_result = monitor.into_result().await.unwrap();
assert!(
!monitor_result.packets.is_empty(),
"detected no traffic to entry server",
);

Ok(())
}

/// Try to connect to an OpenVPN relay via a local, passwordless SOCKS5 server.
/// * No outgoing traffic to the bridge/entry relay is observed from the SUT.
/// * The conncheck reports an unexpected exit relay.
#[test_function]
pub async fn test_local_socks_bridge(
_: TestContext,
rpc: ServiceClient,
mut mullvad_client: MullvadProxyClient,
) -> Result<(), Error> {
let remote_addr = SocketAddr::from((
crate::vm::network::NON_TUN_GATEWAY,
crate::vm::network::SOCKS5_PORT,
));
let socks_server = rpc
.start_tcp_forward("127.0.0.1:0".parse().unwrap(), remote_addr)
.await
.expect("failed to start TCP forward");

mullvad_client
.set_bridge_state(relay_constraints::BridgeState::On)
.await
.expect("failed to enable bridge mode");

mullvad_client
.set_bridge_settings(BridgeSettings {
bridge_type: BridgeType::Custom,
normal: BridgeConstraints::default(),
custom: Some(CustomProxy::Socks5Local(
Socks5Local::new_with_transport_protocol(
remote_addr,
socks_server.bind_addr().port(),
TransportProtocol::Tcp,
),
)),
})
.await
.expect("failed to update bridge settings");

set_relay_settings(
&mut mullvad_client,
RelaySettings::Normal(RelayConstraints {
tunnel_protocol: Constraint::Only(TunnelType::OpenVpn),
..Default::default()
}),
)
.await
.expect("failed to update relay settings");

//
// Connect to VPN
//

connect_and_wait(&mut mullvad_client).await?;

let (entry, exit) = match mullvad_client.get_tunnel_state().await? {
mullvad_types::states::TunnelState::Connected { endpoint, .. } => {
(endpoint.proxy.unwrap().endpoint, endpoint.endpoint)
}
actual => {
panic!("unexpected tunnel state. Expected `TunnelState::Connected` but got {actual:?}")
}
};

log::info!(
"Selected entry bridge {entry_addr} & exit relay {exit_addr}",
entry_addr = entry.address,
exit_addr = exit.address
);

// Start recording outgoing packets. Their destination will be verified
// against the bridge's IP address later.
let monitor = start_packet_monitor(
move |packet| packet.destination.ip() == entry.address.ip(),
MonitorOptions::default(),
)
.await;

//
// Verify exit IP
//

log::info!("Verifying exit server");

assert!(
helpers::using_mullvad_exit(&rpc).await,
"expected Mullvad exit IP"
);

//
// Verify entry IP
//

log::info!("Verifying entry server");

let monitor_result = monitor.into_result().await.unwrap();
assert!(
!monitor_result.packets.is_empty(),
"detected no traffic to entry server",
);

Ok(())
}

0 comments on commit bc51bf6

Please sign in to comment.