diff --git a/linker.libs/NetworkHelper.cs b/linker.libs/NetworkHelper.cs index 518e0d1d..9c2e319d 100644 --- a/linker.libs/NetworkHelper.cs +++ b/linker.libs/NetworkHelper.cs @@ -8,6 +8,7 @@ using System.Net.NetworkInformation; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; +using System.Threading.Tasks; namespace linker.libs { @@ -184,6 +185,18 @@ namespace linker.libs { return new IPAddress(BinaryPrimitives.ReverseEndianness(ip & maskvalue).ToBytes()); } + public static IPAddress ToGatewayIP(IPAddress ip, byte maskLength) + { + uint network = BinaryPrimitives.ReadUInt32BigEndian(ToNetworkIp(ip, NetworkHelper.MaskValue(maskLength)).GetAddressBytes()); + IPAddress gateway = new IPAddress(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(network + 1))); + return gateway; + } + public static IPAddress ToGatewayIP(uint ip, uint maskValue) + { + uint network = BinaryPrimitives.ReadUInt32BigEndian(ToNetworkIp(ip, maskValue).GetAddressBytes()); + IPAddress gateway = new IPAddress(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(network + 1))); + return gateway; + } public static bool NotIPv6Support(IPAddress ip) { diff --git a/linker.libs/extends/IPEndPointExtends.cs b/linker.libs/extends/IPEndPointExtends.cs index 12b4cdb7..5f326960 100644 --- a/linker.libs/extends/IPEndPointExtends.cs +++ b/linker.libs/extends/IPEndPointExtends.cs @@ -55,7 +55,7 @@ namespace linker.libs.extends public static bool GetIsBroadcastAddress(this ReadOnlySpan address) { uint ip = BinaryPrimitives.ReadUInt32BigEndian(address); - return (ip >= 0xE0000000 && ip <= 0xEFFFFFFF) || ip == 0xFFFFFFFF; + return address[3] == 255 || (ip >= 0xE0000000 && ip <= 0xEFFFFFFF) || ip == 0xFFFFFFFF; } diff --git a/linker.tun.test/Program.cs b/linker.tun.test/Program.cs index 6ce72420..1cb4ec49 100644 --- a/linker.tun.test/Program.cs +++ b/linker.tun.test/Program.cs @@ -1,5 +1,4 @@ -using System; -using System.Buffers.Binary; +using System.Buffers.Binary; using System.Net; using System.Runtime.InteropServices; @@ -10,25 +9,28 @@ namespace linker.tun.test public static LinkerTunDeviceAdapter linkerTunDeviceAdapter; static void Main(string[] args) { - - linkerTunDeviceAdapter = new LinkerTunDeviceAdapter(new LinkerTunDeviceCallback()); + linkerTunDeviceAdapter = new LinkerTunDeviceAdapter(); + linkerTunDeviceAdapter.SetCallback(new LinkerTunDeviceCallback()); linkerTunDeviceAdapter.SetUp("linker111" , Guid.Parse("dc6d4efa-2b53-41bd-a403-f416c9bf7129") - , IPAddress.Parse("192.168.55.2") - , IPAddress.Parse("192.168.55.1"), 24); + , IPAddress.Parse("192.168.55.2"), 24); if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.Error)) { Console.WriteLine(linkerTunDeviceAdapter.Error); } - Console.ReadLine(); } } - public unsafe sealed class LinkerTunDeviceCallback : ILinkerTunDeviceCallback + public sealed class LinkerTunDeviceCallback : ILinkerTunDeviceCallback { - public void Callback(LinkerTunDevicPacket packet) + public async Task Callback(LinkerTunDevicPacket packet) + { + ICMPAnswer(packet); + await Task.CompletedTask; + } + private unsafe void ICMPAnswer(LinkerTunDevicPacket packet) { Memory writableMemory = MemoryMarshal.AsMemory(packet.Packet); fixed (byte* ptr = writableMemory.Span) @@ -36,12 +38,12 @@ namespace linker.tun.test //icmp && request if (ptr[9] == 1 && ptr[20] == 8) { - Console.WriteLine($"ICMP to {new IPAddress(writableMemory.Span.Slice(16,4))}"); + Console.WriteLine($"ICMP to {new IPAddress(writableMemory.Span.Slice(16, 4))}"); uint dist = BinaryPrimitives.ReadUInt32LittleEndian(writableMemory.Span.Slice(16, 4)); //目的地址变源地址, - * (uint*)(ptr + 16) = *(uint*)(ptr + 12); + *(uint*)(ptr + 16) = *(uint*)(ptr + 12); //假装是网关回复的 *(uint*)(ptr + 12) = dist; diff --git a/linker.tun/ILinkerTunDevice.cs b/linker.tun/ILinkerTunDevice.cs index 316e5f12..88b7fb47 100644 --- a/linker.tun/ILinkerTunDevice.cs +++ b/linker.tun/ILinkerTunDevice.cs @@ -20,7 +20,7 @@ namespace linker.tun public interface ILinkerTunDeviceCallback { - public void Callback(LinkerTunDevicPacket packet); + public Task Callback(LinkerTunDevicPacket packet); } public struct LinkerTunDevicPacket @@ -33,8 +33,8 @@ namespace linker.tun public sealed class LinkerTunDeviceRouteItem { - public IPAddress Address { get; } - public byte Mask { get; } + public IPAddress Address { get; set; } + public byte Mask { get; set; } } public enum LinkerTunDeviceStatus diff --git a/linker.tun/LinkerTunDeviceAdapter.cs b/linker.tun/LinkerTunDeviceAdapter.cs index 1c45c5ea..76100821 100644 --- a/linker.tun/LinkerTunDeviceAdapter.cs +++ b/linker.tun/LinkerTunDeviceAdapter.cs @@ -1,8 +1,9 @@ -using System.Net; +using linker.libs; +using System.Net; namespace linker.tun { - public unsafe sealed class LinkerTunDeviceAdapter + public sealed class LinkerTunDeviceAdapter { private ILinkerTunDevice linkerTunDevice; private ILinkerTunDeviceCallback linkerTunDeviceCallback; @@ -13,31 +14,45 @@ namespace linker.tun private bool starting = false; - public LinkerTunDeviceStatus Status => linkerTunDevice.Running ? LinkerTunDeviceStatus.Running : (starting ? LinkerTunDeviceStatus.Starting : LinkerTunDeviceStatus.Normal); + public LinkerTunDeviceStatus Status + { + get + { + if (linkerTunDevice == null) return LinkerTunDeviceStatus.Normal; + + return linkerTunDevice.Running + ? LinkerTunDeviceStatus.Running + : starting + ? LinkerTunDeviceStatus.Starting + : LinkerTunDeviceStatus.Normal; + } + } /// /// 构造 /// /// 数据包回调 - public LinkerTunDeviceAdapter(ILinkerTunDeviceCallback linkerTunDeviceCallback) + public LinkerTunDeviceAdapter() + { + } + + public void SetCallback(ILinkerTunDeviceCallback linkerTunDeviceCallback) { this.linkerTunDeviceCallback = linkerTunDeviceCallback; } + /// /// 开启网卡 /// /// 网卡名,如果是osx,需要utunX的命名,X是一个数字 /// windows的时候,需要一个固定guid,不然网卡编号一直递增,注册表一直新增记录 /// 网卡IP - /// 网卡网关 /// 掩码。一般24即可 - public void SetUp(string name, Guid guid, IPAddress address, IPAddress gateway, byte mask) + public void SetUp(string name, Guid guid, IPAddress address, byte mask) { if (starting) return; - Shutdown(); - starting = true; try { @@ -55,7 +70,8 @@ namespace linker.tun if (linkerTunDevice != null) { linkerTunDevice.Shutdown(); - linkerTunDevice.SetUp(address, gateway, mask, out error); + + linkerTunDevice.SetUp(address, NetworkHelper.ToGatewayIP(address, mask), mask, out error); if (string.IsNullOrWhiteSpace(error)) { cancellationTokenSource = new CancellationTokenSource(); @@ -63,28 +79,35 @@ namespace linker.tun { while (cancellationTokenSource.IsCancellationRequested == false) { - ReadOnlyMemory buffer = linkerTunDevice.Read(); - if (buffer.Length == 0) + try + { + ReadOnlyMemory buffer = linkerTunDevice.Read(); + if (buffer.Length == 0) + { + break; + } + + LinkerTunDevicPacket packet = new LinkerTunDevicPacket(); + packet.Packet = buffer; + packet.Version = (byte)(buffer.Span[0] >> 4 & 0b1111); + + if (packet.Version == 4) + { + packet.SourceIPAddress = buffer.Slice(12, 4); + packet.DistIPAddress = buffer.Slice(16, 4); + } + else if (packet.Version == 6) + { + packet.SourceIPAddress = buffer.Slice(8, 16); + packet.DistIPAddress = buffer.Slice(24, 16); + } + + await linkerTunDeviceCallback.Callback(packet); + } + catch (Exception) { break; } - - LinkerTunDevicPacket packet = new LinkerTunDevicPacket(); - packet.Packet = buffer; - packet.Version = (byte)(buffer.Span[0] >> 4 & 0b1111); - - if (packet.Version == 4) - { - packet.SourceIPAddress = buffer.Slice(12, 4); - packet.DistIPAddress = buffer.Slice(16, 4); - } - else if (packet.Version == 6) - { - packet.SourceIPAddress = buffer.Slice(8, 16); - packet.DistIPAddress = buffer.Slice(24, 16); - } - - linkerTunDeviceCallback.Callback(packet); } }); } @@ -157,7 +180,7 @@ namespace linker.tun /// 包头开始位置 /// 包头长度 /// - public ushort Checksum(ushort* addr, uint count) + public unsafe ushort Checksum(ushort* addr, uint count) { ulong sum = 0; while (count > 1) @@ -167,7 +190,7 @@ namespace linker.tun } if (count > 0) { - sum += (ulong)((*addr) & Ntohs(0xFF00)); + sum += (ulong)((*addr) & ((((0xff00) & 0xff) << 8) | (((0xff00) & 0xff00) >> 8))); } while ((sum >> 16) != 0) { @@ -176,9 +199,5 @@ namespace linker.tun sum = ~sum; return ((ushort)sum); } - private ushort Ntohs(ushort value) - { - return ((ushort)((((value) & 0xff) << 8) | (((value) & 0xff00) >> 8))); - } } } diff --git a/linker.tun/LinkerWinTunDevice.cs b/linker.tun/LinkerWinTunDevice.cs index a874f623..8874bb17 100644 --- a/linker.tun/LinkerWinTunDevice.cs +++ b/linker.tun/LinkerWinTunDevice.cs @@ -3,6 +3,7 @@ using System.Buffers.Binary; using System.Net; using System.Net.NetworkInformation; using System.Runtime.InteropServices; +using static linker.libs.winapis.SECUR32; namespace linker.tun { @@ -12,10 +13,12 @@ namespace linker.tun public string Name => name; public bool Running => session != 0; - private IntPtr waitHandle = IntPtr.Zero, adapter = IntPtr.Zero, session = IntPtr.Zero; + private IntPtr waitHandle = IntPtr.Zero, adapter = IntPtr.Zero, session = IntPtr.Zero, session1 = IntPtr.Zero; private Guid guid; private int interfaceNumber = 0; + private CancellationTokenSource tokenSource; + public LinkerWinTunDevice(string name, Guid guid) { this.name = name; @@ -24,6 +27,7 @@ namespace linker.tun public bool SetUp(IPAddress address, IPAddress gateway, byte prefixLength, out string error) { + error = string.Empty; if (adapter != 0) { @@ -47,6 +51,11 @@ namespace linker.tun waitHandle = WintunGetReadWaitEvent(session); + WintunSetLogger((WINTUN_LOGGER_LEVEL level, ulong timestamp,string message) => + { + Console.WriteLine($"[{level}]->{timestamp}->{message}"); + }); + WintunGetAdapterLUID(adapter, out ulong luid); { MIB_UNICASTIPADDRESS_ROW AddressRow = default; @@ -59,6 +68,7 @@ namespace linker.tun uint LastError = CreateUnicastIpAddressEntry(ref AddressRow); if (LastError != 0) throw new InvalidOperationException(); } + /* { MIB_IPFORWARD_ROW2 row = default; InitializeIpForwardEntry(ref row); @@ -71,13 +81,20 @@ namespace linker.tun uint LastError = CreateIpForwardEntry2(ref row); if (LastError != 0) throw new InvalidOperationException(); } - + */ GetWindowsInterfaceNum(); + tokenSource = new CancellationTokenSource(); return true; } public void Shutdown() { + tokenSource?.Cancel(); + if (waitHandle != 0) + { + SetEvent(waitHandle); + waitHandle = 0; + } if (session != 0) { WintunEndSession(session); @@ -126,8 +143,7 @@ namespace linker.tun private byte[] buffer = new byte[2 * 1024]; public unsafe ReadOnlyMemory Read() { - if (session == 0) return Helper.EmptyArray; - for (; ; ) + for (; tokenSource.IsCancellationRequested == false;) { IntPtr packet = WintunReceivePacket(session, out var packetSize); if (packet != 0) @@ -144,6 +160,7 @@ namespace linker.tun } } } + return Helper.EmptyArray; } public unsafe bool Write(ReadOnlyMemory buffer) { @@ -220,6 +237,8 @@ namespace linker.tun private static extern uint CreateIpForwardEntry2(ref MIB_IPFORWARD_ROW2 Row); [DllImport("kernel32.dll")] private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); + [DllImport("kernel32.dll")] + public static extern bool SetEvent(IntPtr hEvent); [DllImport("wintun.dll", SetLastError = true)] private static extern IntPtr WintunCreateAdapter( diff --git a/linker.tunnel/connection/ITunnelConnection.cs b/linker.tunnel/connection/ITunnelConnection.cs index 6cdaf117..b1ef4955 100644 --- a/linker.tunnel/connection/ITunnelConnection.cs +++ b/linker.tunnel/connection/ITunnelConnection.cs @@ -102,7 +102,7 @@ namespace linker.tunnel.connection /// /// 缓冲区大小 /// - public byte BufferSize { get; } + public byte BufferSize { get; } /// /// 已连接 diff --git a/linker.tunnel/connection/TunnelConnectionMsQuic.cs b/linker.tunnel/connection/TunnelConnectionMsQuic.cs index 5e917c8f..a0892395 100644 --- a/linker.tunnel/connection/TunnelConnectionMsQuic.cs +++ b/linker.tunnel/connection/TunnelConnectionMsQuic.cs @@ -250,6 +250,7 @@ namespace linker.tunnel.connection return false; } + public void Dispose() { ticks = 0; diff --git a/linker.tunnel/connection/TunnelConnectionTcp.cs b/linker.tunnel/connection/TunnelConnectionTcp.cs index b3475cd9..c6f2f820 100644 --- a/linker.tunnel/connection/TunnelConnectionTcp.cs +++ b/linker.tunnel/connection/TunnelConnectionTcp.cs @@ -68,7 +68,7 @@ namespace linker.tunnel.connection cancellationTokenSource = new CancellationTokenSource(); _ = ProcessWrite(); - _ = ProcessHeart(); + //_ = ProcessHeart(); } private async Task ProcessWrite() diff --git a/linker.tunnel/proxy/TunnelProxyUdp.cs b/linker.tunnel/proxy/TunnelProxyUdp.cs index 0cc92e52..65edadd6 100644 --- a/linker.tunnel/proxy/TunnelProxyUdp.cs +++ b/linker.tunnel/proxy/TunnelProxyUdp.cs @@ -187,10 +187,7 @@ namespace linker.tunnel.proxy try { asyncUserUdpToken.Connection = tunnelToken.Connection; - if (await ConnectionReceiveUdp(tunnelToken, asyncUserUdpToken).ConfigureAwait(false) == false) - { - await asyncUserUdpToken.SourceSocket.SendToAsync(tunnelToken.Proxy.Data, tunnelToken.Proxy.SourceEP).ConfigureAwait(false); - } + await asyncUserUdpToken.SourceSocket.SendToAsync(tunnelToken.Proxy.Data, tunnelToken.Proxy.SourceEP).ConfigureAwait(false); } catch (Exception ex) { diff --git a/linker.tunnel/transport/TransportTcpPortMap.cs b/linker.tunnel/transport/TransportTcpPortMap.cs index 9b488173..1e07a7c7 100644 --- a/linker.tunnel/transport/TransportTcpPortMap.cs +++ b/linker.tunnel/transport/TransportTcpPortMap.cs @@ -91,7 +91,6 @@ namespace linker.tunnel.transport if (length > 0) { string key = bytes.AsMemory(0, length).GetString(); - LoggerHelper.Instance.Debug(key); if (distDic.TryRemove(key, out TaskCompletionSource tcs)) { await client.SendAsync(bytes.AsMemory(0, length)); diff --git a/linker/linker.csproj b/linker/linker.csproj index 20b61a51..62e8e93b 100644 --- a/linker/linker.csproj +++ b/linker/linker.csproj @@ -49,9 +49,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -62,6 +59,7 @@ + diff --git a/linker/plugins/tuntap/TuntapApiController.cs b/linker/plugins/tuntap/TuntapApiController.cs index dce98f24..8af97b18 100644 --- a/linker/plugins/tuntap/TuntapApiController.cs +++ b/linker/plugins/tuntap/TuntapApiController.cs @@ -1,5 +1,4 @@ using linker.libs.api; -using linker.plugins.tuntap.vea; using linker.plugins.tuntap.messenger; using MemoryPack; using linker.libs.extends; @@ -8,9 +7,9 @@ using linker.config; using linker.tunnel.connection; using linker.plugins.tuntap.proxy; using linker.plugins.client; -using linker.plugins.server; using linker.plugins.capi; using linker.plugins.messenger; +using linker.plugins.tuntap.config; namespace linker.plugins.tuntap { diff --git a/linker/plugins/tuntap/TuntapStartup.cs b/linker/plugins/tuntap/TuntapStartup.cs index ff16ede2..e643699f 100644 --- a/linker/plugins/tuntap/TuntapStartup.cs +++ b/linker/plugins/tuntap/TuntapStartup.cs @@ -1,8 +1,8 @@ using linker.config; using linker.plugins.tuntap.messenger; using linker.plugins.tuntap.proxy; -using linker.plugins.tuntap.vea; using linker.startup; +using linker.tun; using Microsoft.Extensions.DependencyInjection; using System.Reflection; @@ -23,12 +23,8 @@ namespace linker.plugins.tuntap public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies) { - //不同平台下的虚拟网卡 - if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton(); - if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton(); - if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/linker/plugins/tuntap/TuntapTransfer.cs b/linker/plugins/tuntap/TuntapTransfer.cs index bb370ca9..5dd005be 100644 --- a/linker/plugins/tuntap/TuntapTransfer.cs +++ b/linker/plugins/tuntap/TuntapTransfer.cs @@ -2,18 +2,16 @@ using linker.config; using linker.plugins.tuntap.messenger; using linker.plugins.tuntap.proxy; -using linker.plugins.tuntap.vea; using linker.libs; using MemoryPack; using System.Buffers.Binary; using System.Collections.Concurrent; using System.Net; using System.Net.NetworkInformation; -using System.Net.Sockets; -using linker.libs.extends; using linker.plugins.client; using linker.plugins.messenger; -using System; +using linker.plugins.tuntap.config; +using linker.tun; namespace linker.plugins.tuntap { @@ -21,31 +19,31 @@ namespace linker.plugins.tuntap { private readonly MessengerSender messengerSender; private readonly ClientSignInState clientSignInState; - private readonly ITuntapVea tuntapVea; private readonly FileConfig config; private readonly TuntapProxy tuntapProxy; private readonly RunningConfig runningConfig; + private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter; + + private string interfaceName = "linker"; private uint infosVersion = 0; - private readonly ConcurrentDictionary tuntapInfos = new ConcurrentDictionary(); - public ConcurrentDictionary Infos => tuntapInfos; public uint InfosVersion => infosVersion; + private readonly ConcurrentDictionary tuntapInfos = new ConcurrentDictionary(); + public ConcurrentDictionary Infos => tuntapInfos; - private bool starting = false; - public TuntapStatus Status => tuntapVea.Running ? TuntapStatus.Running : (starting ? TuntapStatus.Starting : TuntapStatus.Normal); + public TuntapStatus Status => (TuntapStatus)(byte)linkerTunDeviceAdapter.Status; - public TuntapTransfer(MessengerSender messengerSender, ClientSignInState clientSignInState, ITuntapVea tuntapVea, FileConfig config, TuntapProxy tuntapProxy, RunningConfig runningConfig) + public TuntapTransfer(MessengerSender messengerSender, ClientSignInState clientSignInState, LinkerTunDeviceAdapter linkerTunDeviceAdapter, FileConfig config, TuntapProxy tuntapProxy, RunningConfig runningConfig) { this.messengerSender = messengerSender; this.clientSignInState = clientSignInState; - this.tuntapVea = tuntapVea; + this.linkerTunDeviceAdapter = linkerTunDeviceAdapter; this.config = config; this.tuntapProxy = tuntapProxy; this.runningConfig = runningConfig; GetRouteIps(); - tuntapVea.Kill(); clientSignInState.NetworkEnabledHandle += (times) => { OnChange(); @@ -60,14 +58,16 @@ namespace linker.plugins.tuntap } }; - AppDomain.CurrentDomain.ProcessExit += (s, e) => OnExit(); - Console.CancelKeyPress += (s, e) => OnExit(); + linkerTunDeviceAdapter.SetCallback(tuntapProxy); + linkerTunDeviceAdapter.Shutdown(); + AppDomain.CurrentDomain.ProcessExit += (s, e) => Shutdown(); + Console.CancelKeyPress += (s, e) => Shutdown(); } /// /// 程序关闭 /// - private void OnExit() + private void Shutdown() { bool running = runningConfig.Data.Tuntap.Running; Stop(); @@ -80,12 +80,7 @@ namespace linker.plugins.tuntap /// public void Run() { - if (BooleanHelper.CompareExchange(ref starting, true, false)) - { - return; - } - - Task.Run(async () => + Task.Run(() => { OnChange(); try @@ -95,18 +90,13 @@ namespace linker.plugins.tuntap return; } - tuntapProxy.Start(); - while (tuntapProxy.LocalEndpoint == null) - { - await Task.Delay(1000).ConfigureAwait(false); - } - - bool result = await tuntapVea.Run(tuntapProxy.LocalEndpoint.Port, runningConfig.Data.Tuntap.IP).ConfigureAwait(false); + linkerTunDeviceAdapter.SetUp(interfaceName, runningConfig.Data.Tuntap.InterfaceGuid, runningConfig.Data.Tuntap.IP, 24); runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running; runningConfig.Data.Update(); - if (result == false) + + if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.Error) == false) { - Stop(); + LoggerHelper.Instance.Error(linkerTunDeviceAdapter.Error); } } catch (Exception ex) @@ -115,7 +105,6 @@ namespace linker.plugins.tuntap } finally { - BooleanHelper.CompareExchange(ref starting, false, true); OnChange(); } }); @@ -125,15 +114,10 @@ namespace linker.plugins.tuntap /// public void Stop() { - if (BooleanHelper.CompareExchange(ref starting, true, false)) - { - return; - } try { - tuntapProxy.Stop(); OnChange(); - tuntapVea.Kill(); + linkerTunDeviceAdapter.Shutdown(); runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running; runningConfig.Data.Update(); } @@ -146,7 +130,6 @@ namespace linker.plugins.tuntap } finally { - BooleanHelper.CompareExchange(ref starting, false, true); OnChange(); } } @@ -237,7 +220,7 @@ namespace linker.plugins.tuntap Masks = runningConfig.Data.Tuntap.Masks, MachineId = config.Data.Client.Id, Status = Status, - Error = tuntapVea.Error, + Error = linkerTunDeviceAdapter.Error, BufferSize = runningConfig.Data.Tuntap.BufferSize, HostIP = GetHostIP() }; @@ -279,7 +262,7 @@ namespace linker.plugins.tuntap { List ipsList = ParseIPs(tuntapInfos.Values.ToList()); TuntapVeaLanIPAddress[] ips = ipsList.SelectMany(c => c.IPS).ToArray(); - tuntapVea.DelRoute(ips); + linkerTunDeviceAdapter.DelRoute(ipsList.SelectMany(c => c.IPS).Select(c => new LinkerTunDeviceRouteItem { Address = c.OriginIPAddress, Mask = c.MaskLength }).ToArray()); } /// /// 添加路由 @@ -288,7 +271,7 @@ namespace linker.plugins.tuntap { List ipsList = ParseIPs(tuntapInfos.Values.ToList()); TuntapVeaLanIPAddress[] ips = ipsList.SelectMany(c => c.IPS).ToArray(); - tuntapVea.AddRoute(ips, runningConfig.Data.Tuntap.IP); + linkerTunDeviceAdapter.AddRoute(ipsList.SelectMany(c => c.IPS).Select(c => new LinkerTunDeviceRouteItem { Address = c.OriginIPAddress, Mask = c.MaskLength }).ToArray(), runningConfig.Data.Tuntap.IP); tuntapProxy.SetIPs(ipsList); foreach (var item in tuntapInfos.Values) @@ -345,6 +328,7 @@ namespace linker.plugins.tuntap MaskValue = maskValue, NetWork = ipInt & maskValue, Broadcast = ipInt | (~maskValue), + OriginIPAddress = ip, }; } @@ -361,9 +345,8 @@ namespace linker.plugins.tuntap { try { - if (tuntapVea.Running) + if (Status == TuntapStatus.Running) { - await CheckProxy().ConfigureAwait(false); await Task.Delay(5000).ConfigureAwait(false); await CheckInterface().ConfigureAwait(false); } @@ -377,33 +360,15 @@ namespace linker.plugins.tuntap } private async Task CheckInterface() { - NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == tuntapVea.InterfaceName); + NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == interfaceName); if (networkInterface != null && networkInterface.OperationalStatus != OperationalStatus.Up) { - LoggerHelper.Instance.Error($"tuntap inerface {tuntapVea.InterfaceName} is {networkInterface.OperationalStatus}, restarting"); + LoggerHelper.Instance.Error($"tuntap inerface {interfaceName} is {networkInterface.OperationalStatus}, restarting"); Stop(); await Task.Delay(5000).ConfigureAwait(false); Run(); } } - private async Task CheckProxy() - { - if (tuntapProxy.LocalEndpoint == null || tuntapProxy.LocalEndpoint.Port == 0) return; - try - { - var socket = new Socket(tuntapProxy.LocalEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - await socket.ConnectAsync(new IPEndPoint(IPAddress.Loopback, tuntapProxy.LocalEndpoint.Port)).WaitAsync(TimeSpan.FromMilliseconds(100)).ConfigureAwait(false); - socket.SafeClose(); - } - catch (Exception ex) - { - LoggerHelper.Instance.Error($"tuntap proxy {ex.Message}, restarting"); - Stop(); - await Task.Delay(5000).ConfigureAwait(false); - Run(); - } - } - private IPAddress GetHostIP() { string hostip = Environment.GetEnvironmentVariable("SNLTTY_LINKER_HOST_IP"); diff --git a/linker/plugins/tuntap/config/config.cs b/linker/plugins/tuntap/config/config.cs index f8211340..a1eaa246 100644 --- a/linker/plugins/tuntap/config/config.cs +++ b/linker/plugins/tuntap/config/config.cs @@ -1,4 +1,5 @@ using linker.plugins.tuntap.config; +using MemoryPack; using System.Buffers.Binary; using System.Net; @@ -37,7 +38,66 @@ namespace linker.plugins.tuntap.config /// 是否在运行中 /// public bool Running { get; set; } + + public Guid InterfaceGuid { get; set; } = Guid.NewGuid(); } + + + [MemoryPackable] + public sealed partial class TuntapVeaLanIPAddress + { + /// + /// ip,存小端 + /// + public uint IPAddress { get; set; } + public byte MaskLength { get; set; } + public uint MaskValue { get; set; } + public uint NetWork { get; set; } + public uint Broadcast { get; set; } + + [MemoryPackIgnore] + public IPAddress OriginIPAddress { get; set; } + + + } + + [MemoryPackable] + public sealed partial class TuntapVeaLanIPAddressList + { + public string MachineId { get; set; } + public List IPS { get; set; } + + } + + public enum TuntapStatus : byte + { + Normal = 0, + Starting = 1, + Running = 2 + } + + [MemoryPackable] + public sealed partial class TuntapInfo + { + public string MachineId { get; set; } + + public TuntapStatus Status { get; set; } + + [MemoryPackAllowSerialize] + public IPAddress IP { get; set; } + + [MemoryPackAllowSerialize] + public IPAddress[] LanIPs { get; set; } = Array.Empty(); + public int[] Masks { get; set; } = Array.Empty(); + + public string Error { get; set; } + + public byte BufferSize { get; set; } = 3; + + [MemoryPackAllowSerialize] + public IPAddress HostIP { get; set; } + } + } diff --git a/linker/plugins/tuntap/messenger/TuntapMessenger.cs b/linker/plugins/tuntap/messenger/TuntapMessenger.cs index 944bda48..e9695d58 100644 --- a/linker/plugins/tuntap/messenger/TuntapMessenger.cs +++ b/linker/plugins/tuntap/messenger/TuntapMessenger.cs @@ -1,6 +1,6 @@ using linker.plugins.messenger; using linker.plugins.signin.messenger; -using linker.plugins.tuntap.vea; +using linker.plugins.tuntap.config; using MemoryPack; namespace linker.plugins.tuntap.messenger diff --git a/linker/plugins/tuntap/proxy/TuntapProxy.cs b/linker/plugins/tuntap/proxy/TuntapProxy.cs index d56085e0..e5d16e45 100644 --- a/linker/plugins/tuntap/proxy/TuntapProxy.cs +++ b/linker/plugins/tuntap/proxy/TuntapProxy.cs @@ -1,60 +1,48 @@ using linker.client.config; using linker.config; using linker.plugins.relay; -using linker.plugins.tuntap.vea; using linker.tunnel; using linker.tunnel.connection; -using linker.tunnel.proxy; using linker.libs; using linker.libs.extends; -using linker.libs.socks5; -using System.Buffers.Binary; using System.Collections.Concurrent; using System.Net; -using System.Net.Sockets; +using linker.plugins.tuntap.config; +using linker.tun; +using System.Buffers.Binary; +using System.Text; namespace linker.plugins.tuntap.proxy { - public sealed class TuntapProxy : TunnelProxy + public sealed class TuntapProxy : ILinkerTunDeviceCallback, ITunnelConnectionReceiveCallback { private readonly TunnelTransfer tunnelTransfer; private readonly RelayTransfer relayTransfer; private readonly RunningConfig runningConfig; private readonly FileConfig config; - - private IPEndPoint proxyEP; - - public override IPAddress UdpBindAdress { get; set; } + private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter; private uint[] maskValues = Array.Empty(); - private readonly ConcurrentDictionary dic = new ConcurrentDictionary(); + private readonly ConcurrentDictionary ip2MachineCic = new ConcurrentDictionary(); private readonly ConcurrentDictionary hostipCic = new ConcurrentDictionary(); private readonly ConcurrentDictionary connections = new ConcurrentDictionary(); - private readonly ConcurrentDictionary dicLocks = new ConcurrentDictionary(); - private ConcurrentDictionary broadcastDic = new(new IPEndpointComparer()); - public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, FileConfig config) + SemaphoreSlim slimGlobal = new SemaphoreSlim(1); + private readonly ConcurrentDictionary dicLocks = new ConcurrentDictionary(); + + public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, FileConfig config, LinkerTunDeviceAdapter linkerTunDeviceAdapter) { this.tunnelTransfer = tunnelTransfer; this.relayTransfer = relayTransfer; this.runningConfig = runningConfig; this.config = config; + this.linkerTunDeviceAdapter = linkerTunDeviceAdapter; //监听打洞连接成功 tunnelTransfer.SetConnectedCallback("tuntap", OnConnected); //监听中继连接成功 relayTransfer.SetConnectedCallback("tuntap", OnConnected); - } - public void Start() - { - if (proxyEP != null) - { - Stop(proxyEP.Port); - } - Start(new IPEndPoint(IPAddress.Any, 0), runningConfig.Data.Tuntap.BufferSize); - proxyEP = new IPEndPoint(IPAddress.Any, LocalEndpoint.Port); - ClearTask(); } /// @@ -71,8 +59,51 @@ namespace linker.plugins.tuntap.proxy //connectionOld?.Dispose(); } connections.AddOrUpdate(connection.RemoteMachineId, connection, (a, b) => connection); - BindConnectionReceive(connection); + + connection.BeginReceive(this, null, false); } + public async Task Receive(ITunnelConnection connection, ReadOnlyMemory buffer, object state) + { + linkerTunDeviceAdapter.Write(buffer); + await Task.CompletedTask; + } + public async Task Closed(ITunnelConnection connection, object state) + { + await Task.CompletedTask; + } + + public async Task Callback(LinkerTunDevicPacket packet) + { + if (packet.Version == 4) + { + uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DistIPAddress.Span); + if (packet.DistIPAddress.GetIsBroadcastAddress()) + { + if (connections.IsEmpty == false) + { + await Task.WhenAll(connections.Values.Select(c => c.SendAsync(packet.Packet))); + } + } + else + { + ITunnelConnection connection = await ConnectTunnel(ip); + if (connection != null) + { + await connection.SendAsync(packet.Packet); + } + } + } + else if (packet.Version == 6 && (packet.DistIPAddress.Span[0] & 0xFF) == 0xFF) + { + if (connections.IsEmpty == false) + { + await Task.WhenAll(connections.Values.Select(c => c.SendAsync(packet.Packet))); + } + } + + Console.WriteLine($"IPV{packet.Version}->{new IPAddress(packet.SourceIPAddress.Span)}->{new IPAddress(packet.DistIPAddress.Span)}->{packet.Packet.Length}"); + } + /// /// 设置IP,等下有连接进来,用IP匹配,才能知道这个连接是要连谁 @@ -80,197 +111,25 @@ namespace linker.plugins.tuntap.proxy /// public void SetIPs(List ips) { - dic.Clear(); + ip2MachineCic.Clear(); foreach (var item in ips) { foreach (var ip in item.IPS) { - dic.AddOrUpdate(ip.NetWork, item.MachineId, (a, b) => item.MachineId); + ip2MachineCic.AddOrUpdate(ip.NetWork, item.MachineId, (a, b) => item.MachineId); } } maskValues = ips.SelectMany(c => c.IPS.Select(c => c.MaskValue)).Distinct().OrderBy(c => c).ToArray(); - UdpBindAdress = runningConfig.Data.Tuntap.IP; } public void SetIP(string machineId, uint ip) { - dic.AddOrUpdate(ip, machineId, (a, b) => machineId); - - UdpBindAdress = runningConfig.Data.Tuntap.IP; + ip2MachineCic.AddOrUpdate(ip, machineId, (a, b) => machineId); } public void SetHostIP(uint ip, IPAddress hostip) { hostipCic.AddOrUpdate(ip, hostip, (a, b) => hostip); } - /// - /// tcp连接隧道 - /// - /// - /// - protected override async ValueTask ConnectTunnelConnection(AsyncUserToken token) - { - int length = await token.Socket.ReceiveAsync(token.Buffer.AsMemory(), SocketFlags.None); - if (length == 0) - { - return true; - } - token.Proxy.Data = token.Buffer.AsMemory(0, length); - - token.Proxy.TargetEP = null; - - //步骤,request - token.Proxy.Rsv = (byte)Socks5EnumStep.Request; - if (await ReceiveCommandData(token) == false) - { - return true; - } - await token.Socket.SendAsync(new byte[] { 0x05, 0x00 }).ConfigureAwait(false); - - //步骤,command - token.Proxy.Data = Helper.EmptyArray; - token.Proxy.Rsv = (byte)Socks5EnumStep.Command; - if (await ReceiveCommandData(token).ConfigureAwait(false) == false) - { - return true; - } - Socks5EnumRequestCommand command = (Socks5EnumRequestCommand)token.Proxy.Data.Span[1]; - - //获取远端地址 - ReadOnlyMemory ipArray = Socks5Parser.GetRemoteEndPoint(token.Proxy.Data, out Socks5EnumAddressType addressType, out ushort port, out int index); - token.Proxy.Data = token.Proxy.Data.Slice(index); - token.Proxy.TargetEP = new IPEndPoint(new IPAddress(ipArray.Span), port); - uint targetIP = BinaryPrimitives.ReadUInt32BigEndian(ipArray.Span); - - //不支持域名 和 IPV6 - if (addressType == Socks5EnumAddressType.Domain || addressType == Socks5EnumAddressType.IPV6) - { - byte[] response1 = Socks5Parser.MakeConnectResponse(new IPEndPoint(IPAddress.Any, 0), (byte)Socks5EnumResponseCommand.AddressNotAllow); - await token.Socket.SendAsync(response1.AsMemory()).ConfigureAwait(false); - return true; - } - - //是UDP中继,不做连接操作,等UDP数据过去的时候再绑定 - if (targetIP == 0 || command == Socks5EnumRequestCommand.UdpAssociate) - { - await token.Socket.SendAsync(Socks5Parser.MakeConnectResponse(new IPEndPoint(IPAddress.Any, proxyEP.Port), (byte)Socks5EnumResponseCommand.ConnecSuccess).AsMemory()).ConfigureAwait(false); - return false; - } - - ReplaceTargetIP(token.Proxy.TargetEP, targetIP); - token.Connection = await ConnectTunnel(targetIP).ConfigureAwait(false); - - Socks5EnumResponseCommand resp = token.Connection != null && token.Connection.Connected ? Socks5EnumResponseCommand.ConnecSuccess : Socks5EnumResponseCommand.NetworkError; - byte[] response = Socks5Parser.MakeConnectResponse(new IPEndPoint(IPAddress.Any, 0), (byte)resp); - await token.Socket.SendAsync(response.AsMemory()).ConfigureAwait(false); - - return true; - } - /// - /// udp连接隧道 - /// - /// - /// - protected override async ValueTask ConnectTunnelConnection(AsyncUserUdpToken token) - { - ReadOnlyMemory ipArray = Socks5Parser.GetRemoteEndPoint(token.Proxy.Data, out Socks5EnumAddressType addressType, out ushort port, out int index); - if (addressType == Socks5EnumAddressType.IPV6) - { - return; - } - - uint targetIP = BinaryPrimitives.ReadUInt32BigEndian(ipArray.Span); - token.Proxy.TargetEP = new IPEndPoint(new IPAddress(ipArray.Span), port); - IPEndPoint target = new IPEndPoint(new IPAddress(ipArray.Span), port); - - //解析出udp包的数据部分 - token.Proxy.Data = Socks5Parser.GetUdpData(token.Proxy.Data); - - //是广播消息 - if (ipArray.Span[3] == 255 || token.Proxy.TargetEP.Address.GetIsBroadcastAddress()) - { - token.Proxy.TargetEP.Address = IPAddress.Loopback; - - //我们替换了IP,但是等下要回复UDP数据给socks5时,要用原来的IP,所以缓存一下,等下回复要用 - if (broadcastDic.TryGetValue(token.Proxy.SourceEP, out BroadcastCacheInfo cache) == false) - { - cache = new BroadcastCacheInfo { TargetEP = target }; - broadcastDic.TryAdd(token.Proxy.SourceEP, cache); - } - cache.LastTime = Environment.TickCount64; - - //广播不去连接,直接获取已经有的所有连接 - token.Connections = connections.Values.ToList(); - } - else - { - ReplaceTargetIP(token.Proxy.TargetEP, targetIP); - token.Connection = await ConnectTunnel(targetIP).ConfigureAwait(false); - } - } - - /// - /// //在docker内,我们不应该直接访问自己的虚拟IP,而是去访问宿主机的IP - /// - /// - /// - private void ReplaceTargetIP(IPEndPoint targetEP, uint targetIP) - { - if (hostipCic.TryGetValue(targetIP, out IPAddress hostip) && hostip.Equals(IPAddress.Any) == false) - { - targetEP.Address = hostip; - } - } - - /// - /// udp回复消息自定义处理,因为socks5,要打包一些格式才能返回 - /// - /// - /// - /// - protected override async ValueTask ConnectionReceiveUdp(AsyncUserTunnelToken token, AsyncUserUdpToken asyncUserUdpToken) - { - IPEndPoint target = token.Proxy.TargetEP; - if (broadcastDic.TryGetValue(token.Proxy.SourceEP, out BroadcastCacheInfo cache)) - { - target = cache.TargetEP; - cache.LastTime = Environment.TickCount64; - } - byte[] data = Socks5Parser.MakeUdpResponse(target, token.Proxy.Data, out int length); - try - { - await asyncUserUdpToken.SourceSocket.SendToAsync(data.AsMemory(0, length), token.Proxy.SourceEP).ConfigureAwait(false); - } - catch (Exception ex) - { - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Error(ex); - } - } - finally - { - Socks5Parser.Return(data); - } - return true; - } - private void ClearTask() - { - Task.Run(async () => - { - while (true) - { - long time = Environment.TickCount64; - foreach (var item in broadcastDic.Where(c => time - c.Value.LastTime > 30000).Select(c => c.Key).ToList()) - { - broadcastDic.TryRemove(item, out _); - }; - await Task.Delay(30000); - } - }); - } - - - SemaphoreSlim slimGlobal = new SemaphoreSlim(1); /// /// 打洞或者中继 /// @@ -279,7 +138,7 @@ namespace linker.plugins.tuntap.proxy private async ValueTask ConnectTunnel(uint ip) { //直接按IP查找 - if (dic.TryGetValue(ip, out string machineId)) + if (ip2MachineCic.TryGetValue(ip, out string machineId)) { return await ConnectTunnel(machineId).ConfigureAwait(false); } @@ -288,8 +147,9 @@ namespace linker.plugins.tuntap.proxy for (int i = 0; i < maskValues.Length; i++) { uint network = ip & maskValues[i]; - if (dic.TryGetValue(network, out machineId)) + if (ip2MachineCic.TryGetValue(network, out machineId)) { + ip2MachineCic.TryAdd(ip, machineId); return await ConnectTunnel(machineId).ConfigureAwait(false); } } @@ -364,48 +224,6 @@ namespace linker.plugins.tuntap.proxy return connection; } - /// - /// 接收socks5完整数据包 - /// - /// - /// - private async Task ReceiveCommandData(AsyncUserToken token) - { - int totalLength = token.Proxy.Data.Length; - EnumProxyValidateDataResult validate = ValidateData(token.Proxy); - //太短 - while ((validate & EnumProxyValidateDataResult.TooShort) == EnumProxyValidateDataResult.TooShort) - { - totalLength += await token.Socket.ReceiveAsync(token.Buffer.AsMemory(totalLength), SocketFlags.None).ConfigureAwait(false); - token.Proxy.Data = token.Buffer.AsMemory(0, totalLength); - validate = ValidateData(token.Proxy); - } - - //不短,又不相等,直接关闭连接 - if ((validate & EnumProxyValidateDataResult.Equal) != EnumProxyValidateDataResult.Equal) - { - return false; - } - return true; - } - /// - /// 验证socks5数据包完整性 - /// - /// - /// - private EnumProxyValidateDataResult ValidateData(ProxyInfo info) - { - return (Socks5EnumStep)info.Rsv switch - { - Socks5EnumStep.Request => Socks5Parser.ValidateRequestData(info.Data), - Socks5EnumStep.Command => Socks5Parser.ValidateCommandData(info.Data), - Socks5EnumStep.Auth => Socks5Parser.ValidateAuthData(info.Data, Socks5EnumAuthType.Password), - Socks5EnumStep.Forward => EnumProxyValidateDataResult.Equal, - Socks5EnumStep.ForwardUdp => EnumProxyValidateDataResult.Equal, - _ => EnumProxyValidateDataResult.Equal - }; - } - public ConcurrentDictionary GetConnections() { return connections; @@ -424,24 +242,6 @@ namespace linker.plugins.tuntap.proxy } } - } - public sealed class BroadcastCacheInfo - { - public IPEndPoint TargetEP { get; set; } - public long LastTime { get; set; } = Environment.TickCount64; - - } - - public sealed class IPEndpointComparer : IEqualityComparer - { - public bool Equals(IPEndPoint x, IPEndPoint y) - { - return x.Equals(y); - } - public int GetHashCode(IPEndPoint obj) - { - return obj.GetHashCode(); - } } } diff --git a/linker/plugins/tuntap/tun2socks-linux-arm64 b/linker/plugins/tuntap/tun2socks-linux-arm64 deleted file mode 100644 index eee72df4..00000000 Binary files a/linker/plugins/tuntap/tun2socks-linux-arm64 and /dev/null differ diff --git a/linker/plugins/tuntap/tun2socks-linux-x64 b/linker/plugins/tuntap/tun2socks-linux-x64 deleted file mode 100644 index 074de58f..00000000 Binary files a/linker/plugins/tuntap/tun2socks-linux-x64 and /dev/null differ diff --git a/linker/plugins/tuntap/tun2socks-osx-arm64 b/linker/plugins/tuntap/tun2socks-osx-arm64 deleted file mode 100644 index 3215d148..00000000 Binary files a/linker/plugins/tuntap/tun2socks-osx-arm64 and /dev/null differ diff --git a/linker/plugins/tuntap/tun2socks-osx-x64 b/linker/plugins/tuntap/tun2socks-osx-x64 deleted file mode 100644 index 977b918d..00000000 Binary files a/linker/plugins/tuntap/tun2socks-osx-x64 and /dev/null differ diff --git a/linker/plugins/tuntap/tun2socks-win-arm64 b/linker/plugins/tuntap/tun2socks-win-arm64 deleted file mode 100644 index a2c5cf11..00000000 Binary files a/linker/plugins/tuntap/tun2socks-win-arm64 and /dev/null differ diff --git a/linker/plugins/tuntap/tun2socks-win-x64 b/linker/plugins/tuntap/tun2socks-win-x64 deleted file mode 100644 index 2a051316..00000000 Binary files a/linker/plugins/tuntap/tun2socks-win-x64 and /dev/null differ diff --git a/linker/plugins/tuntap/tun2socks.exe b/linker/plugins/tuntap/tun2socks.exe deleted file mode 100644 index 2a051316..00000000 Binary files a/linker/plugins/tuntap/tun2socks.exe and /dev/null differ diff --git a/linker/plugins/tuntap/vea/ITuntapVea.cs b/linker/plugins/tuntap/vea/ITuntapVea.cs deleted file mode 100644 index 2fea887c..00000000 --- a/linker/plugins/tuntap/vea/ITuntapVea.cs +++ /dev/null @@ -1,89 +0,0 @@ -using MemoryPack; -using System.Net; -using System.Net.NetworkInformation; -using System.Text.Json.Serialization; - -namespace linker.plugins.tuntap.vea -{ - public interface ITuntapVea - { - public bool Running { get; } - public string InterfaceName { get; } - public string Error { get; } - - public Task Run(int proxyPort,IPAddress ip); - public Task SetIp(IPAddress ip); - public void Kill(); - - public void AddRoute(TuntapVeaLanIPAddress[] ips, IPAddress ip); - public void DelRoute(TuntapVeaLanIPAddress[] ips); - - - } - - [MemoryPackable] - public sealed partial class TuntapVeaLanIPAddress - { - /// - /// ip,存小端 - /// - public uint IPAddress { get; set; } - public byte MaskLength { get; set; } - public uint MaskValue { get; set; } - public uint NetWork { get; set; } - public uint Broadcast { get; set; } - - } - - [MemoryPackable] - public sealed partial class TuntapVeaLanIPAddressList - { - public string MachineId { get; set; } - public List IPS { get; set; } - - } - - public enum TuntapStatus : byte - { - Normal = 0, - Starting = 1, - Running = 2 - } - - [MemoryPackable] - public sealed partial class TuntapInfo - { - public string MachineId { get; set; } - - public TuntapStatus Status { get; set; } - - [MemoryPackAllowSerialize] - public IPAddress IP { get; set; } - - [MemoryPackAllowSerialize] - public IPAddress[] LanIPs { get; set; } = Array.Empty(); - public int[] Masks { get; set; } = Array.Empty(); - - public string Error { get; set; } - - public byte BufferSize { get; set; } = 3; - - [MemoryPackAllowSerialize] - public IPAddress HostIP { get; set; } - } - - [MemoryPackable] - public sealed partial class TuntapOnlineInfo - { - public string[] MachineIds { get; set; } - public byte[] Status { get; set; } - - [JsonIgnore] - [MemoryPackInclude] - public List> HostTasks { get; set; } - [JsonIgnore] - [MemoryPackInclude] - public List> PingTasks { get; set; } - } -} - diff --git a/linker/plugins/tuntap/vea/TuntapVeaLinux.cs b/linker/plugins/tuntap/vea/TuntapVeaLinux.cs deleted file mode 100644 index c5e0de73..00000000 --- a/linker/plugins/tuntap/vea/TuntapVeaLinux.cs +++ /dev/null @@ -1,156 +0,0 @@ -using linker.libs; -using System.Diagnostics; -using System.Net; - -namespace linker.plugins.tuntap.vea -{ - public sealed class TuntapVeaLinux : ITuntapVea - { - private string interfaceLinux = string.Empty; - private Process Tun2SocksProcess; - private IPAddress ip; - - public bool Running => string.IsNullOrWhiteSpace(interfaceLinux) == false; - public string InterfaceName => "linker"; - public string Error { get; private set; } - - public TuntapVeaLinux() - { - try - { - File.SetUnixFileMode("./plugins/tuntap/tun2socks", UnixFileMode.GroupExecute | UnixFileMode.OtherExecute | UnixFileMode.UserExecute); - } - catch (Exception) - { - } - } - - public async Task Run(int proxyPort, IPAddress ip) - { - CommandHelper.Linux(string.Empty, new string[] { $"ip tuntap add mode tun dev {InterfaceName}" }); - await SetIp(ip).ConfigureAwait(false); - string str = CommandHelper.Linux(string.Empty, new string[] { $"ifconfig" }); - if (str.Contains(InterfaceName) == false) - { - Error = CommandHelper.Linux(string.Empty, new string[] { $"ip tuntap add mode tun dev {InterfaceName}" }); - LoggerHelper.Instance.Error(Error); - return false; - } - - interfaceLinux = GetLinuxInterfaceNum(); - try - { - string command = $" -device {InterfaceName} -proxy socks5://127.0.0.1:{proxyPort} -interface {interfaceLinux} -loglevel silent"; - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Warning($"vea linux ->exec:{command}"); - } - Tun2SocksProcess = CommandHelper.Execute("./plugins/tuntap/tun2socks", command); - if (Tun2SocksProcess.HasExited) - { - Error = CommandHelper.Execute("./plugins/tuntap/tun2socks", command, Array.Empty()); - LoggerHelper.Instance.Error(Error); - } - - await Task.Delay(10).ConfigureAwait(false); - } - catch (Exception ex) - { - Error = ex.Message; - LoggerHelper.Instance.Error(ex.Message); - return false; - } - - return string.IsNullOrWhiteSpace(interfaceLinux) == false; - } - public async Task SetIp(IPAddress ip) - { - if (this.ip != null) - { - CommandHelper.Linux(string.Empty, new string[] { $"ip addr del {this.ip}/24 dev {InterfaceName}" }); - } - this.ip = ip; - CommandHelper.Linux(string.Empty, new string[] { $"ip addr add {ip}/24 dev {InterfaceName}", $"ip link set dev {InterfaceName} up" }); - return await Task.FromResult(true).ConfigureAwait(false); - } - - public void Kill() - { - if (Tun2SocksProcess != null) - { - try - { - Tun2SocksProcess.Kill(); - } - catch (Exception) - { - } - Tun2SocksProcess = null; - } - foreach (var item in Process.GetProcesses().Where(c => c.ProcessName.Contains("tun2socks"))) - { - try - { - item.Kill(); - } - catch (Exception) - { - } - }; - - interfaceLinux = string.Empty; - CommandHelper.Linux(string.Empty, new string[] { $"ip tuntap del mode tun dev {InterfaceName}" }); - Error = string.Empty; - } - public void AddRoute(TuntapVeaLanIPAddress[] ips, IPAddress ip) - { - string[] commands = ips.Where(c => c.IPAddress > 0).Select(item => - { - IPAddress _ip = NetworkHelper.ToNetworkIp(item.IPAddress, item.MaskValue); - return $"ip route add {_ip}/{item.MaskLength} via {ip} dev {InterfaceName} metric 1 "; - }).ToArray(); - if (commands.Length > 0) - { - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Warning($"vea linux ->add route:{string.Join(Environment.NewLine, commands)}"); - } - CommandHelper.Linux(string.Empty, commands); - } - } - public void DelRoute(TuntapVeaLanIPAddress[] ip) - { - string[] commands = ip.Select(item => - { - IPAddress _ip = NetworkHelper.ToNetworkIp(item.IPAddress, item.MaskValue); - return $"ip route del {_ip}/{item.MaskLength}"; - }).ToArray(); - - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Warning($"vea linux ->del route:{string.Join(Environment.NewLine, commands)}"); - } - CommandHelper.Linux(string.Empty, commands); - } - - private string GetLinuxInterfaceNum() - { - string output = CommandHelper.Linux(string.Empty, new string[] { "ip route" }); - foreach (var item in output.Split(Environment.NewLine)) - { - if (item.StartsWith("default via")) - { - var strs = item.Split(' '); - for (int i = 0; i < strs.Length; i++) - { - if (strs[i] == "dev") - { - return strs[i + 1]; - } - } - } - } - return string.Empty; - } - } -} diff --git a/linker/plugins/tuntap/vea/TuntapVeaMacOs.cs b/linker/plugins/tuntap/vea/TuntapVeaMacOs.cs deleted file mode 100644 index 24f41775..00000000 --- a/linker/plugins/tuntap/vea/TuntapVeaMacOs.cs +++ /dev/null @@ -1,159 +0,0 @@ -using linker.libs; -using System.Diagnostics; -using System.Net; - -namespace linker.plugins.tuntap.vea -{ - public sealed class TuntapVeaMacOs : ITuntapVea - { - private string interfaceOsx = string.Empty; - private Process Tun2SocksProcess; - private IPAddress ip; - - public bool Running => string.IsNullOrWhiteSpace(interfaceOsx) == false; - public string InterfaceName => "utun12138"; - public string Error { get; private set; } - - public TuntapVeaMacOs() - { - try - { - File.SetUnixFileMode("./plugins/tuntap/tun2socks", UnixFileMode.GroupExecute | UnixFileMode.OtherExecute | UnixFileMode.UserExecute); - } - catch (Exception) - { - } - } - - public async Task Run(int proxyPort, IPAddress ip) - { - interfaceOsx = GetOsxInterfaceNum(); - try - { - Tun2SocksProcess = CommandHelper.Execute("./plugins/tuntap/tun2socks", $" -device {InterfaceName} -proxy socks5://127.0.0.1:{proxyPort} -interface {interfaceOsx} -loglevel silent"); - if (Tun2SocksProcess.HasExited) - { - Error = CommandHelper.Execute("./plugins/tuntap/tun2socks", $" -device {InterfaceName} -proxy socks5://127.0.0.1:{proxyPort} -interface {interfaceOsx} -loglevel silent", Array.Empty()); - LoggerHelper.Instance.Error(Error); - } - } - catch (Exception ex) - { - Error = ex.Message; - LoggerHelper.Instance.Error(ex.Message); - return false; - } - - for (int i = 0; i < 5; i++) - { - string output = CommandHelper.Osx(string.Empty, new string[] { "ifconfig" }); - if (output.Contains(InterfaceName)) - { - break; - } - await Task.Delay(1000).ConfigureAwait(false); - } - - await SetIp(ip).ConfigureAwait(false); - - return string.IsNullOrWhiteSpace(interfaceOsx) == false; - } - public async Task SetIp(IPAddress ip) - { - if (this.ip != null) - { - var ips = this.ip.GetAddressBytes(); - ips[^1] = 0; - CommandHelper.Osx(string.Empty, new string[] { $"route delete -net {new IPAddress(ips)}/24 {this.ip}" }); - } - - this.ip = ip; - CommandHelper.Osx(string.Empty, new string[] { $"ifconfig {InterfaceName} {ip} {ip} up" }); - await Task.Delay(10).ConfigureAwait(false); - - var ipBytes = ip.GetAddressBytes(); - ipBytes[^1] = 0; - CommandHelper.Osx(string.Empty, new string[] { $"route add -net {new IPAddress(ipBytes)}/24 {ip}" }); - return true; - } - - public void Kill() - { - if (Tun2SocksProcess != null) - { - try - { - Tun2SocksProcess.Kill(); - } - catch (Exception) - { - } - Tun2SocksProcess = null; - } - foreach (var item in Process.GetProcesses().Where(c => c.ProcessName.Contains("tun2socks"))) - { - try - { - item.Kill(); - } - catch (Exception) - { - } - }; - - interfaceOsx = string.Empty; - var ip = this.ip.GetAddressBytes(); - ip[^1] = 0; - CommandHelper.Osx(string.Empty, new string[] { $"route delete -net {new IPAddress(ip)}/24 {this.ip}" }); - Error = string.Empty; - } - - public void AddRoute(TuntapVeaLanIPAddress[] ips, IPAddress ip) - { - string[] commands = ips.Where(c => c.IPAddress > 0).Select(item => - { - IPAddress _ip = NetworkHelper.ToNetworkIp(item.IPAddress, item.MaskValue); - return $"route add -net {_ip}/{item.MaskLength} {ip}"; - }).ToArray(); - if (commands.Length > 0) - { - CommandHelper.Osx(string.Empty, commands.ToArray()); - } - } - public void DelRoute(TuntapVeaLanIPAddress[] ip) - { - string[] commands = ip.Select(item => - { - IPAddress _ip = NetworkHelper.ToNetworkIp(item.IPAddress, item.MaskValue); - return $"route delete -net {_ip}/{item.MaskLength}"; - }).ToArray(); - if (commands.Length > 0) - { - CommandHelper.Osx(string.Empty, commands.ToArray()); - } - } - - private string GetOsxInterfaceNum() - { - string output = CommandHelper.Osx(string.Empty, new string[] { "ifconfig" }); - var arr = output.Split(Environment.NewLine); - for (int i = 0; i < arr.Length; i++) - { - var item = arr[i]; - if (item.Contains("inet ")) - { - for (int k = i; k >= 0; k--) - { - var itemk = arr[k]; - if (itemk.Contains("flags=") && itemk.StartsWith("en")) - { - return itemk.Split(": ")[0]; - } - } - } - - } - return string.Empty; - } - } -} diff --git a/linker/plugins/tuntap/vea/TuntapVeaWindows.cs b/linker/plugins/tuntap/vea/TuntapVeaWindows.cs deleted file mode 100644 index 9615b847..00000000 --- a/linker/plugins/tuntap/vea/TuntapVeaWindows.cs +++ /dev/null @@ -1,299 +0,0 @@ -using linker.libs; -using Microsoft.Win32; -using System.Diagnostics; -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; - -namespace linker.plugins.tuntap.vea -{ - public sealed class TuntapVeaWindows : ITuntapVea - { - private int interfaceNumber = 0; - private Process Tun2SocksProcess; - - public bool Running => interfaceNumber > 0; - public string InterfaceName => "linker"; - public string Error { get; private set; } - - - public TuntapVeaWindows() - { - ClearRegistry(); - } - - public async Task Run(int proxyPort, IPAddress ip) - { - string command = $" -device tun://{InterfaceName} -proxy socks5://127.0.0.1:{proxyPort} -loglevel silent"; - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Warning($"vea windows ->exec:{command}"); - } - try - { - Tun2SocksProcess = CommandHelper.Execute("./plugins/tuntap/tun2socks.exe", command); - if (Tun2SocksProcess.HasExited) - { - Kill(); - return false; - } - if (await GetWindowsHasInterface(InterfaceName).ConfigureAwait(false) == false) - { - Kill(); - return false; - } - if (await GetWindowsInterfaceNum().ConfigureAwait(false) == false) - { - Kill(); - return false; - } - if (await SetIp(ip).ConfigureAwait(false) == false) - { - Kill(); - return false; - } - - if (await GetWindowsHasRoute(ip).ConfigureAwait(false) == false) - { - Kill(); - return false; - } - } - catch (Exception ex) - { - LoggerHelper.Instance.Error(ex); - } - - if (interfaceNumber <= 0) - { - Error = CommandHelper.Execute("./plugins/tuntap/tun2socks.exe", command, Array.Empty()); - LoggerHelper.Instance.Error(Error); - } - return interfaceNumber > 0; - } - public async Task SetIp(IPAddress ip) - { - if (interfaceNumber == 0) return false; - CommandHelper.Windows(string.Empty, new string[] { $"netsh interface ip set address name=\"{InterfaceName}\" source=static addr={ip} mask=255.255.255.0 gateway=none" }); - for (int k = 0; k < 5; k++) - { - string output = CommandHelper.Windows(string.Empty, new string[] { $"ipconfig" }); - if (output.Contains("Windows IP") == false) - { - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - Error = $"ipconfig command not found"; - LoggerHelper.Instance.Error(Error); - } - return false; - } - if (output.Contains(ip.ToString())) - { - return true; - } - await Task.Delay(1000).ConfigureAwait(false); - } - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - Error = $"vea windows ->set ip fail"; - LoggerHelper.Instance.Error(Error); - } - return false; - } - - - private void ClearRegistry() - { - string[] delValues = ["p2p-tunnel", "cmonitor", "linker"]; - try - { - RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles"); - foreach (var item in key.GetSubKeyNames()) - { - RegistryKey itemKey = key.OpenSubKey(item); - string value = itemKey.GetValue("Description", string.Empty).ToString(); - itemKey.Close(); - if (delValues.Contains(value)) - { - try - { - Registry.LocalMachine.DeleteSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles\\{item}"); - } - catch (Exception) - { - } - } - } - key.Close(); - - key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Signatures\\Unmanaged"); - foreach (var item in key.GetSubKeyNames()) - { - RegistryKey itemKey = key.OpenSubKey(item); - string value = itemKey.GetValue("Description", string.Empty).ToString(); - itemKey.Close(); - if (delValues.Any(c => value.Contains($"{c} ") || value == c)) - { - try - { - Registry.LocalMachine.DeleteSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Signatures\\Unmanaged\\{item}"); - } - catch (Exception) - { - } - } - } - key.Close(); - } - catch (Exception) - { - } - } - - public void Kill() - { - interfaceNumber = 0; - if (Tun2SocksProcess != null) - { - try - { - Tun2SocksProcess.Kill(); - } - catch (Exception) - { - } - - Tun2SocksProcess = null; - } - foreach (var item in Process.GetProcesses().Where(c => c.ProcessName.Contains("tun2socks"))) - { - try - { - item.Kill(); - } - catch (Exception) - { - } - }; - Error = string.Empty; - } - public void AddRoute(TuntapVeaLanIPAddress[] ips, IPAddress ip) - { - if (interfaceNumber > 0) - { - string[] commands = ips.Where(c => c.IPAddress > 0).Select(item => - { - IPAddress mask = NetworkHelper.GetMaskIp(item.MaskValue); - IPAddress _ip = NetworkHelper.ToNetworkIp(item.IPAddress, item.MaskValue); - - return $"route add {_ip} mask {mask} {ip} metric 5 if {interfaceNumber}"; - }).ToArray(); - if (commands.Length > 0) - { - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Warning($"vea windows ->add route:{string.Join(Environment.NewLine, commands)}"); - } - CommandHelper.Windows(string.Empty, commands); - } - } - } - public void DelRoute(TuntapVeaLanIPAddress[] ip) - { - if (interfaceNumber > 0) - { - string[] commands = ip.Where(c => c.IPAddress > 0).Select(item => - { - IPAddress _ip = NetworkHelper.ToNetworkIp(item.IPAddress, item.MaskValue); - return $"route delete {_ip}"; - }).ToArray(); - if (commands.Length > 0) - { - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - LoggerHelper.Instance.Warning($"vea windows ->del route:{string.Join(Environment.NewLine, commands)}"); - } - CommandHelper.Windows(string.Empty, commands.ToArray()); - } - } - } - - - private async Task GetWindowsInterfaceNum() - { - for (int i = 0; i < 10; i++) - { - NetworkInterface adapter = NetworkInterface.GetAllNetworkInterfaces() - .FirstOrDefault(c => c.Name == InterfaceName); - if (adapter != null) - { - interfaceNumber = adapter.GetIPProperties().GetIPv4Properties().Index; - return true; - } - - await Task.Delay(1000).ConfigureAwait(false); - } - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - Error = $"interface number not found"; - LoggerHelper.Instance.Error(Error); - } - return false; - } - private async Task GetWindowsHasInterface(string name) - { - for (int i = 0; i < 10; i++) - { - string output = CommandHelper.Windows(string.Empty, new string[] { $"ipconfig" }); - if (output.Contains("Windows IP") == false) - { - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - Error = $"ipconfig command not found"; - LoggerHelper.Instance.Error(Error); - } - return false; - } - if (output.Contains(name)) - { - return true; - } - await Task.Delay(1000).ConfigureAwait(false); - } - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - Error = $"interface {name} not found"; - LoggerHelper.Instance.Error(Error); - } - return false; - } - private async Task GetWindowsHasRoute(IPAddress ip) - { - for (int i = 0; i < 10; i++) - { - await Task.Delay(1000).ConfigureAwait(false); - string output = CommandHelper.Windows(string.Empty, new string[] { "route print" }); - if (output.Contains("IPv4") == false) - { - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - Error = $"route command not found"; - LoggerHelper.Instance.Error(Error); - } - break; - } - if (output.Contains(ip.ToString())) - { - return true; - } - } - if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) - { - Error = $"interface route set fail"; - LoggerHelper.Instance.Error(Error); - } - return false; - } - - } -}