CLashConfig.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. #include "stdafx.h"
  2. #include "CLashConfig.h"
  3. #include "CApp.h"
  4. #include "comm.h"
  5. #include "FileOperate.h"
  6. #include "SysProxy.h"
  7. 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)
  8. {
  9. SNotifyCenter::getSingleton().addEvent(EVENTID(EventClashPreOceeQut));
  10. }
  11. CLashConfig::~CLashConfig(void)
  12. {
  13. if (m_process)
  14. {
  15. delete m_process;
  16. m_process = nullptr;
  17. }
  18. }
  19. BOOL CLashConfig::MakeClash()
  20. {
  21. buildRules();
  22. YAML::Node root;
  23. root["port"] = m_http_port;
  24. root["socks-port"] = m_socks_port;
  25. root["allow-lan"] = true;
  26. root["external-controller"] = "127.0.0.1:" + std::to_string(m_c_port);
  27. if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode)
  28. {
  29. root["mode"] = "rule";
  30. }
  31. else {
  32. root["mode"] = "rule";
  33. }
  34. #ifdef _DEBUG
  35. root["log-level"] = "debug";
  36. #else
  37. root["log-level"] = "info";
  38. #endif
  39. root["dns"] = buildDnsConfig();
  40. if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode)
  41. {
  42. root["tun"] = builTunConfig();
  43. }
  44. //proxys.reserve(0);
  45. //CList_node::getSingletonPtr()->listnode;
  46. YAML::Node proxies;
  47. for each (auto node in CApp::getSingletonPtr()->GetServerList()->vectlistmode)
  48. {
  49. if (node.type == "shadowsocks") {
  50. proxies.push_back(buildShadowsocks(&node));
  51. }
  52. else if (node.type == "trojan") {
  53. proxies.push_back(buildtrojan(&node));
  54. }
  55. else if (node.type == "v2ray") {
  56. proxies.push_back(buildv2ray(&node));
  57. }
  58. }
  59. root["proxies"] = proxies;
  60. root["proxy-groups"] = buildProxyGroups();
  61. YAML::Node reject;
  62. YAML::Node google;
  63. YAML::Node gfw;
  64. YAML::Node proxy;
  65. YAML::Node cncidr;
  66. reject["type"] = "http";
  67. reject["behavior"] = "domain";
  68. reject["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt";
  69. reject["path"] = "./ruleset/reject.yaml";
  70. reject["interval"] = 86400;
  71. google["type"] = "http";
  72. google["behavior"] = "domain";
  73. google["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt";
  74. google["path"] = "./ruleset/google.yaml";
  75. google["interval"] = 86400;
  76. gfw["type"] = "http";
  77. gfw["behavior"] = "domain";
  78. gfw["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt";
  79. gfw["path"] = "./ruleset/gfw.yaml";
  80. gfw["interval"] = 86400;
  81. proxy["type"] = "http";
  82. proxy["behavior"] = "domain";
  83. proxy["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt";
  84. proxy["path"] = "./ruleset/proxy.yaml";
  85. proxy["interval"] = 86400;
  86. cncidr["type"] = "http";
  87. cncidr["behavior"] = "domain";
  88. cncidr["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt";
  89. cncidr["path"] = "./ruleset/cncidr.yaml";
  90. cncidr["interval"] = 86400;
  91. if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode)
  92. {
  93. root["rule-providers"]["reject"] = reject;
  94. root["rule-providers"]["cncidr"] = cncidr;
  95. root["rule-providers"]["proxy"] = proxy;
  96. root["rule-providers"]["gfw"] = gfw;
  97. root["rule-providers"]["google"] = google;
  98. }
  99. root["rules"] = m_rules;
  100. auto name_file = DSPROXY_CONFIG_ClASH_NAME;
  101. if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode) {
  102. name_file = DSPROXY_CONFIG_TUN_ClASH_NAME;
  103. }
  104. try
  105. {
  106. m_run_config = CApp::getSingletonPtr()->GetConfigPath() / name_file;
  107. std::ofstream ofstream(CApp::getSingletonPtr()->GetConfigPath() / name_file);
  108. ofstream << root;
  109. ofstream.close();
  110. }
  111. catch (const std::exception& e) {
  112. LOG_CAUGHT_EXCEPTION();
  113. return FALSE;
  114. }
  115. return TRUE;
  116. }
  117. BOOL CLashConfig::InitClash()
  118. {
  119. if (!m_process)
  120. {
  121. m_process = new CProcess();
  122. }
  123. m_http_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9300,9500);
  124. m_socks_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9600,9800);
  125. m_c_port = CTool::getSingletonPtr()->FindAvailableTcpPort(9900);
  126. auto name_file = DSPROXY_CONFIG_INIT_ClASH_NAME;
  127. if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode) {
  128. /*name_file = dir + "\\" + CLASHCONFIINIT;*/
  129. name_file = DSPROXY_CONFIG_TUN_ClASH_NAME;
  130. }
  131. YAML::Node root;
  132. root["port"] = m_http_port;
  133. root["socks-port"] = m_socks_port;
  134. root["allow-lan"] = true;
  135. root["external-controller"] = "127.0.0.1:" + std::to_string(m_c_port);
  136. try
  137. {
  138. std::ofstream ofstream(CApp::getSingletonPtr()->GetConfigPath() / name_file);
  139. ofstream << root << std::endl;
  140. ofstream.close();
  141. return TRUE;
  142. }
  143. catch (const std::exception& e)
  144. {
  145. Logger::getSingletonPtr()->INFO(e.what());
  146. LOG_CAUGHT_EXCEPTION();
  147. return FALSE;
  148. }
  149. return TRUE;
  150. }
  151. BOOL CLashConfig::StartClash()
  152. {
  153. auto assetsDir = std::filesystem::current_path() / CLASH_ASSETS_DIR_NAME;
  154. auto confg_path = CApp::getSingletonPtr()->GetConfigPath() / DSPROXY_CONFIG_INIT_ClASH_NAME;
  155. CProcessManager::getSingletonPtr()->SetArgs(assetsDir / DSPROXY_EXE_NAME, assetsDir, std::move(confg_path));
  156. /*ProcessManager::SetConfigFile(confg_path / DSPROXY_CONFIG_INIT_ClASH_NAME);*/
  157. /* m_Asyntask.AddTask(&CLashConfig::ThreadFun_process_Config, this, (LPARAM)CProcessManager::getSingletonPtr());*/
  158. if (CProcessManager::getSingletonPtr()->Start())
  159. {
  160. CApp::getSingletonPtr()->SetCLashRuning(true);
  161. m_AsyntaskProcessMonitor.AddTask(&CLashConfig::ThreadFun_ProcessMonitor_Config, this, (LPARAM)CProcessManager::getSingletonPtr());
  162. }
  163. /*if (m_process)
  164. {
  165. m_process->Create(CProcess::ASYNC);
  166. if (m_process->Execute(path_config.GetBuffer(0)))
  167. {
  168. }
  169. }*/
  170. return 0;
  171. }
  172. BOOL CLashConfig::StopClash()
  173. {
  174. m_is_qut = true;
  175. /*SetEvent(_hEvent.get());*/
  176. //char ch[MAX_PATH];
  177. //memset(ch, 0, MAX_PATH);
  178. //sprintf_s(ch, "ok\n");
  179. //m_process->WriteSome(ch, sizeof(ch));
  180. return 0;
  181. }
  182. int CLashConfig::GetHttpPort()
  183. {
  184. return m_http_port;
  185. }
  186. int CLashConfig::GetSocketPort()
  187. {
  188. return m_socks_port;
  189. }
  190. int CLashConfig::GetClasApiPort()
  191. {
  192. return m_c_port;
  193. }
  194. std::filesystem::path CLashConfig::GetRunConfig()
  195. {
  196. return m_run_config;
  197. }
  198. YAML::Node CLashConfig::buildShadowsocks(CServerListMode* node)
  199. {
  200. YAML::Node t_map;
  201. if (!node)
  202. {
  203. return t_map;
  204. }
  205. t_map["name"] = node->name;
  206. t_map["type"] = std::string("ss");
  207. t_map["server"] = node->host;
  208. t_map["port"] = std::to_string(node->port);
  209. t_map["cipher"] = node->method;
  210. t_map["password"] = node->passwd;
  211. t_map["udp"] = true;
  212. return t_map;
  213. return YAML::Node();
  214. }
  215. YAML::Node CLashConfig::buildtrojan(CServerListMode* node)
  216. {
  217. YAML::Node t_map;
  218. if (!node)
  219. {
  220. return t_map;
  221. }
  222. t_map["name"] = node->name;
  223. t_map["type"] = std::string("trojan");
  224. t_map["server"] = node->host;
  225. t_map["port"] = std::to_string(node->port);
  226. t_map["password"] = node->passwd;
  227. if (!node->sni.empty()) {
  228. t_map["sni"] = node->sni;
  229. }
  230. t_map["udp"] = true;
  231. return t_map;
  232. return YAML::Node();
  233. }
  234. YAML::Node CLashConfig::buildv2ray(CServerListMode* node)
  235. {
  236. YAML::Node t_map;
  237. if (!node)
  238. {
  239. return t_map;
  240. }
  241. std::vector<YAML::Node> p;
  242. t_map["name"] = node->name;
  243. t_map["type"] = std::string("vmess");
  244. t_map["server"] = node->host;
  245. t_map["port"] = std::to_string(node->port);
  246. t_map["uuid"] = node->uuid;
  247. t_map["cipher"] = node->method;
  248. t_map["alterId"] = node->v2_alter_id;
  249. t_map["udp"] = node->udp;
  250. if (node->v2_tls == "tls") {
  251. t_map["tls"] = node->v2_tls;
  252. }
  253. if (node->v2_net == "tcp") {
  254. t_map["network"] = node->v2_net;
  255. }
  256. else if (node->v2_net == "ws") {
  257. t_map["network"] = node->v2_net;
  258. t_map["ws-path"] = node->v2_path;
  259. t_map["ws-headers"] = buildv2rayHost(node);
  260. }
  261. return t_map;
  262. }
  263. std::vector<YAML::Node> CLashConfig::buildv2rayHost(CServerListMode* node)
  264. {
  265. std::vector<YAML::Node> p;
  266. if (node) {
  267. YAML::Node t_map;
  268. t_map["host"] = node->v2_host;
  269. p.push_back(t_map);
  270. }
  271. return p;
  272. }
  273. YAML::Node CLashConfig::builTunConfig()
  274. {
  275. std::vector<std::string> dns;
  276. dns.push_back("198.18.0.2:53");
  277. YAML::Node node;
  278. node["enable"] = true;
  279. node["stack"] = "gvisor";
  280. node["dns-hijack"] = dns;
  281. node["auto-route"] = true;
  282. node["auto-detect-interface"] = true;
  283. return node;
  284. }
  285. YAML::Node CLashConfig::buildDnsConfig()
  286. {
  287. YAML::Node dns;
  288. std::vector<std::string> dns_arr;
  289. dns_arr.push_back("114.114.114.114");
  290. dns_arr.push_back("8.8.8.8");
  291. dns_arr.push_back("tls://dns.rubyfish.cn:853");
  292. dns_arr.push_back("https://1.1.1.1/dns-query");
  293. dns["enable"] = true;
  294. if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::tun_mode)
  295. {
  296. dns["enhanced-mode"] = "redir-host";
  297. }
  298. else
  299. {
  300. //dns["enable"] = false;
  301. }
  302. dns["nameserver"] = dns_arr;
  303. //dns["use-hosts"] = true;
  304. return dns;
  305. }
  306. std::vector<YAML::Node> CLashConfig::buildProxyGroups()
  307. {
  308. std::vector<YAML::Node> dns_arr;
  309. std::vector<std::string> proxy;
  310. YAML::Node proxies;
  311. for each (auto node in CApp::getSingletonPtr()->GetServerList()->vectlistmode)
  312. {
  313. proxy.push_back(node.name.c_str());
  314. }
  315. YAML::Node li;
  316. li["name"] = "Proxy";
  317. li["type"] = "select";
  318. li["proxies"] = proxy;
  319. dns_arr.push_back(li);
  320. return dns_arr;
  321. }
  322. std::vector<YAML::Node> CLashConfig::buildRules()
  323. {
  324. std::vector<YAML::Node> p;
  325. m_rules.clear();
  326. if (CApp::getSingletonPtr()->GetRouteMode() == ROUT_MODE::cn_mode)
  327. {
  328. m_rules.push_back("RULE-SET,proxy,Proxy");
  329. m_rules.push_back("RULE-SET,google,Proxy");
  330. m_rules.push_back("RULE-SET,gfw,Proxy");
  331. m_rules.push_back("RULE-SET,cncidr,DIRECT");
  332. m_rules.push_back("GEOIP,CN,DIRECT");
  333. m_rules.push_back("IP-CIDR,127.0.0.0/8,DIRECT");
  334. m_rules.push_back("IP-CIDR,172.16.0.0/12,DIRECT");
  335. m_rules.push_back("IP-CIDR,192.168.0.0/16,DIRECT");
  336. m_rules.push_back("IP-CIDR,10.0.0.0/8,DIRECT");
  337. m_rules.push_back("IP-CIDR,100.64.0.0/10,DIRECT");
  338. }
  339. else
  340. {
  341. // m_rules.push_back("RULE-SET,proxy,Proxy");
  342. // m_rules.push_back("RULE-SET,google,Proxy");
  343. // m_rules.push_back("RULE-SET,gfw,Proxy");
  344. // m_rules.push_back("RULE-SET,cncidr,Proxy");
  345. m_rules.push_back("GEOIP,CN,Proxy");
  346. m_rules.push_back("IP-CIDR,127.0.0.0/8,DIRECT");
  347. m_rules.push_back("IP-CIDR,172.16.0.0/12,DIRECT");
  348. m_rules.push_back("IP-CIDR,192.168.0.0/16,DIRECT");
  349. m_rules.push_back("IP-CIDR,10.0.0.0/8,DIRECT");
  350. m_rules.push_back("IP-CIDR,100.64.0.0/10,DIRECT");
  351. }
  352. m_rules.push_back("MATCH,Proxy");
  353. return p;
  354. }
  355. std::vector<YAML::Node> CLashConfig::buildruleproviders()
  356. {
  357. std::vector<YAML::Node> pp;
  358. YAML::Node node;
  359. YAML::Node reject;
  360. YAML::Node google;
  361. YAML::Node gfw;
  362. YAML::Node proxy;
  363. YAML::Node cncidr;
  364. reject["type"] = "http";
  365. reject["behavior"] = "domain";
  366. reject["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt";
  367. reject["path"] = "./ruleset/reject.yaml";
  368. reject["interval"] = 86400;
  369. node["reject"] = reject;
  370. pp.push_back(node);
  371. google["type"] = "http";
  372. google["behavior"] = "domain";
  373. google["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt";
  374. google["path"] = "./ruleset/google.yaml";
  375. google["interval"] = 86400;
  376. node["google"] = google;
  377. pp.push_back(node);
  378. gfw["type"] = "http";
  379. gfw["behavior"] = "domain";
  380. gfw["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt";
  381. gfw["path"] = "./ruleset/gfw.yaml";
  382. gfw["interval"] = 86400;
  383. node["gfw"] = gfw;
  384. pp.push_back(node);
  385. proxy["type"] = "http";
  386. proxy["behavior"] = "domain";
  387. proxy["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt";
  388. proxy["path"] = "./ruleset/proxy.yaml";
  389. proxy["interval"] = 86400;
  390. node["proxy"] = proxy;
  391. pp.push_back(node);
  392. cncidr["type"] = "http";
  393. cncidr["behavior"] = "domain";
  394. cncidr["url"] = "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt";
  395. cncidr["path"] = "./ruleset/cncidr.yaml";
  396. cncidr["interval"] = 86400;
  397. node["cncidr"] = proxy;
  398. pp.push_back(node);
  399. return pp;
  400. }
  401. void CLashConfig::ThreadFun_process_Config(LPARAM lParam)
  402. {
  403. }
  404. void CLashConfig::ThreadFun_ProcessMonitor_Config(LPARAM lParam)
  405. {
  406. CProcessManager* p = (CProcessManager*)lParam;
  407. if (p)
  408. {
  409. HANDLE hClashProcess = p->GetClashProcessInfo().hProcess;
  410. HANDLE hSubProcess = p->GetSubProcessInfo().hProcess;
  411. WaitForSingleObject(hClashProcess, INFINITE);
  412. CApp::getSingletonPtr()->SetCLashRuning(false);
  413. if (p->IsRunning() != State::Running)
  414. {
  415. return;
  416. }
  417. DWORD exitCode = 0;
  418. THROW_IF_WIN32_BOOL_FALSE(GetExitCodeProcess(hClashProcess, &exitCode));
  419. LOG_HR_MSG(E_FAIL, "syscode.exe exited with code: %ul", exitCode);
  420. FILETIME creationTime = {}, exitTime = {}, kernelTime = {}, userTime = {};
  421. THROW_IF_WIN32_BOOL_FALSE(GetProcessTimes(hClashProcess, &creationTime, &exitTime, &kernelTime, &userTime));
  422. auto creation = winrt::clock::from_FILETIME(creationTime);
  423. auto exit = winrt::clock::from_FILETIME(exitTime);
  424. if (exit - creation < 5s)
  425. {
  426. /*g_balloonClickAction = BalloonClickAction::ShowConsoleWindow;
  427. ShowBalloon(_(L"Clash process was alive less than 5 seconds\nTap to view console log"), _(L"Error"), NIIF_ERROR);
  428. co_await winrt::resume_on_signal(hSubProcess);*/
  429. WaitForSingleObject(hSubProcess, INFINITE);
  430. }
  431. if (p->IsRunning() != State::Running)
  432. {
  433. return;
  434. }
  435. p->Stop();
  436. EventClashPreOceeQut* pEvt = new EventClashPreOceeQut(nullptr);
  437. pEvt->status = 200;
  438. pEvt->msg = L"";
  439. SNotifyCenter::getSingleton().FireEventAsync(pEvt);
  440. pEvt->Release();
  441. }
  442. }
  443. void CLashConfig::SetProxy()
  444. {
  445. if (CApp::getSingletonPtr()->GetSysMode() == PROXY_MODE::sys_mode)
  446. {
  447. auto proxy = "127.0.0.1:" + std::to_string(m_http_port);
  448. 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.*");
  449. }
  450. }
  451. //winrt::fire_and_forget CLashConfig::_StartClash()
  452. //{
  453. // if (CProcessManager::getSingletonPtr()->Start())
  454. // {
  455. // CApp::getSingletonPtr()->SetCLashRuning(true);
  456. //
  457. //
  458. //
  459. // /*HANDLE hClashProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess;
  460. //
  461. // for (size_t i = 0; i < 5; ++i) {
  462. //
  463. // }*/
  464. // }
  465. //
  466. //
  467. //
  468. //}
  469. //
  470. //winrt::Windows::Foundation::IAsyncAction CLashConfig::ProcessMonitor()
  471. //{
  472. // HANDLE hSubProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess,
  473. // hClashProcess = CProcessManager::getSingletonPtr()->GetClashProcessInfo().hProcess;
  474. //
  475. // winrt::resume_on_signal(hClashProcess);
  476. //
  477. // /*std::future<void> f = std::async(std::launch::async, []() {
  478. // })*/
  479. //
  480. //
  481. //
  482. //
  483. //}