mirror of
https://github.com/netchx/netch.git
synced 2026-03-18 18:13:21 +08:00
Reafctor IController
This commit is contained in:
@@ -4,14 +4,22 @@
|
||||
{
|
||||
public const string TempConfig = "data\\last.json";
|
||||
public const string TempRouteFile = "data\\route.txt";
|
||||
public const string EOF = "\r\n";
|
||||
public const string OutputTemplate = @"[{Timestamp:yyyy-MM-dd HH:mm:ss}][{Level}] {Message:lj}{NewLine}{Exception}";
|
||||
|
||||
public const string AioDnsRuleFile = "bin\\aiodns.conf";
|
||||
public const string NFDriver = "bin\\nfdriver.sys";
|
||||
public const string STUNServersFile = "bin\\stun.txt";
|
||||
|
||||
public const string LogFile = "logging\\application.log";
|
||||
|
||||
public const string OutputTemplate = @"[{Timestamp:yyyy-MM-dd HH:mm:ss}][{Level}] {Message:lj}{NewLine}{Exception}";
|
||||
public const string EOF = "\r\n";
|
||||
|
||||
public static class Parameter
|
||||
{
|
||||
public const string Show = "-show";
|
||||
public const string ForceUpdate = "-forceUpdate";
|
||||
}
|
||||
|
||||
public const string WintunDllFile = "bin\\wintun.dll";
|
||||
}
|
||||
}
|
||||
@@ -7,26 +7,25 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class DNSController : IController
|
||||
{
|
||||
public string Name { get; } = "DNS Service";
|
||||
|
||||
private const string RulePath = "bin\\aiodns.conf";
|
||||
public string Name => "DNS Service";
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动DNS服务
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void Start()
|
||||
{
|
||||
MainController.PortCheck(Global.Settings.AioDNS.ListenPort, "DNS");
|
||||
|
||||
var aioDnsConfig = Global.Settings.AioDNS;
|
||||
var listenAddress = Global.Settings.LocalAddress;
|
||||
|
||||
Dial(NameList.TYPE_REST, "");
|
||||
Dial(NameList.TYPE_ADDR, $"{Global.Settings.LocalAddress}:{Global.Settings.AioDNS.ListenPort}");
|
||||
Dial(NameList.TYPE_LIST, Path.GetFullPath(RulePath));
|
||||
Dial(NameList.TYPE_CDNS, $"{Global.Settings.AioDNS.ChinaDNS}");
|
||||
Dial(NameList.TYPE_ODNS, $"{Global.Settings.AioDNS.OtherDNS}");
|
||||
Dial(NameList.TYPE_ADDR, $"{listenAddress}:{aioDnsConfig.ListenPort}");
|
||||
Dial(NameList.TYPE_LIST, Path.GetFullPath(Constants.AioDnsRuleFile));
|
||||
Dial(NameList.TYPE_CDNS, $"{aioDnsConfig.ChinaDNS}");
|
||||
Dial(NameList.TYPE_ODNS, $"{aioDnsConfig.OtherDNS}");
|
||||
|
||||
if (!Init())
|
||||
throw new Exception("AioDNS start failed.");
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
using Netch.Utils;
|
||||
using Serilog;
|
||||
|
||||
@@ -11,47 +10,17 @@ namespace Netch.Controllers
|
||||
{
|
||||
public static class MainController
|
||||
{
|
||||
public static Mode? Mode;
|
||||
|
||||
public static Server? Server;
|
||||
|
||||
private static Server? _udpServer;
|
||||
public static Mode? Mode { get; private set; }
|
||||
|
||||
public static readonly NTTController NTTController = new();
|
||||
private static IServerController? _serverController;
|
||||
private static IServerController? _udpServerController;
|
||||
|
||||
public static IServerController? ServerController
|
||||
{
|
||||
get => _serverController;
|
||||
private set => _serverController = value;
|
||||
}
|
||||
|
||||
public static IServerController? UdpServerController
|
||||
{
|
||||
get => _udpServerController ?? _serverController;
|
||||
set => _udpServerController = value;
|
||||
}
|
||||
|
||||
public static Server? UdpServer
|
||||
{
|
||||
get => _udpServer ?? Server;
|
||||
set => _udpServer = value;
|
||||
}
|
||||
public static IServerController? ServerController { get; private set; }
|
||||
|
||||
public static IModeController? ModeController { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
/// <exception cref="MessageException"></exception>
|
||||
public static async Task StartAsync(Server server, Mode mode)
|
||||
{
|
||||
Log.Information("启动主控制器: {Server} {Mode}", $"{server.Type}", $"[{(int)mode.Type}]{mode.Remark}");
|
||||
Server = server;
|
||||
Mode = mode;
|
||||
|
||||
// 刷新 DNS 缓存
|
||||
@@ -66,12 +35,9 @@ namespace Netch.Controllers
|
||||
try
|
||||
{
|
||||
if (!ModeHelper.SkipServerController(server, mode))
|
||||
{
|
||||
StartServer(server, mode, out _serverController);
|
||||
StatusPortInfoText.UpdateShareLan();
|
||||
}
|
||||
server = StartServer(server);
|
||||
|
||||
StartMode(mode);
|
||||
StartMode(server, mode);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -91,28 +57,23 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
private static void StartServer(Server server, Mode mode, out IServerController controller)
|
||||
private static Server StartServer(Server server)
|
||||
{
|
||||
controller = ServerHelper.GetUtilByTypeName(server.Type).GetController();
|
||||
ServerController = ServerHelper.GetUtilByTypeName(server.Type).GetController();
|
||||
|
||||
TryReleaseTcpPort(controller.Socks5LocalPort(), "Socks5");
|
||||
TryReleaseTcpPort(ServerController.Socks5LocalPort(), "Socks5");
|
||||
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name));
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ServerController.Name));
|
||||
|
||||
controller.Start(in server, mode);
|
||||
var socks5 = ServerController.Start(server);
|
||||
|
||||
if (server is Socks5 socks5)
|
||||
{
|
||||
if (socks5.Auth())
|
||||
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusPortInfoText.Socks5Port = controller.Socks5LocalPort();
|
||||
}
|
||||
StatusPortInfoText.Socks5Port = socks5.Port;
|
||||
StatusPortInfoText.UpdateShareLan();
|
||||
|
||||
return socks5;
|
||||
}
|
||||
|
||||
private static void StartMode(Mode mode)
|
||||
private static void StartMode(Server server, Mode mode)
|
||||
{
|
||||
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName);
|
||||
|
||||
@@ -121,12 +82,12 @@ namespace Netch.Controllers
|
||||
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
||||
|
||||
ModeController.Start(mode);
|
||||
ModeController.Start(server, mode);
|
||||
}
|
||||
|
||||
public static async Task StopAsync()
|
||||
{
|
||||
if (_serverController == null && ModeController == null)
|
||||
if (ServerController == null && ModeController == null)
|
||||
return;
|
||||
|
||||
StatusPortInfoText.Reset();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.ServiceProcess;
|
||||
@@ -16,15 +17,21 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class NFController : IModeController
|
||||
{
|
||||
private Server? _server;
|
||||
private Mode? _mode;
|
||||
private RedirectorConfig? _rdrConfig;
|
||||
|
||||
private static readonly ServiceController NFService = new("netfilter2");
|
||||
|
||||
private const string BinDriver = "bin\\nfdriver.sys";
|
||||
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
|
||||
|
||||
public string Name { get; } = "Redirector";
|
||||
public string Name => "Redirector";
|
||||
|
||||
public void Start(in Mode mode)
|
||||
public void Start(Server server, Mode mode)
|
||||
{
|
||||
_server = server;
|
||||
_mode = mode;
|
||||
_rdrConfig = Global.Settings.Redirector;
|
||||
CheckDriver();
|
||||
|
||||
Dial(NameList.TYPE_FILTERLOOPBACK, "false");
|
||||
@@ -34,15 +41,15 @@ namespace Netch.Controllers
|
||||
Dial(NameList.TYPE_UDPLISN, p.ToString());
|
||||
|
||||
// Server
|
||||
Dial(NameList.TYPE_FILTERUDP, (Global.Settings.Redirector.FilterProtocol != PortType.TCP).ToString().ToLower());
|
||||
Dial(NameList.TYPE_FILTERTCP, (Global.Settings.Redirector.FilterProtocol != PortType.UDP).ToString().ToLower());
|
||||
dial_Server(Global.Settings.Redirector.FilterProtocol);
|
||||
Dial(NameList.TYPE_FILTERUDP, _rdrConfig.FilterProtocol.HasFlag(PortType.UDP).ToString().ToLower());
|
||||
Dial(NameList.TYPE_FILTERTCP, _rdrConfig.FilterProtocol.HasFlag(PortType.TCP).ToString().ToLower());
|
||||
dial_Server(_rdrConfig.FilterProtocol, _server);
|
||||
|
||||
// Mode Rule
|
||||
dial_Name(mode);
|
||||
dial_Name(_mode);
|
||||
|
||||
// Features
|
||||
Dial(NameList.TYPE_DNSHOST, Global.Settings.Redirector.DNSHijack ? Global.Settings.Redirector.DNSHijackHost : "");
|
||||
Dial(NameList.TYPE_DNSHOST, _rdrConfig.DNSHijack ? _rdrConfig.DNSHijackHost : "");
|
||||
|
||||
if (!Init())
|
||||
throw new MessageException("Redirector start failed.");
|
||||
@@ -95,31 +102,16 @@ namespace Netch.Controllers
|
||||
|
||||
#endregion
|
||||
|
||||
private void dial_Server(in PortType portType)
|
||||
private void dial_Server(PortType portType, in Server server)
|
||||
{
|
||||
if (portType == PortType.Both)
|
||||
{
|
||||
dial_Server(PortType.TCP);
|
||||
dial_Server(PortType.UDP);
|
||||
dial_Server(PortType.TCP, server);
|
||||
dial_Server(PortType.UDP, server);
|
||||
return;
|
||||
}
|
||||
|
||||
int offset;
|
||||
Server server;
|
||||
IServerController controller;
|
||||
|
||||
if (portType == PortType.UDP)
|
||||
{
|
||||
offset = UdpNameListOffset;
|
||||
server = MainController.UdpServer!;
|
||||
controller = MainController.UdpServerController!;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
server = MainController.Server!;
|
||||
controller = MainController.ServerController!;
|
||||
}
|
||||
var offset = portType == PortType.UDP ? UdpNameListOffset : 0;
|
||||
|
||||
if (server is Socks5 socks5)
|
||||
{
|
||||
@@ -129,7 +121,7 @@ namespace Netch.Controllers
|
||||
Dial(NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
|
||||
Dial(NameList.TYPE_TCPMETH + offset, string.Empty);
|
||||
}
|
||||
else if (server is Shadowsocks shadowsocks && !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS)
|
||||
else if (server is Shadowsocks shadowsocks && !shadowsocks.HasPlugin() && _rdrConfig.RedirectorSS)
|
||||
{
|
||||
Dial(NameList.TYPE_TCPTYPE + offset, "Shadowsocks");
|
||||
Dial(NameList.TYPE_TCPHOST + offset, $"{shadowsocks.AutoResolveHostname()}:{shadowsocks.Port}");
|
||||
@@ -138,11 +130,7 @@ namespace Netch.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
Dial(NameList.TYPE_TCPTYPE + offset, "Socks5");
|
||||
Dial(NameList.TYPE_TCPHOST + offset, $"127.0.0.1:{controller.Socks5LocalPort()}");
|
||||
Dial(NameList.TYPE_TCPUSER + offset, string.Empty);
|
||||
Dial(NameList.TYPE_TCPPASS + offset, string.Empty);
|
||||
Dial(NameList.TYPE_TCPMETH + offset, string.Empty);
|
||||
Trace.Assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +163,11 @@ namespace Netch.Controllers
|
||||
|
||||
private static void CheckDriver()
|
||||
{
|
||||
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
|
||||
var binFileVersion = Utils.Utils.GetFileVersion(Constants.NFDriver);
|
||||
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
|
||||
|
||||
Log.Information("内置驱动版本: " + binFileVersion);
|
||||
Log.Information("系统驱动版本: " + systemFileVersion);
|
||||
Log.Information("内置驱动版本: {Name}", binFileVersion);
|
||||
Log.Information("系统驱动版本: {Name}", systemFileVersion);
|
||||
|
||||
if (!File.Exists(SystemDriver))
|
||||
{
|
||||
@@ -222,16 +210,16 @@ namespace Netch.Controllers
|
||||
{
|
||||
Log.Information("安装 NF 驱动");
|
||||
|
||||
if (!File.Exists(BinDriver))
|
||||
if (!File.Exists(Constants.NFDriver))
|
||||
throw new MessageException(i18N.Translate("builtin driver files missing, can't install NF driver"));
|
||||
|
||||
try
|
||||
{
|
||||
File.Copy(BinDriver, SystemDriver);
|
||||
File.Copy(Constants.NFDriver, SystemDriver);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e,"驱动复制失败\n");
|
||||
Log.Error(e, "驱动复制失败\n");
|
||||
throw new MessageException($"Copy NF driver file failed\n{e.Message}");
|
||||
}
|
||||
|
||||
@@ -244,7 +232,7 @@ namespace Netch.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("注册驱动失败: {Result}",result);
|
||||
Log.Error("注册驱动失败: {Result}", result);
|
||||
throw new MessageException($"Register NF driver failed\n{result}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,39 +15,48 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class PcapController : Guard, IModeController
|
||||
{
|
||||
private readonly LogForm _form;
|
||||
private Mode? _mode;
|
||||
private Server? _server;
|
||||
|
||||
public PcapController() : base("pcap2socks.exe", encoding: Encoding.UTF8)
|
||||
{
|
||||
_form = new LogForm(Global.MainForm);
|
||||
_form.CreateControl();
|
||||
}
|
||||
|
||||
~PcapController()
|
||||
{
|
||||
_form.Dispose();
|
||||
}
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] { "└" };
|
||||
|
||||
public override string Name => "pcap2socks";
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] { "└" };
|
||||
|
||||
private readonly LogForm _form;
|
||||
|
||||
public void Start(in Mode mode)
|
||||
public void Start(Server server, Mode mode)
|
||||
{
|
||||
var server = MainController.Server!;
|
||||
_server = server;
|
||||
_mode = mode;
|
||||
|
||||
var outboundNetworkInterface = NetworkInterfaceUtils.GetBest();
|
||||
|
||||
var argument = new StringBuilder($@"-i \Device\NPF_{outboundNetworkInterface.Id}");
|
||||
if (server is Socks5 socks5 && !socks5.Auth())
|
||||
argument.Append($" --destination {server.AutoResolveHostname()}:{server.Port}");
|
||||
if (_server is Socks5 socks5 && !socks5.Auth())
|
||||
argument.Append($" --destination {socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
else
|
||||
argument.Append($" --destination 127.0.0.1:{Global.Settings.Socks5LocalPort}");
|
||||
|
||||
argument.Append($" {mode.GetRules().FirstOrDefault() ?? "-P n"}");
|
||||
argument.Append($" {_mode.GetRules().FirstOrDefault() ?? "-P n"}");
|
||||
StartGuard(argument.ToString());
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
_form.Close();
|
||||
StopGuard();
|
||||
}
|
||||
|
||||
~PcapController()
|
||||
{
|
||||
_form.Dispose();
|
||||
}
|
||||
|
||||
protected override void OnReadNewLine(string line)
|
||||
{
|
||||
Global.MainForm.BeginInvoke(new Action(() => _form.richTextBox1.AppendText(line + "\n")));
|
||||
@@ -73,11 +82,5 @@ namespace Netch.Controllers
|
||||
|
||||
Utils.Utils.Open(LogPath);
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
_form.Close();
|
||||
StopGuard();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Enums;
|
||||
using Netch.Interfaces;
|
||||
using Netch.Interops;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
using Netch.Utils;
|
||||
using Netch.Interops;
|
||||
using Serilog;
|
||||
using static Netch.Interops.tun2socks;
|
||||
|
||||
@@ -16,24 +17,23 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class TUNController : IModeController
|
||||
{
|
||||
public string Name => "tun2socks";
|
||||
|
||||
private const string DummyDns = "6.6.6.6";
|
||||
|
||||
private readonly DNSController _aioDnsController = new();
|
||||
|
||||
private NetRoute _outbound;
|
||||
private Mode _mode = null!;
|
||||
private IPAddress? _serverRemoteAddress;
|
||||
private TUNConfig _tunConfig = null!;
|
||||
|
||||
private NetRoute _tun;
|
||||
private NetRoute _outbound;
|
||||
|
||||
private IPAddress? _serverRemoteAddress;
|
||||
public string Name => "tun2socks";
|
||||
|
||||
private Mode _mode = null!;
|
||||
|
||||
public void Start(in Mode mode)
|
||||
public void Start(Server server, Mode mode)
|
||||
{
|
||||
_mode = mode;
|
||||
var server = MainController.Server!;
|
||||
_tunConfig = Global.Settings.TUNTAP;
|
||||
_serverRemoteAddress = DnsUtils.Lookup(server.Hostname);
|
||||
|
||||
if (_serverRemoteAddress != null && IPAddress.IsLoopback(_serverRemoteAddress))
|
||||
@@ -56,9 +56,9 @@ namespace Netch.Controllers
|
||||
|
||||
if (server is Socks5 socks5)
|
||||
{
|
||||
Dial(NameList.TYPE_TCPHOST, $"{server.AutoResolveHostname()}:{server.Port}");
|
||||
Dial(NameList.TYPE_TCPHOST, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
|
||||
Dial(NameList.TYPE_UDPHOST, $"{server.AutoResolveHostname()}:{server.Port}");
|
||||
Dial(NameList.TYPE_UDPHOST, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
|
||||
if (socks5.Auth())
|
||||
{
|
||||
@@ -71,22 +71,19 @@ namespace Netch.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
Dial(NameList.TYPE_TCPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}");
|
||||
|
||||
Dial(NameList.TYPE_UDPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}");
|
||||
Trace.Assert(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DNS
|
||||
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
if (_tunConfig.UseCustomDNS)
|
||||
{
|
||||
Dial(NameList.TYPE_DNSADDR, Global.Settings.TUNTAP.HijackDNS);
|
||||
Dial(NameList.TYPE_DNSADDR, _tunConfig.HijackDNS);
|
||||
}
|
||||
else
|
||||
{
|
||||
MainController.PortCheck(Global.Settings.AioDNS.ListenPort, "DNS");
|
||||
_aioDnsController.Start();
|
||||
Dial(NameList.TYPE_DNSADDR, $"127.0.0.1:{Global.Settings.AioDNS.ListenPort}");
|
||||
}
|
||||
@@ -97,19 +94,55 @@ namespace Netch.Controllers
|
||||
throw new MessageException("tun2socks start failed.");
|
||||
|
||||
var tunIndex = (int)RouteHelper.ConvertLuidToIndex(tun_luid());
|
||||
_tun = NetRoute.TemplateBuilder(Global.Settings.TUNTAP.Gateway, tunIndex);
|
||||
_tun = NetRoute.TemplateBuilder(_tunConfig.Gateway, tunIndex);
|
||||
|
||||
RouteHelper.CreateUnicastIP(AddressFamily.InterNetwork,
|
||||
Global.Settings.TUNTAP.Address,
|
||||
(byte)Utils.Utils.SubnetToCidr(Global.Settings.TUNTAP.Netmask),
|
||||
_tunConfig.Address,
|
||||
(byte)Utils.Utils.SubnetToCidr(_tunConfig.Netmask),
|
||||
(ulong)tunIndex);
|
||||
|
||||
SetupRouteTable(mode);
|
||||
SetupRouteTable();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
var tasks = new[]
|
||||
{
|
||||
Task.Run(Free),
|
||||
Task.Run(ClearRouteTable),
|
||||
Task.Run(_aioDnsController.Stop)
|
||||
};
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
private void CheckDriver()
|
||||
{
|
||||
string binDriver = Path.Combine(Global.NetchDir, Constants.WintunDllFile);
|
||||
string sysDriver = $@"{Environment.SystemDirectory}\wintun.dll";
|
||||
|
||||
var binHash = Utils.Utils.SHA256CheckSum(binDriver);
|
||||
var sysHash = Utils.Utils.SHA256CheckSum(sysDriver);
|
||||
Log.Information("自带 wintun.dll Hash: {Hash}", binHash);
|
||||
Log.Information("系统 wintun.dll Hash: {Hash}", sysHash);
|
||||
if (binHash == sysHash)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Log.Information("Copy wintun.dll to System Directory");
|
||||
File.Copy(binDriver, sysDriver, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "复制 wintun.dll 异常");
|
||||
throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#region Route
|
||||
|
||||
private void SetupRouteTable(Mode mode)
|
||||
private void SetupRouteTable()
|
||||
{
|
||||
Global.MainForm.StatusText(i18N.Translate("Setup Route Table Rule"));
|
||||
Log.Information("设置路由规则");
|
||||
@@ -119,33 +152,33 @@ namespace Netch.Controllers
|
||||
RouteUtils.CreateRoute(_outbound.FillTemplate(_serverRemoteAddress.ToString(), 32));
|
||||
|
||||
// Global Bypass IPs
|
||||
RouteUtils.CreateRouteFill(_outbound, Global.Settings.TUNTAP.BypassIPs);
|
||||
RouteUtils.CreateRouteFill(_outbound, _tunConfig.BypassIPs);
|
||||
|
||||
var tunNetworkInterface = NetworkInterfaceUtils.Get(_tun.InterfaceIndex);
|
||||
switch (mode.Type)
|
||||
switch (_mode.Type)
|
||||
{
|
||||
case ModeType.ProxyRuleIPs:
|
||||
// rules
|
||||
RouteUtils.CreateRouteFill(_tun, mode.GetRules());
|
||||
RouteUtils.CreateRouteFill(_tun, _mode.GetRules());
|
||||
|
||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||
if (_tunConfig.ProxyDNS)
|
||||
{
|
||||
tunNetworkInterface.SetDns(DummyDns);
|
||||
// proxy dummy dns
|
||||
RouteUtils.CreateRoute(_tun.FillTemplate(DummyDns, 32));
|
||||
|
||||
if (!Global.Settings.TUNTAP.UseCustomDNS)
|
||||
if (!_tunConfig.UseCustomDNS)
|
||||
// proxy AioDNS other dns
|
||||
RouteUtils.CreateRoute(_tun.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.OtherDNS), 32));
|
||||
}
|
||||
|
||||
break;
|
||||
case ModeType.BypassRuleIPs:
|
||||
RouteUtils.CreateRouteFill(_outbound, mode.GetRules());
|
||||
RouteUtils.CreateRouteFill(_outbound, _mode.GetRules());
|
||||
|
||||
tunNetworkInterface.SetDns(DummyDns);
|
||||
|
||||
if (!Global.Settings.TUNTAP.UseCustomDNS)
|
||||
if (!_tunConfig.UseCustomDNS)
|
||||
// bypass AioDNS other dns
|
||||
RouteUtils.CreateRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
|
||||
|
||||
@@ -172,41 +205,5 @@ namespace Netch.Controllers
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
var tasks = new[]
|
||||
{
|
||||
Task.Run(Free),
|
||||
Task.Run(ClearRouteTable),
|
||||
Task.Run(_aioDnsController.Stop)
|
||||
};
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
private void CheckDriver()
|
||||
{
|
||||
string binDriver = Path.Combine(Global.NetchDir, @"bin\wintun.dll");
|
||||
string sysDriver = $@"{Environment.SystemDirectory}\wintun.dll";
|
||||
|
||||
var binHash = Utils.Utils.SHA256CheckSum(binDriver);
|
||||
var sysHash = Utils.Utils.SHA256CheckSum(sysDriver);
|
||||
Log.Information("自带 wintun.dll Hash: {Hash}", binHash);
|
||||
Log.Information("系统 wintun.dll Hash: {Hash}", sysHash);
|
||||
if (binHash == sysHash)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Log.Information("Copy wintun.dll to System Directory");
|
||||
File.Copy(binDriver, sysDriver, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "复制 wintun.dll 异常");
|
||||
throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -509,20 +509,21 @@ namespace Netch.Forms
|
||||
|
||||
// 自动检测延迟
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (State == State.Started)
|
||||
if (Global.Settings.StartedPingInterval >= 0)
|
||||
{
|
||||
server.Test();
|
||||
ServerComboBox.Refresh();
|
||||
{
|
||||
while (State == State.Started)
|
||||
if (Global.Settings.StartedPingInterval >= 0)
|
||||
{
|
||||
server.Test();
|
||||
ServerComboBox.Refresh();
|
||||
|
||||
Thread.Sleep(Global.Settings.StartedPingInterval * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(5000);
|
||||
}
|
||||
}).Forget();
|
||||
Thread.Sleep(Global.Settings.StartedPingInterval * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(5000);
|
||||
}
|
||||
})
|
||||
.Forget();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1144,7 +1145,6 @@ namespace Netch.Forms
|
||||
{
|
||||
NatTypeStatusText(i18N.Translate("Testing NAT"));
|
||||
|
||||
// Monitor.TryEnter() Monitor.Exit() (a.k.a. lock) not work with async/await
|
||||
var (result, _, publicEnd) = await MainController.NTTController.Start();
|
||||
|
||||
if (!string.IsNullOrEmpty(publicEnd))
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
using Netch.Models;
|
||||
using Netch.Properties;
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
@@ -8,6 +5,9 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Properties;
|
||||
using Netch.Utils;
|
||||
using Serilog;
|
||||
|
||||
namespace Netch.Forms
|
||||
@@ -60,7 +60,7 @@ namespace Netch.Forms
|
||||
object[]? stuns;
|
||||
try
|
||||
{
|
||||
stuns = File.ReadLines("bin\\stun.txt").Cast<object>().ToArray();
|
||||
stuns = File.ReadLines(Constants.STUNServersFile).Cast<object>().ToArray();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,6 @@ namespace Netch.Interfaces
|
||||
{
|
||||
public interface IModeController : IController
|
||||
{
|
||||
public void Start(in Mode mode);
|
||||
public void Start(Server server, Mode mode);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
|
||||
namespace Netch.Interfaces
|
||||
{
|
||||
@@ -8,13 +9,7 @@ namespace Netch.Interfaces
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="s">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public abstract void Start(in Server s, in Mode mode);
|
||||
public Socks5 Start(in Server s);
|
||||
}
|
||||
|
||||
public static class ServerControllerExtension
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public void Start(in Server s, in Mode mode)
|
||||
public Socks5.Socks5 Start(in Server s)
|
||||
{
|
||||
var server = (Shadowsocks)s;
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
};
|
||||
|
||||
StartGuard(command.ToString());
|
||||
return new Socks5.Socks5(this.LocalAddress(), this.Socks5LocalPort());
|
||||
}
|
||||
|
||||
[Verb]
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public void Start(in Server s, in Mode mode)
|
||||
public Socks5.Socks5 Start(in Server s)
|
||||
{
|
||||
var server = (ShadowsocksR)s;
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
};
|
||||
|
||||
StartGuard(command.ToString());
|
||||
return new Socks5.Socks5(this.LocalAddress(), this.Socks5LocalPort());
|
||||
}
|
||||
|
||||
[Verb]
|
||||
|
||||
@@ -7,11 +7,13 @@ namespace Netch.Servers.Socks5
|
||||
{
|
||||
public override string Name { get; } = "Socks5";
|
||||
|
||||
public override void Start(in Server s, in Mode mode)
|
||||
public override Socks5 Start(in Server s)
|
||||
{
|
||||
var server = (Socks5)s;
|
||||
if (server.Auth())
|
||||
base.Start(s, mode);
|
||||
base.Start(s);
|
||||
|
||||
return server;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,22 @@ namespace Netch.Servers.Socks5
|
||||
|
||||
public override string Type { get; } = "Socks5";
|
||||
|
||||
public Socks5()
|
||||
{
|
||||
}
|
||||
|
||||
public Socks5(string hostname, ushort port)
|
||||
{
|
||||
Hostname = hostname;
|
||||
Port = port;
|
||||
}
|
||||
|
||||
public Socks5(string hostname, ushort port, string username, string password) : this(hostname, port)
|
||||
{
|
||||
Username = username;
|
||||
Password = password;
|
||||
}
|
||||
|
||||
public bool Auth()
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password);
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Netch.Servers.Trojan
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public void Start(in Server s, in Mode mode)
|
||||
public Socks5.Socks5 Start(in Server s)
|
||||
{
|
||||
var server = (Trojan)s;
|
||||
var trojanConfig = new TrojanConfig
|
||||
@@ -48,6 +48,7 @@ namespace Netch.Servers.Trojan
|
||||
File.WriteAllBytes(Constants.TempConfig, JsonSerializer.SerializeToUtf8Bytes(trojanConfig, Global.NewDefaultJsonSerializerOptions));
|
||||
|
||||
StartGuard("-c ..\\data\\last.json");
|
||||
return new Socks5.Socks5(this.LocalAddress(), this.Socks5LocalPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using Netch.Enums;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.V2ray.Models;
|
||||
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
|
||||
@@ -10,15 +9,15 @@ namespace Netch.Servers.V2ray.Utils
|
||||
{
|
||||
public static class V2rayConfigUtils
|
||||
{
|
||||
public static string GenerateClientConfig(Server server, Mode mode)
|
||||
public static string GenerateClientConfig(Server server)
|
||||
{
|
||||
var v2rayConfig = new V2rayConfig();
|
||||
|
||||
inbound(server, ref v2rayConfig);
|
||||
|
||||
routing(server, mode, ref v2rayConfig);
|
||||
routing(server, ref v2rayConfig);
|
||||
|
||||
outbound(server, mode, ref v2rayConfig);
|
||||
outbound(server, ref v2rayConfig);
|
||||
|
||||
return JsonSerializer.Serialize(v2rayConfig, Global.NewDefaultJsonSerializerOptions);
|
||||
}
|
||||
@@ -46,7 +45,7 @@ namespace Netch.Servers.V2ray.Utils
|
||||
}
|
||||
}
|
||||
|
||||
private static void routing(Server server, Mode mode, ref V2rayConfig v2rayConfig)
|
||||
private static void routing(Server server, ref V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -66,14 +65,6 @@ namespace Netch.Servers.V2ray.Utils
|
||||
outboundTag = "block"
|
||||
};
|
||||
|
||||
if (mode.Type is ModeType.Process or ModeType.ProxyRuleIPs or ModeType.BypassRuleIPs)
|
||||
{
|
||||
blockRuleObject.ip.Add("0.0.0.0/8");
|
||||
blockRuleObject.ip.Add("224.0.0.0/4");
|
||||
blockRuleObject.ip.Add("255.255.255.255/32");
|
||||
blockRuleObject.ip.Add("fc00::/8");
|
||||
}
|
||||
|
||||
static bool CheckRuleItem(ref RulesItem rulesItem)
|
||||
{
|
||||
bool ipResult, domainResult;
|
||||
@@ -98,7 +89,7 @@ namespace Netch.Servers.V2ray.Utils
|
||||
}
|
||||
}
|
||||
|
||||
private static void outbound(Server server, Mode mode, ref V2rayConfig v2rayConfig)
|
||||
private static void outbound(Server server, ref V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -25,10 +25,11 @@ namespace Netch.Servers.V2ray
|
||||
|
||||
public string? LocalAddress { get; set; }
|
||||
|
||||
public virtual void Start(in Server s, in Mode mode)
|
||||
public virtual Socks5.Socks5 Start(in Server s)
|
||||
{
|
||||
File.WriteAllText(Constants.TempConfig, V2rayConfigUtils.GenerateClientConfig(s, mode));
|
||||
File.WriteAllText(Constants.TempConfig, V2rayConfigUtils.GenerateClientConfig(s));
|
||||
StartGuard("-config ..\\data\\last.json");
|
||||
return new Socks5.Socks5(this.LocalAddress(), this.Socks5LocalPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user