diff --git a/Netch/Controllers/DNSController.cs b/Netch/Controllers/DNSController.cs index 0c4ab3f0..5b3363c8 100644 --- a/Netch/Controllers/DNSController.cs +++ b/Netch/Controllers/DNSController.cs @@ -1,20 +1,21 @@ using System; using System.Diagnostics; -using System.IO; using Netch.Forms; using Netch.Utils; namespace Netch.Controllers { - public class DNSController + public class DNSController : Controller { - /// - /// 进程实例 - /// - public Process Instance; + public DNSController() + { + MainName = "unbound"; + ExtFiles = new[] {"unbound-service.conf", "forward-zone.conf"}; + ready = BeforeStartProgress(); + } /// - /// 启动DNS服务 + /// 启动DNS服务 /// /// public bool Start() @@ -22,13 +23,7 @@ namespace Netch.Controllers MainForm.Instance.StatusText(i18N.Translate("Starting dns Service")); try { - if (!File.Exists("bin\\unbound.exe") && !File.Exists("bin\\unbound-service.conf") && !File.Exists("bin\\forward-zone.conf")) - { - return false; - } - - Instance = MainController.GetProcess(); - Instance.StartInfo.FileName = "bin\\unbound.exe"; + Instance = MainController.GetProcess("bin\\unbound.exe"); Instance.StartInfo.Arguments = "-c unbound-service.conf -v"; @@ -49,35 +44,9 @@ namespace Netch.Controllers } } - /// - /// 停止 - /// - public void Stop() - { - try - { - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - Instance.WaitForExit(); - } - } - catch (Exception e) - { - Logging.Info(e.ToString()); - } - } - public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) { - if (!string.IsNullOrWhiteSpace(e.Data)) - { - if (File.Exists("logging\\dns-unbound.log")) - { - File.Delete("logging\\dns-unbound.log"); - } - File.AppendAllText("logging\\dns-unbound.log", $"{e.Data}\r\n"); - } + WriteLog(e); } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/HTTPController.cs b/Netch/Controllers/HTTPController.cs index 87716f36..9a92feff 100644 --- a/Netch/Controllers/HTTPController.cs +++ b/Netch/Controllers/HTTPController.cs @@ -9,16 +9,16 @@ namespace Netch.Controllers { public class HTTPController { - private bool prevEnabled; - private string prevBypass, prevHTTP, prevPAC; - /// /// 实例 /// public PrivoxyController pPrivoxyController = new PrivoxyController(); + private string prevBypass, prevHTTP, prevPAC; + private bool prevEnabled; + /// - /// 启动 + /// 启动 /// /// 服务器 /// 模式 @@ -30,10 +30,7 @@ namespace Netch.Controllers { if (server.Type == "Socks5") { - if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) - { - return false; - } + if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) return false; pPrivoxyController.Start(server, mode); } @@ -42,17 +39,12 @@ namespace Netch.Controllers pPrivoxyController.Start(server, mode); } - if (mode.Type != 5) - { - NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", ""); - } + if (mode.Type != 5) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", ""); } catch (Exception e) { - if (MessageBoxX.Show(i18N.Translate("Failed to set the system proxy, it may be caused by the lack of dependent programs. Do you want to jump to Netch's official website to download dependent programs?"), confirm:true) == DialogResult.OK) - { - Process.Start("https://netch.org/#/?id=%e4%be%9d%e8%b5%96"); - } + if (MessageBoxX.Show(i18N.Translate("Failed to set the system proxy, it may be caused by the lack of dependent programs. Do you want to jump to Netch's official website to download dependent programs?"), confirm: true) == DialogResult.OK) Process.Start("https://netch.org/#/?id=%e4%be%9d%e8%b5%96"); + Logging.Info("设置系统代理失败" + e); return false; } @@ -69,18 +61,16 @@ namespace Netch.Controllers prevPAC = prevHTTP = prevBypass = ""; return; } - + prevPAC = registry.GetValue("AutoConfigURL")?.ToString() ?? ""; - if ((registry.GetValue("ProxyEnable")?.Equals(1) ?? false) || prevPAC != "") - { - prevEnabled = true; - } + if ((registry.GetValue("ProxyEnable")?.Equals(1) ?? false) || prevPAC != "") prevEnabled = true; + prevHTTP = registry.GetValue("ProxyServer")?.ToString() ?? ""; prevBypass = registry.GetValue("ProxyOverride")?.ToString() ?? ""; } /// - /// 停止 + /// 停止 /// public void Stop() { @@ -108,4 +98,4 @@ namespace Netch.Controllers } } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/Interface/Controller.cs b/Netch/Controllers/Interface/Controller.cs new file mode 100644 index 00000000..e5a5ce2f --- /dev/null +++ b/Netch/Controllers/Interface/Controller.cs @@ -0,0 +1,101 @@ +using System; +using System.Diagnostics; +using System.IO; +using Netch.Models; +using Netch.Utils; + +namespace Netch.Controllers +{ + public class Controller + { + protected string[] ExtFiles; + + /// + /// 进程实例 + /// + public Process Instance; + + /// + /// 程序名 + /// + public string MainName; + + public bool ready; + + /// + /// 当前状态 + /// + protected State State = State.Waiting; + + /// + /// 停止 + /// + public void Stop() + { + try + { + if (Instance == null || Instance.HasExited) return; + Instance.Kill(); + Instance.WaitForExit(); + } + catch (Exception e) + { + Logging.Info(e.ToString()); + } + } + + + /// + /// 杀残留进程,清除日志,检查文件 + /// + /// + protected bool BeforeStartProgress() + { + var result = false; + // 杀残留 + MainController.KillProcessByName(MainName); + // 清日志 + try + { + if (File.Exists($"logging\\{MainName}.log")) File.Delete($"logging\\{MainName}.log"); + } + catch (Exception) + { + // ignore + } + + // 检查文件 + if (!File.Exists($"bin\\{MainName}.exe")) Logging.Info($"bin\\{MainName}.exe 文件不存在"); + + if (ExtFiles == null) + result = true; + else + foreach (var f in ExtFiles) + if (!File.Exists($"bin\\{f}")) + Logging.Info($"bin\\{f}.exe 文件不存在"); + + if (!ready) Logging.Info(MainName + "未能就绪"); + return result; + } + + /// + /// 写日志 + /// + /// + /// e是否为空 + public bool WriteLog(DataReceivedEventArgs e) + { + if (string.IsNullOrWhiteSpace(e.Data)) return false; + try + { + File.AppendAllText($"logging\\{MainName}.log", $@"{e.Data}{Global.EOF}"); + } + catch (Exception exception) + { + Logging.Info($"写入{MainName}日志失败" + exception); + } + + return true; + } + } +} \ No newline at end of file diff --git a/Netch/Controllers/Interface/ServerClient.cs b/Netch/Controllers/Interface/ServerClient.cs new file mode 100644 index 00000000..40db32f0 --- /dev/null +++ b/Netch/Controllers/Interface/ServerClient.cs @@ -0,0 +1,32 @@ +using System.Diagnostics; +using Netch.Models; + +namespace Netch.Controllers +{ + public abstract class ServerClient : Controller + { + /// + /// 启动 + /// + /// 服务器 + /// 模式 + /// 是否启动成功 + public abstract bool Start(Server server, Mode mode); + + /// + /// ServerClient 停止 + /// + /// 注意 对象类型 以调用子类 Stop() 方法 + /// + public new void Stop() + { + base.Stop(); + + // SSController Stop() + // 不能自动转换对象类型的兼容代码 :( + if (Global.Settings.BootShadowsocksFromDLL) NativeMethods.Shadowsocks.Stop(); + } + + public abstract void OnOutputDataReceived(object sender, DataReceivedEventArgs e); + } +} \ No newline at end of file diff --git a/Netch/Controllers/MainController.cs b/Netch/Controllers/MainController.cs index fcfb6303..6ce17c77 100644 --- a/Netch/Controllers/MainController.cs +++ b/Netch/Controllers/MainController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -11,65 +12,34 @@ namespace Netch.Controllers { public class MainController { - [DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")] - public static extern uint FlushDNSResolverCache(); - public static Process GetProcess() - { - var process = new Process(); - process.StartInfo.WorkingDirectory = string.Format("{0}\\bin", Directory.GetCurrentDirectory()); - process.StartInfo.CreateNoWindow = true; - process.StartInfo.RedirectStandardError = true; - process.StartInfo.RedirectStandardInput = true; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.UseShellExecute = false; - process.EnableRaisingEvents = true; - - return process; - } - - /// - /// SS 控制器 - /// - public SSController pSSController; - - /// - /// SSR 控制器 - /// - public SSRController pSSRController; - - /// - /// V2Ray 控制器 - /// - public VMessController pVMessController; - - /// - /// Trojan 控制器 - /// - public TrojanController pTrojanController; - - /// - /// NF 控制器 - /// - public NFController pNFController; - /// /// HTTP 控制器 /// public HTTPController pHTTPController; + /// + /// NF 控制器 + /// + public NFController pNFController; + + /// + /// NTT 控制器 + /// + public NTTController pNTTController; + + public ServerClient pServerClientController; + /// /// TUN/TAP 控制器 /// public TUNTAPController pTUNTAPController; - /// - /// NTT 控制器 - /// - public NTTController pNTTController; + [DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")] + public static extern uint FlushDNSResolverCache(); /// - /// 启动 + /// 启动 /// /// 服务器 /// 模式 @@ -79,207 +49,129 @@ namespace Netch.Controllers FlushDNSResolverCache(); var result = false; - switch (server.Type) + if (server.Type == "Socks5") { - case "Socks5": - if (mode.Type == 4) - { + result = mode.Type != 4; + } + else + { + switch (server.Type) + { + case "SS": + pServerClientController = new SSController(); + break; + case "SSR": + pServerClientController = new SSRController(); + break; + case "VMess": + pServerClientController = new VMessController(); + break; + case "Trojan": + pServerClientController = new TrojanController(); + break; + } + + MainForm.Instance.StatusText(i18N.Translate("Starting ", pServerClientController.MainName)); + if (pServerClientController.ready) result = pServerClientController.Start(server, mode); + } + + if (result) // If server runs,then run mode + switch (mode.Type) + { + case 0: // 进程代理模式 + pNFController ??= new NFController(); + pNTTController ??= new NTTController(); + if (pNFController.ready) result = pNFController.Start(server, mode, false); + + if (!result && pNFController.ready) + { + MainForm.Instance.StatusText(i18N.Translate("Restarting Redirector")); + Logging.Info("正常启动失败后尝试停止驱动服务再重新启动"); + //正常启动失败后尝试停止驱动服务再重新启动 + result = pNFController.Start(server, mode, true); + } + + if (result) + Task.Run(() => pNTTController.Start()); + break; + case 1: // TUN/TAP 黑名单代理模式 + case 2: // TUN/TAP 白名单代理模式 + pTUNTAPController ??= new TUNTAPController(); + pNTTController ??= new NTTController(); + result = pTUNTAPController.Start(server, mode); + if (result) + Task.Run(() => pNTTController.Start()); + break; + case 3: // HTTP 系统代理和 Socks5 和 HTTP 代理模式 + case 5: + pHTTPController ??= new HTTPController(); + result = pHTTPController.Start(server, mode); + break; + case 4: // Socks5 代理模式,不需要启动额外的Server + break; + default: result = false; - } - else - { - result = true; - } - break; - case "SS": - KillProcess("Shadowsocks"); - if (pSSController == null) - { - pSSController = new SSController(); - } - result = pSSController.Start(server, mode); - break; - case "SSR": - KillProcess("ShadowsocksR"); - if (pSSRController == null) - { - pSSRController = new SSRController(); - } - result = pSSRController.Start(server, mode); - break; - case "VMess": - KillProcess("v2ray"); - if (pVMessController == null) - { - pVMessController = new VMessController(); - } - result = pVMessController.Start(server, mode); - break; - case "Trojan": - KillProcess("Trojan"); - if (pTrojanController == null) - { - pTrojanController = new TrojanController(); - } - result = pTrojanController.Start(server, mode); - break; - } + break; + } - if (result) - { - if (mode.Type == 0) - { - if (pNFController == null) - { - pNFController = new NFController(); - } - if (pNTTController == null) - { - pNTTController = new NTTController(); - } - // 进程代理模式,启动 NF 控制器 - result = pNFController.Start(server, mode, false); - if (!result) - { - MainForm.Instance.StatusText(i18N.Translate("Restarting Redirector")); - Logging.Info("正常启动失败后尝试停止驱动服务再重新启动"); - //正常启动失败后尝试停止驱动服务再重新启动 - result = pNFController.Start(server, mode, true); - } - else - { - Task.Run(() => pNTTController.Start()); - } - } - else if (mode.Type == 1) - { - if (pTUNTAPController == null) - { - pTUNTAPController = new TUNTAPController(); - } - if (pNTTController == null) - { - pNTTController = new NTTController(); - } - // TUN/TAP 黑名单代理模式,启动 TUN/TAP 控制器 - result = pTUNTAPController.Start(server, mode); - if (result) - { - Task.Run(() => pNTTController.Start()); - } - } - else if (mode.Type == 2) - { - if (pTUNTAPController == null) - { - pTUNTAPController = new TUNTAPController(); - } - if (pNTTController == null) - { - pNTTController = new NTTController(); - } - // TUN/TAP 白名单代理模式,启动 TUN/TAP 控制器 - result = pTUNTAPController.Start(server, mode); - if (result) - { - Task.Run(() => pNTTController.Start()); - } - } - else if (mode.Type == 3 || mode.Type == 5) - { - if (pHTTPController == null) - { - pHTTPController = new HTTPController(); - } - // HTTP 系统代理和 Socks5 和 HTTP 代理模式,启动 HTTP 控制器 - result = pHTTPController.Start(server, mode); - } - else if (mode.Type == 4) - { - // Socks5 代理模式,不需要启动额外的控制器 - } - else - { - result = false; - } - } - - if (!result) - { - Stop(); - } + if (!result) Stop(); return result; } /// - /// 停止 + /// 停止 /// public void Stop() { - if (pSSController != null) - { - pSSController.Stop(); - } - else if (pSSRController != null) - { - pSSRController.Stop(); - } - else if (pVMessController != null) - { - pVMessController.Stop(); - } - else if (pTrojanController != null) - { - pTrojanController.Stop(); - } + pServerClientController?.Stop(); if (pNFController != null) - { pNFController.Stop(); - } else if (pTUNTAPController != null) - { pTUNTAPController.Stop(); - } - else if (pHTTPController != null) - { - pHTTPController.Stop(); - } + else + pHTTPController?.Stop(); - if (pNTTController != null) - { - pNTTController.Stop(); - } + pNTTController?.Stop(); } - public void KillProcess(string name) + public static Process GetProcess(string path = null) { - var processes = Process.GetProcessesByName(name); - foreach (var p in processes) + var p = new Process { - if (IsChildProcess(p, name)) + StartInfo = { - p.Kill(); - } - } + Arguments = "", + WorkingDirectory = $"{Global.NetchDir}\\bin", + CreateNoWindow = true, + RedirectStandardError = true, + RedirectStandardInput = true, + RedirectStandardOutput = true, + UseShellExecute = false + }, + EnableRaisingEvents = true + }; + if (path != null) p.StartInfo.FileName = Path.GetFullPath(path); + return p; } - private static bool IsChildProcess(Process process, string name) + public static void KillProcessByName(string name) { - bool result; try { - var FileName = (Directory.GetCurrentDirectory() + "\\bin\\" + name + ".exe").ToLower(); - var procFileName = process.MainModule.FileName.ToLower(); - result = FileName.Equals(procFileName, StringComparison.Ordinal); + foreach (var p in Process.GetProcessesByName(name)) + if (p.MainModule != null && p.MainModule.FileName.StartsWith(Global.NetchDir)) + p.Kill(); } - catch (Exception e) + catch (Win32Exception e) { - Logging.Info(e.Message); - result = false; + Logging.Info($"结束进程 {name} 错误: " + e.Message); + } + catch (Exception) + { + // ignore } - return result; } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/NFController.cs b/Netch/Controllers/NFController.cs index ad9071b6..a67f766e 100644 --- a/Netch/Controllers/NFController.cs +++ b/Netch/Controllers/NFController.cs @@ -11,13 +11,8 @@ using nfapinet; namespace Netch.Controllers { - public class NFController + public class NFController : Controller { - /// - /// 流量变动事件 - /// - public event BandwidthUpdateHandler OnBandwidthUpdated; - /// /// 流量变动处理器 /// @@ -25,21 +20,22 @@ namespace Netch.Controllers /// 下载 public delegate void BandwidthUpdateHandler(long upload, long download); + /// 驱动文件路径 + private readonly string _driverPath = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys"; + + public NFController() + { + MainName = "Redirector"; + ready = BeforeStartProgress(); + } + /// - /// 进程实例 + /// 流量变动事件 /// - public Process Instance; + public event BandwidthUpdateHandler OnBandwidthUpdated; /// - /// 当前状态 - /// - public State State = State.Waiting; - - // 生成驱动文件路径 - public string driverPath = string.Format("{0}\\drivers\\netfilter2.sys", Environment.SystemDirectory); - - /// - /// 启动 + /// 启动 /// /// 服务器 /// 模式 @@ -50,13 +46,8 @@ namespace Netch.Controllers if (!StopServiceAndRestart) MainForm.Instance.StatusText(i18N.Translate("Starting Redirector")); - if (!File.Exists("bin\\Redirector.exe")) - { - return false; - } - // 检查驱动是否存在 - if (File.Exists(driverPath)) + if (File.Exists(_driverPath)) { // 生成系统版本 var version = $"{Environment.OSVersion.Version.Major.ToString()}.{Environment.OSVersion.Version.Minor.ToString()}"; @@ -81,7 +72,7 @@ namespace Netch.Controllers } // 检查驱动版本号 - var SystemfileVerInfo = FileVersionInfo.GetVersionInfo(driverPath); + var SystemfileVerInfo = FileVersionInfo.GetVersionInfo(_driverPath); var BinFileVerInfo = FileVersionInfo.GetVersionInfo(string.Format("bin\\{0}", driverName)); if (!SystemfileVerInfo.FileVersion.Equals(BinFileVerInfo.FileVersion)) @@ -96,10 +87,11 @@ namespace Netch.Controllers service.Stop(); service.WaitForStatus(ServiceControllerStatus.Stopped); } + NFAPI.nf_unRegisterDriver("netfilter2"); //删除老驱动 - File.Delete(driverPath); + File.Delete(_driverPath); if (!InstallDriver()) return false; @@ -109,16 +101,11 @@ namespace Netch.Controllers { Logging.Info("更新驱动出错"); } - } - } else { - if (!InstallDriver()) - { - return false; - } + if (!InstallDriver()) return false; } try @@ -157,11 +144,10 @@ namespace Netch.Controllers processes += proc; processes += ","; } + processes += "NTT.exe"; - Instance = MainController.GetProcess(); - Instance.StartInfo.FileName = "bin\\Redirector.exe"; - Instance.StartInfo.Arguments = ""; + Instance = MainController.GetProcess("bin\\Redirector.exe"); if (server.Type != "Socks5") { @@ -177,21 +163,14 @@ namespace Netch.Controllers } Instance.StartInfo.Arguments += $"-r {result}:{server.Port} -p \"{processes}\""; - if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) - { - Instance.StartInfo.Arguments += $" -username \"{server.Username}\" -password \"{server.Password}\""; - } - } - - if (File.Exists("logging\\redirector.log")) - { - File.Delete("logging\\redirector.log"); + if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) Instance.StartInfo.Arguments += $" -username \"{server.Username}\" -password \"{server.Password}\""; } Instance.StartInfo.Arguments += $" -t {Global.Settings.RedirectorTCPPort}"; Logging.Info(Instance.StartInfo.Arguments); Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; + State = State.Starting; Instance.Start(); Instance.BeginOutputReadLine(); @@ -201,10 +180,7 @@ namespace Netch.Controllers { Thread.Sleep(1000); - if (State == State.Started) - { - return true; - } + if (State == State.Started) return true; } Logging.Info("NF 进程启动超时"); @@ -212,27 +188,8 @@ namespace Netch.Controllers return false; } - /// - /// 停止 - /// - public void Stop() - { - try - { - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - Instance.WaitForExit(); - } - } - catch (Exception e) - { - Logging.Info(e.ToString()); - } - } public bool InstallDriver() { - Logging.Info("安装驱动中"); // 生成系统版本 var version = $"{Environment.OSVersion.Version.Major.ToString()}.{Environment.OSVersion.Version.Minor.ToString()}"; @@ -243,17 +200,17 @@ namespace Netch.Controllers switch (version) { case "10.0": - File.Copy("bin\\Win-10.sys", driverPath); + File.Copy("bin\\Win-10.sys", _driverPath); Logging.Info("已复制 Win10 驱动"); break; case "6.3": case "6.2": - File.Copy("bin\\Win-8.sys", driverPath); + File.Copy("bin\\Win-8.sys", _driverPath); Logging.Info("已复制 Win8 驱动"); break; case "6.1": case "6.0": - File.Copy("bin\\Win-7.sys", driverPath); + File.Copy("bin\\Win-7.sys", _driverPath); Logging.Info("已复制 Win7 驱动"); break; default: @@ -267,6 +224,7 @@ namespace Netch.Controllers Logging.Info(e.ToString()); return false; } + MainForm.Instance.StatusText(i18N.Translate("Register driver")); // 注册驱动文件 var result = NFAPI.nf_registerDriver("netfilter2"); @@ -275,51 +233,37 @@ namespace Netch.Controllers Logging.Info($"注册驱动失败,返回值:{result}"); return false; } + return true; } public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) { - if (!string.IsNullOrWhiteSpace(e.Data)) + if (!WriteLog(e)) return; + if (State == State.Starting) { - File.AppendAllText("logging\\redirector.log", string.Format("{0}\r\n", e.Data)); - - if (State == State.Starting) + if (Instance.HasExited) + State = State.Stopped; + else if (e.Data.Contains("Started")) + State = State.Started; + else if (e.Data.Contains("Failed") || e.Data.Contains("Unable")) State = State.Stopped; + } + else if (State == State.Started) + { + if (e.Data.StartsWith("[APP][Bandwidth]")) { - if (Instance.HasExited) + var splited = e.Data.Replace("[APP][Bandwidth]", "").Trim().Split(','); + if (splited.Length == 2) { - State = State.Stopped; - } - else if (e.Data.Contains("Started")) - { - State = State.Started; - } - else if (e.Data.Contains("Failed") || e.Data.Contains("Unable")) - { - State = State.Stopped; - } - } - else if (State == State.Started) - { - if (e.Data.StartsWith("[APP][Bandwidth]")) - { - var splited = e.Data.Replace("[APP][Bandwidth]", "").Trim().Split(','); - if (splited.Length == 2) - { - var uploadSplited = splited[0].Split(':'); - var downloadSplited = splited[1].Split(':'); + var uploadSplited = splited[0].Split(':'); + var downloadSplited = splited[1].Split(':'); - if (uploadSplited.Length == 2 && downloadSplited.Length == 2) - { - if (long.TryParse(uploadSplited[1], out var upload) && long.TryParse(downloadSplited[1], out var download)) - { - Task.Run(() => OnBandwidthUpdated(upload, download)); - } - } - } + if (uploadSplited.Length == 2 && downloadSplited.Length == 2) + if (long.TryParse(uploadSplited[1], out var upload) && long.TryParse(downloadSplited[1], out var download)) + Task.Run(() => OnBandwidthUpdated(upload, download)); } } } } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/NTTController.cs b/Netch/Controllers/NTTController.cs index eb9b19c7..7e9fc39f 100644 --- a/Netch/Controllers/NTTController.cs +++ b/Netch/Controllers/NTTController.cs @@ -8,20 +8,16 @@ using Netch.Utils; namespace Netch.Controllers { - public class NTTController + public class NTTController : Controller { - /// - /// 进程实例 - /// - public Process Instance; + public NTTController() + { + MainName = "NTT"; + ready = BeforeStartProgress(); + } /// - /// 当前状态 - /// - public State State = State.Waiting; - - /// - /// 启动NatTypeTester + /// 启动NatTypeTester /// /// public (bool, string, string, string) Start() @@ -30,13 +26,7 @@ namespace Netch.Controllers MainForm.Instance.NatTypeStatusText(i18N.Translate("Starting NatTester")); try { - if (!File.Exists("bin\\NTT.exe")) - { - return (false, null, null, null); - } - - Instance = MainController.GetProcess(); - Instance.StartInfo.FileName = "bin\\NTT.exe"; + Instance = MainController.GetProcess("bin\\NTT.exe"); Instance.StartInfo.Arguments = $" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}"; @@ -49,7 +39,7 @@ namespace Netch.Controllers Instance.BeginErrorReadLine(); Instance.WaitForExit(); - var result = File.ReadAllText("logging\\NTT.log").Split('#'); + var result = File.ReadAllText($"logging\\{MainName}.log").Split('#'); var natType = result[0]; var localEnd = result[1]; var publicEnd = result[2]; @@ -65,36 +55,9 @@ namespace Netch.Controllers } } - /// - /// 停止 - /// - public void Stop() - { - try - { - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - Instance.WaitForExit(); - } - } - catch (Exception e) - { - Logging.Info(e.ToString()); - } - } - public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) { - if (!string.IsNullOrWhiteSpace(e.Data)) - { - if (File.Exists("logging\\NTT.log")) - { - File.Delete("logging\\NTT.log"); - } - - File.AppendAllText("logging\\NTT.log", $"{e.Data}\r\n"); - } + WriteLog(e); } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/PrivoxyController.cs b/Netch/Controllers/PrivoxyController.cs index 4a2cf7d7..9e9fbc38 100644 --- a/Netch/Controllers/PrivoxyController.cs +++ b/Netch/Controllers/PrivoxyController.cs @@ -1,59 +1,33 @@ -using System; -using System.Diagnostics; +using System.Diagnostics; using System.IO; using Netch.Models; namespace Netch.Controllers { - public class PrivoxyController + public class PrivoxyController : Controller { - /// - /// 进程实例 - /// - public Process Instance; + public PrivoxyController() + { + MainName = "Privoxy"; + ExtFiles = new[] {"default.conf"}; + ready = BeforeStartProgress(); + } - /// - /// 启动 - /// - /// 服务器 - /// 模式 - /// 是否启动成功 public bool Start(Server server, Mode mode) { - foreach (var proc in Process.GetProcessesByName("Privoxy")) - { - try - { - proc.Kill(); - } - catch (Exception) - { - // 跳过 - } - } - - if (!File.Exists("bin\\Privoxy.exe") || !File.Exists("bin\\default.conf")) - { - return false; - } - if (server.Type != "Socks5") - { File.WriteAllText("data\\privoxy.conf", File.ReadAllText("bin\\default.conf").Replace("_BIND_PORT_", Global.Settings.HTTPLocalPort.ToString()).Replace("_DEST_PORT_", Global.Settings.Socks5LocalPort.ToString()).Replace("0.0.0.0", Global.Settings.LocalAddress)); - } else - { File.WriteAllText("data\\privoxy.conf", File.ReadAllText("bin\\default.conf").Replace("_BIND_PORT_", Global.Settings.HTTPLocalPort.ToString()).Replace("_DEST_PORT_", server.Port.ToString()).Replace("s 0.0.0.0", $"s {Global.Settings.LocalAddress}").Replace("/ 127.0.0.1", $"/ {server.Hostname}")); - } Instance = new Process { StartInfo = { - FileName = string.Format("{0}\\bin\\Privoxy.exe", Directory.GetCurrentDirectory()), + FileName = $"{Global.NetchDir}\\bin\\Privoxy.exe", Arguments = "..\\data\\privoxy.conf", - WorkingDirectory = string.Format("{0}\\bin", Directory.GetCurrentDirectory()), + WorkingDirectory = $"{Global.NetchDir}\\bin", WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = true, CreateNoWindow = true @@ -63,24 +37,5 @@ namespace Netch.Controllers return true; } - - /// - /// 停止 - /// - public void Stop() - { - try - { - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - Instance.WaitForExit(); - } - } - catch (Exception) - { - // 跳过 - } - } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/SSController.cs b/Netch/Controllers/SSController.cs index b3bbb4c0..bb04cdf4 100644 --- a/Netch/Controllers/SSController.cs +++ b/Netch/Controllers/SSController.cs @@ -1,37 +1,21 @@ -using System; -using System.Diagnostics; -using System.IO; +using System.Diagnostics; using System.Text; using System.Threading; -using Netch.Forms; using Netch.Models; using Netch.Utils; namespace Netch.Controllers { - public class SSController + public class SSController : ServerClient { - /// - /// 进程实例 - /// - public Process Instance; - - /// - /// 当前状态 - /// - public State State = State.Waiting; - - /// - /// 启动 - /// - /// 服务器 - /// 模式 - /// 是否启动成功 - public bool Start(Server server, Mode mode) + public SSController() { - MainForm.Instance.StatusText(i18N.Translate("Starting Shadowsocks")); + MainName = "Shadowsocks"; + ready = BeforeStartProgress(); + } - File.Delete("logging\\shadowsocks.log"); + public override bool Start(Server server, Mode mode) + { //从DLL启动Shaowsocks if (Global.Settings.BootShadowsocksFromDLL && (mode.Type == 0 || mode.Type == 1 || mode.Type == 2 || mode.Type == 3)) { @@ -46,6 +30,7 @@ namespace Netch.Controllers Logging.Info("DLL SS INFO 设置失败!"); return false; } + Logging.Info("DLL SS INFO 设置成功!"); if (!NativeMethods.Shadowsocks.Start()) @@ -54,31 +39,23 @@ namespace Netch.Controllers Logging.Info("DLL SS 启动失败!"); return false; } + Logging.Info("DLL SS 启动成功!"); State = State.Started; return true; } - if (!File.Exists("bin\\Shadowsocks.exe")) - { - return false; - } - Instance = MainController.GetProcess(); - Instance.StartInfo.FileName = "bin\\Shadowsocks.exe"; + Instance = MainController.GetProcess("bin\\Shadowsocks.exe"); + + #region Instance.Arguments if (!string.IsNullOrWhiteSpace(server.Plugin) && !string.IsNullOrWhiteSpace(server.PluginOption)) - { Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u --plugin {server.Plugin} --plugin-opts \"{server.PluginOption}\""; - } else - { Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -m {server.EncryptMethod} -k \"{server.Password}\" -u"; - } + if (mode.BypassChina) Instance.StartInfo.Arguments += " --acl default.acl"; - if (mode.BypassChina) - { - Instance.StartInfo.Arguments += " --acl default.acl"; - } + #endregion Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; @@ -91,10 +68,7 @@ namespace Netch.Controllers { Thread.Sleep(10); - if (State == State.Started) - { - return true; - } + if (State == State.Started) return true; if (State == State.Stopped) { @@ -111,59 +85,25 @@ namespace Netch.Controllers } /// - /// 停止 + /// SSController 停止 /// - public void Stop() + public new void Stop() { - try - { - if (Global.Settings.BootShadowsocksFromDLL) - { - NativeMethods.Shadowsocks.Stop(); - return; - } - - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - Instance.WaitForExit(); - } - } - catch (Exception e) - { - Logging.Info(e.ToString()); - } + base.Stop(); + if (Global.Settings.BootShadowsocksFromDLL) NativeMethods.Shadowsocks.Stop(); } - public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) + public override void OnOutputDataReceived(object sender, DataReceivedEventArgs e) { - try + if (!WriteLog(e)) return; + if (State == State.Starting) { - if (!string.IsNullOrWhiteSpace(e.Data)) - { - File.AppendAllText("logging\\shadowsocks.log", $"{e.Data}\r\n"); - - if (State == State.Starting) - { - if (Instance.HasExited) - { - State = State.Stopped; - } - else if (e.Data.Contains("listening at")) - { - State = State.Started; - } - else if (e.Data.Contains("Invalid config path") || e.Data.Contains("usage") || e.Data.Contains("plugin service exit unexpectedly")) - { - State = State.Stopped; - } - } - } - } - catch (Exception ec) - { - Logging.Info("写入Shadowsocks日志失败" + ec); + if (Instance.HasExited) + State = State.Stopped; + else if (e.Data.Contains("listening at")) + State = State.Started; + else if (e.Data.Contains("Invalid config path") || e.Data.Contains("usage") || e.Data.Contains("plugin service exit unexpectedly")) State = State.Stopped; } } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/SSRController.cs b/Netch/Controllers/SSRController.cs index ba243802..9df0d015 100644 --- a/Netch/Controllers/SSRController.cs +++ b/Netch/Controllers/SSRController.cs @@ -1,88 +1,59 @@ -using System; -using System.Diagnostics; -using System.IO; +using System.Diagnostics; using System.Threading; -using Netch.Forms; using Netch.Models; using Netch.Utils; namespace Netch.Controllers { - public class SSRController + public class SSRController : ServerClient { - /// - /// 进程实例 - /// - public Process Instance; - - /// - /// 当前状态 - /// - public State State = State.Waiting; - - /// - /// 启动 - /// - /// 服务器 - /// 模式 - /// 是否启动成功 - public bool Start(Server server, Mode mode) + public SSRController() { - MainForm.Instance.StatusText(i18N.Translate("Starting ShadowsocksR")); + MainName = "ShadowsocksR"; + ready = BeforeStartProgress(); + } - File.Delete("logging\\shadowsocksr.log"); - - if (!File.Exists("bin\\ShadowsocksR.exe")) - { - return false; - } - - Instance = MainController.GetProcess(); + public override bool Start(Server server, Mode mode) + { + Instance = MainController.GetProcess("bin\\ShadowsocksR.exe"); Instance.StartInfo.FileName = "bin\\ShadowsocksR.exe"; + Instance.OutputDataReceived += OnOutputDataReceived; + Instance.ErrorDataReceived += OnOutputDataReceived; + + #region Instance.Arguments + Instance.StartInfo.Arguments = $"-s {server.Hostname} -p {server.Port} -k \"{server.Password}\" -m {server.EncryptMethod} -t 120"; if (!string.IsNullOrEmpty(server.Protocol)) { Instance.StartInfo.Arguments += $" -O {server.Protocol}"; - if (!string.IsNullOrEmpty(server.ProtocolParam)) - { - Instance.StartInfo.Arguments += $" -G \"{server.ProtocolParam}\""; - } + if (!string.IsNullOrEmpty(server.ProtocolParam)) Instance.StartInfo.Arguments += $" -G \"{server.ProtocolParam}\""; } if (!string.IsNullOrEmpty(server.OBFS)) { Instance.StartInfo.Arguments += $" -o {server.OBFS}"; - if (!string.IsNullOrEmpty(server.OBFSParam)) - { - Instance.StartInfo.Arguments += $" -g \"{server.OBFSParam}\""; - } + if (!string.IsNullOrEmpty(server.OBFSParam)) Instance.StartInfo.Arguments += $" -g \"{server.OBFSParam}\""; } Instance.StartInfo.Arguments += $" -b {Global.Settings.LocalAddress} -l {Global.Settings.Socks5LocalPort} -u"; - if (mode.BypassChina) - { - Instance.StartInfo.Arguments += " --acl default.acl"; - } + if (mode.BypassChina) Instance.StartInfo.Arguments += " --acl default.acl"; - Instance.OutputDataReceived += OnOutputDataReceived; - Instance.ErrorDataReceived += OnOutputDataReceived; + #endregion State = State.Starting; Instance.Start(); Instance.BeginOutputReadLine(); Instance.BeginErrorReadLine(); + for (var i = 0; i < 1000; i++) { Thread.Sleep(10); - if (State == State.Started) - { - return true; - } + if (State == State.Started) return true; if (State == State.Stopped) { @@ -98,47 +69,17 @@ namespace Netch.Controllers return false; } - /// - /// 停止 - /// - public void Stop() + public override void OnOutputDataReceived(object sender, DataReceivedEventArgs e) { - try + if (!WriteLog(e)) return; + if (State == State.Starting) { - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - Instance.WaitForExit(); - } - } - catch (Exception e) - { - Logging.Info(e.ToString()); - } - } - - public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) - { - if (!string.IsNullOrWhiteSpace(e.Data)) - { - File.AppendAllText("logging\\shadowsocksr.log", $"{e.Data}\r\n"); - - if (State == State.Starting) - { - if (Instance.HasExited) - { - State = State.Stopped; - } - else if (e.Data.Contains("listening at")) - { - State = State.Started; - } - else if (e.Data.Contains("Invalid config path") || e.Data.Contains("usage")) - { - State = State.Stopped; - } - } + if (Instance.HasExited) + State = State.Stopped; + else if (e.Data.Contains("listening at")) + State = State.Started; + else if (e.Data.Contains("Invalid config path") || e.Data.Contains("usage")) State = State.Stopped; } } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/TUNTAPController.cs b/Netch/Controllers/TUNTAPController.cs index ce54400d..ea759620 100644 --- a/Netch/Controllers/TUNTAPController.cs +++ b/Netch/Controllers/TUNTAPController.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net; @@ -12,36 +11,33 @@ using Netch.Utils; namespace Netch.Controllers { - public class TUNTAPController + public class TUNTAPController : Controller { - /// - /// 进程实例(tun2socks) - /// - public Process Instance; + // ByPassLan IP + private readonly List BypassLanIPs = new List {"10.0.0.0/8", "172.16.0.0/16", "192.168.0.0/16"}; /// - /// 当前状态 + /// 本地 DNS 服务控制器 /// - public State State = State.Waiting; + public DNSController pDNSController = new DNSController(); - /// - /// 服务器 IP 地址 - /// - public IPAddress[] ServerAddresses = new IPAddress[0]; + public Mode SavedMode = new Mode(); /// /// 保存传入的规则 /// public Server SavedServer = new Server(); - public Mode SavedMode = new Mode(); /// - /// 本地 DNS 服务控制器 + /// 服务器 IP 地址 /// - public DNSController pDNSController = new DNSController(); + public IPAddress[] ServerAddresses = new IPAddress[0]; - // ByPassLan IP - List BypassLanIPs = new List { "10.0.0.0/8", "172.16.0.0/16", "192.168.0.0/16" }; + public TUNTAPController() + { + MainName = "tun2socks"; + ready = BeforeStartProgress(); + } /// /// 配置 TUNTAP 适配器 @@ -52,10 +48,7 @@ namespace Netch.Controllers var destination = Dns.GetHostAddressesAsync(SavedServer.Hostname); if (destination.Wait(1000)) { - if (destination.Result.Length == 0) - { - return false; - } + if (destination.Result.Length == 0) return false; ServerAddresses = destination.Result; } @@ -73,12 +66,8 @@ namespace Netch.Controllers Logging.Info("设置绕行规则 → 设置让服务器 IP 走直连"); // 让服务器 IP 走直连 foreach (var address in ServerAddresses) - { if (!IPAddress.IsLoopback(address)) - { NativeMethods.CreateRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } - } // 处理模式的绕过中国 if (SavedMode.BypassChina) @@ -104,10 +93,7 @@ namespace Netch.Controllers var info = ip.Split('/'); var address = IPAddress.Parse(info[0]); - if (!IPAddress.IsLoopback(address)) - { - NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } + if (!IPAddress.IsLoopback(address)) NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); } Logging.Info("设置绕行规则 → 处理绕过局域网 IP"); @@ -117,10 +103,7 @@ namespace Netch.Controllers var info = ip.Split('/'); var address = IPAddress.Parse(info[0]); - if (!IPAddress.IsLoopback(address)) - { - NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } + if (!IPAddress.IsLoopback(address)) NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); } if (SavedMode.Type == 2) // 处理仅规则内走直连 @@ -146,10 +129,7 @@ namespace Netch.Controllers { State = State.Stopped; - foreach (var address in ServerAddresses) - { - NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } + foreach (var address in ServerAddresses) NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index); return false; } @@ -161,12 +141,8 @@ namespace Netch.Controllers var info = ip.Split('/'); if (info.Length == 2) - { if (int.TryParse(info[1], out var prefix)) - { NativeMethods.CreateRoute(info[0], prefix, Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } - } } } else if (SavedMode.Type == 1) // 处理仅规则内走代理 @@ -177,34 +153,25 @@ namespace Netch.Controllers var info = ip.Split('/'); if (info.Length == 2) - { if (int.TryParse(info[1], out var prefix)) - { NativeMethods.CreateRoute(info[0], prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } - } } + //处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP,自己记录解析了返回的 IP,仅支持默认检测服务器 if (Global.Settings.STUN_Server == "stun.stunprotocol.org") - { try { var nttAddress = Dns.GetHostAddresses(Global.Settings.STUN_Server)[0]; - if (int.TryParse("32", out var prefix)) - { - NativeMethods.CreateRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } + if (int.TryParse("32", out var prefix)) NativeMethods.CreateRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); + var nttrAddress = Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0]; - if (int.TryParse("32", out var prefixr)) - { - NativeMethods.CreateRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } + if (int.TryParse("32", out var prefixr)) NativeMethods.CreateRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); } catch { Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表"); } - } + //处理DNS代理 if (Global.Settings.TUNTAP.ProxyDNS) { @@ -220,10 +187,7 @@ namespace Netch.Controllers dns = dns.Trim(); dns = dns.Substring(0, dns.Length - 1); - if (int.TryParse("32", out var prefix)) - { - NativeMethods.CreateRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } + if (int.TryParse("32", out var prefix)) NativeMethods.CreateRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); } else { @@ -237,6 +201,7 @@ namespace Netch.Controllers } } } + return true; } @@ -255,12 +220,8 @@ namespace Netch.Controllers var info = ip.Split('/'); if (info.Length == 2) - { if (int.TryParse(info[1], out var prefix)) - { NativeMethods.DeleteRoute(info[0], prefix, Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } - } } } else if (SavedMode.Type == 1) @@ -270,30 +231,23 @@ namespace Netch.Controllers var info = ip.Split('/'); if (info.Length == 2) - { if (int.TryParse(info[1], out var prefix)) - { NativeMethods.DeleteRoute(info[0], prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } - } } + if (Global.Settings.STUN_Server == "stun.stunprotocol.org") - { try { var nttAddress = Dns.GetHostAddresses(Global.Settings.STUN_Server)[0]; - if (int.TryParse("32", out var prefix)) - { - NativeMethods.DeleteRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } + if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); + var nttrAddress = Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0]; - if (int.TryParse("32", out var prefixr)) - { - NativeMethods.DeleteRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } + if (int.TryParse("32", out var prefixr)) NativeMethods.DeleteRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); } - catch { } - } + catch + { + } + if (Global.Settings.TUNTAP.ProxyDNS) { if (Global.Settings.TUNTAP.UseCustomDNS) @@ -307,17 +261,11 @@ namespace Netch.Controllers dns = dns.Trim(); dns = dns.Substring(0, dns.Length - 1); - if (int.TryParse("32", out var prefix)) - { - NativeMethods.DeleteRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } + if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); } else { - if (int.TryParse("32", out var prefix)) - { - NativeMethods.DeleteRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); - } + if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index); } } } @@ -327,24 +275,18 @@ namespace Netch.Controllers var info = ip.Split('/'); var address = IPAddress.Parse(info[0]); - if (!IPAddress.IsLoopback(address)) - { - NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } + if (!IPAddress.IsLoopback(address)) NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); } + foreach (var ip in BypassLanIPs) { var info = ip.Split('/'); var address = IPAddress.Parse(info[0]); - if (!IPAddress.IsLoopback(address)) - { - NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } + if (!IPAddress.IsLoopback(address)) NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); } if (SavedMode.BypassChina) - { using (var sr = new StringReader(Encoding.UTF8.GetString(Resources.CNIP))) { string text; @@ -356,63 +298,34 @@ namespace Netch.Controllers NativeMethods.DeleteRoute(info[0], int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index); } } - } foreach (var address in ServerAddresses) - { if (!IPAddress.IsLoopback(address)) - { NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index); - } - } + return true; } /// - /// 启动 + /// 启动 /// /// 配置 /// 是否成功 public bool Start(Server server, Mode mode) { MainForm.Instance.StatusText(i18N.Translate("Starting Tap")); - foreach (var proc in Process.GetProcessesByName("tun2socks")) - { - try - { - proc.Kill(); - } - catch (Exception) - { - // 跳过 - } - } - - if (!File.Exists("bin\\tun2socks.exe")) - { - return false; - } - - if (File.Exists("logging\\tun2socks.log")) - { - File.Delete("logging\\tun2socks.log"); - } SavedMode = mode; SavedServer = server; - if (!Configure()) - { - return false; - } + if (!Configure()) return false; Logging.Info("设置绕行规则"); SetupBypass(); Logging.Info("设置绕行规则完毕"); - Instance = new Process(); - Instance.StartInfo.WorkingDirectory = string.Format("{0}\\bin", Directory.GetCurrentDirectory()); - Instance.StartInfo.FileName = string.Format("{0}\\bin\\tun2socks.exe", Directory.GetCurrentDirectory()); + Instance = MainController.GetProcess("bin\\tun2socks.exe"); + var adapterName = TUNTAP.GetName(Global.TUNTAP.ComponentID); Logging.Info($"tun2sock使用适配器:{adapterName}"); @@ -436,26 +349,14 @@ namespace Netch.Controllers pDNSController.Start(); dns = "127.0.0.1"; } - if (Global.Settings.TUNTAP.UseFakeDNS) - { - dns += " -fakeDns"; - } + + if (Global.Settings.TUNTAP.UseFakeDNS) dns += " -fakeDns"; if (server.Type == "Socks5") - { Instance.StartInfo.Arguments = string.Format("-proxyServer {0}:{1} -tunAddr {2} -tunMask {3} -tunGw {4} -tunDns {5} -tunName \"{6}\"", server.Hostname, server.Port, Global.Settings.TUNTAP.Address, Global.Settings.TUNTAP.Netmask, Global.Settings.TUNTAP.Gateway, dns, adapterName); - } else - { Instance.StartInfo.Arguments = string.Format("-proxyServer 127.0.0.1:{0} -tunAddr {1} -tunMask {2} -tunGw {3} -tunDns {4} -tunName \"{5}\"", Global.Settings.Socks5LocalPort, Global.Settings.TUNTAP.Address, Global.Settings.TUNTAP.Netmask, Global.Settings.TUNTAP.Gateway, dns, adapterName); - } - Instance.StartInfo.CreateNoWindow = true; - Instance.StartInfo.RedirectStandardError = true; - Instance.StartInfo.RedirectStandardInput = true; - Instance.StartInfo.RedirectStandardOutput = true; - Instance.StartInfo.UseShellExecute = false; - Instance.EnableRaisingEvents = true; Instance.ErrorDataReceived += OnOutputDataReceived; Instance.OutputDataReceived += OnOutputDataReceived; @@ -471,10 +372,7 @@ namespace Netch.Controllers { Thread.Sleep(10); - if (State == State.Started) - { - return true; - } + if (State == State.Started) return true; if (State == State.Stopped) { @@ -487,46 +385,24 @@ namespace Netch.Controllers } /// - /// 停止 + /// TUN/TAP停止 /// - public void Stop() + public new void Stop() { - try - { - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - } - - //pDNSController.Stop(); - //修复点击停止按钮后再启动,DNS服务没监听的BUG - ClearBypass(); - pDNSController.Stop(); - } - catch (Exception e) - { - Logging.Info(e.ToString()); - } + base.Stop(); + ClearBypass(); + pDNSController.Stop(); } public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) { - if (!string.IsNullOrEmpty(e.Data)) + if (!WriteLog(e)) return; + if (State == State.Starting) { - File.AppendAllText("logging\\tun2socks.log", string.Format("{0}\r\n", e.Data.Trim())); - - if (State == State.Starting) - { - if (e.Data.Contains("Running")) - { - State = State.Started; - } - else if (e.Data.Contains("failed") || e.Data.Contains("invalid vconfig file")) - { - State = State.Stopped; - } - } + if (e.Data.Contains("Running")) + State = State.Started; + else if (e.Data.Contains("failed") || e.Data.Contains("invalid vconfig file")) State = State.Stopped; } } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/TrojanController.cs b/Netch/Controllers/TrojanController.cs index c49420d0..25ad80de 100644 --- a/Netch/Controllers/TrojanController.cs +++ b/Netch/Controllers/TrojanController.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; @@ -10,34 +9,18 @@ using Newtonsoft.Json; namespace Netch.Controllers { - public class TrojanController + public class TrojanController : ServerClient { - /// - /// 进程实例 - /// - public Process Instance; + public TrojanController() + { + MainName = "Trojan"; + ready = BeforeStartProgress(); + } - /// - /// 当前状态 - /// - public State State = State.Waiting; - - /// - /// 启动 - /// - /// 服务器 - /// 模式 - /// 是否启动成功 - public bool Start(Server server, Mode mode) + public override bool Start(Server server, Mode mode) { MainForm.Instance.StatusText(i18N.Translate("Starting Trojan")); - File.Delete("logging\\trojan.log"); - if (!File.Exists("bin\\Trojan.exe")) - { - return false; - } - File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new Trojan { local_addr = Global.Settings.LocalAddress, @@ -50,8 +33,7 @@ namespace Netch.Controllers } })); - Instance = MainController.GetProcess(); - Instance.StartInfo.FileName = "bin\\Trojan.exe"; + Instance = MainController.GetProcess("bin\\Trojan.exe"); Instance.StartInfo.Arguments = "-c ..\\data\\last.json"; Instance.OutputDataReceived += OnOutputDataReceived; Instance.ErrorDataReceived += OnOutputDataReceived; @@ -64,10 +46,7 @@ namespace Netch.Controllers { Thread.Sleep(10); - if (State == State.Started) - { - return true; - } + if (State == State.Started) return true; if (State == State.Stopped) { @@ -83,47 +62,17 @@ namespace Netch.Controllers return false; } - /// - /// 停止 - /// - public void Stop() + public override void OnOutputDataReceived(object sender, DataReceivedEventArgs e) { - try + if (!WriteLog(e)) return; + if (State == State.Starting) { - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - Instance.WaitForExit(); - } - } - catch (Exception e) - { - Logging.Info(e.ToString()); - } - } - - public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) - { - if (!string.IsNullOrWhiteSpace(e.Data)) - { - File.AppendAllText("logging\\trojan.log", $"{e.Data}\r\n"); - - if (State == State.Starting) - { - if (Instance.HasExited) - { - State = State.Stopped; - } - else if (e.Data.Contains("started")) - { - State = State.Started; - } - else if (e.Data.Contains("exiting")) - { - State = State.Stopped; - } - } + if (Instance.HasExited) + State = State.Stopped; + else if (e.Data.Contains("started")) + State = State.Started; + else if (e.Data.Contains("exiting")) State = State.Stopped; } } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/UpdateChecker.cs b/Netch/Controllers/UpdateChecker.cs index dc7234f8..2c8e7b5a 100644 --- a/Netch/Controllers/UpdateChecker.cs +++ b/Netch/Controllers/UpdateChecker.cs @@ -17,6 +17,10 @@ namespace Netch.Controllers public const string Owner = @"NetchX"; public const string Repo = @"Netch"; + public const string Name = @"Netch"; + public const string Copyright = @"Copyright © 2019 - 2020"; + public const string Version = @"1.4.11"; + public string LatestVersionNumber; public string LatestVersionUrl; @@ -24,10 +28,6 @@ namespace Netch.Controllers public event EventHandler NewVersionFoundFailed; public event EventHandler NewVersionNotFound; - public const string Name = @"Netch"; - public const string Copyright = @"Copyright © 2019 - 2020"; - public const string Version = @"1.4.11"; - public async void Check(bool notifyNoFound, bool isPreRelease) { try @@ -48,19 +48,13 @@ namespace Netch.Controllers else { LatestVersionNumber = latestRelease.tag_name; - if (notifyNoFound) - { - NewVersionNotFound?.Invoke(this, new EventArgs()); - } + if (notifyNoFound) NewVersionNotFound?.Invoke(this, new EventArgs()); } } catch (Exception e) { Debug.WriteLine(e.Message); - if (notifyNoFound) - { - NewVersionFoundFailed?.Invoke(this, new EventArgs()); - } + if (notifyNoFound) NewVersionFoundFailed?.Invoke(this, new EventArgs()); } } @@ -84,4 +78,4 @@ namespace Netch.Controllers return resultStr; } } -} +} \ No newline at end of file diff --git a/Netch/Controllers/VMessController.cs b/Netch/Controllers/VMessController.cs index 3689aebf..5c782145 100644 --- a/Netch/Controllers/VMessController.cs +++ b/Netch/Controllers/VMessController.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; -using Netch.Forms; using Netch.Models; using Netch.Utils; using Newtonsoft.Json; @@ -11,32 +9,16 @@ using VMess = Netch.Models.Information.VMess; namespace Netch.Controllers { - public class VMessController + public class VMessController : ServerClient { - /// - /// 进程实例 - /// - public Process Instance; - - /// - /// 当前状态 - /// - public State State = State.Waiting; - - /// - /// 启动 - /// - /// 服务器 - /// 模式 - /// 是否启动成功 - public bool Start(Server server, Mode mode) + public VMessController() { - MainForm.Instance.StatusText(i18N.Translate("Starting V2ray")); - if (!File.Exists("bin\\v2ray.exe") || !File.Exists("bin\\v2ctl.exe")) - { - return false; - } + MainName = "v2ray"; + ready = BeforeStartProgress(); + } + public override bool Start(Server server, Mode mode) + { File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new VMess.Config { inbounds = new List @@ -76,50 +58,60 @@ namespace Netch.Controllers { network = server.TransferProtocol, security = server.TLSSecure ? "tls" : "", - wsSettings = server.TransferProtocol == "ws" ? new VMess.WebSocketSettings - { - path = server.Path == "" ? "/" : server.Path, - headers = new VMess.WSHeaders + wsSettings = server.TransferProtocol == "ws" + ? new VMess.WebSocketSettings { - Host = server.Host == "" ? server.Hostname : server.Host - } - } : null, - tcpSettings = server.FakeType == "http" ? new VMess.TCPSettings - { - header = new VMess.TCPHeaders - { - type = server.FakeType, - request = new VMess.TCPRequest + path = server.Path == "" ? "/" : server.Path, + headers = new VMess.WSHeaders { - path = server.Path == "" ? "/" : server.Path, - headers = new VMess.TCPRequestHeaders + Host = server.Host == "" ? server.Hostname : server.Host + } + } + : null, + tcpSettings = server.FakeType == "http" + ? new VMess.TCPSettings + { + header = new VMess.TCPHeaders + { + type = server.FakeType, + request = new VMess.TCPRequest { - Host = server.Host == "" ? server.Hostname : server.Host + path = server.Path == "" ? "/" : server.Path, + headers = new VMess.TCPRequestHeaders + { + Host = server.Host == "" ? server.Hostname : server.Host + } } } } - } : null, - kcpSettings = server.TransferProtocol == "kcp" ? new VMess.KCPSettings - { - header = new VMess.TCPHeaders + : null, + kcpSettings = server.TransferProtocol == "kcp" + ? new VMess.KCPSettings { - type = server.FakeType + header = new VMess.TCPHeaders + { + type = server.FakeType + } } - } : null, - quicSettings = server.TransferProtocol == "quic" ? new VMess.QUICSettings - { - security = server.QUICSecure, - key = server.QUICSecret, - header = new VMess.TCPHeaders + : null, + quicSettings = server.TransferProtocol == "quic" + ? new VMess.QUICSettings { - type = server.FakeType + security = server.QUICSecure, + key = server.QUICSecret, + header = new VMess.TCPHeaders + { + type = server.FakeType + } } - } : null, - httpSettings = server.TransferProtocol == "h2" ? new VMess.HTTPSettings - { - host = server.Host == "" ? server.Hostname : server.Host, - path = server.Path == "" ? "/" : server.Path - } : null, + : null, + httpSettings = server.TransferProtocol == "h2" + ? new VMess.HTTPSettings + { + host = server.Host == "" ? server.Hostname : server.Host, + path = server.Path == "" ? "/" : server.Path + } + : null, tlsSettings = new VMess.TLSSettings { allowInsecure = true, @@ -131,58 +123,51 @@ namespace Netch.Controllers enabled = server.UseMux } }, - (mode.Type==0||mode.Type==1||mode.Type==2) ? new VMess.Outbounds - { - tag = "TUNTAP", - protocol = "freedom" - }: new VMess.Outbounds - { - tag = "direct", - protocol = "freedom" - } + mode.Type == 0 || mode.Type == 1 || mode.Type == 2 + ? new VMess.Outbounds + { + tag = "TUNTAP", + protocol = "freedom" + } + : new VMess.Outbounds + { + tag = "direct", + protocol = "freedom" + } }, routing = new VMess.Routing { rules = new List { - mode.BypassChina ? new VMess.RoutingRules - { - type = "field", - ip = new List + mode.BypassChina + ? new VMess.RoutingRules { - "geoip:cn", - "geoip:private" - - }, - domain = new List + type = "field", + ip = new List + { + "geoip:cn", + "geoip:private" + }, + domain = new List + { + "geosite:cn" + }, + outboundTag = "direct" + } + : new VMess.RoutingRules { - "geosite:cn" - }, - outboundTag = "direct" - } : new VMess.RoutingRules - { - type = "field", - ip = new List - { - "geoip:private" - }, - outboundTag = "direct" - } + type = "field", + ip = new List + { + "geoip:private" + }, + outboundTag = "direct" + } } } })); - // 清理上一次的日志文件,防止淤积占用磁盘空间 - if (Directory.Exists("logging")) - { - if (File.Exists("logging\\v2ray.log")) - { - File.Delete("logging\\v2ray.log"); - } - } - - Instance = MainController.GetProcess(); - Instance.StartInfo.FileName = "bin\\v2ray.exe"; + Instance = MainController.GetProcess("bin\\v2ray.exe"); Instance.StartInfo.Arguments = "-config ..\\data\\last.json"; Instance.OutputDataReceived += OnOutputDataReceived; @@ -198,10 +183,8 @@ namespace Netch.Controllers if (State == State.Started) { - if (File.Exists("data\\last.json")) - { - File.Delete("data\\last.json"); - } + if (File.Exists("data\\last.json")) File.Delete("data\\last.json"); + return true; } @@ -219,47 +202,17 @@ namespace Netch.Controllers return false; } - /// - /// 停止 - /// - public void Stop() + public override void OnOutputDataReceived(object sender, DataReceivedEventArgs e) { - try + if (!WriteLog(e)) return; + if (State == State.Starting) { - if (Instance != null && !Instance.HasExited) - { - Instance.Kill(); - Instance.WaitForExit(); - } - } - catch (Exception e) - { - Logging.Info(e.ToString()); - } - } - - public void OnOutputDataReceived(object sender, DataReceivedEventArgs e) - { - if (!string.IsNullOrWhiteSpace(e.Data)) - { - File.AppendAllText("logging\\v2ray.log", $"{e.Data}\r\n"); - - if (State == State.Starting) - { - if (Instance.HasExited) - { - State = State.Stopped; - } - else if (e.Data.Contains("started")) - { - State = State.Started; - } - else if (e.Data.Contains("config file not readable") || e.Data.Contains("failed to")) - { - State = State.Stopped; - } - } + if (Instance.HasExited) + State = State.Stopped; + else if (e.Data.Contains("started")) + State = State.Started; + else if (e.Data.Contains("config file not readable") || e.Data.Contains("failed to")) State = State.Stopped; } } } -} +} \ No newline at end of file diff --git a/Netch/Forms/MainForm.Control.cs b/Netch/Forms/MainForm.Control.cs index 6389d78c..20f855af 100644 --- a/Netch/Forms/MainForm.Control.cs +++ b/Netch/Forms/MainForm.Control.cs @@ -151,7 +151,7 @@ namespace Netch.Forms else { UpdateStatus(State.Stopped); - StatusText(i18N.Translate("Start Failed")); + StatusText(i18N.Translate("Start failed")); } }); } diff --git a/Netch/Global.cs b/Netch/Global.cs index fdb05de4..c4e253b3 100644 --- a/Netch/Global.cs +++ b/Netch/Global.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Net; using System.Net.NetworkInformation; @@ -6,6 +7,14 @@ namespace Netch { public static class Global { + + /// + /// 换行 + /// + public static string EOF = "\r\n"; + + public static readonly string NetchDir = (AppDomain.CurrentDomain.BaseDirectory).TrimEnd(); + /// /// 主窗体 /// diff --git a/Netch/Resources/zh-CN b/Netch/Resources/zh-CN index ec95bbf1..79be3937 100644 --- a/Netch/Resources/zh-CN +++ b/Netch/Resources/zh-CN @@ -16,10 +16,8 @@ "Started": "已启动", "Stopping": "正在停止中", "Stopped": "已停止", - "Starting Shadowsocks": "正在启动 Shadowsocks", - "Starting ShadowsocksR": "正在启动 ShadowsocksR", - "Starting V2ray": "正在启动 V2Ray", - "Starting Trojan": "正在启动 Trojan", + "Starting ": "正在启动 ", + "v2ray": "V2Ray", "Starting Tap": "正在启动 TUN/TAP", "Starting NatTester": "正在启动 NAT 测试", "Starting LocalDns service": "正在启动本地 DNS 服务", diff --git a/Netch/Utils/Bandwidth.cs b/Netch/Utils/Bandwidth.cs index 5ee6daf7..bb2e273e 100644 --- a/Netch/Utils/Bandwidth.cs +++ b/Netch/Utils/Bandwidth.cs @@ -58,21 +58,10 @@ namespace Netch.Utils { processList.Add(Process.GetCurrentProcess().Id); } - else if (server.Type.Equals("SS") && mainController.pSSController != null) + else if (mainController.pServerClientController != null) { - processList.Add(mainController.pSSController.Instance.Id); - } - else if (server.Type.Equals("SSR") && mainController.pSSRController != null) - { - processList.Add(mainController.pSSRController.Instance.Id); - } - else if (server.Type.Equals("VMess") && mainController.pVMessController != null) - { - processList.Add(mainController.pVMessController.Instance.Id); - } - else if (server.Type.Equals("TR") && mainController.pTrojanController != null) - { - processList.Add(mainController.pTrojanController.Instance.Id); + // mainController.pServerClientController.Instance + processList.Add(mainController.pServerClientController.Instance.Id); } else if (mainController.pTUNTAPController != null) { diff --git a/Netch/Utils/Firewall.cs b/Netch/Utils/Firewall.cs index 33adfd18..e61f1359 100644 --- a/Netch/Utils/Firewall.cs +++ b/Netch/Utils/Firewall.cs @@ -49,7 +49,7 @@ namespace Netch.Utils /// public static void AddNetchFwRules() { - if (GetFwRulePath(_netch).StartsWith(AppDomain.CurrentDomain.BaseDirectory) && GetFwRulesNumber(_netch) >= ProgramPath.Length) return; + if (GetFwRulePath(_netch).StartsWith(Global.NetchDir) && GetFwRulesNumber(_netch) >= ProgramPath.Length) return; RemoveNetchFwRules(); foreach (var p in ProgramPath) { diff --git a/Netch/Utils/Logging.cs b/Netch/Utils/Logging.cs index f19d3887..eeba7723 100644 --- a/Netch/Utils/Logging.cs +++ b/Netch/Utils/Logging.cs @@ -5,10 +5,6 @@ namespace Netch.Utils { public static class Logging { - /// - /// 换行 - /// - public static string EOF = "\r\n"; /// /// 信息 @@ -16,7 +12,7 @@ namespace Netch.Utils /// 内容 public static void Info(string text) { - File.AppendAllText("logging\\application.log", string.Format("[{0}] {1}{2}", DateTime.Now, text, EOF)); + File.AppendAllText("logging\\application.log", $@"[{DateTime.Now}] {text}{Global.EOF}"); } } }