#include "stdafx.h" #include "CLashConfig.h" #include "CApp.h" #include "comm.h" #include "FileOperate.h" #include "SysProxy.h" CLashConfig::CLashConfig() : m_socks_port(9200), m_http_port(9300), m_c_port(9090), m_process(nullptr), m_Asyntask(1), m_AsyntaskProcessMonitor(1), m_is_qut(false) { SNotifyCenter::getSingleton().addEvent(EVENTID(EventClashPreOceeQut)); } CLashConfig::~CLashConfig(void) { if (m_process) { delete m_process; m_process = nullptr; } } BOOL CLashConfig::MakeClash() { buildRules(); YAML::Node root; root["port"] = m_http_port; root["socks-port"] = m_socks_port; root["allow-lan"] = true; root["external-controller"] = "127.0.0.1:" + std::to_string(m_c_port); if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode) { root["mode"] = "rule"; } else { root["mode"] = "rule"; } #ifdef _DEBUG root["log-level"] = "debug"; #else root["log-level"] = "info"; #endif root["dns"] = buildDnsConfig(); if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode) { root["tun"] = builTunConfig(); } //proxys.reserve(0); //CList_node::getSingletonPtr()->listnode; YAML::Node proxies; for each (auto node in CApp::getSingletonPtr()->GetServerList()->vectlistmode) { if (node.type == "shadowsocks") { proxies.push_back(buildShadowsocks(&node)); } else if (node.type == "trojan") { proxies.push_back(buildtrojan(&node)); } else if (node.type == "v2ray") { proxies.push_back(buildv2ray(&node)); } } root["proxies"] = proxies; //root["proxy-providers"] = buildProxyproviders(); root["proxy-groups"] = buildProxyGroups(); YAML::Node reject; YAML::Node google; YAML::Node gfw; YAML::Node proxy; YAML::Node cncidr; reject["type"] = "http"; reject["behavior"] = "domain"; reject["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt"; reject["path"] = "./ruleset/reject.yaml"; reject["interval"] = 86400; google["type"] = "http"; google["behavior"] = "domain"; google["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt"; google["path"] = "./ruleset/google.yaml"; google["interval"] = 86400; gfw["type"] = "http"; gfw["behavior"] = "domain"; gfw["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt"; gfw["path"] = "./ruleset/gfw.yaml"; gfw["interval"] = 86400; proxy["type"] = "http"; proxy["behavior"] = "domain"; proxy["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt"; proxy["path"] = "./ruleset/proxy.yaml"; proxy["interval"] = 86400; cncidr["type"] = "http"; cncidr["behavior"] = "domain"; cncidr["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt"; cncidr["path"] = "./ruleset/cncidr.yaml"; cncidr["interval"] = 86400; if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode) { root["rule-providers"]["reject"] = reject; root["rule-providers"]["cncidr"] = cncidr; root["rule-providers"]["proxy"] = proxy; root["rule-providers"]["gfw"] = gfw; root["rule-providers"]["google"] = google; } root["rules"] = m_rules; auto name_file = DSPROXY_CONFIG_ClASH_NAME; if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode) { name_file = DSPROXY_CONFIG_TUN_ClASH_NAME; } try { m_run_config = CApp::getSingletonPtr()->GetConfigPath() / name_file; std::ofstream ofstream(CApp::getSingletonPtr()->GetConfigPath() / name_file); ofstream << root; ofstream.close(); } catch (const std::exception& e) { LOG_CAUGHT_EXCEPTION(); return FALSE; } return TRUE; } BOOL CLashConfig::InitClash() { if (!m_process) { m_process = new CProcess(); } m_http_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9300,9500); m_socks_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9600,9800); m_c_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9900); auto name_file = DSPROXY_CONFIG_INIT_ClASH_NAME; if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode) { /*name_file = dir + "\\" + CLASHCONFIINIT;*/ name_file = DSPROXY_CONFIG_TUN_ClASH_NAME; } YAML::Node root; root["port"] = m_http_port; root["socks-port"] = m_socks_port; root["allow-lan"] = true; root["external-controller"] = "127.0.0.1:" + std::to_string(m_c_port); try { std::ofstream ofstream(CApp::getSingletonPtr()->GetConfigPath() / name_file); ofstream << root << std::endl; ofstream.close(); return TRUE; } catch (const std::exception& e) { Logger::getSingletonPtr()->INFO(e.what()); LOG_CAUGHT_EXCEPTION(); return FALSE; } return TRUE; } BOOL CLashConfig::StartClash() { auto assetsDir = std::filesystem::current_path() / CLASH_ASSETS_DIR_NAME; auto confg_path = CApp::getSingletonPtr()->GetConfigPath() / DSPROXY_CONFIG_INIT_ClASH_NAME; CProcessManager::getSingletonPtr()->SetArgs(assetsDir / DSPROXY_EXE_NAME, assetsDir, std::move(confg_path)); /*ProcessManager::SetConfigFile(confg_path / DSPROXY_CONFIG_INIT_ClASH_NAME);*/ /* m_Asyntask.AddTask(&CLashConfig::ThreadFun_process_Config, this, (LPARAM)CProcessManager::getSingletonPtr());*/ if (CProcessManager::getSingletonPtr()->Start()) { CApp::getSingletonPtr()->SetCLashRuning(true); m_AsyntaskProcessMonitor.AddTask(&CLashConfig::ThreadFun_ProcessMonitor_Config, this, (LPARAM)CProcessManager::getSingletonPtr()); } /*if (m_process) { m_process->Create(CProcess::ASYNC); if (m_process->Execute(path_config.GetBuffer(0))) { } }*/ return 0; } BOOL CLashConfig::StopClash() { m_is_qut = true; /*SetEvent(_hEvent.get());*/ //char ch[MAX_PATH]; //memset(ch, 0, MAX_PATH); //sprintf_s(ch, "ok\n"); //m_process->WriteSome(ch, sizeof(ch)); return 0; } int CLashConfig::GetHttpPort() { return m_http_port; } int CLashConfig::GetSocketPort() { return m_socks_port; } int CLashConfig::GetClasApiPort() { return m_c_port; } std::filesystem::path CLashConfig::GetRunConfig() { return m_run_config; } YAML::Node CLashConfig::buildShadowsocks(CServerListMode* node) { YAML::Node t_map; if (!node) { return t_map; } t_map["name"] = node->name; t_map["type"] = std::string("ss"); t_map["server"] = node->host; t_map["port"] = std::to_string(node->port); t_map["cipher"] = node->method; t_map["password"] = CApp::getSingletonPtr()->GetUserinfo()->uuid; t_map["udp"] = true; return t_map; return YAML::Node(); } YAML::Node CLashConfig::buildtrojan(CServerListMode* node) { YAML::Node t_map; if (!node) { return t_map; } t_map["name"] = node->name; t_map["type"] = std::string("trojan"); t_map["server"] = node->host; t_map["port"] = std::to_string(node->port); t_map["password"] = CApp::getSingletonPtr()->GetUserinfo()->uuid; if (!node->serverName.empty()) { t_map["serverName"] = node->serverName; } t_map["udp"] = true; return t_map; return YAML::Node(); } YAML::Node CLashConfig::buildv2ray(CServerListMode* node) { YAML::Node t_map; if (!node) { return t_map; } std::vector p; t_map["name"] = node->name; t_map["type"] = std::string("vmess"); t_map["server"] = node->host; t_map["port"] = std::to_string(node->port); t_map["uuid"] = CApp::getSingletonPtr()->GetUserinfo()->uuid; t_map["cipher"] = "auto"; t_map["alterId"] = 0; t_map["udp"] = true; if (node->tls == 1) { t_map["tls"] = true; } if (node->network == "tcp") { t_map["skip-cert-verify"] = false; t_map["network"] = node->network; if (!node->serverName.empty()) { t_map["servername"] = node->serverName; } } //else if (node->v2_net == "ws") { // YAML::Node t_host; // t_map["skip-cert-verify"] = false; // /* // max-early-data: 2048 // early-data-header-name: Sec-WebSocket-Protocol // * // */ // t_host["host"] = node->v2_host; // t_map["network"] = node->v2_net; // t_map["ws-opts"]["headers"] = t_host; // t_map["ws-opts"]["path"] = node->v2_path; // t_map["ws-opts"]["max-early-data"] = 2048; // t_map["ws-opts"]["early-data-header-name"] = "Sec-WebSocket-Protocol"; // /*t_map["ws-path"] = node->v2_path; // t_map["ws-headers"] = t_host;*/ //} return t_map; } std::vector CLashConfig::buildv2rayHost(CServerListMode* node) { std::vector p; if (node) { YAML::Node t_map; //t_map["host"] = node->v2_host; p.push_back(t_map); } return p; } YAML::Node CLashConfig::builTunConfig() { std::vector dns; dns.push_back("198.18.0.2:53"); YAML::Node node; node["enable"] = true; node["stack"] = "gvisor"; node["dns-hijack"] = dns; node["auto-route"] = true; node["auto-detect-interface"] = true; return node; } YAML::Node CLashConfig::buildDnsConfig() { YAML::Node dns; std::vector dns_arr; if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode) { dns["enhanced-mode"] = "redir-host"; } dns_arr.push_back("114.114.114.114"); dns_arr.push_back("8.8.8.8"); dns_arr.push_back("tls://dns.rubyfish.cn:853"); dns_arr.push_back("https://1.1.1.1/dns-query"); /*if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::qg_mode) { dns["enable"] = false; } else { dns["enable"] = true; }*/ dns["enable"] = true; dns["nameserver"] = dns_arr; //dns["use-hosts"] = true; return dns; } std::vector CLashConfig::buildProxyGroups() { std::vector dns_arr; std::vector proxy; YAML::Node proxies; for each (auto node in CApp::getSingletonPtr()->GetServerList()->vectlistmode) { proxy.push_back(node.name.c_str()); } YAML::Node li; li["name"] = "Proxy"; li["type"] = "select"; li["proxies"] = proxy; dns_arr.push_back(li); /*proxy.push_back("foo"); YAML::Node li; li["name"] = "Proxy"; li["type"] = "select"; li["use"] = proxy; dns_arr.push_back(li);*/ return dns_arr; } YAML::Node CLashConfig::buildProxyproviders() { YAML::Node p; YAML::Node healthCheck; p["foo"]["type"] = "http"; p["foo"]["path"] = "./profiles/proxies/foo.yaml"; p["foo"]["url"] = CApp::getSingletonPtr()->GetUserinfo()->clash_config; p["foo"]["interval"] = "3600"; healthCheck["enable"] = true; healthCheck["url"] = "http://www.gstatic.com/generate_204"; healthCheck["interval"] = "3600"; p["foo"]["health-check"] = healthCheck; return p; } std::vector CLashConfig::buildRules() { std::vector p; m_rules.clear(); if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode) { m_rules.push_back("RULE-SET,proxy,Proxy"); m_rules.push_back("RULE-SET,google,Proxy"); m_rules.push_back("RULE-SET,gfw,Proxy"); m_rules.push_back("RULE-SET,cncidr,DIRECT"); m_rules.push_back("GEOIP,CN,DIRECT"); m_rules.push_back("IP-CIDR,127.0.0.0/8,DIRECT"); m_rules.push_back("IP-CIDR,172.16.0.0/12,DIRECT"); m_rules.push_back("IP-CIDR,192.168.0.0/16,DIRECT"); m_rules.push_back("IP-CIDR,10.0.0.0/8,DIRECT"); m_rules.push_back("IP-CIDR,100.64.0.0/10,DIRECT"); } else { // m_rules.push_back("RULE-SET,proxy,Proxy"); // m_rules.push_back("RULE-SET,google,Proxy"); // m_rules.push_back("RULE-SET,gfw,Proxy"); // m_rules.push_back("RULE-SET,cncidr,Proxy"); //m_rules.push_back("GEOIP,CN,Proxy"); m_rules.push_back("IP-CIDR,127.0.0.0/8,DIRECT"); m_rules.push_back("IP-CIDR,172.16.0.0/12,DIRECT"); m_rules.push_back("IP-CIDR,192.168.0.0/16,DIRECT"); m_rules.push_back("IP-CIDR,10.0.0.0/8,DIRECT"); m_rules.push_back("IP-CIDR,100.64.0.0/10,DIRECT"); } m_rules.push_back("MATCH,Proxy"); return p; } std::vector CLashConfig::buildruleproviders() { std::vector pp; YAML::Node node; YAML::Node reject; YAML::Node google; YAML::Node gfw; YAML::Node proxy; YAML::Node cncidr; reject["type"] = "http"; reject["behavior"] = "domain"; reject["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt"; reject["path"] = "./ruleset/reject.yaml"; reject["interval"] = 86400; node["reject"] = reject; pp.push_back(node); google["type"] = "http"; google["behavior"] = "domain"; google["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt"; google["path"] = "./ruleset/google.yaml"; google["interval"] = 86400; node["google"] = google; pp.push_back(node); gfw["type"] = "http"; gfw["behavior"] = "domain"; gfw["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt"; gfw["path"] = "./ruleset/gfw.yaml"; gfw["interval"] = 86400; node["gfw"] = gfw; pp.push_back(node); proxy["type"] = "http"; proxy["behavior"] = "domain"; proxy["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt"; proxy["path"] = "./ruleset/proxy.yaml"; proxy["interval"] = 86400; node["proxy"] = proxy; pp.push_back(node); cncidr["type"] = "http"; cncidr["behavior"] = "domain"; cncidr["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt"; cncidr["path"] = "./ruleset/cncidr.yaml"; cncidr["interval"] = 86400; node["cncidr"] = proxy; pp.push_back(node); return pp; } void CLashConfig::ThreadFun_process_Config(LPARAM lParam) { } void CLashConfig::ThreadFun_ProcessMonitor_Config(LPARAM lParam) { CProcessManager* p = (CProcessManager*)lParam; if (p) { HANDLE hClashProcess = p->GetClashProcessInfo().hProcess; HANDLE hSubProcess = p->GetSubProcessInfo().hProcess; WaitForSingleObject(hClashProcess, INFINITE); CApp::getSingletonPtr()->SetCLashRuning(false); if (p->IsRunning() != State::Running) { return; } DWORD exitCode = 0; THROW_IF_WIN32_BOOL_FALSE(GetExitCodeProcess(hClashProcess, &exitCode)); LOG_HR_MSG(E_FAIL, "syscode.exe exited with code: %ul", exitCode); FILETIME creationTime = {}, exitTime = {}, kernelTime = {}, userTime = {}; THROW_IF_WIN32_BOOL_FALSE(GetProcessTimes(hClashProcess, &creationTime, &exitTime, &kernelTime, &userTime)); auto creation = winrt::clock::from_FILETIME(creationTime); auto exit = winrt::clock::from_FILETIME(exitTime); if (exit - creation < 5s) { /*g_balloonClickAction = BalloonClickAction::ShowConsoleWindow; ShowBalloon(_(L"Clash process was alive less than 5 seconds\nTap to view console log"), _(L"Error"), NIIF_ERROR); co_await winrt::resume_on_signal(hSubProcess);*/ WaitForSingleObject(hSubProcess, INFINITE); } if (p->IsRunning() != State::Running) { return; } p->Stop(); EventClashPreOceeQut* pEvt = new EventClashPreOceeQut(nullptr); pEvt->status = 200; pEvt->msg = L""; SNotifyCenter::getSingleton().FireEventAsync(pEvt); pEvt->Release(); } } BOOL CLashConfig::SetProxy() { BOOL isok = FALSE; /*if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::sys_mode) { auto proxy = "127.0.0.1:" + std::to_string(m_http_port); isok = SetSystemProxy(S_CA2W(proxy.c_str()), NULL, L"localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;172.32.*;192.168.*"); }*/ auto proxy = "127.0.0.1:" + std::to_string(m_http_port); isok = SetSystemProxy(S_CA2W(proxy.c_str()), NULL, L"localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;172.32.*;192.168.*"); return isok; } //winrt::fire_and_forget CLashConfig::_StartClash() //{ // if (CProcessManager::getSingletonPtr()->Start()) // { // CApp::getSingletonPtr()->SetCLashRuning(true); // // // // /*HANDLE hClashProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess; // // for (size_t i = 0; i < 5; ++i) { // // }*/ // } // // // //} // //winrt::Windows::Foundation::IAsyncAction CLashConfig::ProcessMonitor() //{ // HANDLE hSubProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess, // hClashProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess; // // winrt::resume_on_signal(hClashProcess); // // /*std::future f = std::async(std::launch::async, []() { // })*/ // // // // //}