Files
clash-proxy/src-tauri/src/enhance/tun.rs
Sline 5db4677ff8 fix: linux tun timeout (#4993)
* fix: linux tun timeout

* docs: UPDATELOG.md
2025-10-09 15:09:17 +08:00

108 lines
3.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use serde_yaml_ng::{Mapping, Value};
#[cfg(target_os = "macos")]
use crate::process::AsyncHandler;
macro_rules! revise {
($map: expr, $key: expr, $val: expr) => {
let ret_key = Value::String($key.into());
$map.insert(ret_key, Value::from($val));
};
}
// if key not exists then append value
#[allow(unused_macros)]
macro_rules! append {
($map: expr, $key: expr, $val: expr) => {
let ret_key = Value::String($key.into());
if !$map.contains_key(&ret_key) {
$map.insert(ret_key, Value::from($val));
}
};
}
pub fn use_tun(mut config: Mapping, enable: bool) -> Mapping {
let tun_key = Value::from("tun");
let tun_val = config.get(&tun_key);
let mut tun_val = tun_val.map_or(Mapping::new(), |val| {
val.as_mapping().cloned().unwrap_or(Mapping::new())
});
if enable {
#[cfg(target_os = "linux")]
{
let stack_key = Value::from("stack");
let should_override = match tun_val.get(&stack_key) {
Some(value) => value
.as_str()
.map(|stack| stack.eq_ignore_ascii_case("gvisor"))
.unwrap_or(false),
None => true,
};
if should_override {
revise!(tun_val, "stack", "mixed");
log::warn!(
target: "app",
"gVisor TUN stack detected on Linux; falling back to 'mixed' for compatibility"
);
}
}
// 读取DNS配置
let dns_key = Value::from("dns");
let dns_val = config.get(&dns_key);
let mut dns_val = dns_val.map_or(Mapping::new(), |val| {
val.as_mapping().cloned().unwrap_or(Mapping::new())
});
let ipv6_key = Value::from("ipv6");
let ipv6_val = config
.get(&ipv6_key)
.and_then(|v| v.as_bool())
.unwrap_or(false);
// 检查现有的 enhanced-mode 设置
let current_mode = dns_val
.get(Value::from("enhanced-mode"))
.and_then(|v| v.as_str())
.unwrap_or("fake-ip");
// 只有当 enhanced-mode 是 fake-ip 或未设置时才修改 DNS 配置
if current_mode == "fake-ip" || !dns_val.contains_key(Value::from("enhanced-mode")) {
revise!(dns_val, "enable", true);
revise!(dns_val, "ipv6", ipv6_val);
if !dns_val.contains_key(Value::from("enhanced-mode")) {
revise!(dns_val, "enhanced-mode", "fake-ip");
}
if !dns_val.contains_key(Value::from("fake-ip-range")) {
revise!(dns_val, "fake-ip-range", "198.18.0.1/16");
}
#[cfg(target_os = "macos")]
{
AsyncHandler::spawn(move || async move {
crate::utils::resolve::dns::restore_public_dns().await;
crate::utils::resolve::dns::set_public_dns("223.6.6.6".to_string()).await;
});
}
}
// 当TUN启用时将修改后的DNS配置写回
revise!(config, "dns", dns_val);
} else {
// TUN未启用时仅恢复系统DNS不修改配置文件中的DNS设置
#[cfg(target_os = "macos")]
AsyncHandler::spawn(move || async move {
crate::utils::resolve::dns::restore_public_dns().await;
});
}
// 更新TUN配置
revise!(tun_val, "enable", enable);
revise!(config, "tun", tun_val);
config
}