mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-07-25 05:40:50 +02:00
fix: properly handle location spoofing for socks5 proxies
This commit is contained in:
+34
-17
@@ -28,7 +28,9 @@ pub async fn fetch_public_ip(proxy: Option<&str>) -> Result<String, IpError> {
|
||||
"https://ipecho.net/plain",
|
||||
];
|
||||
|
||||
let client_builder = reqwest::Client::builder().timeout(std::time::Duration::from_secs(5));
|
||||
// 10s rather than 5s: residential proxies that allocate an exit on first
|
||||
// connect routinely need more than 5s for the initial request.
|
||||
let client_builder = reqwest::Client::builder().timeout(std::time::Duration::from_secs(10));
|
||||
|
||||
let client = if let Some(proxy_url) = proxy {
|
||||
let proxy = reqwest::Proxy::all(proxy_url)
|
||||
@@ -46,25 +48,40 @@ pub async fn fetch_public_ip(proxy: Option<&str>) -> Result<String, IpError> {
|
||||
|
||||
let mut errors = Vec::new();
|
||||
|
||||
// Overall deadline across all endpoints. Without it, a proxy that accepts
|
||||
// connections but stalls holds callers for the full 6 x 10s; slow-but-live
|
||||
// proxies still get the whole 10s on the endpoints that fit the budget.
|
||||
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(30);
|
||||
|
||||
for url in &urls {
|
||||
match client.get(*url).send().await {
|
||||
Ok(response) if response.status().is_success() => match response.text().await {
|
||||
Ok(text) => {
|
||||
let ip = text.trim().to_string();
|
||||
if validate_ip(&ip) {
|
||||
return Ok(ip);
|
||||
let remaining = deadline.saturating_duration_since(std::time::Instant::now());
|
||||
if remaining.is_zero() {
|
||||
errors.push(format!("{}: skipped (30s overall deadline reached)", url));
|
||||
continue;
|
||||
}
|
||||
|
||||
let attempt = async {
|
||||
match client.get(*url).send().await {
|
||||
Ok(response) if response.status().is_success() => match response.text().await {
|
||||
Ok(text) => {
|
||||
let ip = text.trim().to_string();
|
||||
if validate_ip(&ip) {
|
||||
Ok(ip)
|
||||
} else {
|
||||
Err(format!("{}: response is not an IP address", url))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
errors.push(format!("{}: {}", url, e));
|
||||
}
|
||||
},
|
||||
Ok(response) => {
|
||||
errors.push(format!("{}: HTTP {}", url, response.status()));
|
||||
}
|
||||
Err(e) => {
|
||||
errors.push(format!("{}: {}", url, e));
|
||||
Err(e) => Err(format!("{}: {}", url, e)),
|
||||
},
|
||||
Ok(response) => Err(format!("{}: HTTP {}", url, response.status())),
|
||||
Err(e) => Err(format!("{}: {}", url, e)),
|
||||
}
|
||||
};
|
||||
|
||||
match tokio::time::timeout(remaining, attempt).await {
|
||||
Ok(Ok(ip)) => return Ok(ip),
|
||||
Ok(Err(e)) => errors.push(e),
|
||||
Err(_) => errors.push(format!("{}: timed out (30s overall deadline reached)", url)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user