mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 00:35:38 +08:00
refactor: restructure DNS setting logic
This commit is contained in:
@@ -77,3 +77,142 @@ pub async fn clash_api_get_proxy_delay(
|
||||
pub async fn test_delay(url: String) -> CmdResult<u32> {
|
||||
Ok(feat::test_delay(url).await.unwrap_or(10000u32))
|
||||
}
|
||||
|
||||
/// 保存DNS配置到单独文件
|
||||
#[tauri::command]
|
||||
pub async fn save_dns_config(dns_config: Mapping) -> CmdResult {
|
||||
use crate::utils::dirs;
|
||||
use serde_yaml;
|
||||
use std::fs;
|
||||
|
||||
// 获取DNS配置文件路径
|
||||
let dns_path = dirs::app_home_dir().map_err(|e| e.to_string())?
|
||||
.join("dns_config.yaml");
|
||||
|
||||
// 保存DNS配置到文件
|
||||
let yaml_str = serde_yaml::to_string(&dns_config).map_err(|e| e.to_string())?;
|
||||
fs::write(&dns_path, yaml_str).map_err(|e| e.to_string())?;
|
||||
log::info!(target: "app", "DNS config saved to {:?}", dns_path);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 应用或撤销DNS配置
|
||||
#[tauri::command]
|
||||
pub fn apply_dns_config(apply: bool) -> CmdResult {
|
||||
use crate::utils::dirs;
|
||||
use crate::core::{handle, CoreManager};
|
||||
use crate::config::Config;
|
||||
use tauri::async_runtime;
|
||||
|
||||
// 使用spawn来处理异步操作
|
||||
async_runtime::spawn(async move {
|
||||
if apply {
|
||||
// 读取DNS配置文件
|
||||
let dns_path = match dirs::app_home_dir() {
|
||||
Ok(path) => path.join("dns_config.yaml"),
|
||||
Err(e) => {
|
||||
log::error!(target: "app", "Failed to get home dir: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if !dns_path.exists() {
|
||||
log::warn!(target: "app", "DNS config file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
let dns_yaml = match std::fs::read_to_string(&dns_path) {
|
||||
Ok(content) => content,
|
||||
Err(e) => {
|
||||
log::error!(target: "app", "Failed to read DNS config: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// 解析DNS配置并创建patch
|
||||
let patch_config = match serde_yaml::from_str::<serde_yaml::Mapping>(&dns_yaml) {
|
||||
Ok(config) => {
|
||||
let mut patch = serde_yaml::Mapping::new();
|
||||
patch.insert("dns".into(), config.into());
|
||||
patch
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!(target: "app", "Failed to parse DNS config: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
log::info!(target: "app", "Applying DNS config from file");
|
||||
|
||||
// 重新生成配置,确保DNS配置被正确应用
|
||||
// 这里不调用patch_clash以避免将DNS配置写入config.yaml
|
||||
Config::runtime().latest().patch_config(patch_config.clone());
|
||||
|
||||
// 首先重新生成配置
|
||||
if let Err(err) = Config::generate().await {
|
||||
log::error!(target: "app", "Failed to regenerate config with DNS: {}", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// 然后应用新配置
|
||||
if let Err(err) = CoreManager::global().update_config().await {
|
||||
log::error!(target: "app", "Failed to apply config with DNS: {}", err);
|
||||
} else {
|
||||
log::info!(target: "app", "DNS config successfully applied");
|
||||
handle::Handle::refresh_clash();
|
||||
}
|
||||
} else {
|
||||
// 当关闭DNS设置时,不需要对配置进行任何修改
|
||||
// 直接重新生成配置,让enhance函数自动跳过DNS配置的加载
|
||||
log::info!(target: "app", "DNS settings disabled, regenerating config");
|
||||
|
||||
// 重新生成配置
|
||||
if let Err(err) = Config::generate().await {
|
||||
log::error!(target: "app", "Failed to regenerate config: {}", err);
|
||||
return;
|
||||
}
|
||||
|
||||
// 应用新配置
|
||||
match CoreManager::global().update_config().await {
|
||||
Ok(_) => {
|
||||
log::info!(target: "app", "Config regenerated successfully");
|
||||
handle::Handle::refresh_clash();
|
||||
},
|
||||
Err(err) => {
|
||||
log::error!(target: "app", "Failed to apply regenerated config: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 检查DNS配置文件是否存在
|
||||
#[tauri::command]
|
||||
pub fn check_dns_config_exists() -> CmdResult<bool> {
|
||||
use crate::utils::dirs;
|
||||
|
||||
let dns_path = dirs::app_home_dir().map_err(|e| e.to_string())?
|
||||
.join("dns_config.yaml");
|
||||
|
||||
Ok(dns_path.exists())
|
||||
}
|
||||
|
||||
/// 获取DNS配置文件内容
|
||||
#[tauri::command]
|
||||
pub async fn get_dns_config_content() -> CmdResult<String> {
|
||||
use crate::utils::dirs;
|
||||
use std::fs;
|
||||
|
||||
let dns_path = dirs::app_home_dir().map_err(|e| e.to_string())?
|
||||
.join("dns_config.yaml");
|
||||
|
||||
if !dns_path.exists() {
|
||||
return Err("DNS config file not found".into());
|
||||
}
|
||||
|
||||
let content = fs::read_to_string(&dns_path).map_err(|e| e.to_string())?;
|
||||
Ok(content)
|
||||
}
|
||||
|
||||
@@ -38,56 +38,7 @@ impl IClashTemp {
|
||||
tun.insert("strict-route".into(), false.into());
|
||||
tun.insert("auto-detect-interface".into(), true.into());
|
||||
tun.insert("dns-hijack".into(), vec!["any:53"].into());
|
||||
|
||||
// 添加默认的DNS配置
|
||||
let mut dns = Mapping::new();
|
||||
dns.insert("enable".into(), true.into());
|
||||
dns.insert("listen".into(), ":53".into());
|
||||
dns.insert("enhanced-mode".into(), "fake-ip".into());
|
||||
dns.insert("fake-ip-range".into(), "198.18.0.1/16".into());
|
||||
dns.insert("fake-ip-filter-mode".into(), "blacklist".into());
|
||||
dns.insert("prefer-h3".into(), false.into());
|
||||
dns.insert("respect-rules".into(), false.into());
|
||||
dns.insert("use-hosts".into(), false.into());
|
||||
dns.insert("use-system-hosts".into(), false.into());
|
||||
|
||||
// 添加fake-ip-filter
|
||||
dns.insert("fake-ip-filter".into(), vec![
|
||||
"*.lan", "*.local", "*.arpa", "time.*.com", "ntp.*.com", "time.*.com",
|
||||
"+.market.xiaomi.com", "localhost.ptlogin2.qq.com", "*.msftncsi.com", "www.msftconnecttest.com"
|
||||
].into());
|
||||
|
||||
// 添加nameserver相关配置
|
||||
dns.insert("default-nameserver".into(), vec!["223.6.6.6", "8.8.8.8"].into());
|
||||
dns.insert("nameserver".into(), vec![
|
||||
"8.8.8.8", "https://doh.pub/dns-query", "https://dns.alidns.com/dns-query"
|
||||
].into());
|
||||
|
||||
// 添加fallback配置
|
||||
dns.insert("fallback".into(), vec![
|
||||
"https://dns.alidns.com/dns-query", "https://dns.google/dns-query", "https://cloudflare-dns.com/dns-query"
|
||||
].into());
|
||||
|
||||
// 添加proxy-server-nameserver
|
||||
dns.insert("proxy-server-nameserver".into(), vec![
|
||||
"https://doh.pub/dns-query", "https://dns.alidns.com/dns-query"
|
||||
].into());
|
||||
|
||||
// 添加direct-nameserver
|
||||
dns.insert("direct-nameserver".into(), Vec::<String>::new().into());
|
||||
dns.insert("direct-nameserver-follow-policy".into(), false.into());
|
||||
|
||||
// 添加nameserver-policy (空对象)
|
||||
dns.insert("nameserver-policy".into(), Mapping::new().into());
|
||||
|
||||
// 添加fallback-filter
|
||||
let mut fallback_filter = Mapping::new();
|
||||
fallback_filter.insert("geoip".into(), true.into());
|
||||
fallback_filter.insert("geoip-code".into(), "CN".into());
|
||||
fallback_filter.insert("ipcidr".into(), vec!["240.0.0.0/4", "0.0.0.0/32"].into());
|
||||
fallback_filter.insert("domain".into(), vec!["+.google.com", "+.facebook.com", "+.youtube.com"].into());
|
||||
dns.insert("fallback-filter".into(), fallback_filter.into());
|
||||
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
map.insert("redir-port".into(), 7895.into());
|
||||
#[cfg(target_os = "linux")]
|
||||
@@ -104,7 +55,6 @@ impl IClashTemp {
|
||||
cors_map.insert("allow-origins".into(), vec!["*"].into());
|
||||
map.insert("secret".into(), "".into());
|
||||
map.insert("tun".into(), tun.into());
|
||||
map.insert("dns".into(), dns.into());
|
||||
map.insert("external-controller-cors".into(), cors_map.into());
|
||||
map.insert("unified-delay".into(), true.into());
|
||||
Self(map)
|
||||
|
||||
@@ -70,6 +70,9 @@ pub struct IVerge {
|
||||
/// enable proxy guard
|
||||
pub enable_proxy_guard: Option<bool>,
|
||||
|
||||
/// enable dns settings - this controls whether dns_config.yaml is applied
|
||||
pub enable_dns_settings: Option<bool>,
|
||||
|
||||
/// always use default bypass
|
||||
pub use_default_bypass: Option<bool>,
|
||||
|
||||
@@ -287,6 +290,7 @@ impl IVerge {
|
||||
enable_tray_speed: Some(true),
|
||||
enable_global_hotkey: Some(true),
|
||||
enable_lite_mode: Some(false),
|
||||
enable_dns_settings: Some(true),
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
@@ -369,6 +373,7 @@ impl IVerge {
|
||||
patch!(webdav_password);
|
||||
patch!(enable_tray_speed);
|
||||
patch!(enable_lite_mode);
|
||||
patch!(enable_dns_settings);
|
||||
}
|
||||
|
||||
/// 在初始化前尝试拿到单例端口的值
|
||||
@@ -458,6 +463,7 @@ pub struct IVergeResponse {
|
||||
pub webdav_password: Option<String>,
|
||||
pub enable_tray_speed: Option<bool>,
|
||||
pub enable_lite_mode: Option<bool>,
|
||||
pub enable_dns_settings: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<IVerge> for IVergeResponse {
|
||||
@@ -521,6 +527,7 @@ impl From<IVerge> for IVergeResponse {
|
||||
webdav_password: verge.webdav_password,
|
||||
enable_tray_speed: verge.enable_tray_speed,
|
||||
enable_lite_mode: verge.enable_lite_mode,
|
||||
enable_dns_settings: verge.enable_dns_settings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
// config.yaml 的订阅
|
||||
let clash_config = { Config::clash().latest().0.clone() };
|
||||
|
||||
let (clash_core, enable_tun, enable_builtin, socks_enabled, http_enabled) = {
|
||||
let (clash_core, enable_tun, enable_builtin, socks_enabled, http_enabled, enable_dns_settings) = {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
(
|
||||
@@ -34,6 +34,7 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
verge.enable_builtin_enhanced.unwrap_or(true),
|
||||
verge.verge_socks_enabled.unwrap_or(false),
|
||||
verge.verge_http_enabled.unwrap_or(false),
|
||||
verge.enable_dns_settings.unwrap_or(false),
|
||||
)
|
||||
};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
@@ -262,6 +263,27 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
config = use_tun(config, enable_tun).await;
|
||||
config = use_sort(config);
|
||||
|
||||
// 应用独立的DNS配置(如果启用)
|
||||
if enable_dns_settings {
|
||||
use crate::utils::dirs;
|
||||
use std::fs;
|
||||
|
||||
// 尝试读取dns_config.yaml
|
||||
if let Ok(app_dir) = dirs::app_home_dir() {
|
||||
let dns_path = app_dir.join("dns_config.yaml");
|
||||
|
||||
if dns_path.exists() {
|
||||
if let Ok(dns_yaml) = fs::read_to_string(&dns_path) {
|
||||
if let Ok(dns_config) = serde_yaml::from_str::<serde_yaml::Mapping>(&dns_yaml) {
|
||||
// 将DNS配置合并到最终配置中
|
||||
config.insert("dns".into(), dns_config.into());
|
||||
log::info!(target: "app", "apply dns_config.yaml");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut exists_set = HashSet::new();
|
||||
exists_set.extend(exists_keys);
|
||||
exists_keys = exists_set.into_iter().collect();
|
||||
|
||||
@@ -163,6 +163,10 @@ pub fn run() {
|
||||
cmd::copy_clash_env,
|
||||
cmd::get_proxies,
|
||||
cmd::get_providers_proxies,
|
||||
cmd::save_dns_config,
|
||||
cmd::apply_dns_config,
|
||||
cmd::check_dns_config_exists,
|
||||
cmd::get_dns_config_content,
|
||||
// verge
|
||||
cmd::get_verge_config,
|
||||
cmd::patch_verge_config,
|
||||
|
||||
@@ -133,6 +133,81 @@ pub fn delete_log() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 初始化DNS配置文件
|
||||
fn init_dns_config() -> Result<()> {
|
||||
use serde_yaml::Value;
|
||||
|
||||
// 获取默认DNS配置
|
||||
let default_dns_config = serde_yaml::Mapping::from_iter([
|
||||
("enable".into(), Value::Bool(true)),
|
||||
("listen".into(), Value::String(":53".into())),
|
||||
("enhanced-mode".into(), Value::String("fake-ip".into())),
|
||||
("fake-ip-range".into(), Value::String("198.18.0.1/16".into())),
|
||||
("fake-ip-filter-mode".into(), Value::String("blacklist".into())),
|
||||
("prefer-h3".into(), Value::Bool(false)),
|
||||
("respect-rules".into(), Value::Bool(false)),
|
||||
("use-hosts".into(), Value::Bool(false)),
|
||||
("use-system-hosts".into(), Value::Bool(false)),
|
||||
("fake-ip-filter".into(), Value::Sequence(vec![
|
||||
Value::String("*.lan".into()),
|
||||
Value::String("*.local".into()),
|
||||
Value::String("*.arpa".into()),
|
||||
Value::String("time.*.com".into()),
|
||||
Value::String("ntp.*.com".into()),
|
||||
Value::String("time.*.com".into()),
|
||||
Value::String("+.market.xiaomi.com".into()),
|
||||
Value::String("localhost.ptlogin2.qq.com".into()),
|
||||
Value::String("*.msftncsi.com".into()),
|
||||
Value::String("www.msftconnecttest.com".into()),
|
||||
])),
|
||||
("default-nameserver".into(), Value::Sequence(vec![
|
||||
Value::String("223.6.6.6".into()),
|
||||
Value::String("8.8.8.8".into()),
|
||||
])),
|
||||
("nameserver".into(), Value::Sequence(vec![
|
||||
Value::String("8.8.8.8".into()),
|
||||
Value::String("https://doh.pub/dns-query".into()),
|
||||
Value::String("https://dns.alidns.com/dns-query".into()),
|
||||
])),
|
||||
("fallback".into(), Value::Sequence(vec![
|
||||
Value::String("https://dns.alidns.com/dns-query".into()),
|
||||
Value::String("https://dns.google/dns-query".into()),
|
||||
Value::String("https://cloudflare-dns.com/dns-query".into()),
|
||||
])),
|
||||
("nameserver-policy".into(), Value::Mapping(serde_yaml::Mapping::new())),
|
||||
("proxy-server-nameserver".into(), Value::Sequence(vec![
|
||||
Value::String("https://doh.pub/dns-query".into()),
|
||||
Value::String("https://dns.alidns.com/dns-query".into()),
|
||||
])),
|
||||
("direct-nameserver".into(), Value::Sequence(vec![])),
|
||||
("direct-nameserver-follow-policy".into(), Value::Bool(false)),
|
||||
("fallback-filter".into(), Value::Mapping(serde_yaml::Mapping::from_iter([
|
||||
("geoip".into(), Value::Bool(true)),
|
||||
("geoip-code".into(), Value::String("CN".into())),
|
||||
("ipcidr".into(), Value::Sequence(vec![
|
||||
Value::String("240.0.0.0/4".into()),
|
||||
Value::String("0.0.0.0/32".into()),
|
||||
])),
|
||||
("domain".into(), Value::Sequence(vec![
|
||||
Value::String("+.google.com".into()),
|
||||
Value::String("+.facebook.com".into()),
|
||||
Value::String("+.youtube.com".into()),
|
||||
])),
|
||||
]))),
|
||||
]);
|
||||
|
||||
// 检查DNS配置文件是否存在
|
||||
let app_dir = dirs::app_home_dir()?;
|
||||
let dns_path = app_dir.join("dns_config.yaml");
|
||||
|
||||
if !dns_path.exists() {
|
||||
log::info!(target: "app", "Creating default DNS config file");
|
||||
help::save_yaml(&dns_path, &default_dns_config, Some("# Clash Verge DNS Config"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initialize all the config files
|
||||
/// before tauri setup
|
||||
pub fn init_config() -> Result<()> {
|
||||
@@ -173,6 +248,9 @@ pub fn init_config() -> Result<()> {
|
||||
<Result<()>>::Ok(())
|
||||
}));
|
||||
|
||||
// 初始化DNS配置文件
|
||||
let _ = init_dns_config();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user