diff --git a/Cargo.lock b/Cargo.lock index 57adb256c0..60dcfbd665 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2377,6 +2377,7 @@ dependencies = [ "hickory-resolver", "iroh-base", "iroh-metrics", + "iroh-quinn", "iroh-relay", "iroh-test 0.29.0", "netwatch", diff --git a/iroh-net-report/Cargo.toml b/iroh-net-report/Cargo.toml index d5b84c8599..78a20c7e9d 100644 --- a/iroh-net-report/Cargo.toml +++ b/iroh-net-report/Cargo.toml @@ -27,6 +27,7 @@ iroh-metrics = { version = "0.29.0", default-features = false } iroh-relay = { version = "0.29", path = "../iroh-relay" } netwatch = { version = "0.2.0" } portmapper = { version = "0.2.0", default-features = false } +quinn = { package = "iroh-quinn", version = "0.12.0" } rand = "0.8" reqwest = { version = "0.12", default-features = false } rustls = { version = "0.23", default-features = false } diff --git a/iroh-net-report/src/defaults.rs b/iroh-net-report/src/defaults.rs index 094697386d..ef26f4cdc6 100644 --- a/iroh-net-report/src/defaults.rs +++ b/iroh-net-report/src/defaults.rs @@ -1,9 +1,6 @@ //! Default values used in net_report. -/// The default STUN port used by the Relay server. -/// -/// The STUN port as defined by [RFC 8489]() -pub const DEFAULT_STUN_PORT: u16 = 3478; +pub(crate) use iroh_base::relay_map::{DEFAULT_RELAY_QUIC_PORT, DEFAULT_STUN_PORT}; /// Contains all timeouts that we use in `iroh-net-report`. pub(crate) mod timeouts { diff --git a/iroh-net-report/src/lib.rs b/iroh-net-report/src/lib.rs index 44cbb4b122..d0ac11379a 100644 --- a/iroh-net-report/src/lib.rs +++ b/iroh-net-report/src/lib.rs @@ -34,6 +34,7 @@ mod ping; mod reportgen; pub use metrics::Metrics; +pub use reportgen::QuicConfig; const FULL_REPORT_INTERVAL: Duration = Duration::from_secs(5 * 60); @@ -240,13 +241,23 @@ impl Client { /// /// If these are not passed in this will bind sockets for STUN itself, though results /// may not be as reliable. + /// + /// The *quic_config* takes a [`QuicConfig`], a combination of a QUIC endpoint and + /// a client configuration that can be use for verifying the relay server connection. + /// When available, the report will attempt to get an observed public address + /// using QUIC address discovery. + /// + /// When `None`, it will disable the QUIC address discovery probes. pub async fn get_report( &mut self, dm: RelayMap, stun_conn4: Option>, stun_conn6: Option>, + quic_config: Option, ) -> Result> { - let rx = self.get_report_channel(dm, stun_conn4, stun_conn6).await?; + let rx = self + .get_report_channel(dm, stun_conn4, stun_conn6, quic_config) + .await?; match rx.await { Ok(res) => res, Err(_) => Err(anyhow!("channel closed, actor awol")), @@ -259,6 +270,7 @@ impl Client { dm: RelayMap, stun_conn4: Option>, stun_conn6: Option>, + quic_config: Option, ) -> Result>>> { // TODO: consider if RelayMap should be made to easily clone? It seems expensive // right now. @@ -268,6 +280,7 @@ impl Client { relay_map: dm, stun_sock_v4: stun_conn4, stun_sock_v6: stun_conn6, + quic_config, response_tx: tx, }) .await?; @@ -307,6 +320,11 @@ pub(crate) enum Message { /// /// Like `stun_sock_v4` but for IPv6. stun_sock_v6: Option>, + /// Endpoint and client configuration to create a QUIC + /// connection to do QUIC address discovery. + /// + /// If not provided, will not do QUIC address discovery. + quic_config: Option, /// Channel to receive the response. response_tx: oneshot::Sender>>, }, @@ -446,9 +464,16 @@ impl Actor { relay_map, stun_sock_v4, stun_sock_v6, + quic_config, response_tx, } => { - self.handle_run_check(relay_map, stun_sock_v4, stun_sock_v6, response_tx); + self.handle_run_check( + relay_map, + stun_sock_v4, + stun_sock_v6, + quic_config, + response_tx, + ); } Message::ReportReady { report } => { self.handle_report_ready(report); @@ -476,6 +501,7 @@ impl Actor { relay_map: RelayMap, stun_sock_v4: Option>, stun_sock_v6: Option>, + quic_config: Option, response_tx: oneshot::Sender>>, ) { if self.current_report_run.is_some() { @@ -526,6 +552,7 @@ impl Actor { relay_map, stun_sock_v4, stun_sock_v6, + quic_config, self.dns_resolver.clone(), ); @@ -975,7 +1002,7 @@ mod tests { // Note that the ProbePlan will change with each iteration. for i in 0..5 { println!("--round {}", i); - let r = client.get_report(dm.clone(), None, None).await?; + let r = client.get_report(dm.clone(), None, None, None).await?; assert!(r.udp, "want UDP"); assert_eq!( @@ -1016,7 +1043,7 @@ mod tests { let resolver = crate::dns::tests::resolver(); let mut client = Client::new(None, resolver.clone())?; - let r = client.get_report(dm, None, None).await?; + let r = client.get_report(dm, None, None, None).await?; let mut r: Report = (*r).clone(); r.portmap_probe = None; @@ -1285,7 +1312,7 @@ mod tests { ) }; - let r = client.get_report(dm, Some(sock), None).await?; + let r = client.get_report(dm, Some(sock), None, None).await?; dbg!(&r); assert_eq!(r.hair_pinning, Some(true)); diff --git a/iroh-net-report/src/reportgen.rs b/iroh-net-report/src/reportgen.rs index 25847b5ce6..e43d6e523e 100644 --- a/iroh-net-report/src/reportgen.rs +++ b/iroh-net-report/src/reportgen.rs @@ -45,7 +45,7 @@ use url::Host; use crate::Metrics; use crate::{ self as net_report, - defaults::DEFAULT_STUN_PORT, + defaults::{DEFAULT_RELAY_QUIC_PORT, DEFAULT_STUN_PORT}, dns::ResolverExt, ping::{PingError, Pinger}, RelayMap, RelayNode, RelayUrl, Report, @@ -72,6 +72,7 @@ pub(super) struct Client { } impl Client { + #[allow(clippy::too_many_arguments)] /// Creates a new actor generating a single report. /// /// The actor starts running immediately and only generates a single report, after which @@ -83,6 +84,7 @@ impl Client { relay_map: RelayMap, stun_sock4: Option>, stun_sock6: Option>, + quic_config: Option, dns_resolver: DnsResolver, ) -> Self { let (msg_tx, msg_rx) = mpsc::channel(32); @@ -98,6 +100,7 @@ impl Client { relay_map, stun_sock4, stun_sock6, + quic_config, report: Report::default(), hairpin_actor: hairpin::Client::new(net_report, addr), outstanding_tasks: OutstandingTasks::default(), @@ -171,6 +174,8 @@ struct Actor { stun_sock4: Option>, /// Socket so send IPv6 STUN requests from. stun_sock6: Option>, + /// QUIC configuration to do QUIC address Discovery + quic_config: Option, // Internal state. /// The report being built. @@ -544,6 +549,7 @@ impl Actor { let reportstate = self.addr(); let stun_sock4 = self.stun_sock4.clone(); let stun_sock6 = self.stun_sock6.clone(); + let quic_config = self.quic_config.clone(); let relay_node = probe.node().clone(); let probe = probe.clone(); let net_report = self.net_report.clone(); @@ -555,6 +561,7 @@ impl Actor { reportstate, stun_sock4, stun_sock6, + quic_config, relay_node, probe.clone(), net_report, @@ -668,6 +675,15 @@ enum ProbeError { Error(anyhow::Error, Probe), } +/// Pieces needed to do QUIC address discovery. +#[derive(Debug, Clone)] +pub struct QuicConfig { + /// A QUIC Endpoint + pub ep: quinn::Endpoint, + /// A client config. + pub client_config: rustls::ClientConfig, +} + /// Executes a particular [`Probe`], including using a delayed start if needed. /// /// If *stun_sock4* and *stun_sock6* are `None` the STUN probes are disabled. @@ -676,6 +692,7 @@ async fn run_probe( reportstate: Addr, stun_sock4: Option>, stun_sock6: Option>, + quic_config: Option, relay_node: Arc, probe: Probe, net_report: net_report::Addr, @@ -762,6 +779,22 @@ async fn run_probe( } } } + + Probe::QuicIpv4 { ref node, .. } | Probe::QuicIpv6 { ref node, .. } => { + debug!("sending QUIC address discovery probe"); + let url = node.url.clone(); + match quic_config { + Some(quic_config) => { + run_quic_probe(quic_config, url, relay_addr, probe).await?; + } + None => { + return Err(ProbeError::AbortSet( + anyhow!("No QUIC endpoint for {}", probe.proto()), + probe.clone(), + )); + } + } + } } trace!("probe successful"); @@ -851,6 +884,44 @@ async fn run_stun_probe( } } +/// Run a QUIC address discovery probe. +async fn run_quic_probe( + quic_config: QuicConfig, + url: RelayUrl, + relay_addr: SocketAddr, + probe: Probe, +) -> Result { + match probe.proto() { + ProbeProto::QuicIpv4 => debug_assert!(relay_addr.is_ipv4()), + ProbeProto::QuicIpv6 => debug_assert!(relay_addr.is_ipv6()), + _ => debug_assert!(false, "wrong probe"), + } + let host = match url.host_str() { + Some(host) => host, + None => { + return Err(ProbeError::Error( + anyhow!("URL must have 'host' to use QUIC address discovery probes"), + probe.clone(), + )); + } + }; + let quic_client = iroh_relay::quic::QuicClient::new(quic_config.ep, quic_config.client_config) + .map_err(|e| ProbeError::Error(e, probe.clone()))?; + let (addr, latency) = quic_client + .get_addr_and_latency(relay_addr, host) + .await + .map_err(|e| ProbeError::Error(e, probe.clone()))?; + let mut result = ProbeReport::new(probe.clone()); + if matches!(probe, Probe::QuicIpv4 { .. }) { + result.ipv4_can_send = true; + } else { + result.ipv6_can_send = true; + } + result.addr = Some(addr); + result.latency = Some(latency); + Ok(result) +} + /// Reports whether or not we think the system is behind a /// captive portal, detected by making a request to a URL that we know should /// return a "204 No Content" response and checking if that's what we get. @@ -936,6 +1007,30 @@ async fn check_captive_portal( Ok(has_captive) } +/// Returns the proper port based on the protocol of the probe. +fn get_port(relay_node: &RelayNode, proto: &ProbeProto) -> Result { + match proto { + ProbeProto::QuicIpv4 | ProbeProto::QuicIpv6 => { + if let Some(ref quic) = relay_node.quic { + if quic.port == 0 { + Ok(DEFAULT_RELAY_QUIC_PORT) + } else { + Ok(quic.port) + } + } else { + bail!("Relay node not suitable for QUIC address discovery probes"); + } + } + _ => { + if relay_node.stun_port == 0 { + Ok(DEFAULT_STUN_PORT) + } else { + Ok(relay_node.stun_port) + } + } + } +} + /// Returns the IP address to use to communicate to this relay node. /// /// *proto* specifies the protocol of the probe. Depending on the protocol we may return @@ -946,50 +1041,49 @@ async fn get_relay_addr( relay_node: &RelayNode, proto: ProbeProto, ) -> Result { - let port = if relay_node.stun_port == 0 { - DEFAULT_STUN_PORT - } else { - relay_node.stun_port - }; - if relay_node.stun_only && !matches!(proto, ProbeProto::StunIpv4 | ProbeProto::StunIpv6) { bail!("Relay node not suitable for non-STUN probes"); } + let port = get_port(relay_node, &proto)?; match proto { - ProbeProto::StunIpv4 | ProbeProto::IcmpV4 => match relay_node.url.host() { - Some(url::Host::Domain(hostname)) => { - debug!(?proto, %hostname, "Performing DNS A lookup for relay addr"); - match dns_resolver.lookup_ipv4_staggered(hostname).await { - Ok(mut addrs) => addrs - .next() - .map(|ip| ip.to_canonical()) - .map(|addr| SocketAddr::new(addr, port)) - .ok_or(anyhow!("No suitable relay addr found")), - Err(err) => Err(err.context("No suitable relay addr found")), + ProbeProto::StunIpv4 | ProbeProto::IcmpV4 | ProbeProto::QuicIpv4 => { + match relay_node.url.host() { + Some(url::Host::Domain(hostname)) => { + debug!(?proto, %hostname, "Performing DNS A lookup for relay addr"); + match dns_resolver.lookup_ipv4_staggered(hostname).await { + Ok(mut addrs) => addrs + .next() + .map(|ip| ip.to_canonical()) + .map(|addr| SocketAddr::new(addr, port)) + .ok_or(anyhow!("No suitable relay addr found")), + Err(err) => Err(err.context("No suitable relay addr found")), + } } + Some(url::Host::Ipv4(addr)) => Ok(SocketAddr::new(addr.into(), port)), + Some(url::Host::Ipv6(_addr)) => Err(anyhow!("No suitable relay addr found")), + None => Err(anyhow!("No valid hostname in RelayUrl")), } - Some(url::Host::Ipv4(addr)) => Ok(SocketAddr::new(addr.into(), port)), - Some(url::Host::Ipv6(_addr)) => Err(anyhow!("No suitable relay addr found")), - None => Err(anyhow!("No valid hostname in RelayUrl")), - }, - - ProbeProto::StunIpv6 | ProbeProto::IcmpV6 => match relay_node.url.host() { - Some(url::Host::Domain(hostname)) => { - debug!(?proto, %hostname, "Performing DNS AAAA lookup for relay addr"); - match dns_resolver.lookup_ipv6_staggered(hostname).await { - Ok(mut addrs) => addrs - .next() - .map(|ip| ip.to_canonical()) - .map(|addr| SocketAddr::new(addr, port)) - .ok_or(anyhow!("No suitable relay addr found")), - Err(err) => Err(err.context("No suitable relay addr found")), + } + + ProbeProto::StunIpv6 | ProbeProto::IcmpV6 | ProbeProto::QuicIpv6 => { + match relay_node.url.host() { + Some(url::Host::Domain(hostname)) => { + debug!(?proto, %hostname, "Performing DNS AAAA lookup for relay addr"); + match dns_resolver.lookup_ipv6_staggered(hostname).await { + Ok(mut addrs) => addrs + .next() + .map(|ip| ip.to_canonical()) + .map(|addr| SocketAddr::new(addr, port)) + .ok_or(anyhow!("No suitable relay addr found")), + Err(err) => Err(err.context("No suitable relay addr found")), + } } + Some(url::Host::Ipv4(_addr)) => Err(anyhow!("No suitable relay addr found")), + Some(url::Host::Ipv6(addr)) => Ok(SocketAddr::new(addr.into(), port)), + None => Err(anyhow!("No valid hostname in RelayUrl")), } - Some(url::Host::Ipv4(_addr)) => Err(anyhow!("No suitable relay addr found")), - Some(url::Host::Ipv6(addr)) => Ok(SocketAddr::new(addr.into(), port)), - None => Err(anyhow!("No valid hostname in RelayUrl")), - }, + } ProbeProto::Https => Err(anyhow!("Not implemented")), } @@ -1114,7 +1208,10 @@ fn update_report(report: &mut Report, probe_report: ProbeReport) { if matches!( probe_report.probe.proto(), - ProbeProto::StunIpv4 | ProbeProto::StunIpv6 + ProbeProto::StunIpv4 + | ProbeProto::StunIpv6 + | ProbeProto::QuicIpv4 + | ProbeProto::QuicIpv6 ) { report.udp = true; @@ -1464,4 +1561,43 @@ mod tests { assert_eq!(ip, relay_url_ip); Ok(()) } + + #[tokio::test] + async fn test_quic_probe() -> TestResult { + let _logging_guard = iroh_test::logging::setup(); + let (server, relay) = test_utils::relay().await; + let client_config = iroh_relay::client::make_dangerous_client_config(); + let ep = quinn::Endpoint::client(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0))?; + let client_addr = ep.local_addr()?; + let quic_addr_disc = QuicConfig { + ep: ep.clone(), + client_config, + }; + let url = relay.url.clone(); + let port = server.quic_addr().unwrap().port(); + let probe = Probe::QuicIpv4 { + delay: Duration::from_secs(0), + node: relay.clone(), + }; + let probe = match run_quic_probe( + quic_addr_disc, + url, + (Ipv4Addr::LOCALHOST, port).into(), + probe, + ) + .await + { + Ok(probe) => probe, + Err(e) => match e { + ProbeError::AbortSet(err, _) | ProbeError::Error(err, _) => { + return Err(err.into()); + } + }, + }; + assert!(probe.ipv4_can_send); + assert_eq!(probe.addr.unwrap(), client_addr); + ep.wait_idle().await; + server.shutdown().await?; + Ok(()) + } } diff --git a/iroh-net-report/src/reportgen/probes.rs b/iroh-net-report/src/reportgen/probes.rs index 08bbe1163b..241ad62771 100644 --- a/iroh-net-report/src/reportgen/probes.rs +++ b/iroh-net-report/src/reportgen/probes.rs @@ -54,6 +54,10 @@ pub(super) enum ProbeProto { IcmpV4, /// ICMP IPv6 IcmpV6, + /// QUIC Address Discovery Ipv4 + QuicIpv4, + /// QUIC Address Discovery Ipv6 + QuicIpv6, } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, derive_more::Display)] @@ -88,6 +92,16 @@ pub(super) enum Probe { delay: Duration, node: Arc, }, + #[display("QAD Ipv4 after {delay:?} to {node}")] + QuicIpv4 { + delay: Duration, + node: Arc, + }, + #[display("QAD Ipv6 after {delay:?} to {node}")] + QuicIpv6 { + delay: Duration, + node: Arc, + }, } impl Probe { @@ -97,7 +111,9 @@ impl Probe { | Probe::StunIpv6 { delay, .. } | Probe::Https { delay, .. } | Probe::IcmpV4 { delay, .. } - | Probe::IcmpV6 { delay, .. } => *delay, + | Probe::IcmpV6 { delay, .. } + | Probe::QuicIpv4 { delay, .. } + | Probe::QuicIpv6 { delay, .. } => *delay, } } @@ -108,6 +124,8 @@ impl Probe { Probe::Https { .. } => ProbeProto::Https, Probe::IcmpV4 { .. } => ProbeProto::IcmpV4, Probe::IcmpV6 { .. } => ProbeProto::IcmpV6, + Probe::QuicIpv4 { .. } => ProbeProto::QuicIpv4, + Probe::QuicIpv6 { .. } => ProbeProto::QuicIpv6, } } @@ -117,7 +135,9 @@ impl Probe { | Probe::StunIpv6 { node, .. } | Probe::Https { node, .. } | Probe::IcmpV4 { node, .. } - | Probe::IcmpV6 { node, .. } => node, + | Probe::IcmpV6 { node, .. } + | Probe::QuicIpv4 { node, .. } + | Probe::QuicIpv6 { node, .. } => node, } } } @@ -206,6 +226,8 @@ impl ProbePlan { for relay_node in relay_map.nodes() { let mut stun_ipv4_probes = ProbeSet::new(ProbeProto::StunIpv4); let mut stun_ipv6_probes = ProbeSet::new(ProbeProto::StunIpv6); + let mut quic_ipv4_probes = ProbeSet::new(ProbeProto::QuicIpv4); + let mut quic_ipv6_probes = ProbeSet::new(ProbeProto::QuicIpv6); for attempt in 0..3 { let delay = DEFAULT_INITIAL_RETRANSMIT * attempt as u32; @@ -217,6 +239,12 @@ impl ProbePlan { node: relay_node.clone(), }) .expect("adding StunIpv4 probe to a StunIpv4 probe set"); + quic_ipv4_probes + .push(Probe::QuicIpv4 { + delay, + node: relay_node.clone(), + }) + .expect("adding QuicIpv4 probe to a QuicIpv4 probe set"); } if if_state.have_v6 { stun_ipv6_probes @@ -226,9 +254,17 @@ impl ProbePlan { }) .expect("adding StunIpv6 probe to a StunIpv6 probe set"); } + quic_ipv6_probes + .push(Probe::QuicIpv6 { + delay, + node: relay_node.clone(), + }) + .expect("adding QuicIpv6 probe to a QuicAddrIpv6 probe set"); } plan.add(stun_ipv4_probes); plan.add(stun_ipv6_probes); + plan.add(quic_ipv4_probes); + plan.add(quic_ipv6_probes); // The HTTP and ICMP probes only start after the STUN probes have had a chance. let mut https_probes = ProbeSet::new(ProbeProto::Https); @@ -327,6 +363,8 @@ impl ProbePlan { let mut stun_ipv4_probes = ProbeSet::new(ProbeProto::StunIpv4); let mut stun_ipv6_probes = ProbeSet::new(ProbeProto::StunIpv6); + let mut quic_ipv4_probes = ProbeSet::new(ProbeProto::QuicIpv4); + let mut quic_ipv6_probes = ProbeSet::new(ProbeProto::QuicIpv6); for attempt in 0..attempts { let delay = (retransmit_delay * attempt as u32) @@ -338,6 +376,12 @@ impl ProbePlan { node: relay_node.clone(), }) .expect("Pushing StunIpv4 Probe to StunIpv4 ProbeSet"); + quic_ipv4_probes + .push(Probe::QuicIpv4 { + delay, + node: relay_node.clone(), + }) + .expect("adding QuicIpv4 probe to a QuicAddrIpv4 probe set"); } if do6 { stun_ipv6_probes @@ -346,10 +390,18 @@ impl ProbePlan { node: relay_node.clone(), }) .expect("Pushing StunIpv6 Probe to StunIpv6 ProbeSet"); + quic_ipv6_probes + .push(Probe::QuicIpv6 { + delay, + node: relay_node.clone(), + }) + .expect("adding QuicIpv6 probe to a QuicAddrIpv6 probe set"); } } plan.add(stun_ipv4_probes); plan.add(stun_ipv6_probes); + plan.add(quic_ipv4_probes); + plan.add(quic_ipv6_probes); // The HTTP and ICMP probes only start after the STUN probes have had a chance. let mut https_probes = ProbeSet::new(ProbeProto::Https); @@ -518,6 +570,20 @@ mod tests { Duration::from_millis(100), Duration::from_millis(200)], }, + probeset! { + proto: ProbeProto::QuicIpv4, + relay: relay_node_1.clone(), + delays: [Duration::ZERO, + Duration::from_millis(100), + Duration::from_millis(200)], + }, + probeset! { + proto: ProbeProto::QuicIpv6, + relay: relay_node_1.clone(), + delays: [Duration::ZERO, + Duration::from_millis(100), + Duration::from_millis(200)], + }, probeset! { proto: ProbeProto::Https, relay: relay_node_1.clone(), @@ -553,6 +619,20 @@ mod tests { Duration::from_millis(100), Duration::from_millis(200)], }, + probeset! { + proto: ProbeProto::QuicIpv4, + relay: relay_node_2.clone(), + delays: [Duration::ZERO, + Duration::from_millis(100), + Duration::from_millis(200)], + }, + probeset! { + proto: ProbeProto::QuicIpv6, + relay: relay_node_2.clone(), + delays: [Duration::ZERO, + Duration::from_millis(100), + Duration::from_millis(200)], + }, probeset! { proto: ProbeProto::Https, relay: relay_node_2.clone(), @@ -640,6 +720,22 @@ mod tests { Duration::from_micros(104_800), Duration::from_micros(157_200)], }, + probeset! { + proto: ProbeProto::QuicIpv4, + relay: relay_node_1.clone(), + delays: [Duration::ZERO, + Duration::from_micros(52_400), + Duration::from_micros(104_800), + Duration::from_micros(157_200)], + }, + probeset! { + proto: ProbeProto::QuicIpv6, + relay: relay_node_1.clone(), + delays: [Duration::ZERO, + Duration::from_micros(52_400), + Duration::from_micros(104_800), + Duration::from_micros(157_200)], + }, probeset! { proto: ProbeProto::Https, relay: relay_node_1.clone(), @@ -676,6 +772,18 @@ mod tests { delays: [Duration::ZERO, Duration::from_micros(52_400)], }, + probeset! { + proto: ProbeProto::QuicIpv4, + relay: relay_node_2.clone(), + delays: [Duration::ZERO, + Duration::from_micros(52_400)], + }, + probeset! { + proto: ProbeProto::QuicIpv6, + relay: relay_node_2.clone(), + delays: [Duration::ZERO, + Duration::from_micros(52_400)], + }, probeset! { proto: ProbeProto::Https, relay: relay_node_2.clone(), diff --git a/iroh-relay/src/client.rs b/iroh-relay/src/client.rs index beb9819a7f..3c8ecc2fe4 100644 --- a/iroh-relay/src/client.rs +++ b/iroh-relay/src/client.rs @@ -345,11 +345,11 @@ impl ClientBuilder { } } -#[cfg(test)] +#[cfg(any(test, feature = "test-utils"))] /// Creates a client config that trusts any servers without verifying their TLS certificate. /// /// Should be used for testing local relay setups only. -pub(crate) fn make_dangerous_client_config() -> rustls::ClientConfig { +pub fn make_dangerous_client_config() -> rustls::ClientConfig { warn!( "Insecure config: SSL certificates from relay servers will be trusted without verification" ); diff --git a/iroh-relay/src/server/testing.rs b/iroh-relay/src/server/testing.rs index 4e95ceeec6..ee4fa46e4d 100644 --- a/iroh-relay/src/server/testing.rs +++ b/iroh-relay/src/server/testing.rs @@ -1,5 +1,5 @@ //! Exposes functions to quickly configure a server suitable for testing. -use std::net::{Ipv4Addr, Ipv6Addr}; +use std::net::Ipv4Addr; use super::{CertConfig, QuicConfig, RelayConfig, ServerConfig, StunConfig, TlsConfig}; @@ -71,12 +71,12 @@ pub fn relay_config() -> RelayConfig<()> { /// Creates a [`QuicConfig`] suitable for testing. /// -/// - Binds to an OS assigned port on ipv6 and ipv4, if dual stack is enabled. +/// - Binds to an OS assigned port on ipv4 /// - Uses [`self_signed_tls_certs_and_config`] to create tls certificates pub fn quic_config() -> QuicConfig { let (_, server_config) = self_signed_tls_certs_and_config(); QuicConfig { - bind_addr: (Ipv6Addr::UNSPECIFIED, 0).into(), + bind_addr: (Ipv4Addr::UNSPECIFIED, 0).into(), server_config, } } diff --git a/iroh/src/magicsock.rs b/iroh/src/magicsock.rs index cd4c3067f2..92b4c5eb7c 100644 --- a/iroh/src/magicsock.rs +++ b/iroh/src/magicsock.rs @@ -2336,10 +2336,12 @@ impl Actor { let pconn4 = Some(self.pconn4.clone()); let pconn6 = self.pconn6.clone(); + let quic_config = None; + debug!("requesting net_report report"); match self .net_reporter - .get_report_channel(relay_map, pconn4, pconn6) + .get_report_channel(relay_map, pconn4, pconn6, quic_config) .await { Ok(rx) => {