Use the registry to edit System DNS instead of WMI, check network connection before start mode

This commit is contained in:
ChsBuffer
2020-09-19 19:05:12 +08:00
parent 383efc453d
commit f777fae3d8
7 changed files with 112 additions and 116 deletions

View File

@@ -33,6 +33,13 @@ namespace Netch.Controllers
}
NativeMethods.FlushDNSResolverCache();
if (!Utils.Utils.SearchOutboundAdapter())
{
MessageBoxX.Show("No internet connection");
return false;
}
_ = Task.Run(Firewall.AddNetchFwRules);
try

View File

@@ -1,9 +1,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using Netch.Models;
using Netch.Utils;
@@ -17,7 +15,7 @@ namespace Netch.Controllers
private static readonly string BinDriver = string.Empty;
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
private static string[] _sysDns = { };
private static string _sysDns;
static NFController()
{
@@ -92,9 +90,8 @@ namespace Netch.Controllers
if (Global.Settings.ModifySystemDNS)
{
// 备份并替换系统 DNS
_sysDns = DNS.getSystemDns();
string[] dns = {"1.1.1.1", "8.8.8.8"};
DNS.SetDNS(dns);
_sysDns = DNS.OutboundDNS;
DNS.OutboundDNS = "1.1.1.1,8.8.8.8";
}
return aio_init();
@@ -106,7 +103,7 @@ namespace Netch.Controllers
{
if (Global.Settings.ModifySystemDNS)
//恢复系统DNS
DNS.SetDNS(_sysDns);
DNS.OutboundDNS = _sysDns;
});
aio_free();

View File

@@ -18,7 +18,8 @@ namespace Netch.Controllers
public class TUNTAPController : ModeController
{
// ByPassLan IP
private readonly List<string> _bypassLanIPs = new List<string> {"10.0.0.0/8", "172.16.0.0/16", "192.168.0.0/16"};
private readonly List<string> _bypassLanIPs = new List<string>
{"10.0.0.0/8", "172.16.0.0/16", "192.168.0.0/16"};
private Mode _savedMode = new Mode();
private Server _savedServer = new Server();
@@ -56,7 +57,7 @@ namespace Netch.Controllers
}
// 搜索出口
return SearchAdapters();
return SearchTapAdapter();
}
private readonly List<IPNetwork> _directIPs = new List<IPNetwork>();
@@ -75,7 +76,8 @@ namespace Netch.Controllers
_directIPs.AddRange(Global.Settings.BypassIPs.Select(IPNetwork.Parse));
Logging.Info("绕行 → 服务器 IP");
_directIPs.AddRange(_serverAddresses.Where(address => !IPAddress.IsLoopback(address)).Select(address => IPNetwork.Parse(address.ToString(), 32)));
_directIPs.AddRange(_serverAddresses.Where(address => !IPAddress.IsLoopback(address))
.Select(address => IPNetwork.Parse(address.ToString(), 32)));
Logging.Info("绕行 → 局域网 IP");
_directIPs.AddRange(_bypassLanIPs.Select(IPNetwork.Parse));
@@ -121,7 +123,9 @@ namespace Netch.Controllers
}
else
{
_proxyIPs.AddRange(new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip => IPNetwork.Parse(ip, 32)));
_proxyIPs.AddRange(
new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip =>
IPNetwork.Parse(ip, 32)));
}
}
@@ -231,7 +235,8 @@ namespace Netch.Controllers
else
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 \"{adapterName}\" ");
argument.Append(
$"-tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {dns} -tunName \"{adapterName}\" ");
if (Global.Settings.TUNTAP.UseFakeDNS)
argument.Append("-fakeDns ");
@@ -256,22 +261,14 @@ namespace Netch.Controllers
/// <summary>
/// 搜索出口和TUNTAP适配器
/// </summary>
private static bool SearchAdapters()
public static bool SearchTapAdapter()
{
// 寻找出口适配器
if (Win32Native.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) != 0)
{
Logging.Error("GetBestRoute 搜索失败(找不到出口适配器)");
return false;
}
Global.Adapter.Index = pRoute.dwForwardIfIndex;
// 搜索 TUN/TAP 适配器的索引
if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID = TUNTAP.GetComponentID()))
{
Logging.Info("找不到 TAP 适配器");
if (MessageBoxX.Show(i18N.Translate("TUN/TAP driver is not detected. Is it installed now?"), confirm: true) == DialogResult.OK)
if (MessageBoxX.Show(i18N.Translate("TUN/TAP driver is not detected. Is it installed now?"),
confirm: true) == DialogResult.OK)
{
Configuration.addtap();
// 给点时间不然立马安装完毕就查找适配器可能会导致找不到适配器ID
@@ -289,42 +286,14 @@ namespace Netch.Controllers
}
}
// 根据 IP Index 寻找 出口适配器
var errorAdaptersId = new List<string>();
try
{
var adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ =>
{
try
{
return _.GetIPProperties().GetIPv4Properties().Index == Global.Adapter.Index;
}
catch (NetworkInformationException)
{
errorAdaptersId.Add(_.Id);
return false;
}
});
Global.Adapter.Address = adapter.GetIPProperties().UnicastAddresses.First(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork).Address;
Global.Adapter.Gateway = new IPAddress(pRoute.dwForwardNextHop);
Logging.Info($"出口 IPv4 地址:{Global.Adapter.Address}");
Logging.Info($"出口 网关 地址:{Global.Adapter.Gateway}");
Logging.Info($"出口适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.Adapter.Index}");
}
catch (Exception e)
{
Logging.Error($"找不到 IP Index 为 {Global.Adapter.Index} 的出口适配器: {e.Message}");
PrintAdapters();
return false;
}
// 根据 ComponentID 寻找 Tap适配器
try
{
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}");
Logging.Info(
$"TAP 适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.TUNTAP.Index}");
}
catch (Exception e)
{
@@ -335,18 +304,10 @@ namespace Netch.Controllers
_ => $"Tap 适配器其他异常: {e}"
};
Logging.Error(msg);
PrintAdapters();
return false;
}
return true;
void PrintAdapters()
{
Logging.Info("所有适配器:\n" +
NetworkInterface.GetAllNetworkInterfaces().Aggregate(string.Empty, (current, adapter)
=> current + $"{ /*如果加了 * 代表遍历中出现异常的适配器 */(errorAdaptersId.Contains(adapter.Id) ? "*" : "")}{adapter.Name} {adapter.Id} {adapter.Description}{Global.EOF}"));
}
}
@@ -362,7 +323,8 @@ namespace Netch.Controllers
Delete
}
private static void RouteAction(Action action, IEnumerable<IPNetwork> ipNetworks, RouteType routeType, int metric = 0)
private static void RouteAction(Action action, IEnumerable<IPNetwork> ipNetworks, RouteType routeType,
int metric = 0)
{
foreach (var address in ipNetworks)
{
@@ -382,8 +344,8 @@ namespace Netch.Controllers
switch (routeType)
{
case RouteType.Gateway:
gateway = Global.Adapter.Gateway.ToString();
index = Global.Adapter.Index;
gateway = Global.Outbound.Gateway.ToString();
index = Global.Outbound.Index;
break;
case RouteType.TUNTAP:
gateway = Global.Settings.TUNTAP.Gateway;
@@ -395,8 +357,10 @@ namespace Netch.Controllers
var result = action switch
{
Action.Create => NativeMethods.CreateRoute(ipNetwork.Network.ToString(), ipNetwork.Cidr, gateway, index, metric),
Action.Delete => NativeMethods.DeleteRoute(ipNetwork.Network.ToString(), ipNetwork.Cidr, gateway, index, metric),
Action.Create => NativeMethods.CreateRoute(ipNetwork.Network.ToString(), ipNetwork.Cidr, gateway, index,
metric),
Action.Delete => NativeMethods.DeleteRoute(ipNetwork.Network.ToString(), ipNetwork.Cidr, gateway, index,
metric),
_ => throw new ArgumentOutOfRangeException(nameof(action), action, null)
};

View File

@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Windows.Forms;
using Netch.Forms;
using Netch.Models;
@@ -155,9 +157,9 @@ namespace Netch
};
/// <summary>
/// 适配器
/// 出口适配器
/// </summary>
public static class Adapter
public static class Outbound
{
/// <summary>
/// 索引
@@ -167,12 +169,14 @@ namespace Netch
/// <summary>
/// 地址
/// </summary>
public static IPAddress Address;
public static IPAddress Address => Adapter.GetIPProperties().UnicastAddresses.First(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork).Address;
/// <summary>
/// 网关
/// </summary>
public static IPAddress Gateway;
public static NetworkInterface Adapter;
}
/// <summary>

View File

@@ -73,9 +73,6 @@
</ItemGroup>
<ItemGroup>
<Reference Include="System.IO.Compression" />
<Reference Include="System.Management" />
<Reference Include="System.Net.Http" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Web" />
</ItemGroup>

View File

@@ -1,9 +1,7 @@
using System;
using System.Collections;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using Microsoft.Win32;
namespace Netch.Utils
{
@@ -48,51 +46,32 @@ namespace Netch.Utils
return null;
}
}
/// <summary>
/// 设置DNS
/// </summary>
/// <param name="dns"></param>
public static void SetDNS(string[] dns)
{
var wmi = new ManagementClass("Win32_NetworkAdapterConfiguration");
var moc = wmi.GetInstances();
ManagementBaseObject inPar = null;
ManagementBaseObject outPar = null;
foreach (ManagementObject mo in moc)
{
//如果没有启用IP设置的网络设备则跳过如果是虚拟机网卡也跳过
if (!(bool)mo["IPEnabled"] ||
mo["Description"].ToString().Contains("Virtual") ||
mo["Description"].ToString().Contains("VMware") ||
mo["Description"].ToString().Contains("TAP"))
continue;
//设置DNS地址
if (dns != null)
private static RegistryKey AdapterRegistry(bool write = false)
{
return Registry.LocalMachine.OpenSubKey(
$@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{Global.Outbound.Adapter.Id}", write);
}
/// <summary>
/// 出口网卡 DNS
/// <para></para>
/// 依赖 <see cref="Global.Outbound.Adapter"/>
/// </summary>
public static string OutboundDNS
{
get
{
try
{
inPar = mo.GetMethodParameters("SetDNSServerSearchOrder");
inPar["DNSServerSearchOrder"] = dns;
outPar = mo.InvokeMethod("SetDNSServerSearchOrder", inPar, null);
return (string) AdapterRegistry().GetValue("NameServer");
}
catch
{
return string.Empty;
}
}
}
/// <summary>
/// 从网卡获取ip设置信息
/// </summary>
public static string[] getSystemDns()
{
var systemDns = new[] { "223.5.5.5", "1.1.1.1" };
foreach (var network in NetworkInterface.GetAllNetworkInterfaces())
if (!network.Description.Contains("Virtual") &&
!network.Description.Contains("VMware") &&
!network.Description.Contains("TAP") &&
network.OperationalStatus == OperationalStatus.Up &&
network.GetIPProperties()?.GatewayAddresses.Count != 0)
{
systemDns = network.GetIPProperties().DnsAddresses.Select(dns => dns.ToString()).ToArray();
}
return systemDns;
set => AdapterRegistry(true).SetValue("NameServer", value, RegistryValueKind.String);
}
}
}

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
@@ -122,5 +124,51 @@ namespace Netch.Utils
}
public static string FileVersion(string file) => File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty;
public static bool SearchOutboundAdapter()
{
// 寻找出口适配器
if (Win32Native.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0),
0, out var pRoute) != 0)
{
Logging.Error("GetBestRoute 搜索失败");
return false;
}
Global.Outbound.Index = pRoute.dwForwardIfIndex;
// 根据 IP Index 寻找 出口适配器
try
{
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);
Logging.Info($"出口 IPv4 地址:{Global.Outbound.Address}");
Logging.Info($"出口 网关 地址:{Global.Outbound.Gateway}");
Logging.Info(
$"出口适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.Outbound.Index}");
return true;
}
catch (Exception)
{
Logging.Error("找不到出口IP所在网卡");
return false;
}
}
public static void LoggingAdapters(string id)
{
var adapter = NetworkInterface.GetAllNetworkInterfaces().First(adapter => adapter.Id == id);
Logging.Warning($"检索此网卡信息出错: {adapter.Name} {adapter.Id} {adapter.Description}");
}
}
}