diff --git a/Netch/Controllers/MainController.cs b/Netch/Controllers/MainController.cs
index 9658ac20..b94b2136 100644
--- a/Netch/Controllers/MainController.cs
+++ b/Netch/Controllers/MainController.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Netch.Models;
@@ -62,16 +61,7 @@ namespace Netch.Controllers
// 刷新DNS缓存
NativeMethods.FlushDNSResolverCache();
- try
- {
- WebUtil.BestLocalEndPoint(new IPEndPoint(0x72727272, 53));
- }
- catch (Exception)
- {
- throw new MessageException(i18N.Translate("No internet connection"));
- }
-
- if (Global.Settings.ResolveServerHostname && DNS.Lookup(server.Hostname) == null)
+ if (DNS.Lookup(server.Hostname) == null)
throw new MessageException(i18N.Translate("Lookup Server hostname failed"));
// 添加Netch到防火墙
diff --git a/Netch/Controllers/NFController.cs b/Netch/Controllers/NFController.cs
index 6273c469..6089cf83 100644
--- a/Netch/Controllers/NFController.cs
+++ b/Netch/Controllers/NFController.cs
@@ -18,9 +18,11 @@ namespace Netch.Controllers
{
private static readonly ServiceController NFService = new("netfilter2");
- private static readonly string BinDriver = string.Empty;
+ private static readonly string BinDriver;
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
- private static string _sysDns = string.Empty;
+
+ private static string? _sysDns;
+ private OutboundAdapter? _outbound;
static NFController()
{
@@ -39,8 +41,7 @@ namespace Netch.Controllers
fileName = "Win-7.sys";
break;
default:
- Logging.Error($"不支持的系统版本:{Environment.OSVersion.Version}");
- return;
+ throw new MessageException($"不支持的系统版本:{Environment.OSVersion.Version}");
}
BinDriver = "bin\\" + fileName;
@@ -93,12 +94,13 @@ namespace Netch.Controllers
if (Global.Settings.ModifySystemDNS)
{
+ _outbound = new OutboundAdapter();
// 备份并替换系统 DNS
- _sysDns = DNS.OutboundDNS;
+ _sysDns = _outbound.DNS;
if (string.IsNullOrWhiteSpace(Global.Settings.ModifiedDNS))
Global.Settings.ModifiedDNS = "1.1.1.1,8.8.8.8";
- DNS.OutboundDNS = Global.Settings.ModifiedDNS;
+ _outbound.DNS = Global.Settings.ModifiedDNS;
}
if (!aio_init())
@@ -111,7 +113,7 @@ namespace Netch.Controllers
{
if (Global.Settings.ModifySystemDNS)
//恢复系统DNS
- DNS.OutboundDNS = _sysDns;
+ _outbound!.DNS = _sysDns!;
});
aio_free();
diff --git a/Netch/Controllers/TUNTAPController.cs b/Netch/Controllers/TUNTAPController.cs
index b960f18b..b88499a5 100644
--- a/Netch/Controllers/TUNTAPController.cs
+++ b/Netch/Controllers/TUNTAPController.cs
@@ -3,9 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
-using System.Net.NetworkInformation;
using System.Text;
-using System.Threading;
using System.Threading.Tasks;
using Netch.Models;
using Netch.Servers.Socks5;
@@ -21,7 +19,7 @@ namespace Netch.Controllers
///
/// 服务器 IP 地址
///
- private IPAddress? _serverAddresses;
+ private IPAddress _serverAddresses = null!;
///
/// 本地 DNS 服务控制器
@@ -38,47 +36,35 @@ namespace Netch.Controllers
public override string Name { get; } = "tun2socks";
+ private readonly OutboundAdapter _outbound = new();
+ private TapAdapter _tap = null!;
+
public void Start(in Mode mode)
{
var server = MainController.Server!;
- // 查询服务器 IP 地址
- _serverAddresses = DNS.Lookup(server.Hostname)!;
+ _serverAddresses = DNS.Lookup(server.Hostname)!; // server address have been cached when MainController.Start
- // 查找出口适配器
- Utils.Utils.SearchOutboundAdapter();
+ if (TUNTAP.GetComponentID() == null)
+ TUNTAP.AddTap();
- // 查找并安装 TAP 适配器
- if (string.IsNullOrEmpty(TUNTAP.GetComponentID()))
- AddTap();
+ _tap = new TapAdapter();
- SearchTapAdapter();
-
- SetupRouteTable(mode);
-
- Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", Name));
-
- string dns;
+ List dns;
if (Global.Settings.TUNTAP.UseCustomDNS)
{
- if (Global.Settings.TUNTAP.DNS.Any())
- {
- dns = DNS.Join(Global.Settings.TUNTAP.DNS);
- }
- else
- {
- Global.Settings.TUNTAP.DNS.Add("1.1.1.1");
- dns = "1.1.1.1";
- }
+ dns = Global.Settings.TUNTAP.DNS.Any() ? Global.Settings.TUNTAP.DNS : Global.Settings.TUNTAP.DNS = new List {"1.1.1.1"};
}
else
{
MainController.PortCheck(53, "DNS");
-
DNSController.Start();
-
- dns = "127.0.0.1";
+ dns = new List {"127.0.0.1"};
}
+ SetupRouteTable(mode);
+
+ Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", Name));
+
var argument = new StringBuilder();
if (server is Socks5 socks5 && !socks5.Auth())
argument.Append($"-proxyServer {server.AutoResolveHostname()}:{server.Port} ");
@@ -86,7 +72,7 @@ namespace Netch.Controllers
argument.Append($"-proxyServer 127.0.0.1:{Global.Settings.Socks5LocalPort} ");
argument.Append(
- $"-tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {dns} -tunName \"{TUNTAP.GetName(Global.TUNTAP.ComponentID)}\" ");
+ $"-tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {DNS.Join(dns)} -tunName \"{TUNTAP.GetName(_tap.ComponentID)}\" ");
if (Global.Settings.TUNTAP.UseFakeDNS && Global.Flags.SupportFakeDns)
argument.Append("-fakeDns ");
@@ -164,7 +150,7 @@ namespace Netch.Controllers
Process.Start(new ProcessStartInfo
{
FileName = "netsh",
- Arguments = $"interface ip set interface {Global.TUNTAP.Index} metric=0",
+ Arguments = $"interface ip set interface {_tap.Index} metric=0",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
CreateNoWindow = true
@@ -218,45 +204,6 @@ namespace Netch.Controllers
}
}
- ///
- /// 搜索出口和TUNTAP适配器
- ///
- public static void SearchTapAdapter()
- {
- Global.TUNTAP.Adapter = null;
- Global.TUNTAP.Index = -1;
- Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
-
- // 搜索 TUN/TAP 适配器的索引
- if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID))
- {
- const string s = "TAP 适配器未安装";
- Logging.Info(s);
- throw new Exception(s);
- }
-
- // 根据 ComponentID 寻找 Tap适配器
- var adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => _.Id == Global.TUNTAP.ComponentID);
- Global.TUNTAP.Adapter = adapter;
- Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index;
- Logging.Info($"TAP 适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.TUNTAP.Index}");
- }
-
- private static bool AddTap()
- {
- TUNTAP.addtap();
- // 给点时间,不然立马安装完毕就查找适配器可能会导致找不到适配器ID
- Thread.Sleep(1000);
- if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID = TUNTAP.GetComponentID()))
- {
- const string s = "TAP 驱动安装失败,找不到 ComponentID 注册表项";
- Logging.Error(s);
- throw new Exception(s);
- }
-
- return true;
- }
-
private void RouteAction(Action action, in IEnumerable ipNetworks, RouteType routeType, int metric = 0)
{
foreach (var address in ipNetworks)
@@ -265,54 +212,42 @@ namespace Netch.Controllers
private bool RouteAction(Action action, in string ipNetwork, RouteType routeType, int metric = 0)
{
- string gateway;
- int index;
- switch (routeType)
- {
- case RouteType.Outbound:
- gateway = Global.Outbound.Gateway!.ToString();
- index = Global.Outbound.Index;
- break;
- case RouteType.TUNTAP:
- gateway = Global.Settings.TUNTAP.Gateway;
- index = Global.TUNTAP.Index;
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null);
- }
-
- string network;
- ushort cidr;
- try
- {
- var s = ipNetwork.Split('/');
- network = s[0];
- cidr = ushort.Parse(s[1]);
- }
- catch
+ var s = ipNetwork.Split('/');
+ if (s.Length != 2)
{
Logging.Warning($"Failed to parse rule {ipNetwork}");
return false;
}
+ IAdapter adapter;
+ List ipList;
+
+ switch (routeType)
+ {
+ case RouteType.TUNTAP:
+ adapter = _tap;
+ ipList = _proxyIPs;
+ break;
+ case RouteType.Outbound:
+ adapter = _outbound;
+ ipList = _directIPs;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null);
+ }
+
+ string network = s[0];
+ var cidr = ushort.Parse(s[1]);
+ string gateway = adapter.Gateway.ToString();
+ var index = adapter.Index;
+
bool result;
switch (action)
{
case Action.Create:
- {
result = NativeMethods.CreateRoute(network, cidr, gateway, index, metric);
- switch (routeType)
- {
- case RouteType.Outbound:
- _directIPs.Add(ipNetwork);
- break;
- case RouteType.TUNTAP:
- _proxyIPs.Add(ipNetwork);
- break;
- }
-
+ ipList.Add(ipNetwork);
break;
- }
case Action.Delete:
result = NativeMethods.DeleteRoute(network, cidr, gateway, index, metric);
break;
diff --git a/Netch/Global.cs b/Netch/Global.cs
index 68a8478c..c4cc8fa6 100644
--- a/Netch/Global.cs
+++ b/Netch/Global.cs
@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Net.NetworkInformation;
-using System.Net.Sockets;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading;
@@ -66,52 +62,6 @@ namespace Netch
public static bool SupportFakeDns => LazySupportFakeDns.Value;
}
- ///
- /// 出口适配器
- ///
- public static class Outbound
- {
- ///
- /// 索引
- ///
- public static int Index = -1;
-
- ///
- /// 网关
- ///
- public static IPAddress? Gateway;
-
- public static NetworkInterface? Adapter;
-
- ///
- /// 地址
- ///
- public static IPAddress Address => Adapter!.GetIPProperties()
- .UnicastAddresses.First(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork)
- .Address;
- }
-
- ///
- /// TUN/TAP 适配器
- ///
- public static class TUNTAP
- {
- ///
- /// 适配器
- ///
- public static NetworkInterface? Adapter;
-
- ///
- /// 索引
- ///
- public static int Index = -1;
-
- ///
- /// 组件 ID
- ///
- public static string ComponentID = string.Empty;
- }
-
///
/// 主窗体的静态实例
///
diff --git a/Netch/Models/IAdapter.cs b/Netch/Models/IAdapter.cs
new file mode 100644
index 00000000..f82dae8d
--- /dev/null
+++ b/Netch/Models/IAdapter.cs
@@ -0,0 +1,15 @@
+using System.Net;
+using System.Net.NetworkInformation;
+
+namespace Netch.Models
+{
+ public interface IAdapter
+ {
+ public abstract int Index { get; }
+
+ public abstract IPAddress Gateway { get; }
+
+ public abstract NetworkInterface NetworkInterface { get; }
+
+ }
+}
\ No newline at end of file
diff --git a/Netch/Models/OutboundAdapter.cs b/Netch/Models/OutboundAdapter.cs
new file mode 100644
index 00000000..55f321fc
--- /dev/null
+++ b/Netch/Models/OutboundAdapter.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using Microsoft.Win32;
+using Netch.Controllers;
+using Netch.Utils;
+using Vanara.PInvoke;
+
+namespace Netch.Models
+{
+ public class OutboundAdapter : IAdapter
+ {
+ public OutboundAdapter(bool logging = true)
+ {
+ // 寻找出口适配器
+ if (IpHlpApi.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) != 0)
+ {
+ throw new MessageException("GetBestRoute 搜索失败");
+ }
+
+ NetworkInterface = NetworkInterface.GetAllNetworkInterfaces()
+ .First(ni => ni.Supports(NetworkInterfaceComponent.IPv4) &&
+ ni.GetIPProperties().GetIPv4Properties().Index == pRoute.dwForwardIfIndex);
+
+ Index = (int) pRoute.dwForwardIfIndex;
+ Gateway = new IPAddress(pRoute.dwForwardNextHop.S_un_b);
+ _parametersRegistry =
+ Registry.LocalMachine.OpenSubKey($@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{NetworkInterface.Id}", true)!;
+
+ if (logging)
+ {
+ Logging.Info($"出口 网关 地址:{Gateway}");
+ Logging.Info($"出口适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {Index}");
+ }
+ }
+
+ ///
+ /// 索引
+ ///
+ public int Index { get; }
+
+ ///
+ /// 网关
+ ///
+ public IPAddress Gateway { get; }
+
+ public NetworkInterface NetworkInterface { get; }
+
+
+ public string DNS
+ {
+ get
+ {
+ try
+ {
+ return (string) _parametersRegistry.GetValue("NameServer");
+ }
+ catch
+ {
+ return string.Empty;
+ }
+ }
+ set => _parametersRegistry.SetValue("NameServer", value, RegistryValueKind.String);
+ }
+
+ private readonly RegistryKey _parametersRegistry;
+ }
+}
\ No newline at end of file
diff --git a/Netch/Models/TapAdapter.cs b/Netch/Models/TapAdapter.cs
new file mode 100644
index 00000000..196b789f
--- /dev/null
+++ b/Netch/Models/TapAdapter.cs
@@ -0,0 +1,30 @@
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using Netch.Controllers;
+using Netch.Utils;
+
+namespace Netch.Models
+{
+ public class TapAdapter : IAdapter
+ {
+ public TapAdapter()
+ {
+ Index = -1;
+ ComponentID = TUNTAP.GetComponentID() ?? throw new MessageException("TAP 适配器未安装");
+
+ // 根据 ComponentID 寻找 Tap适配器
+ NetworkInterface = NetworkInterface.GetAllNetworkInterfaces().First(i => i.Id == ComponentID);
+ Index = NetworkInterface.GetIPProperties().GetIPv4Properties().Index;
+ Logging.Info($"TAP 适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {Index}");
+ }
+
+ public string ComponentID { get; }
+
+ public int Index { get; }
+
+ public IPAddress Gateway => IPAddress.Parse(Global.Settings.TUNTAP.Gateway);
+
+ public NetworkInterface NetworkInterface { get; }
+ }
+}
\ No newline at end of file
diff --git a/Netch/Utils/DNS.cs b/Netch/Utils/DNS.cs
index 7d5bfc17..7eb0434b 100644
--- a/Netch/Utils/DNS.cs
+++ b/Netch/Utils/DNS.cs
@@ -3,7 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
-using Microsoft.Win32;
namespace Netch.Utils
{
@@ -14,27 +13,6 @@ namespace Netch.Utils
///
public static Hashtable Cache = new();
- ///
- /// 出口网卡 DNS
- ///
- /// 依赖
- ///
- public static string OutboundDNS
- {
- get
- {
- try
- {
- return (string) AdapterRegistry().GetValue("NameServer");
- }
- catch
- {
- return string.Empty;
- }
- }
- set => AdapterRegistry(true).SetValue("NameServer", value, RegistryValueKind.String);
- }
-
///
/// 查询
///
@@ -64,15 +42,6 @@ namespace Netch.Utils
}
}
- private static RegistryKey AdapterRegistry(bool write = false)
- {
- if (Global.Outbound.Adapter == null)
- Utils.SearchOutboundAdapter();
-
- return Registry.LocalMachine.OpenSubKey($@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{Global.Outbound.Adapter!.Id}",
- write)!;
- }
-
public static IEnumerable Split(string dns)
{
return dns.SplitRemoveEmptyEntriesAndTrimEntries(',');
diff --git a/Netch/Utils/TUNTAP.cs b/Netch/Utils/TUNTAP.cs
index b966c448..cce38550 100644
--- a/Netch/Utils/TUNTAP.cs
+++ b/Netch/Utils/TUNTAP.cs
@@ -1,7 +1,10 @@
using System;
using System.Diagnostics;
using System.IO;
+using System.Linq;
+using System.Threading;
using Microsoft.Win32;
+using Netch.Controllers;
namespace Netch.Utils
{
@@ -9,35 +12,37 @@ namespace Netch.Utils
{
public static string TUNTAP_COMPONENT_ID_0901 = "tap0901";
public static string TUNTAP_COMPONENT_ID_0801 = "tap0801";
- public static string NETWORK_KEY = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
- public static string ADAPTER_KEY = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
+ public static string NETWORK_KEY = @"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}";
+ public static string ADAPTER_KEY = @"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}";
///
/// 获取 TUN/TAP 适配器 ID
///
/// 适配器 ID
- public static string GetComponentID()
+ public static string? GetComponentID()
{
try
{
- var adaptersRegistry = Registry.LocalMachine.OpenSubKey(ADAPTER_KEY);
+ var adaptersRegistry = Registry.LocalMachine.OpenSubKey(ADAPTER_KEY)!;
- foreach (var adapterRegistryName in adaptersRegistry.GetSubKeyNames())
- if (adapterRegistryName != "Configuration" && adapterRegistryName != "Properties")
- {
- var adapterRegistry = adaptersRegistry.OpenSubKey(adapterRegistryName);
+ foreach (var keyName in adaptersRegistry.GetSubKeyNames().Where(s => s is not ("Configuration" or "Properties")))
+ {
+ var adapterRegistry = adaptersRegistry.OpenSubKey(keyName)!;
+ var componentId = adapterRegistry.GetValue("ComponentId")?.ToString();
+ if (componentId == null)
+ continue;
- var adapterComponentId = adapterRegistry.GetValue("ComponentId", "").ToString();
- if (adapterComponentId == TUNTAP_COMPONENT_ID_0901 || adapterComponentId == TUNTAP_COMPONENT_ID_0801)
- return adapterRegistry.GetValue("NetCfgInstanceId", "").ToString();
- }
+ if (componentId == TUNTAP_COMPONENT_ID_0901 || componentId == TUNTAP_COMPONENT_ID_0801)
+ return (string) (adapterRegistry.GetValue("NetCfgInstanceId") ??
+ throw new Exception("Tap adapter have no NetCfgInstanceId key"));
+ }
}
catch (Exception e)
{
Logging.Warning(e.ToString());
}
- return "";
+ return null;
}
///
@@ -78,16 +83,21 @@ namespace Netch.Utils
///
/// 安装tap网卡
///
- public static void addtap()
+ public static void AddTap()
{
Logging.Info("安装 TUN/TAP 适配器");
//安装Tap Driver
- var installProcess = new Process
- {StartInfo = {WindowStyle = ProcessWindowStyle.Hidden, FileName = Path.Combine("bin/tap-driver", "addtap.bat")}};
+ using var process = Process.Start(new ProcessStartInfo
+ {
+ FileName = Path.Combine("bin/tap-driver", "addtap.bat"),
+ WindowStyle = ProcessWindowStyle.Hidden
+ })!;
- installProcess.Start();
- installProcess.WaitForExit();
- installProcess.Close();
+ process.WaitForExit();
+
+ Thread.Sleep(1000);
+ if (GetComponentID() == null)
+ throw new MessageException("TAP 驱动安装失败,找不到 ComponentID 注册表项");
}
}
}
\ No newline at end of file
diff --git a/Netch/Utils/Utils.cs b/Netch/Utils/Utils.cs
index 82ae87e1..0ee22a92 100644
--- a/Netch/Utils/Utils.cs
+++ b/Netch/Utils/Utils.cs
@@ -13,7 +13,6 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using MaxMind.GeoIP2;
using Microsoft.Win32.TaskScheduler;
-using Vanara.PInvoke;
using Task = System.Threading.Tasks.Task;
namespace Netch.Utils
@@ -138,40 +137,6 @@ namespace Netch.Utils
return File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty;
}
- public static void SearchOutboundAdapter(bool logging = true)
- {
- // 寻找出口适配器
- if (IpHlpApi.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) != 0)
- {
- Logging.Error("GetBestRoute 搜索失败");
- throw new Exception("GetBestRoute 搜索失败");
- }
-
- Global.Outbound.Index = (int) pRoute.dwForwardIfIndex;
- // 根据 IP Index 寻找 出口适配器
- var adapter = NetworkInterface.GetAllNetworkInterfaces()
- .First(_ =>
- {
- try
- {
- return _.GetIPProperties().GetIPv4Properties().Index == Global.Outbound.Index;
- }
- catch
- {
- return false;
- }
- });
-
- Global.Outbound.Adapter = adapter;
- Global.Outbound.Gateway = new IPAddress(pRoute.dwForwardNextHop.S_un_b);
-
- if (logging)
- {
- Logging.Info($"出口 IPv4 地址:{Global.Outbound.Address}");
- Logging.Info($"出口 网关 地址:{Global.Outbound.Gateway}");
- Logging.Info($"出口适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.Outbound.Index}");
- }
- }
public static void DrawCenterComboBox(object sender, DrawItemEventArgs e)
{