using System; using System.IO; using System.Runtime.InteropServices; using System.ServiceProcess; using System.Threading.Tasks; using Netch.Forms; using Netch.Models; using Netch.Servers.Socks5; using Netch.Utils; using nfapinet; namespace Netch.Controllers { public class NFController : IModeController { private static readonly ServiceController NFService = new ServiceController("netfilter2"); private static readonly string BinDriver = string.Empty; private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys"; private static string _sysDns; public string Name { get; } = "Redirector"; static NFController() { string fileName; switch ($"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}") { case "10.0": fileName = "Win-10.sys"; break; case "6.3": case "6.2": fileName = "Win-8.sys"; break; case "6.1": case "6.0": fileName = "Win-7.sys"; break; default: Logging.Error($"不支持的系统版本:{Environment.OSVersion.Version}"); return; } BinDriver = "bin\\" + fileName; } public bool Start(Server s, Mode mode) { Logging.Info("内置驱动版本: " + Utils.Utils.GetFileVersion(BinDriver)); if (Utils.Utils.GetFileVersion(SystemDriver) != Utils.Utils.GetFileVersion(BinDriver)) { if (File.Exists(SystemDriver)) { Logging.Info("系统驱动版本: " + Utils.Utils.GetFileVersion(SystemDriver)); Logging.Info("更新驱动"); UninstallDriver(); } if (!InstallDriver()) return false; } aio_dial((int) NameList.TYPE_CLRNAME, ""); foreach (var rule in mode.FullRule) { aio_dial((int) NameList.TYPE_ADDNAME, rule); } aio_dial((int) NameList.TYPE_ADDNAME, "NTT.exe"); if (s is Socks5 socks5) { if (!socks5.Auth()) { aio_dial((int) NameList.TYPE_TCPHOST, $"{socks5.AutoResolveHostname()}:{socks5.Port}"); aio_dial((int) NameList.TYPE_UDPHOST, $"{socks5.AutoResolveHostname()}:{socks5.Port}"); } else { /* TODO Direct handled by redirector aio_dial((int) NameList.TYPE_TCPHOST, $"{socks5.AutoResolveHostname()}:{socks5.Port}"); aio_dial((int) NameList.TYPE_UDPHOST, $"{socks5.AutoResolveHostname()}:{socks5.Port}"); aio_dial((int) NameList.TYPE_, socks5.Username); aio_dial((int) NameList.TYPE_, socks5.Password); */ aio_dial((int) NameList.TYPE_TCPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}"); aio_dial((int) NameList.TYPE_UDPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}"); } } else { aio_dial((int) NameList.TYPE_TCPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}"); aio_dial((int) NameList.TYPE_UDPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}"); } if (Global.Settings.ModifySystemDNS) { // 备份并替换系统 DNS _sysDns = DNS.OutboundDNS; DNS.OutboundDNS = "1.1.1.1,8.8.8.8"; } return aio_init(); } public void Stop() { Task.Run(() => { if (Global.Settings.ModifySystemDNS) //恢复系统DNS DNS.OutboundDNS = _sysDns; }); aio_free(); } #region NativeMethods [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] public static extern bool aio_dial(int name, [MarshalAs(UnmanagedType.LPWStr)] string value); [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] public static extern bool aio_init(); [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] public static extern bool aio_free(); [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] public static extern ulong aio_getUP(); [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] public static extern ulong aio_getDL(); #endregion #region Utils /// /// 安装 NF 驱动 /// /// 驱动是否安装成功 public static bool InstallDriver() { Logging.Info("安装 NF 驱动"); try { File.Copy(BinDriver, SystemDriver); } catch (Exception e) { Logging.Error("驱动复制失败\n" + e); return false; } Global.MainForm.StatusText(i18N.Translate("Register driver")); // 注册驱动文件 var result = NFAPI.nf_registerDriver("netfilter2"); if (result == NF_STATUS.NF_STATUS_SUCCESS) { Logging.Info("驱动安装成功"); } else { Logging.Error($"注册驱动失败,返回值:{result}"); return false; } return true; } /// /// 卸载 NF 驱动 /// /// 是否成功卸载 public static bool UninstallDriver() { Global.MainForm.StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service")); Logging.Info("卸载 NF 驱动"); try { if (NFService.Status == ServiceControllerStatus.Running) { NFService.Stop(); NFService.WaitForStatus(ServiceControllerStatus.Stopped); } } catch (Exception) { // ignored } if (!File.Exists(SystemDriver)) return true; NFAPI.nf_unRegisterDriver("netfilter2"); File.Delete(SystemDriver); return true; } #endregion } }