diff --git a/src/client/legacy/connect/http.rs b/src/client/legacy/connect/http.rs index 3d19babb..41c34519 100644 --- a/src/client/legacy/connect/http.rs +++ b/src/client/legacy/connect/http.rs @@ -529,7 +529,7 @@ where let config = &self.config; let (host, port) = get_host_port(config, &dst)?; - let host = host.trim_start_matches('[').trim_end_matches(']'); + let host = crate::client::strip_ipv6_brackets(host); // If the host is already an IP addr (v4 or v6), // skip resolving the dns and start connecting right away. diff --git a/src/client/legacy/connect/proxy/socks/v4/mod.rs b/src/client/legacy/connect/proxy/socks/v4/mod.rs index 610d09be..ede1ce0f 100644 --- a/src/client/legacy/connect/proxy/socks/v4/mod.rs +++ b/src/client/legacy/connect/proxy/socks/v4/mod.rs @@ -138,11 +138,7 @@ where // Whilst SOCKSv4 does not support IPv6, this bracket stripping will enable an IPv6 // destination to be correctly rejected down the line. Without it, we would end up with // a DNS resolution failure which would be confusing. - let host = host_from_uri - .strip_prefix('[') - .and_then(|s| s.strip_suffix(']')) - .unwrap_or(host_from_uri) - .to_string(); + let host = crate::client::strip_ipv6_brackets(host_from_uri).to_string(); let conn = connecting.await.map_err(SocksError::Inner)?; config.execute(conn, host, port).await diff --git a/src/client/legacy/connect/proxy/socks/v5/mod.rs b/src/client/legacy/connect/proxy/socks/v5/mod.rs index cbf88de3..d1c6f229 100644 --- a/src/client/legacy/connect/proxy/socks/v5/mod.rs +++ b/src/client/legacy/connect/proxy/socks/v5/mod.rs @@ -265,11 +265,7 @@ where // Note: host() returns the host part of the URI which could be a square bracketed IPv6 // address. We need to remove any brackets to make it a valid IP address. - let host = host_from_uri - .strip_prefix('[') - .and_then(|s| s.strip_suffix(']')) - .unwrap_or(host_from_uri) - .to_string(); + let host = crate::client::strip_ipv6_brackets(host_from_uri).to_string(); let conn = connecting.await.map_err(SocksError::Inner)?; config.execute(conn, host, port).await diff --git a/src/client/mod.rs b/src/client/mod.rs index 268cadf0..9e3ee139 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -9,3 +9,24 @@ pub mod pool; #[cfg(feature = "client-proxy")] pub mod proxy; + +#[cfg(any(feature = "client-legacy", feature = "client-proxy"))] +fn strip_ipv6_brackets(host: &str) -> &str { + host.strip_prefix('[') + .and_then(|host| host.strip_suffix(']')) + .unwrap_or(host) +} + +#[cfg(all(test, any(feature = "client-legacy", feature = "client-proxy")))] +mod tests { + use super::strip_ipv6_brackets; + + #[test] + fn test_strip_ipv6_brackets() { + assert_eq!(strip_ipv6_brackets("[::1]"), "::1"); + assert_eq!(strip_ipv6_brackets("::1"), "::1"); + assert_eq!(strip_ipv6_brackets("example.com"), "example.com"); + assert_eq!(strip_ipv6_brackets("[example.com"), "[example.com"); + assert_eq!(strip_ipv6_brackets("example.com]"), "example.com]"); + } +} diff --git a/src/client/proxy/matcher.rs b/src/client/proxy/matcher.rs index b91b7aa9..d0b71981 100644 --- a/src/client/proxy/matcher.rs +++ b/src/client/proxy/matcher.rs @@ -470,12 +470,7 @@ impl NoProxy { pub fn contains(&self, host: &str) -> bool { // According to RFC3986, raw IPv6 hosts will be wrapped in []. So we need to strip those off // the end in order to parse correctly - let host = if host.starts_with('[') { - let x: &[_] = &['[', ']']; - host.trim_matches(x) - } else { - host - }; + let host = crate::client::strip_ipv6_brackets(host); match host.parse::() { // If we can parse an IP addr, then use it, otherwise, assume it is a domain Ok(ip) => self.ips.contains(ip),