捕捉到未处理错误打开日志

减少TUN/TAP设置路由表代码
日志细节优化
This commit is contained in:
ChsBuffer
2020-07-28 16:10:26 +08:00
parent b6a3f5bc36
commit c9396bd6b2
13 changed files with 240 additions and 352 deletions

View File

@@ -38,6 +38,7 @@ namespace Netch.Controllers
/// <returns>是否启动成功</returns>
public bool Start(Server server, Mode mode)
{
Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
FlushDNSResolverCache();
var result = false;
@@ -90,7 +91,6 @@ namespace Netch.Controllers
if (result)
{
Logging.Info("加密代理已启动");
switch (mode.Type)
{
case 0: // 进程代理模式
@@ -136,7 +136,11 @@ namespace Netch.Controllers
}
}
if (!result) Stop();
if (!result)
{
Logging.Error("主控制器启动失败");
Stop();
}
return result;
}

View File

@@ -175,7 +175,7 @@ namespace Netch.Controllers
public static bool UninstallDriver()
{
Global.MainForm.StatusText(i18N.Translate("Uninstalling NF Service"));
Logging.Info("卸载NF驱动");
Logging.Info("卸载 NF 驱动");
try
{
if (NFService.Status == ServiceControllerStatus.Running)
@@ -211,7 +211,7 @@ namespace Netch.Controllers
/// <returns>驱动是否安装成功</returns>
public static bool InstallDriver()
{
Logging.Info("安装NF驱动");
Logging.Info("安装 NF 驱动");
try
{
File.Copy(BinDriver, SystemDriver);
@@ -227,7 +227,7 @@ namespace Netch.Controllers
var result = NFAPI.nf_registerDriver("netfilter2");
if (result == NF_STATUS.NF_STATUS_SUCCESS)
{
Logging.Info($"驱动安装成功,当前驱动版本:{DriverVersion(SystemDriver)}");
Logging.Info($"驱动安装成功");
}
else
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
@@ -38,7 +38,7 @@ namespace Netch.Controllers
Name = "Tap";
MainFile = "tun2socks.exe";
StartedKeywords("Running");
StoppedKeywords("failed","invalid vconfig file");
StoppedKeywords("failed", "invalid vconfig file");
}
/// <summary>
@@ -56,154 +56,113 @@ namespace Netch.Controllers
}
// 搜索出口
return SearchOutbounds();
return SearchAdapters();
}
private readonly List<IPNetwork> _directIPs = new List<IPNetwork>();
private readonly List<IPNetwork> _proxyIPs = new List<IPNetwork>();
/// <summary>
/// 设置绕行规则
/// <returns>是否设置成功</returns>
/// </summary>
private bool SetupBypass()
private bool SetupRouteTable()
{
Logging.Info("收集路由表规则");
Global.MainForm.StatusText(i18N.Translate("SetupBypass"));
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);
// 处理模式的绕过中国
Logging.Info("绕行 → 全局绕过 IP");
_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)));
if (_savedMode.BypassChina)
{
Logging.Info("设置绕行规则 → 处理模式的绕过中国");
using (var sr = new StringReader(Encoding.UTF8.GetString(Resources.CNIP)))
{
string text;
while ((text = sr.ReadLine()) != null)
{
var info = text.Split('/');
NativeMethods.CreateRoute(info[0], int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
}
Logging.Info("绕行 → 中国 IP");
_directIPs.AddRange(Encoding.UTF8.GetString(Resources.CNIP).Split('\n').Select(IPNetwork.Parse));
}
Logging.Info("设置绕行规则 → 处理全局绕过 IP");
// 处理全局绕过 IP
foreach (var ip in Global.Settings.BypassIPs)
Logging.Info("绕行 → 局域网 IP");
_directIPs.AddRange(_bypassLanIPs.Select(IPNetwork.Parse));
switch (_savedMode.Type)
{
var info = ip.Split('/');
var address = IPAddress.Parse(info[0]);
case 1:
// 代理规则
Logging.Info("代理 → 规则 IP");
_proxyIPs.AddRange(_savedMode.Rule.Select(IPNetwork.Parse));
if (!IPAddress.IsLoopback(address)) NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
Logging.Info("设置绕行规则 → 处理绕过局域网 IP");
// 处理绕过局域网 IP
foreach (var ip in _bypassLanIPs)
{
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 (_savedMode.Type == 2) // 处理仅规则内走直连
{
Logging.Info("设置绕行规则 → 处理仅规则内走直连");
// 将 TUN/TAP 网卡权重放到最高
var instance = new Process
{
StartInfo =
{
FileName = "netsh",
Arguments = string.Format("interface ip set interface {0} metric=0", Global.TUNTAP.Index),
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
CreateNoWindow = true
}
};
instance.Start();
Logging.Info("设置绕行规则 → 创建默认路由");
// 创建默认路由
if (!NativeMethods.CreateRoute("0.0.0.0", 0, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index, 10))
{
State = State.Stopped;
foreach (var address in _serverAddresses) NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
return false;
}
Logging.Info("设置绕行规则 → 创建规则路由");
// 创建规则路由
foreach (var ip in _savedMode.Rule)
{
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) // 处理仅规则内走代理
{
Logging.Info("设置绕行规则->处理仅规则内走代理");
foreach (var ip in _savedMode.Rule)
{
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);
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);
}
catch
{
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
}
//处理DNS代理
if (Global.Settings.TUNTAP.ProxyDNS)
{
Logging.Info("设置绕行规则 → 处理自定义 DNS 代理");
if (Global.Settings.TUNTAP.UseCustomDNS)
{
var dns = string.Empty;
foreach (var value in Global.Settings.TUNTAP.DNS)
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP自己记录解析了返回的 IP仅支持默认检测服务器
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
try
{
dns += value;
dns += ',';
Logging.Info("代理 → STUN 服务器 IP");
_proxyIPs.AddRange(new[]
{
Dns.GetHostAddresses(Global.Settings.STUN_Server)[0],
Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0]
}.Select(ip => IPNetwork.Parse(ip.ToString(), 32)));
}
catch
{
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
}
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);
}
else
if (Global.Settings.TUNTAP.ProxyDNS)
{
if (int.TryParse("32", out var prefix))
Logging.Info("代理 → 自定义 DNS");
if (Global.Settings.TUNTAP.UseCustomDNS)
{
NativeMethods.CreateRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
NativeMethods.CreateRoute("8.8.8.8", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
NativeMethods.CreateRoute("9.9.9.9", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
NativeMethods.CreateRoute("185.222.222.222", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
var dns = string.Empty;
foreach (var value in Global.Settings.TUNTAP.DNS)
{
dns += value;
dns += ',';
}
dns = dns.Trim();
dns = dns.Substring(0, dns.Length - 1);
RouteAction(Action.Create, dns, 32, RouteType.TUNTAP);
}
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)));
}
}
}
break;
case 2:
// 绕过规则
// 将 TUN/TAP 网卡权重放到最高
Process.Start(new ProcessStartInfo
{
FileName = "netsh",
Arguments = $"interface ip set interface {Global.TUNTAP.Index} metric=0",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
CreateNoWindow = true
}
);
Logging.Info("绕行 → 规则 IP");
_directIPs.AddRange(_savedMode.Rule.Select(IPNetwork.Parse));
Logging.Info("代理 → 全局");
if (!RouteAction(Action.Create, IPNetwork.Parse("0.0.0.0", 0), RouteType.TUNTAP))
{
State = State.Stopped;
return false;
}
break;
}
Logging.Info("设置路由规则");
RouteAction(Action.Create, _directIPs, RouteType.Gateway);
RouteAction(Action.Create, _proxyIPs, RouteType.TUNTAP);
return true;
}
@@ -211,100 +170,21 @@ namespace Netch.Controllers
/// <summary>
/// 清除绕行规则
/// </summary>
public bool ClearBypass()
private bool ClearBypass()
{
if (_savedMode.Type == 2)
switch (_savedMode.Type)
{
NativeMethods.DeleteRoute("0.0.0.0", 0, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index, 10);
foreach (var ip in _savedMode.Rule)
{
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)
{
foreach (var ip in _savedMode.Rule)
{
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);
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);
}
catch
{
}
if (Global.Settings.TUNTAP.ProxyDNS)
{
if (Global.Settings.TUNTAP.UseCustomDNS)
{
var dns = string.Empty;
foreach (var value in Global.Settings.TUNTAP.DNS)
{
dns += value;
dns += ',';
}
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);
}
else
{
if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
}
}
case 1:
break;
case 2:
RouteAction(Action.Delete, "0.0.0.0", 0, RouteType.TUNTAP, 10);
break;
}
foreach (var ip in Global.Settings.BypassIPs)
{
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);
}
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 (_savedMode.BypassChina)
using (var sr = new StringReader(Encoding.UTF8.GetString(Resources.CNIP)))
{
string text;
while ((text = sr.ReadLine()) != null)
{
var info = text.Split('/');
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);
RouteAction(Action.Delete, _directIPs, RouteType.Gateway);
RouteAction(Action.Delete, _proxyIPs, RouteType.TUNTAP);
_directIPs.Clear();
_proxyIPs.Clear();
return true;
}
@@ -317,14 +197,11 @@ namespace Netch.Controllers
if (!Configure()) return false;
Logging.Info("设置绕行规则");
SetupBypass();
Logging.Info("设置绕行规则完毕");
SetupRouteTable();
Instance = GetProcess();
var adapterName = TUNTAP.GetName(Global.TUNTAP.ComponentID);
Logging.Info($"tun2sock使用适配器{adapterName}");
string dns;
//V2ray使用Unbound本地DNS会导致查询异常缓慢故此V2ray不启动unbound而是使用自定义DNS
@@ -372,8 +249,8 @@ namespace Netch.Controllers
case State.Started:
return true;
case State.Stopped:
Stop();
return false;
Stop();
return false;
}
}
@@ -395,74 +272,25 @@ namespace Netch.Controllers
}
/// <summary>
/// 搜索出口
/// 搜索出口和TUNTAP适配器
/// </summary>
public static bool SearchOutbounds()
private static bool SearchAdapters()
{
Logging.Info("正在搜索出口中");
NetworkInterface adapter;
Logging.Info("搜索适配器");
if (Win32Native.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) == 0)
{
Global.Adapter.Index = pRoute.dwForwardIfIndex;
adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => _.GetIPProperties().GetIPv4Properties().Index == Global.Adapter.Index);
Global.Adapter.Address = adapter.GetIPProperties().UnicastAddresses.First(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork).Address;
Global.Adapter.Gateway = new IPAddress(pRoute.dwForwardNextHop);
Logging.Info($"当前 网关 地址:{Global.Adapter.Gateway}");
Logging.Info($"出口 IPv4 地址:{Global.Adapter.Address}");
Logging.Info($"出口 网关 地址:{Global.Adapter.Gateway}");
Logging.Info($"出口适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.Adapter.Index}");
}
else
{
Logging.Error("GetBestRoute 搜索失败");
return false;
}
Logging.Info($"搜索适配器index{Global.Adapter.Index}");
var AddressGot = false;
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
try
{
var adapterProperties = adapter.GetIPProperties();
var p = adapterProperties.GetIPv4Properties();
Logging.Info($"检测适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {p.Index}");
// 通过索引查找对应适配器的 IPv4 地址
if (p.Index == Global.Adapter.Index)
{
var AdapterIPs = string.Empty;
foreach (var ip in adapterProperties.UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
AddressGot = true;
Global.Adapter.Address = ip.Address;
Logging.Info($"当前出口 IPv4 地址:{Global.Adapter.Address}");
break;
}
AdapterIPs = $"{ip.Address} | ";
}
if (!AddressGot)
{
if (AdapterIPs.Length > 3)
{
AdapterIPs = AdapterIPs.Substring(0, AdapterIPs.Length - 3);
Logging.Info($"所有出口地址:{AdapterIPs}");
}
Logging.Error("出口无 IPv4 地址,当前只支持 IPv4 地址");
return false;
}
break;
}
}
catch (Exception)
{
// ignored
}
if (!AddressGot)
{
Logging.Error("无法找到当前使用适配器");
Logging.Error("GetBestRoute 搜索失败(找不到出口适配器)");
return false;
}
@@ -470,11 +298,11 @@ namespace Netch.Controllers
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID))
{
Logging.Error("未找到可用 TUN/TAP 适配器");
Logging.Error("未找到可用 TAP 适配器");
if (MessageBoxX.Show(i18N.Translate("TUN/TAP driver is not detected. Is it installed now?"), confirm: true) == DialogResult.OK)
{
Configuration.addtap();
//给点时间不然立马安装完毕就查找适配器可能会导致找不到适配器ID
// 给点时间不然立马安装完毕就查找适配器可能会导致找不到适配器ID
Thread.Sleep(1000);
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
}
@@ -482,24 +310,62 @@ namespace Netch.Controllers
{
return false;
}
//MessageBoxX.Show(i18N.Translate("Please install TAP-Windows and create an TUN/TAP adapter manually"));
// return false;
}
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
if (adapter.Id == Global.TUNTAP.ComponentID)
{
Global.TUNTAP.Adapter = adapter;
Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index;
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}");
return true;
}
Logging.Info($"找到适配器TUN/TAP{adapter.Id}");
return true;
}
private enum RouteType
{
Gateway,
TUNTAP
}
Logging.Error("无法找到出口");
return false;
private enum Action
{
Create,
Delete
}
private static bool RouteAction(Action action, IEnumerable<IPNetwork> ipNetworks, RouteType routeType, int metric = 0)
{
return ipNetworks.All(address => RouteAction(action, address, routeType, metric));
}
private static bool RouteAction(Action action, string address, byte cidr, RouteType routeType, int metric = 0)
{
return RouteAction(action, IPNetwork.Parse(address, cidr), routeType, metric);
}
private static bool RouteAction(Action action, IPNetwork ipNetwork, RouteType routeType, int metric = 0)
{
string gateway;
int index;
switch (routeType)
{
case RouteType.Gateway:
gateway = Global.Adapter.Gateway.ToString();
index = Global.Adapter.Index;
break;
case RouteType.TUNTAP:
gateway = Global.Settings.TUNTAP.Gateway;
index = Global.TUNTAP.Index;
break;
default:
throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null);
}
return 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),
_ => throw new ArgumentOutOfRangeException(nameof(action), action, null)
};
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using Netch.Models;
using Netch.Utils;
@@ -43,7 +44,7 @@ namespace Netch.Controllers
return (true, natType, localEnd, publicEnd);
}
catch (Exception e)
catch (Win32Exception e)
{
Logging.Error("NTT 进程出错\n" + e);
Stop();