@@ -128,6 +128,15 @@ impl CredentialArgs {
128128 }
129129}
130130
131+ #[ derive( Args ) ]
132+ pub struct Socks5Args {
133+ #[ arg( long, default_value_t = 45 ) ]
134+ mixnet_client_timeout_sec : u64 ,
135+
136+ #[ arg( long, default_value_t = 10 ) ]
137+ test_count : u64 ,
138+ }
139+
131140#[ derive( Default , Debug ) ]
132141pub enum TestedNode {
133142 #[ default]
@@ -167,6 +176,7 @@ pub struct Probe {
167176 amnezia_args : String ,
168177 netstack_args : NetstackArgs ,
169178 credentials_args : CredentialArgs ,
179+ socks5_args : Socks5Args ,
170180}
171181
172182impl Probe {
@@ -175,13 +185,15 @@ impl Probe {
175185 tested_node : TestedNode ,
176186 netstack_args : NetstackArgs ,
177187 credentials_args : CredentialArgs ,
188+ socks5_args : Socks5Args ,
178189 ) -> Self {
179190 Self {
180191 entrypoint,
181192 tested_node,
182193 amnezia_args : "" . into ( ) ,
183194 netstack_args,
184195 credentials_args,
196+ socks5_args,
185197 }
186198 }
187199 pub fn with_amnezia ( & mut self , args : & str ) -> & Self {
@@ -197,7 +209,7 @@ impl Probe {
197209 ) -> anyhow:: Result < ProbeResult > {
198210 let exit_gateway = match gateway_key {
199211 Some ( gateway_key) => NodeIdentity :: from_base58_string ( gateway_key) ?,
200- None => directory. random_exit_with_ipr ( ) ?,
212+ None => directory. random_exit_with_nr ( ) ?,
201213 } ;
202214 info ! ( "Testing SOCKS5 only on exit gateway {}" , exit_gateway) ;
203215 let node_info = directory
@@ -206,7 +218,15 @@ impl Probe {
206218
207219 let socks5_outcome = {
208220 if let Some ( ref nr_details) = node_info. network_requester_details {
209- match do_socks5_connectivity_test ( & nr_details. address , network_details) . await {
221+ match do_socks5_connectivity_test (
222+ & nr_details. address ,
223+ network_details,
224+ directory,
225+ self . socks5_args . mixnet_client_timeout_sec ,
226+ self . socks5_args . test_count ,
227+ )
228+ . await
229+ {
210230 Ok ( results) => Some ( results) ,
211231 Err ( e) => {
212232 error ! ( "SOCKS5 test failed: {}" , e) ;
@@ -274,6 +294,7 @@ impl Probe {
274294 nyxd_url,
275295 tested_entry,
276296 only_wireguard,
297+ directory,
277298 )
278299 . await
279300 }
@@ -354,6 +375,7 @@ impl Probe {
354375 nyxd_url,
355376 tested_entry,
356377 only_wireguard,
378+ directory,
357379 )
358380 . await
359381 }
@@ -410,6 +432,7 @@ impl Probe {
410432 nyxd_url : Url ,
411433 tested_entry : bool ,
412434 only_wireguard : bool ,
435+ directory : NymApiDirectory ,
413436 ) -> anyhow:: Result < ProbeResult >
414437 where
415438 T : MixnetClientStorage + Clone + ' static ,
@@ -532,6 +555,9 @@ impl Probe {
532555 match do_socks5_connectivity_test (
533556 & nr_details. address ,
534557 NymNetworkDetails :: new_from_env ( ) ,
558+ directory,
559+ self . socks5_args . mixnet_client_timeout_sec ,
560+ self . socks5_args . test_count ,
535561 )
536562 . await
537563 {
@@ -849,14 +875,15 @@ async fn do_ping_exit(
849875 listen_for_icmp_ping_replies ( mixnet_client, our_ips) . await
850876}
851877
852- const TEST_REPEAT_COUNT : usize = 10 ;
853-
854878/// Creates a SOCKS5 proxy connection through the mixnet to the exit GW
855879/// and performs necessary tests.
856880#[ instrument( level = "info" , name = "socks5_test" , skip_all) ]
857881async fn do_socks5_connectivity_test (
858882 network_requester_address : & str ,
859883 network_details : NymNetworkDetails ,
884+ directory : NymApiDirectory ,
885+ mixnet_client_timeout : u64 ,
886+ test_run_count : u64 ,
860887) -> anyhow:: Result < Socks5ProbeResults > {
861888 info ! (
862889 "Starting SOCKS5 test through Network Requester: {}" ,
@@ -866,7 +893,7 @@ async fn do_socks5_connectivity_test(
866893 let mut results = Socks5ProbeResults :: default ( ) ;
867894
868895 // parse the network requester address
869- let _nr_recipient = match network_requester_address. parse :: < Recipient > ( ) {
896+ let nr_recipient = match network_requester_address. parse :: < Recipient > ( ) {
870897 Ok ( addr) => addr,
871898 Err ( e) => {
872899 error ! ( "Invalid Network Requester address: {}" , e) ;
@@ -876,19 +903,58 @@ async fn do_socks5_connectivity_test(
876903 }
877904 } ;
878905
906+ info ! (
907+ "Network Requester gateway: {}" ,
908+ nr_recipient. gateway( ) . to_base58_string( )
909+ ) ;
910+ info ! (
911+ "Network Requester identity: {}" ,
912+ nr_recipient. identity( ) . to_base58_string( )
913+ ) ;
914+
879915 // create ephemeral SOCKS5 client
880916 let socks5_config = Socks5 :: new ( network_requester_address. to_string ( ) ) ;
881917
882- // mainnet
918+ // Create debug config similar to main probe
919+ let mut debug_config = nym_client_core:: config:: DebugConfig :: default ( ) ;
920+ debug_config
921+ . traffic
922+ . disable_main_poisson_packet_distribution = true ;
923+ debug_config. cover_traffic . disable_loop_cover_traffic_stream = true ;
924+ debug_config. topology . ignore_egress_epoch_role = true ;
925+ // since we define both entry & exit gateways to be the same tested GW,
926+ // this shouldn't negatively affect mixnet layers but it will force route
927+ // construction in case GW would get filtered out on topology refresh
928+ debug_config. topology . minimum_gateway_performance = 0 ;
929+
930+ // Verify the NR gateway exists in the directory with exit_nr role
931+ let nr_gateway_id = nr_recipient. gateway ( ) ;
932+ if let Err ( e) = directory. exit_gateway_nr ( & nr_gateway_id) {
933+ results. https_connectivity = HttpsConnectivityResult :: with_error ( e. to_string ( ) ) ;
934+ return Ok ( results) ;
935+ } else {
936+ info ! ( "✔️ Network Requester gateway found in directory with exit_nr role" ) ;
937+ }
938+
939+ // use intended exit as entry as well
940+ let entry_gateway = nr_gateway_id;
941+
883942 let socks5_client_builder = MixnetClientBuilder :: new_ephemeral ( )
943+ // Specify entry gateway explicitly
944+ . request_gateway ( entry_gateway. to_base58_string ( ) )
884945 . socks5_config ( socks5_config)
885946 . network_details ( network_details)
947+ . debug_config ( debug_config)
886948 . build ( ) ?;
887949
888950 // connect to mixnet via SOCKS5
889951 let socks5_client = match socks5_client_builder. connect_to_mixnet_via_socks5 ( ) . await {
890952 Ok ( client) => {
891953 info ! ( "Successfully established SOCKS5 proxy connection" ) ;
954+ info ! (
955+ "Connected via entry gateway: {}" ,
956+ client. nym_address( ) . gateway( ) . to_base58_string( )
957+ ) ;
892958 results. can_connect_socks5 = true ;
893959 client
894960 }
@@ -900,7 +966,10 @@ async fn do_socks5_connectivity_test(
900966 }
901967 } ;
902968
903- let test = HttpsConnectivityTest :: new ( TEST_REPEAT_COUNT ) ;
969+ info ! ( "Waiting for network topology to be ready..." ) ;
970+ tokio:: time:: sleep ( Duration :: from_secs ( 10 ) ) . await ;
971+
972+ let test = HttpsConnectivityTest :: new ( test_run_count, mixnet_client_timeout) ;
904973 results. https_connectivity = test. run_tests ( socks5_client. socks5_url ( ) ) . await ;
905974
906975 // cleanup
0 commit comments