diff --git a/Netch/Controllers/TUNController.cs b/Netch/Controllers/TUNController.cs index e5ac7166..375778a7 100644 --- a/Netch/Controllers/TUNController.cs +++ b/Netch/Controllers/TUNController.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; -using System.Net.Sockets; +using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -11,12 +11,13 @@ using Netch.Models; using Netch.Servers.Socks5; using Netch.Utils; using Vanara.PInvoke; +using static Netch.Controllers.TUNInterop; using static Vanara.PInvoke.IpHlpApi; using static Vanara.PInvoke.Ws2_32; namespace Netch.Controllers { - public class TUNController : Guard, IModeController + public class TUNController : IModeController { private readonly List _directIPs = new(); @@ -29,56 +30,95 @@ namespace Netch.Controllers /// /// 本地 DNS 服务控制器 /// - public DNSController DNSController = new(); + public readonly DNSController DNSController = new(); - protected override IEnumerable StartedKeywords { get; set; } = new[] {"Started"}; - - protected override IEnumerable StoppedKeywords { get; set; } = new List(); - - public override string MainFile { get; protected set; } = "tun2socks.exe"; - - protected override Encoding InstanceOutputEncoding { get; } = Encoding.UTF8; - - public override string Name { get; } = "tun2socks"; + public string Name { get; } = "tun2socks"; private readonly OutboundAdapter _outboundAdapter = new(); private IAdapter _tunAdapter = null!; + private readonly TUNInterop _tunInterop = new(); public void Start(in Mode mode) { var server = MainController.Server!; _serverAddresses = DnsUtils.Lookup(server.Hostname)!; // server address have been cached when MainController.Start - var parameter = new WinTun2socksParameter(); + _tunInterop.Dial(NameList.TYPE_ADAPMTU, "1500"); + _tunInterop.Dial(NameList.TYPE_BYPBIND, "10.0.0.100"); + _tunInterop.Dial(NameList.TYPE_BYPLIST, "disabled"); + + + #region Server + + _tunInterop.Dial(NameList.TYPE_TCPREST, ""); + _tunInterop.Dial(NameList.TYPE_TCPTYPE, "Socks5"); + + _tunInterop.Dial(NameList.TYPE_UDPREST, ""); + _tunInterop.Dial(NameList.TYPE_UDPTYPE, "Socks5"); if (server is Socks5 socks5) { - parameter.hostname = $"{server.AutoResolveHostname()}:{server.Port}"; + _tunInterop.Dial(NameList.TYPE_TCPHOST, $"{server.AutoResolveHostname()}:{server.Port}"); + + _tunInterop.Dial(NameList.TYPE_UDPHOST, $"{server.AutoResolveHostname()}:{server.Port}"); + if (socks5.Auth()) { - parameter.username = socks5.Username!; - parameter.password = socks5.Password!; + _tunInterop.Dial(NameList.TYPE_TCPUSER, socks5.Username!); + _tunInterop.Dial(NameList.TYPE_TCPPASS, socks5.Password!); + + _tunInterop.Dial(NameList.TYPE_UDPUSER, socks5.Username!); + _tunInterop.Dial(NameList.TYPE_UDPPASS, socks5.Password!); } } else - parameter.hostname = $"127.0.0.1:{Global.Settings.Socks5LocalPort}"; + { + _tunInterop.Dial(NameList.TYPE_TCPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}"); + + _tunInterop.Dial(NameList.TYPE_UDPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}"); + } + + #endregion + + #region DNS + + List dns; + if (Global.Settings.WinTUN.UseCustomDNS) + { + dns = Global.Settings.WinTUN.DNS.Any() ? Global.Settings.WinTUN.DNS : Global.Settings.WinTUN.DNS = new List {"1.1.1.1"}; + } + else + { + MainController.PortCheck(53, "DNS"); + DNSController.Start(); + dns = new List {"127.0.0.1"}; + } + + _tunInterop.Dial(NameList.TYPE_DNSADDR, DnsUtils.Join(dns)); + + #endregion + + Console.WriteLine("tun2socks init"); + _tunInterop.Init(); - MainFile = "tun2socks.exe"; - StartInstanceAuto(parameter.ToString()); _tunAdapter = new TunAdapter(); - NativeMethods.CreateUnicastIP((int)AddressFamily.InterNetwork, Global.Settings.WinTUN.Address, 24, _tunAdapter.InterfaceIndex); + NativeMethods.CreateUnicastIP((int) AddressFamily.InterNetwork, Global.Settings.WinTUN.Address, 24, _tunAdapter.InterfaceIndex); SetupRouteTable(mode); } /// /// TUN/TAP停止 /// - public override void Stop() + public void Stop() { var tasks = new[] { - Task.Run(StopInstance), + Task.Run(() => + { + _tunInterop.Free(); + // _tunInterop.Unload(); + }), Task.Run(ClearRouteTable), Task.Run(DNSController.Stop) }; @@ -168,20 +208,6 @@ namespace Netch.Controllers return true; } - public bool TestFakeDNS() - { - try - { - InitInstance("-h"); - Instance!.Start(); - return Instance.StandardError.ReadToEnd().Contains("-fakeDns"); - } - catch - { - return false; - } - } - #region Package private void RouteAction(Action action, in IEnumerable ipNetworks, RouteType routeType, int metric = 0) @@ -225,22 +251,19 @@ namespace Netch.Controllers switch (action) { case Action.Create: - - result = NativeMethods.CreateRoute((int)AddressFamily.InterNetwork, network, cidr, gateway, index, metric); -#if DEBUG - Console.WriteLine($"CreateRoute(\"{network}\", {cidr}, \"{gateway}\", {index}, {metric})"); -#endif + result = NativeMethods.CreateRoute((int) AddressFamily.InterNetwork, network, cidr, gateway, index, metric); ipList.Add(ipNetwork); break; case Action.Delete: - result = NativeMethods.DeleteRoute((int)AddressFamily.InterNetwork, network, cidr, gateway, index, metric); + result = NativeMethods.DeleteRoute((int) AddressFamily.InterNetwork, network, cidr, gateway, index, metric); break; default: throw new ArgumentOutOfRangeException(nameof(action), action, null); } + Logging.Debug($"{action}Route(\"{network}\", {cidr}, \"{gateway}\", {index}, {metric})"); if (!result) - Logging.Warning($"Failed to {action} Route on {routeType} Adapter: {ipNetwork} metric {metric}"); + Logging.Warning($"Failed to invoke {action}Route(\"{network}\", {cidr}, \"{gateway}\", {index}, {metric})"); return result; } @@ -257,45 +280,6 @@ namespace Netch.Controllers Delete } - [Verb] - public class Tap2SocksParameter : ParameterBase - { - public string? proxyServer { get; set; } - - public string? tunAddr { get; set; } - - public string? tunMask { get; set; } - - public string? tunGw { get; set; } - - public string? tunDns { get; set; } - - public string? tunName { get; set; } - - public bool fakeDns { get; set; } - } - - [Verb] - class WinTun2socksParameter : ParameterBase - { - public string? bind { get; set; } = "10.0.0.100"; - - [Quote] - public string? list { get; set; } = "disabled"; - - public string? hostname { get; set; } - - [Optional] - public string? username { get; set; } - - [Optional] - public string? password { get; set; } - - public string? dns { get; set; } = "1.1.1.1:53"; - - public int? mtu { get; set; } = 1500; - } - #endregion } } \ No newline at end of file diff --git a/Netch/Controllers/TUNInterop.cs b/Netch/Controllers/TUNInterop.cs new file mode 100644 index 00000000..35e575bc --- /dev/null +++ b/Netch/Controllers/TUNInterop.cs @@ -0,0 +1,74 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; +using Netch.Utils; + +namespace Netch.Controllers +{ + public class TUNInterop + { + public enum NameList + { + TYPE_BYPBIND, + TYPE_BYPLIST, + TYPE_DNSADDR, + TYPE_ADAPMTU, + TYPE_TCPREST, + TYPE_TCPTYPE, + TYPE_TCPHOST, + TYPE_TCPUSER, + TYPE_TCPPASS, + TYPE_TCPMETH, + TYPE_TCPPROT, + TYPE_TCPPRPA, + TYPE_TCPOBFS, + TYPE_TCPOBPA, + TYPE_UDPREST, + TYPE_UDPTYPE, + TYPE_UDPHOST, + TYPE_UDPUSER, + TYPE_UDPPASS, + TYPE_UDPMETH, + TYPE_UDPPROT, + TYPE_UDPPRPA, + TYPE_UDPOBFS, + TYPE_UDPOBPA + } + + public bool Dial(NameList name, string value) + { + Logging.Debug($"Dial {name} {value}"); + return tun_dial(name, Encoding.UTF8.GetBytes(value)); + } + + public bool Init() + { + return tun_init(); + } + + public bool Free() + { + return tun_free(); + } + + private const string tun2socks_bin = "tun2socks.bin"; + + [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] + public static extern bool tun_dial(NameList name, byte[] value); + + [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] + public static extern bool tun_init(); + + [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] + public static extern bool tun_free(); + + [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] + public static extern ulong tun_luid(); + + [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] + public static extern ulong tun_getUP(); + + [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] + public static extern ulong tun_getDL(); + } +} \ No newline at end of file diff --git a/Netch/Forms/SettingForm.Designer.cs b/Netch/Forms/SettingForm.Designer.cs index 6bc14419..d829f56c 100644 --- a/Netch/Forms/SettingForm.Designer.cs +++ b/Netch/Forms/SettingForm.Designer.cs @@ -549,7 +549,6 @@ namespace Netch.Forms this.TUNTAPGroupBox.TabIndex = 0; this.TUNTAPGroupBox.TabStop = false; this.TUNTAPGroupBox.Text = "TUN/TAP"; - this.TUNTAPGroupBox.Visible = false; // // TUNTAPAddressLabel // @@ -584,6 +583,7 @@ namespace Netch.Forms this.TUNTAPNetmaskTextBox.Size = new System.Drawing.Size(294, 21); this.TUNTAPNetmaskTextBox.TabIndex = 3; this.TUNTAPNetmaskTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.TUNTAPNetmaskTextBox.Visible = false; // // TUNTAPGatewayLabel // diff --git a/Netch/Models/TunAdapter.cs b/Netch/Models/TunAdapter.cs index 17c50bf5..6d462726 100644 --- a/Netch/Models/TunAdapter.cs +++ b/Netch/Models/TunAdapter.cs @@ -13,17 +13,18 @@ namespace Netch.Models public TunAdapter() { AdapterId = AdapterUtils.GetAdapterId(ComponentIdWintun) ?? throw new Exception("wintun adapter not found"); - NetworkInterface = NetworkInterface.GetAllNetworkInterfaces().First(i => i.Id == AdapterId); InterfaceIndex = NetworkInterface.GetIPProperties().GetIPv4Properties().Index; - Logging.Info($"TAP 适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}"); + Gateway = IPAddress.Parse(Global.Settings.WinTUN.Gateway); + + Logging.Info($"WinTUN 适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}"); } public string AdapterId { get; set; } public int InterfaceIndex { get; } - public IPAddress Gateway { get; } = IPAddress.Parse("100.64.0.1"); + public IPAddress Gateway { get; } public NetworkInterface NetworkInterface { get; } } diff --git a/binaries b/binaries index 0535f7b3..85be39db 160000 --- a/binaries +++ b/binaries @@ -1 +1 @@ -Subproject commit 0535f7b31098048ac1f7343ae8fd465eb619d07d +Subproject commit 85be39db26891c6c5a47eab3f2aeeb9c0dce654c