NFController.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. using ClashDotNetFramework.Utils;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.ServiceProcess;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. namespace ClashDotNetFramework.Controllers
  11. {
  12. public class NFController : Guard
  13. {
  14. private readonly string BinDriver = string.Empty;
  15. private readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
  16. public NFController()
  17. {
  18. string fileName;
  19. switch ($"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}")
  20. {
  21. case "10.0": // Win 10
  22. case "6.3": // Win 8
  23. case "6.2": // Win 8
  24. case "6.1": // Win 7
  25. case "6.0": // Win 7
  26. if (SystemHelper.Is64BitOperatingSystem())
  27. fileName = "netfilter2-amd64.sys";
  28. else
  29. fileName = "netfilter2-i386.sys";
  30. break;
  31. default:
  32. Logging.Error($"不支持的系统版本:{Environment.OSVersion.Version}");
  33. return;
  34. }
  35. BinDriver = Path.Combine(Global.ClashDotNetFrameworkDir, $"bin\\{fileName}");
  36. RedirectStd = true;
  37. }
  38. public override string MainFile { get; protected set; } = "Redirector.exe";
  39. public override string Name { get; } = "Redirector";
  40. #region NetFilter Controller
  41. public void Start()
  42. {
  43. if (!CheckDriver())
  44. return;
  45. try
  46. {
  47. _ = Task.Run(FireWallController.AddFireWallRules);
  48. string arguments = $"-m {string.Join(",", Global.Settings.RedirectTraffic)} -l {Global.Settings.ProcessMode} -b {string.Join(",", Global.Settings.BypassType)} -p {string.Join(",", Global.Settings.Processes)} -r 127.0.0.1:{Global.ClashMixedPort}";
  49. StartInstanceAuto(arguments);
  50. }
  51. catch
  52. {
  53. }
  54. }
  55. public override void Stop()
  56. {
  57. StopInstance();
  58. }
  59. #endregion
  60. #region NetFilter Driver
  61. /// <summary>
  62. /// 检查 NF 驱动
  63. /// </summary>
  64. private bool CheckDriver()
  65. {
  66. var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
  67. var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
  68. Logging.Info("内置驱动版本: " + binFileVersion);
  69. Logging.Info("系统驱动版本: " + systemFileVersion);
  70. if (!File.Exists(BinDriver))
  71. {
  72. Logging.Warning("内置驱动不存在");
  73. if (File.Exists(SystemDriver))
  74. {
  75. Logging.Warning("使用系统驱动");
  76. return true;
  77. }
  78. Logging.Error("未安装驱动");
  79. return false;
  80. }
  81. if (!File.Exists(SystemDriver))
  82. {
  83. return InstallDriver();
  84. }
  85. var reinstallFlag = false;
  86. if (Version.TryParse(binFileVersion, out var binResult) && Version.TryParse(systemFileVersion, out var systemResult))
  87. {
  88. if (binResult.CompareTo(systemResult) > 0)
  89. // Bin greater than Installed
  90. reinstallFlag = true;
  91. else if (systemResult.Major != binResult.Major)
  92. // Installed greater than Bin but Major Version Difference (has breaking changes), do downgrade
  93. reinstallFlag = true;
  94. }
  95. else
  96. {
  97. if (!systemFileVersion.Equals(binFileVersion))
  98. reinstallFlag = true;
  99. }
  100. if (!reinstallFlag)
  101. return true;
  102. return ReinstallDriver();
  103. }
  104. /// <summary>
  105. /// 安装 NF 驱动
  106. /// </summary>
  107. /// <returns>驱动是否安装成功</returns>
  108. public bool InstallDriver()
  109. {
  110. Logging.Info("安装 NF 驱动");
  111. if (!File.Exists(BinDriver))
  112. throw new Exception("builtin driver files missing, can't install NF driver");
  113. Process proc = new Process
  114. {
  115. StartInfo =
  116. {
  117. FileName = Path.GetFullPath($"bin\\NetFilterHelper.exe"),
  118. WorkingDirectory = $"{Global.ClashDotNetFrameworkDir}\\bin",
  119. Arguments = "install",
  120. CreateNoWindow = true,
  121. WindowStyle = ProcessWindowStyle.Hidden,
  122. UseShellExecute = true,
  123. Verb = "runas"
  124. }
  125. };
  126. proc.Start();
  127. proc.WaitForExit();
  128. return proc.ExitCode == 0;
  129. }
  130. // <summary>
  131. /// 卸载 NF 驱动
  132. /// </summary>
  133. /// <returns>是否成功卸载</returns>
  134. public bool UninstallDriver()
  135. {
  136. Logging.Info("卸载 NF 驱动");
  137. Process proc = new Process
  138. {
  139. StartInfo =
  140. {
  141. FileName = Path.GetFullPath($"bin\\NetFilterHelper.exe"),
  142. WorkingDirectory = $"{Global.ClashDotNetFrameworkDir}\\bin",
  143. Arguments = "uninstall",
  144. CreateNoWindow = true,
  145. WindowStyle = ProcessWindowStyle.Hidden,
  146. UseShellExecute = true,
  147. Verb = "runas"
  148. }
  149. };
  150. proc.Start();
  151. proc.WaitForExit();
  152. return proc.ExitCode == 0;
  153. }
  154. /// <summary>
  155. /// 更新 NF 驱动
  156. /// </summary>
  157. /// <returns>是否更新成功</returns>
  158. public bool ReinstallDriver()
  159. {
  160. Logging.Info("更新 NF 驱动");
  161. Process proc = new Process
  162. {
  163. StartInfo =
  164. {
  165. FileName = Path.GetFullPath($"bin\\NetFilterHelper.exe"),
  166. WorkingDirectory = $"{Global.ClashDotNetFrameworkDir}\\bin",
  167. Arguments = "reinstall",
  168. CreateNoWindow = true,
  169. WindowStyle = ProcessWindowStyle.Hidden,
  170. UseShellExecute = true,
  171. Verb = "runas"
  172. }
  173. };
  174. proc.Start();
  175. proc.WaitForExit();
  176. return proc.ExitCode == 0;
  177. }
  178. #endregion
  179. }
  180. }