@@ -11,8 +11,9 @@ use mullvad_types::relay_constraints::{
11
11
Udp2TcpObfuscationSettings , WireguardConstraints ,
12
12
} ;
13
13
use mullvad_types:: wireguard;
14
+ use std:: net:: SocketAddr ;
14
15
use talpid_types:: net:: {
15
- proxy:: { CustomProxy , Socks5Remote } ,
16
+ proxy:: { CustomProxy , Socks5Local , Socks5Remote } ,
16
17
TransportProtocol , TunnelType ,
17
18
} ;
18
19
use test_macro:: test_function;
@@ -666,3 +667,106 @@ pub async fn test_remote_socks_bridge(
666
667
667
668
Ok ( ( ) )
668
669
}
670
+
671
+ /// Try to connect to an OpenVPN relay via a local, passwordless SOCKS5 server.
672
+ /// * No outgoing traffic to the bridge/entry relay is observed from the SUT.
673
+ /// * The conncheck reports an unexpected exit relay.
674
+ #[ test_function]
675
+ pub async fn test_local_socks_bridge (
676
+ _: TestContext ,
677
+ rpc : ServiceClient ,
678
+ mut mullvad_client : MullvadProxyClient ,
679
+ ) -> Result < ( ) , Error > {
680
+ let remote_addr = SocketAddr :: from ( (
681
+ crate :: vm:: network:: NON_TUN_GATEWAY ,
682
+ crate :: vm:: network:: SOCKS5_PORT ,
683
+ ) ) ;
684
+ let socks_server = rpc
685
+ . start_tcp_forward ( "127.0.0.1:0" . parse ( ) . unwrap ( ) , remote_addr)
686
+ . await
687
+ . expect ( "failed to start TCP forward" ) ;
688
+
689
+ mullvad_client
690
+ . set_bridge_state ( relay_constraints:: BridgeState :: On )
691
+ . await
692
+ . expect ( "failed to enable bridge mode" ) ;
693
+
694
+ mullvad_client
695
+ . set_bridge_settings ( BridgeSettings {
696
+ bridge_type : BridgeType :: Custom ,
697
+ normal : BridgeConstraints :: default ( ) ,
698
+ custom : Some ( CustomProxy :: Socks5Local (
699
+ Socks5Local :: new_with_transport_protocol (
700
+ remote_addr,
701
+ socks_server. bind_addr ( ) . port ( ) ,
702
+ TransportProtocol :: Tcp ,
703
+ ) ,
704
+ ) ) ,
705
+ } )
706
+ . await
707
+ . expect ( "failed to update bridge settings" ) ;
708
+
709
+ set_relay_settings (
710
+ & mut mullvad_client,
711
+ RelaySettings :: Normal ( RelayConstraints {
712
+ tunnel_protocol : Constraint :: Only ( TunnelType :: OpenVpn ) ,
713
+ ..Default :: default ( )
714
+ } ) ,
715
+ )
716
+ . await
717
+ . expect ( "failed to update relay settings" ) ;
718
+
719
+ //
720
+ // Connect to VPN
721
+ //
722
+
723
+ connect_and_wait ( & mut mullvad_client) . await ?;
724
+
725
+ let ( entry, exit) = match mullvad_client. get_tunnel_state ( ) . await ? {
726
+ mullvad_types:: states:: TunnelState :: Connected { endpoint, .. } => {
727
+ ( endpoint. proxy . unwrap ( ) . endpoint , endpoint. endpoint )
728
+ }
729
+ actual => {
730
+ panic ! ( "unexpected tunnel state. Expected `TunnelState::Connected` but got {actual:?}" )
731
+ }
732
+ } ;
733
+
734
+ log:: info!(
735
+ "Selected entry bridge {entry_addr} & exit relay {exit_addr}" ,
736
+ entry_addr = entry. address,
737
+ exit_addr = exit. address
738
+ ) ;
739
+
740
+ // Start recording outgoing packets. Their destination will be verified
741
+ // against the bridge's IP address later.
742
+ let monitor = start_packet_monitor (
743
+ move |packet| packet. destination . ip ( ) == entry. address . ip ( ) ,
744
+ MonitorOptions :: default ( ) ,
745
+ )
746
+ . await ;
747
+
748
+ //
749
+ // Verify exit IP
750
+ //
751
+
752
+ log:: info!( "Verifying exit server" ) ;
753
+
754
+ assert ! (
755
+ helpers:: using_mullvad_exit( & rpc) . await ,
756
+ "expected Mullvad exit IP"
757
+ ) ;
758
+
759
+ //
760
+ // Verify entry IP
761
+ //
762
+
763
+ log:: info!( "Verifying entry server" ) ;
764
+
765
+ let monitor_result = monitor. into_result ( ) . await . unwrap ( ) ;
766
+ assert ! (
767
+ !monitor_result. packets. is_empty( ) ,
768
+ "detected no traffic to entry server" ,
769
+ ) ;
770
+
771
+ Ok ( ( ) )
772
+ }
0 commit comments