This commit is contained in:
snltty
2024-08-01 22:33:53 +08:00
parent 4663856b4c
commit c813f2f577
29 changed files with 265 additions and 1100 deletions

View File

@@ -8,6 +8,7 @@ using System.Net.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace linker.libs namespace linker.libs
{ {
@@ -184,6 +185,18 @@ namespace linker.libs
{ {
return new IPAddress(BinaryPrimitives.ReverseEndianness(ip & maskvalue).ToBytes()); 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) public static bool NotIPv6Support(IPAddress ip)
{ {

View File

@@ -55,7 +55,7 @@ namespace linker.libs.extends
public static bool GetIsBroadcastAddress(this ReadOnlySpan<byte> address) public static bool GetIsBroadcastAddress(this ReadOnlySpan<byte> address)
{ {
uint ip = BinaryPrimitives.ReadUInt32BigEndian(address); uint ip = BinaryPrimitives.ReadUInt32BigEndian(address);
return (ip >= 0xE0000000 && ip <= 0xEFFFFFFF) || ip == 0xFFFFFFFF; return address[3] == 255 || (ip >= 0xE0000000 && ip <= 0xEFFFFFFF) || ip == 0xFFFFFFFF;
} }

View File

@@ -1,5 +1,4 @@
using System; using System.Buffers.Binary;
using System.Buffers.Binary;
using System.Net; using System.Net;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -10,25 +9,28 @@ namespace linker.tun.test
public static LinkerTunDeviceAdapter linkerTunDeviceAdapter; public static LinkerTunDeviceAdapter linkerTunDeviceAdapter;
static void Main(string[] args) static void Main(string[] args)
{ {
linkerTunDeviceAdapter = new LinkerTunDeviceAdapter();
linkerTunDeviceAdapter = new LinkerTunDeviceAdapter(new LinkerTunDeviceCallback()); linkerTunDeviceAdapter.SetCallback(new LinkerTunDeviceCallback());
linkerTunDeviceAdapter.SetUp("linker111" linkerTunDeviceAdapter.SetUp("linker111"
, Guid.Parse("dc6d4efa-2b53-41bd-a403-f416c9bf7129") , Guid.Parse("dc6d4efa-2b53-41bd-a403-f416c9bf7129")
, IPAddress.Parse("192.168.55.2") , IPAddress.Parse("192.168.55.2"), 24);
, IPAddress.Parse("192.168.55.1"), 24);
if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.Error)) if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.Error))
{ {
Console.WriteLine(linkerTunDeviceAdapter.Error); Console.WriteLine(linkerTunDeviceAdapter.Error);
} }
Console.ReadLine(); 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<byte> writableMemory = MemoryMarshal.AsMemory(packet.Packet); Memory<byte> writableMemory = MemoryMarshal.AsMemory(packet.Packet);
fixed (byte* ptr = writableMemory.Span) fixed (byte* ptr = writableMemory.Span)
@@ -36,12 +38,12 @@ namespace linker.tun.test
//icmp && request //icmp && request
if (ptr[9] == 1 && ptr[20] == 8) 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 dist = BinaryPrimitives.ReadUInt32LittleEndian(writableMemory.Span.Slice(16, 4));
//目的地址变源地址, //目的地址变源地址,
* (uint*)(ptr + 16) = *(uint*)(ptr + 12); *(uint*)(ptr + 16) = *(uint*)(ptr + 12);
//假装是网关回复的 //假装是网关回复的
*(uint*)(ptr + 12) = dist; *(uint*)(ptr + 12) = dist;

View File

@@ -20,7 +20,7 @@ namespace linker.tun
public interface ILinkerTunDeviceCallback public interface ILinkerTunDeviceCallback
{ {
public void Callback(LinkerTunDevicPacket packet); public Task Callback(LinkerTunDevicPacket packet);
} }
public struct LinkerTunDevicPacket public struct LinkerTunDevicPacket
@@ -33,8 +33,8 @@ namespace linker.tun
public sealed class LinkerTunDeviceRouteItem public sealed class LinkerTunDeviceRouteItem
{ {
public IPAddress Address { get; } public IPAddress Address { get; set; }
public byte Mask { get; } public byte Mask { get; set; }
} }
public enum LinkerTunDeviceStatus public enum LinkerTunDeviceStatus

View File

@@ -1,8 +1,9 @@
using System.Net; using linker.libs;
using System.Net;
namespace linker.tun namespace linker.tun
{ {
public unsafe sealed class LinkerTunDeviceAdapter public sealed class LinkerTunDeviceAdapter
{ {
private ILinkerTunDevice linkerTunDevice; private ILinkerTunDevice linkerTunDevice;
private ILinkerTunDeviceCallback linkerTunDeviceCallback; private ILinkerTunDeviceCallback linkerTunDeviceCallback;
@@ -13,31 +14,45 @@ namespace linker.tun
private bool starting = false; 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;
}
}
/// <summary> /// <summary>
/// 构造 /// 构造
/// </summary> /// </summary>
/// <param name="linkerTunDeviceCallback">数据包回调</param> /// <param name="linkerTunDeviceCallback">数据包回调</param>
public LinkerTunDeviceAdapter(ILinkerTunDeviceCallback linkerTunDeviceCallback) public LinkerTunDeviceAdapter()
{
}
public void SetCallback(ILinkerTunDeviceCallback linkerTunDeviceCallback)
{ {
this.linkerTunDeviceCallback = linkerTunDeviceCallback; this.linkerTunDeviceCallback = linkerTunDeviceCallback;
} }
/// <summary> /// <summary>
/// 开启网卡 /// 开启网卡
/// </summary> /// </summary>
/// <param name="name">网卡名如果是osx需要utunX的命名X是一个数字</param> /// <param name="name">网卡名如果是osx需要utunX的命名X是一个数字</param>
/// <param name="guid">windows的时候需要一个固定guid不然网卡编号一直递增注册表一直新增记录</param> /// <param name="guid">windows的时候需要一个固定guid不然网卡编号一直递增注册表一直新增记录</param>
/// <param name="address">网卡IP</param> /// <param name="address">网卡IP</param>
/// <param name="gateway">网卡网关</param>
/// <param name="mask">掩码。一般24即可</param> /// <param name="mask">掩码。一般24即可</param>
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; if (starting) return;
Shutdown(); Shutdown();
starting = true; starting = true;
try try
{ {
@@ -55,7 +70,8 @@ namespace linker.tun
if (linkerTunDevice != null) if (linkerTunDevice != null)
{ {
linkerTunDevice.Shutdown(); linkerTunDevice.Shutdown();
linkerTunDevice.SetUp(address, gateway, mask, out error);
linkerTunDevice.SetUp(address, NetworkHelper.ToGatewayIP(address, mask), mask, out error);
if (string.IsNullOrWhiteSpace(error)) if (string.IsNullOrWhiteSpace(error))
{ {
cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource = new CancellationTokenSource();
@@ -63,28 +79,35 @@ namespace linker.tun
{ {
while (cancellationTokenSource.IsCancellationRequested == false) while (cancellationTokenSource.IsCancellationRequested == false)
{ {
ReadOnlyMemory<byte> buffer = linkerTunDevice.Read(); try
if (buffer.Length == 0) {
ReadOnlyMemory<byte> 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; 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
/// <param name="addr">包头开始位置</param> /// <param name="addr">包头开始位置</param>
/// <param name="count">包头长度</param> /// <param name="count">包头长度</param>
/// <returns></returns> /// <returns></returns>
public ushort Checksum(ushort* addr, uint count) public unsafe ushort Checksum(ushort* addr, uint count)
{ {
ulong sum = 0; ulong sum = 0;
while (count > 1) while (count > 1)
@@ -167,7 +190,7 @@ namespace linker.tun
} }
if (count > 0) if (count > 0)
{ {
sum += (ulong)((*addr) & Ntohs(0xFF00)); sum += (ulong)((*addr) & ((((0xff00) & 0xff) << 8) | (((0xff00) & 0xff00) >> 8)));
} }
while ((sum >> 16) != 0) while ((sum >> 16) != 0)
{ {
@@ -176,9 +199,5 @@ namespace linker.tun
sum = ~sum; sum = ~sum;
return ((ushort)sum); return ((ushort)sum);
} }
private ushort Ntohs(ushort value)
{
return ((ushort)((((value) & 0xff) << 8) | (((value) & 0xff00) >> 8)));
}
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Buffers.Binary;
using System.Net; using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static linker.libs.winapis.SECUR32;
namespace linker.tun namespace linker.tun
{ {
@@ -12,10 +13,12 @@ namespace linker.tun
public string Name => name; public string Name => name;
public bool Running => session != 0; 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 Guid guid;
private int interfaceNumber = 0; private int interfaceNumber = 0;
private CancellationTokenSource tokenSource;
public LinkerWinTunDevice(string name, Guid guid) public LinkerWinTunDevice(string name, Guid guid)
{ {
this.name = name; this.name = name;
@@ -24,6 +27,7 @@ namespace linker.tun
public bool SetUp(IPAddress address, IPAddress gateway, byte prefixLength, out string error) public bool SetUp(IPAddress address, IPAddress gateway, byte prefixLength, out string error)
{ {
error = string.Empty; error = string.Empty;
if (adapter != 0) if (adapter != 0)
{ {
@@ -47,6 +51,11 @@ namespace linker.tun
waitHandle = WintunGetReadWaitEvent(session); waitHandle = WintunGetReadWaitEvent(session);
WintunSetLogger((WINTUN_LOGGER_LEVEL level, ulong timestamp,string message) =>
{
Console.WriteLine($"[{level}]->{timestamp}->{message}");
});
WintunGetAdapterLUID(adapter, out ulong luid); WintunGetAdapterLUID(adapter, out ulong luid);
{ {
MIB_UNICASTIPADDRESS_ROW AddressRow = default; MIB_UNICASTIPADDRESS_ROW AddressRow = default;
@@ -59,6 +68,7 @@ namespace linker.tun
uint LastError = CreateUnicastIpAddressEntry(ref AddressRow); uint LastError = CreateUnicastIpAddressEntry(ref AddressRow);
if (LastError != 0) throw new InvalidOperationException(); if (LastError != 0) throw new InvalidOperationException();
} }
/*
{ {
MIB_IPFORWARD_ROW2 row = default; MIB_IPFORWARD_ROW2 row = default;
InitializeIpForwardEntry(ref row); InitializeIpForwardEntry(ref row);
@@ -71,13 +81,20 @@ namespace linker.tun
uint LastError = CreateIpForwardEntry2(ref row); uint LastError = CreateIpForwardEntry2(ref row);
if (LastError != 0) throw new InvalidOperationException(); if (LastError != 0) throw new InvalidOperationException();
} }
*/
GetWindowsInterfaceNum(); GetWindowsInterfaceNum();
tokenSource = new CancellationTokenSource();
return true; return true;
} }
public void Shutdown() public void Shutdown()
{ {
tokenSource?.Cancel();
if (waitHandle != 0)
{
SetEvent(waitHandle);
waitHandle = 0;
}
if (session != 0) if (session != 0)
{ {
WintunEndSession(session); WintunEndSession(session);
@@ -126,8 +143,7 @@ namespace linker.tun
private byte[] buffer = new byte[2 * 1024]; private byte[] buffer = new byte[2 * 1024];
public unsafe ReadOnlyMemory<byte> Read() public unsafe ReadOnlyMemory<byte> Read()
{ {
if (session == 0) return Helper.EmptyArray; for (; tokenSource.IsCancellationRequested == false;)
for (; ; )
{ {
IntPtr packet = WintunReceivePacket(session, out var packetSize); IntPtr packet = WintunReceivePacket(session, out var packetSize);
if (packet != 0) if (packet != 0)
@@ -144,6 +160,7 @@ namespace linker.tun
} }
} }
} }
return Helper.EmptyArray;
} }
public unsafe bool Write(ReadOnlyMemory<byte> buffer) public unsafe bool Write(ReadOnlyMemory<byte> buffer)
{ {
@@ -220,6 +237,8 @@ namespace linker.tun
private static extern uint CreateIpForwardEntry2(ref MIB_IPFORWARD_ROW2 Row); private static extern uint CreateIpForwardEntry2(ref MIB_IPFORWARD_ROW2 Row);
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern bool SetEvent(IntPtr hEvent);
[DllImport("wintun.dll", SetLastError = true)] [DllImport("wintun.dll", SetLastError = true)]
private static extern IntPtr WintunCreateAdapter( private static extern IntPtr WintunCreateAdapter(

View File

@@ -102,7 +102,7 @@ namespace linker.tunnel.connection
/// <summary> /// <summary>
/// 缓冲区大小 /// 缓冲区大小
/// </summary> /// </summary>
public byte BufferSize { get; } public byte BufferSize { get; }
/// <summary> /// <summary>
/// 已连接 /// 已连接

View File

@@ -250,6 +250,7 @@ namespace linker.tunnel.connection
return false; return false;
} }
public void Dispose() public void Dispose()
{ {
ticks = 0; ticks = 0;

View File

@@ -68,7 +68,7 @@ namespace linker.tunnel.connection
cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource = new CancellationTokenSource();
_ = ProcessWrite(); _ = ProcessWrite();
_ = ProcessHeart(); //_ = ProcessHeart();
} }
private async Task ProcessWrite() private async Task ProcessWrite()

View File

@@ -187,10 +187,7 @@ namespace linker.tunnel.proxy
try try
{ {
asyncUserUdpToken.Connection = tunnelToken.Connection; 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) catch (Exception ex)
{ {

View File

@@ -91,7 +91,6 @@ namespace linker.tunnel.transport
if (length > 0) if (length > 0)
{ {
string key = bytes.AsMemory(0, length).GetString(); string key = bytes.AsMemory(0, length).GetString();
LoggerHelper.Instance.Debug(key);
if (distDic.TryRemove(key, out TaskCompletionSource<Socket> tcs)) if (distDic.TryRemove(key, out TaskCompletionSource<Socket> tcs))
{ {
await client.SendAsync(bytes.AsMemory(0, length)); await client.SendAsync(bytes.AsMemory(0, length));

View File

@@ -49,9 +49,6 @@
<None Update="msquic.dll" Condition="'$(RuntimeIdentifier)'=='win-x64' or '$(RuntimeIdentifier)'=='win-arm64'"> <None Update="msquic.dll" Condition="'$(RuntimeIdentifier)'=='win-x64' or '$(RuntimeIdentifier)'=='win-arm64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="plugins\tuntap\tun2socks.exe" Condition="'$(Configuration)'=='Debug'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Plugins\Tuntap\wintun.dll" Condition="'$(RuntimeIdentifier)'=='win-x64' or '$(RuntimeIdentifier)'=='win-arm64' or '$(Configuration)'=='Debug'"> <None Update="Plugins\Tuntap\wintun.dll" Condition="'$(RuntimeIdentifier)'=='win-x64' or '$(RuntimeIdentifier)'=='win-arm64' or '$(Configuration)'=='Debug'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -62,6 +59,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\linker.tunnel\linker.tunnel.csproj" /> <ProjectReference Include="..\linker.tunnel\linker.tunnel.csproj" />
<ProjectReference Include="..\linker.libs\linker.libs.csproj" /> <ProjectReference Include="..\linker.libs\linker.libs.csproj" />
<ProjectReference Include="..\linker.tun\linker.tun.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="LiteDB" Version="5.0.17" /> <PackageReference Include="LiteDB" Version="5.0.17" />

View File

@@ -1,5 +1,4 @@
using linker.libs.api; using linker.libs.api;
using linker.plugins.tuntap.vea;
using linker.plugins.tuntap.messenger; using linker.plugins.tuntap.messenger;
using MemoryPack; using MemoryPack;
using linker.libs.extends; using linker.libs.extends;
@@ -8,9 +7,9 @@ using linker.config;
using linker.tunnel.connection; using linker.tunnel.connection;
using linker.plugins.tuntap.proxy; using linker.plugins.tuntap.proxy;
using linker.plugins.client; using linker.plugins.client;
using linker.plugins.server;
using linker.plugins.capi; using linker.plugins.capi;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.tuntap.config;
namespace linker.plugins.tuntap namespace linker.plugins.tuntap
{ {

View File

@@ -1,8 +1,8 @@
using linker.config; using linker.config;
using linker.plugins.tuntap.messenger; using linker.plugins.tuntap.messenger;
using linker.plugins.tuntap.proxy; using linker.plugins.tuntap.proxy;
using linker.plugins.tuntap.vea;
using linker.startup; using linker.startup;
using linker.tun;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System.Reflection; using System.Reflection;
@@ -23,12 +23,8 @@ namespace linker.plugins.tuntap
public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies) public void AddClient(ServiceCollection serviceCollection, FileConfig config, Assembly[] assemblies)
{ {
//不同平台下的虚拟网卡
if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<ITuntapVea, TuntapVeaWindows>();
if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<ITuntapVea, TuntapVeaLinux>();
if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<ITuntapVea, TuntapVeaMacOs>();
serviceCollection.AddSingleton<TuntapClientApiController>(); serviceCollection.AddSingleton<TuntapClientApiController>();
serviceCollection.AddSingleton<LinkerTunDeviceAdapter>();
serviceCollection.AddSingleton<TuntapTransfer>(); serviceCollection.AddSingleton<TuntapTransfer>();
serviceCollection.AddSingleton<TuntapProxy>(); serviceCollection.AddSingleton<TuntapProxy>();

View File

@@ -2,18 +2,16 @@
using linker.config; using linker.config;
using linker.plugins.tuntap.messenger; using linker.plugins.tuntap.messenger;
using linker.plugins.tuntap.proxy; using linker.plugins.tuntap.proxy;
using linker.plugins.tuntap.vea;
using linker.libs; using linker.libs;
using MemoryPack; using MemoryPack;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Net; using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Net.Sockets;
using linker.libs.extends;
using linker.plugins.client; using linker.plugins.client;
using linker.plugins.messenger; using linker.plugins.messenger;
using System; using linker.plugins.tuntap.config;
using linker.tun;
namespace linker.plugins.tuntap namespace linker.plugins.tuntap
{ {
@@ -21,31 +19,31 @@ namespace linker.plugins.tuntap
{ {
private readonly MessengerSender messengerSender; private readonly MessengerSender messengerSender;
private readonly ClientSignInState clientSignInState; private readonly ClientSignInState clientSignInState;
private readonly ITuntapVea tuntapVea;
private readonly FileConfig config; private readonly FileConfig config;
private readonly TuntapProxy tuntapProxy; private readonly TuntapProxy tuntapProxy;
private readonly RunningConfig runningConfig; private readonly RunningConfig runningConfig;
private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter;
private string interfaceName = "linker";
private uint infosVersion = 0; private uint infosVersion = 0;
private readonly ConcurrentDictionary<string, TuntapInfo> tuntapInfos = new ConcurrentDictionary<string, TuntapInfo>();
public ConcurrentDictionary<string, TuntapInfo> Infos => tuntapInfos;
public uint InfosVersion => infosVersion; public uint InfosVersion => infosVersion;
private readonly ConcurrentDictionary<string, TuntapInfo> tuntapInfos = new ConcurrentDictionary<string, TuntapInfo>();
public ConcurrentDictionary<string, TuntapInfo> Infos => tuntapInfos;
private bool starting = false; public TuntapStatus Status => (TuntapStatus)(byte)linkerTunDeviceAdapter.Status;
public TuntapStatus Status => tuntapVea.Running ? TuntapStatus.Running : (starting ? TuntapStatus.Starting : TuntapStatus.Normal);
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.messengerSender = messengerSender;
this.clientSignInState = clientSignInState; this.clientSignInState = clientSignInState;
this.tuntapVea = tuntapVea; this.linkerTunDeviceAdapter = linkerTunDeviceAdapter;
this.config = config; this.config = config;
this.tuntapProxy = tuntapProxy; this.tuntapProxy = tuntapProxy;
this.runningConfig = runningConfig; this.runningConfig = runningConfig;
GetRouteIps(); GetRouteIps();
tuntapVea.Kill();
clientSignInState.NetworkEnabledHandle += (times) => clientSignInState.NetworkEnabledHandle += (times) =>
{ {
OnChange(); OnChange();
@@ -60,14 +58,16 @@ namespace linker.plugins.tuntap
} }
}; };
AppDomain.CurrentDomain.ProcessExit += (s, e) => OnExit(); linkerTunDeviceAdapter.SetCallback(tuntapProxy);
Console.CancelKeyPress += (s, e) => OnExit(); linkerTunDeviceAdapter.Shutdown();
AppDomain.CurrentDomain.ProcessExit += (s, e) => Shutdown();
Console.CancelKeyPress += (s, e) => Shutdown();
} }
/// <summary> /// <summary>
/// 程序关闭 /// 程序关闭
/// </summary> /// </summary>
private void OnExit() private void Shutdown()
{ {
bool running = runningConfig.Data.Tuntap.Running; bool running = runningConfig.Data.Tuntap.Running;
Stop(); Stop();
@@ -80,12 +80,7 @@ namespace linker.plugins.tuntap
/// </summary> /// </summary>
public void Run() public void Run()
{ {
if (BooleanHelper.CompareExchange(ref starting, true, false)) Task.Run(() =>
{
return;
}
Task.Run(async () =>
{ {
OnChange(); OnChange();
try try
@@ -95,18 +90,13 @@ namespace linker.plugins.tuntap
return; return;
} }
tuntapProxy.Start(); linkerTunDeviceAdapter.SetUp(interfaceName, runningConfig.Data.Tuntap.InterfaceGuid, runningConfig.Data.Tuntap.IP, 24);
while (tuntapProxy.LocalEndpoint == null)
{
await Task.Delay(1000).ConfigureAwait(false);
}
bool result = await tuntapVea.Run(tuntapProxy.LocalEndpoint.Port, runningConfig.Data.Tuntap.IP).ConfigureAwait(false);
runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running; runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running;
runningConfig.Data.Update(); runningConfig.Data.Update();
if (result == false)
if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.Error) == false)
{ {
Stop(); LoggerHelper.Instance.Error(linkerTunDeviceAdapter.Error);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -115,7 +105,6 @@ namespace linker.plugins.tuntap
} }
finally finally
{ {
BooleanHelper.CompareExchange(ref starting, false, true);
OnChange(); OnChange();
} }
}); });
@@ -125,15 +114,10 @@ namespace linker.plugins.tuntap
/// </summary> /// </summary>
public void Stop() public void Stop()
{ {
if (BooleanHelper.CompareExchange(ref starting, true, false))
{
return;
}
try try
{ {
tuntapProxy.Stop();
OnChange(); OnChange();
tuntapVea.Kill(); linkerTunDeviceAdapter.Shutdown();
runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running; runningConfig.Data.Tuntap.Running = Status == TuntapStatus.Running;
runningConfig.Data.Update(); runningConfig.Data.Update();
} }
@@ -146,7 +130,6 @@ namespace linker.plugins.tuntap
} }
finally finally
{ {
BooleanHelper.CompareExchange(ref starting, false, true);
OnChange(); OnChange();
} }
} }
@@ -237,7 +220,7 @@ namespace linker.plugins.tuntap
Masks = runningConfig.Data.Tuntap.Masks, Masks = runningConfig.Data.Tuntap.Masks,
MachineId = config.Data.Client.Id, MachineId = config.Data.Client.Id,
Status = Status, Status = Status,
Error = tuntapVea.Error, Error = linkerTunDeviceAdapter.Error,
BufferSize = runningConfig.Data.Tuntap.BufferSize, BufferSize = runningConfig.Data.Tuntap.BufferSize,
HostIP = GetHostIP() HostIP = GetHostIP()
}; };
@@ -279,7 +262,7 @@ namespace linker.plugins.tuntap
{ {
List<TuntapVeaLanIPAddressList> ipsList = ParseIPs(tuntapInfos.Values.ToList()); List<TuntapVeaLanIPAddressList> ipsList = ParseIPs(tuntapInfos.Values.ToList());
TuntapVeaLanIPAddress[] ips = ipsList.SelectMany(c => c.IPS).ToArray(); 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());
} }
/// <summary> /// <summary>
/// 添加路由 /// 添加路由
@@ -288,7 +271,7 @@ namespace linker.plugins.tuntap
{ {
List<TuntapVeaLanIPAddressList> ipsList = ParseIPs(tuntapInfos.Values.ToList()); List<TuntapVeaLanIPAddressList> ipsList = ParseIPs(tuntapInfos.Values.ToList());
TuntapVeaLanIPAddress[] ips = ipsList.SelectMany(c => c.IPS).ToArray(); 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); tuntapProxy.SetIPs(ipsList);
foreach (var item in tuntapInfos.Values) foreach (var item in tuntapInfos.Values)
@@ -345,6 +328,7 @@ namespace linker.plugins.tuntap
MaskValue = maskValue, MaskValue = maskValue,
NetWork = ipInt & maskValue, NetWork = ipInt & maskValue,
Broadcast = ipInt | (~maskValue), Broadcast = ipInt | (~maskValue),
OriginIPAddress = ip,
}; };
} }
@@ -361,9 +345,8 @@ namespace linker.plugins.tuntap
{ {
try try
{ {
if (tuntapVea.Running) if (Status == TuntapStatus.Running)
{ {
await CheckProxy().ConfigureAwait(false);
await Task.Delay(5000).ConfigureAwait(false); await Task.Delay(5000).ConfigureAwait(false);
await CheckInterface().ConfigureAwait(false); await CheckInterface().ConfigureAwait(false);
} }
@@ -377,33 +360,15 @@ namespace linker.plugins.tuntap
} }
private async Task CheckInterface() 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) 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(); Stop();
await Task.Delay(5000).ConfigureAwait(false); await Task.Delay(5000).ConfigureAwait(false);
Run(); 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() private IPAddress GetHostIP()
{ {
string hostip = Environment.GetEnvironmentVariable("SNLTTY_LINKER_HOST_IP"); string hostip = Environment.GetEnvironmentVariable("SNLTTY_LINKER_HOST_IP");

View File

@@ -1,4 +1,5 @@
using linker.plugins.tuntap.config; using linker.plugins.tuntap.config;
using MemoryPack;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Net; using System.Net;
@@ -37,7 +38,66 @@ namespace linker.plugins.tuntap.config
/// 是否在运行中 /// 是否在运行中
/// </summary> /// </summary>
public bool Running { get; set; } public bool Running { get; set; }
public Guid InterfaceGuid { get; set; } = Guid.NewGuid();
} }
[MemoryPackable]
public sealed partial class TuntapVeaLanIPAddress
{
/// <summary>
/// ip存小端
/// </summary>
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<TuntapVeaLanIPAddress> 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<IPAddress>();
public int[] Masks { get; set; } = Array.Empty<int>();
public string Error { get; set; }
public byte BufferSize { get; set; } = 3;
[MemoryPackAllowSerialize]
public IPAddress HostIP { get; set; }
}
} }

View File

@@ -1,6 +1,6 @@
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.signin.messenger; using linker.plugins.signin.messenger;
using linker.plugins.tuntap.vea; using linker.plugins.tuntap.config;
using MemoryPack; using MemoryPack;
namespace linker.plugins.tuntap.messenger namespace linker.plugins.tuntap.messenger

View File

@@ -1,60 +1,48 @@
using linker.client.config; using linker.client.config;
using linker.config; using linker.config;
using linker.plugins.relay; using linker.plugins.relay;
using linker.plugins.tuntap.vea;
using linker.tunnel; using linker.tunnel;
using linker.tunnel.connection; using linker.tunnel.connection;
using linker.tunnel.proxy;
using linker.libs; using linker.libs;
using linker.libs.extends; using linker.libs.extends;
using linker.libs.socks5;
using System.Buffers.Binary;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Net; 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 namespace linker.plugins.tuntap.proxy
{ {
public sealed class TuntapProxy : TunnelProxy public sealed class TuntapProxy : ILinkerTunDeviceCallback, ITunnelConnectionReceiveCallback
{ {
private readonly TunnelTransfer tunnelTransfer; private readonly TunnelTransfer tunnelTransfer;
private readonly RelayTransfer relayTransfer; private readonly RelayTransfer relayTransfer;
private readonly RunningConfig runningConfig; private readonly RunningConfig runningConfig;
private readonly FileConfig config; private readonly FileConfig config;
private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter;
private IPEndPoint proxyEP;
public override IPAddress UdpBindAdress { get; set; }
private uint[] maskValues = Array.Empty<uint>(); private uint[] maskValues = Array.Empty<uint>();
private readonly ConcurrentDictionary<uint, string> dic = new ConcurrentDictionary<uint, string>(); private readonly ConcurrentDictionary<uint, string> ip2MachineCic = new ConcurrentDictionary<uint, string>();
private readonly ConcurrentDictionary<uint, IPAddress> hostipCic = new ConcurrentDictionary<uint, IPAddress>(); private readonly ConcurrentDictionary<uint, IPAddress> hostipCic = new ConcurrentDictionary<uint, IPAddress>();
private readonly ConcurrentDictionary<string, ITunnelConnection> connections = new ConcurrentDictionary<string, ITunnelConnection>(); private readonly ConcurrentDictionary<string, ITunnelConnection> connections = new ConcurrentDictionary<string, ITunnelConnection>();
private readonly ConcurrentDictionary<string, SemaphoreSlim> dicLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
private ConcurrentDictionary<IPEndPoint, BroadcastCacheInfo> broadcastDic = new(new IPEndpointComparer());
public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, FileConfig config) SemaphoreSlim slimGlobal = new SemaphoreSlim(1);
private readonly ConcurrentDictionary<string, SemaphoreSlim> dicLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
public TuntapProxy(TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, RunningConfig runningConfig, FileConfig config, LinkerTunDeviceAdapter linkerTunDeviceAdapter)
{ {
this.tunnelTransfer = tunnelTransfer; this.tunnelTransfer = tunnelTransfer;
this.relayTransfer = relayTransfer; this.relayTransfer = relayTransfer;
this.runningConfig = runningConfig; this.runningConfig = runningConfig;
this.config = config; this.config = config;
this.linkerTunDeviceAdapter = linkerTunDeviceAdapter;
//监听打洞连接成功 //监听打洞连接成功
tunnelTransfer.SetConnectedCallback("tuntap", OnConnected); tunnelTransfer.SetConnectedCallback("tuntap", OnConnected);
//监听中继连接成功 //监听中继连接成功
relayTransfer.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();
} }
/// <summary> /// <summary>
@@ -71,8 +59,51 @@ namespace linker.plugins.tuntap.proxy
//connectionOld?.Dispose(); //connectionOld?.Dispose();
} }
connections.AddOrUpdate(connection.RemoteMachineId, connection, (a, b) => connection); connections.AddOrUpdate(connection.RemoteMachineId, connection, (a, b) => connection);
BindConnectionReceive(connection);
connection.BeginReceive(this, null, false);
} }
public async Task Receive(ITunnelConnection connection, ReadOnlyMemory<byte> 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}");
}
/// <summary> /// <summary>
/// 设置IP等下有连接进来用IP匹配才能知道这个连接是要连谁 /// 设置IP等下有连接进来用IP匹配才能知道这个连接是要连谁
@@ -80,197 +111,25 @@ namespace linker.plugins.tuntap.proxy
/// <param name="ips"></param> /// <param name="ips"></param>
public void SetIPs(List<TuntapVeaLanIPAddressList> ips) public void SetIPs(List<TuntapVeaLanIPAddressList> ips)
{ {
dic.Clear(); ip2MachineCic.Clear();
foreach (var item in ips) foreach (var item in ips)
{ {
foreach (var ip in item.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(); 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) public void SetIP(string machineId, uint ip)
{ {
dic.AddOrUpdate(ip, machineId, (a, b) => machineId); ip2MachineCic.AddOrUpdate(ip, machineId, (a, b) => machineId);
UdpBindAdress = runningConfig.Data.Tuntap.IP;
} }
public void SetHostIP(uint ip, IPAddress hostip) public void SetHostIP(uint ip, IPAddress hostip)
{ {
hostipCic.AddOrUpdate(ip, hostip, (a, b) => hostip); hostipCic.AddOrUpdate(ip, hostip, (a, b) => hostip);
} }
/// <summary>
/// tcp连接隧道
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
protected override async ValueTask<bool> 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<byte> 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;
}
/// <summary>
/// udp连接隧道
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
protected override async ValueTask ConnectTunnelConnection(AsyncUserUdpToken token)
{
ReadOnlyMemory<byte> 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);
}
}
/// <summary>
/// //在docker内我们不应该直接访问自己的虚拟IP而是去访问宿主机的IP
/// </summary>
/// <param name="targetEP"></param>
/// <param name="targetIP"></param>
private void ReplaceTargetIP(IPEndPoint targetEP, uint targetIP)
{
if (hostipCic.TryGetValue(targetIP, out IPAddress hostip) && hostip.Equals(IPAddress.Any) == false)
{
targetEP.Address = hostip;
}
}
/// <summary>
/// udp回复消息自定义处理因为socks5要打包一些格式才能返回
/// </summary>
/// <param name="token"></param>
/// <param name="asyncUserUdpToken"></param>
/// <returns></returns>
protected override async ValueTask<bool> 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);
/// <summary> /// <summary>
/// 打洞或者中继 /// 打洞或者中继
/// </summary> /// </summary>
@@ -279,7 +138,7 @@ namespace linker.plugins.tuntap.proxy
private async ValueTask<ITunnelConnection> ConnectTunnel(uint ip) private async ValueTask<ITunnelConnection> ConnectTunnel(uint ip)
{ {
//直接按IP查找 //直接按IP查找
if (dic.TryGetValue(ip, out string machineId)) if (ip2MachineCic.TryGetValue(ip, out string machineId))
{ {
return await ConnectTunnel(machineId).ConfigureAwait(false); return await ConnectTunnel(machineId).ConfigureAwait(false);
} }
@@ -288,8 +147,9 @@ namespace linker.plugins.tuntap.proxy
for (int i = 0; i < maskValues.Length; i++) for (int i = 0; i < maskValues.Length; i++)
{ {
uint network = ip & maskValues[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); return await ConnectTunnel(machineId).ConfigureAwait(false);
} }
} }
@@ -364,48 +224,6 @@ namespace linker.plugins.tuntap.proxy
return connection; return connection;
} }
/// <summary>
/// 接收socks5完整数据包
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
private async Task<bool> 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;
}
/// <summary>
/// 验证socks5数据包完整性
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
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<string, ITunnelConnection> GetConnections() public ConcurrentDictionary<string, ITunnelConnection> GetConnections()
{ {
return connections; 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<IPEndPoint>
{
public bool Equals(IPEndPoint x, IPEndPoint y)
{
return x.Equals(y);
}
public int GetHashCode(IPEndPoint obj)
{
return obj.GetHashCode();
}
} }
} }

Binary file not shown.

View File

@@ -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<bool> Run(int proxyPort,IPAddress ip);
public Task<bool> SetIp(IPAddress ip);
public void Kill();
public void AddRoute(TuntapVeaLanIPAddress[] ips, IPAddress ip);
public void DelRoute(TuntapVeaLanIPAddress[] ips);
}
[MemoryPackable]
public sealed partial class TuntapVeaLanIPAddress
{
/// <summary>
/// ip存小端
/// </summary>
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<TuntapVeaLanIPAddress> 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<IPAddress>();
public int[] Masks { get; set; } = Array.Empty<int>();
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<Task<IPHostEntry>> HostTasks { get; set; }
[JsonIgnore]
[MemoryPackInclude]
public List<Task<PingReply>> PingTasks { get; set; }
}
}

View File

@@ -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<bool> 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<string>());
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<bool> 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;
}
}
}

View File

@@ -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<bool> 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<string>());
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<bool> 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;
}
}
}

View File

@@ -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<bool> 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<string>());
LoggerHelper.Instance.Error(Error);
}
return interfaceNumber > 0;
}
public async Task<bool> 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<bool> 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<bool> 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<bool> 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;
}
}
}