mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-24 04:32:07 +08:00
fix: report legacy TLS subscription failures
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
### 🐞 修复问题
|
||||
|
||||
- macOS 托盘速率可能的样式错误
|
||||
- 订阅导入 TLS 1.0/1.1 等过旧协议时显示更明确错误原因
|
||||
|
||||
<details>
|
||||
<summary><strong> ✨ 新增功能 </strong></summary>
|
||||
|
||||
@@ -24,6 +24,14 @@ use std::time::Duration;
|
||||
|
||||
static CURRENT_SWITCHING_PROFILE: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
fn profile_import_error(err: &anyhow::Error) -> std::string::String {
|
||||
if let Some(cause) = err.chain().find(|cause| cause.to_string().contains("TLS 1.0/1.1")) {
|
||||
return cause.to_string();
|
||||
}
|
||||
|
||||
format!("导入订阅失败: {err:#}")
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_profiles() -> CmdResult<SharedDraft<IProfiles>> {
|
||||
logging!(debug, Type::Cmd, "获取配置文件列表");
|
||||
@@ -70,7 +78,7 @@ pub async fn import_profile(url: std::string::String, option: Option<PrfOption>)
|
||||
}
|
||||
Err(e) => {
|
||||
logging!(error, Type::Cmd, "[导入订阅] 下载失败: {}", e);
|
||||
return Err(format!("导入订阅失败: {}", e).into());
|
||||
return Err(profile_import_error(&e).into());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ impl PrfItem {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
bail!("failed to fetch remote profile: {}", e);
|
||||
return Err(e).context("failed to fetch remote profile");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -121,6 +121,10 @@ impl NetworkManager {
|
||||
}
|
||||
|
||||
fn should_retry_with_static_webpki_roots(err: &anyhow::Error) -> bool {
|
||||
if err.chain().any(Self::is_legacy_tls_protocol_error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
err.chain().any(|e| {
|
||||
let msg = e.to_string().to_ascii_lowercase();
|
||||
[
|
||||
@@ -141,6 +145,22 @@ impl NetworkManager {
|
||||
})
|
||||
}
|
||||
|
||||
fn context_reqwest_error(err: reqwest::Error, context: &'static str) -> anyhow::Error {
|
||||
let legacy_tls = Self::is_legacy_tls_protocol_error(&err);
|
||||
let err = anyhow::Error::new(err).context(context);
|
||||
|
||||
if legacy_tls {
|
||||
err.context("Subscription server uses legacy TLS; only TLS 1.2/1.3 is supported. TLS 1.0/1.1 is insecure")
|
||||
} else {
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
fn is_legacy_tls_protocol_error(err: &(dyn std::error::Error + 'static)) -> bool {
|
||||
let detail = format!("{err:#?}").to_ascii_lowercase();
|
||||
detail.contains("protocolversion") || detail.contains("protocol version")
|
||||
}
|
||||
|
||||
pub async fn create_request(
|
||||
&self,
|
||||
proxy_type: ProxyType,
|
||||
@@ -207,7 +227,7 @@ impl NetworkManager {
|
||||
let response = match request_builder.send().await {
|
||||
Ok(resp) => resp,
|
||||
Err(e) => {
|
||||
return Err(anyhow::Error::new(e).context("Request failed"));
|
||||
return Err(Self::context_reqwest_error(e, "Request failed"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -216,7 +236,7 @@ impl NetworkManager {
|
||||
let body = match response.text().await {
|
||||
Ok(text) => text.into(),
|
||||
Err(e) => {
|
||||
return Err(anyhow::anyhow!("Failed to read response body: {}", e));
|
||||
return Err(Self::context_reqwest_error(e, "Failed to read response body"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -299,9 +319,7 @@ impl NetworkManager {
|
||||
)
|
||||
.await
|
||||
.map_err(|fallback_err| {
|
||||
anyhow::anyhow!(
|
||||
"platform TLS verifier failed: {err}; static webpki roots fallback failed: {fallback_err}"
|
||||
)
|
||||
fallback_err.context("static webpki roots fallback failed after platform TLS verifier failed")
|
||||
}),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
|
||||
@@ -292,7 +292,6 @@ const ProfilePage = () => {
|
||||
setUrl('')
|
||||
await performRobustRefresh()
|
||||
}
|
||||
|
||||
try {
|
||||
// 尝试正常导入
|
||||
await importProfile(url)
|
||||
@@ -300,6 +299,11 @@ const ProfilePage = () => {
|
||||
} catch (initialErr) {
|
||||
console.warn('[订阅导入] 首次导入失败:', initialErr)
|
||||
|
||||
if (String(initialErr).toLowerCase().includes('legacy tls')) {
|
||||
showNotice.error(String(initialErr))
|
||||
return
|
||||
}
|
||||
|
||||
showNotice.info('profiles.page.feedback.notifications.importRetry')
|
||||
try {
|
||||
// 使用自身代理尝试导入
|
||||
|
||||
Reference in New Issue
Block a user