@@ -6,11 +6,15 @@ use crate::network_monitor::{start_packet_monitor, MonitorOptions};
6
6
7
7
use mullvad_management_interface:: MullvadProxyClient ;
8
8
use mullvad_types:: relay_constraints:: {
9
- self , BridgeSettings , Constraint , OpenVpnConstraints , RelayConstraints , RelaySettings ,
10
- SelectedObfuscation , TransportPort , Udp2TcpObfuscationSettings , WireguardConstraints ,
9
+ self , BridgeConstraints , BridgeSettings , BridgeType , Constraint , OpenVpnConstraints ,
10
+ RelayConstraints , RelaySettings , SelectedObfuscation , TransportPort ,
11
+ Udp2TcpObfuscationSettings , WireguardConstraints ,
11
12
} ;
12
13
use mullvad_types:: wireguard;
13
- use talpid_types:: net:: { TransportProtocol , TunnelType } ;
14
+ use talpid_types:: net:: {
15
+ proxy:: { CustomProxy , Socks5Remote } ,
16
+ TransportProtocol , TunnelType ,
17
+ } ;
14
18
use test_macro:: test_function;
15
19
use test_rpc:: meta:: Os ;
16
20
use test_rpc:: mullvad_daemon:: ServiceStatus ;
@@ -571,3 +575,185 @@ pub async fn test_quantum_resistant_multihop_udp2tcp_tunnel(
571
575
572
576
Ok ( ( ) )
573
577
}
578
+
579
+ /// Try to connect to an OpenVPN relay via a remote, passwordless SOCKS5 server.
580
+ /// * No outgoing traffic to the bridge/entry relay is observed from the SUT.
581
+ /// * The conncheck reports an unexpected exit relay.
582
+ #[ test_function]
583
+ pub async fn test_remote_socks_bridge (
584
+ _: TestContext ,
585
+ rpc : ServiceClient ,
586
+ mut mullvad_client : MullvadProxyClient ,
587
+ ) -> Result < ( ) , Error > {
588
+ mullvad_client
589
+ . set_bridge_state ( relay_constraints:: BridgeState :: On )
590
+ . await
591
+ . expect ( "failed to enable bridge mode" ) ;
592
+
593
+ mullvad_client
594
+ . set_bridge_settings ( BridgeSettings {
595
+ bridge_type : BridgeType :: Custom ,
596
+ normal : BridgeConstraints :: default ( ) ,
597
+ custom : Some ( CustomProxy :: Socks5Remote ( Socks5Remote :: new ( (
598
+ crate :: vm:: network:: NON_TUN_GATEWAY ,
599
+ crate :: vm:: network:: SOCKS5_PORT ,
600
+ ) ) ) ) ,
601
+ } )
602
+ . await
603
+ . expect ( "failed to update bridge settings" ) ;
604
+
605
+ set_relay_settings (
606
+ & mut mullvad_client,
607
+ RelaySettings :: Normal ( RelayConstraints {
608
+ tunnel_protocol : Constraint :: Only ( TunnelType :: OpenVpn ) ,
609
+ ..Default :: default ( )
610
+ } ) ,
611
+ )
612
+ . await
613
+ . expect ( "failed to update relay settings" ) ;
614
+
615
+ //
616
+ // Connect to VPN
617
+ //
618
+
619
+ connect_and_wait ( & mut mullvad_client) . await ?;
620
+
621
+ let ( entry, exit) = match mullvad_client. get_tunnel_state ( ) . await ? {
622
+ mullvad_types:: states:: TunnelState :: Connected { endpoint, .. } => {
623
+ ( endpoint. proxy . unwrap ( ) . endpoint , endpoint. endpoint )
624
+ }
625
+ actual => {
626
+ panic ! ( "unexpected tunnel state. Expected `TunnelState::Connected` but got {actual:?}" )
627
+ }
628
+ } ;
629
+
630
+ log:: info!(
631
+ "Selected entry bridge {entry_addr} & exit relay {exit_addr}" ,
632
+ entry_addr = entry. address,
633
+ exit_addr = exit. address
634
+ ) ;
635
+
636
+ // Start recording outgoing packets. Their destination will be verified
637
+ // against the bridge's IP address later.
638
+ let monitor = start_packet_monitor (
639
+ move |packet| packet. destination . ip ( ) == entry. address . ip ( ) ,
640
+ MonitorOptions :: default ( ) ,
641
+ )
642
+ . await ;
643
+
644
+ //
645
+ // Verify exit IP
646
+ //
647
+
648
+ log:: info!( "Verifying exit server" ) ;
649
+
650
+ assert ! (
651
+ helpers:: using_mullvad_exit( & rpc) . await ,
652
+ "expected Mullvad exit IP"
653
+ ) ;
654
+
655
+ //
656
+ // Verify entry IP
657
+ //
658
+
659
+ log:: info!( "Verifying entry server" ) ;
660
+
661
+ let monitor_result = monitor. into_result ( ) . await . unwrap ( ) ;
662
+ assert ! (
663
+ !monitor_result. packets. is_empty( ) ,
664
+ "detected no traffic to entry server" ,
665
+ ) ;
666
+
667
+ Ok ( ( ) )
668
+ }
669
+
670
+ /// Try to connect to an OpenVPN relay via a local, passwordless SOCKS5 server.
671
+ /// * No outgoing traffic to the bridge/entry relay is observed from the SUT.
672
+ /// * The conncheck reports an unexpected exit relay.
673
+ #[ test_function]
674
+ pub async fn test_local_socks_bridge (
675
+ _: TestContext ,
676
+ rpc : ServiceClient ,
677
+ mut mullvad_client : MullvadProxyClient ,
678
+ ) -> Result < ( ) , Error > {
679
+ mullvad_client
680
+ . set_bridge_state ( relay_constraints:: BridgeState :: On )
681
+ . await
682
+ . expect ( "failed to enable bridge mode" ) ;
683
+
684
+ mullvad_client
685
+ . set_bridge_settings ( BridgeSettings {
686
+ bridge_type : BridgeType :: Custom ,
687
+ normal : BridgeConstraints :: default ( ) ,
688
+ custom : Some ( CustomProxy :: Socks5Remote ( Socks5Remote :: new ( (
689
+ crate :: vm:: network:: NON_TUN_GATEWAY ,
690
+ crate :: vm:: network:: SOCKS5_PORT ,
691
+ ) ) ) ) ,
692
+ } )
693
+ . await
694
+ . expect ( "failed to update bridge settings" ) ;
695
+
696
+ set_relay_settings (
697
+ & mut mullvad_client,
698
+ RelaySettings :: Normal ( RelayConstraints {
699
+ tunnel_protocol : Constraint :: Only ( TunnelType :: OpenVpn ) ,
700
+ ..Default :: default ( )
701
+ } ) ,
702
+ )
703
+ . await
704
+ . expect ( "failed to update relay settings" ) ;
705
+
706
+ //
707
+ // Connect to VPN
708
+ //
709
+
710
+ connect_and_wait ( & mut mullvad_client) . await ?;
711
+
712
+ let ( entry, exit) = match mullvad_client. get_tunnel_state ( ) . await ? {
713
+ mullvad_types:: states:: TunnelState :: Connected { endpoint, .. } => {
714
+ ( endpoint. proxy . unwrap ( ) . endpoint , endpoint. endpoint )
715
+ }
716
+ actual => {
717
+ panic ! ( "unexpected tunnel state. Expected `TunnelState::Connected` but got {actual:?}" )
718
+ }
719
+ } ;
720
+
721
+ log:: info!(
722
+ "Selected entry bridge {entry_addr} & exit relay {exit_addr}" ,
723
+ entry_addr = entry. address,
724
+ exit_addr = exit. address
725
+ ) ;
726
+
727
+ // Start recording outgoing packets. Their destination will be verified
728
+ // against the bridge's IP address later.
729
+ let monitor = start_packet_monitor (
730
+ move |packet| packet. destination . ip ( ) == entry. address . ip ( ) ,
731
+ MonitorOptions :: default ( ) ,
732
+ )
733
+ . await ;
734
+
735
+ //
736
+ // Verify exit IP
737
+ //
738
+
739
+ log:: info!( "Verifying exit server" ) ;
740
+
741
+ assert ! (
742
+ helpers:: using_mullvad_exit( & rpc) . await ,
743
+ "expected Mullvad exit IP"
744
+ ) ;
745
+
746
+ //
747
+ // Verify entry IP
748
+ //
749
+
750
+ log:: info!( "Verifying entry server" ) ;
751
+
752
+ let monitor_result = monitor. into_result ( ) . await . unwrap ( ) ;
753
+ assert ! (
754
+ !monitor_result. packets. is_empty( ) ,
755
+ "detected no traffic to entry server" ,
756
+ ) ;
757
+
758
+ Ok ( ( ) )
759
+ }
0 commit comments