mirror of
				https://github.com/snltty/linker.git
				synced 2025-10-31 12:36:48 +08:00 
			
		
		
		
	sync
This commit is contained in:
		| @@ -1,4 +1,7 @@ | |||||||
| using System.Net; | using linker.libs.extends; | ||||||
|  | using System.Buffers.Binary; | ||||||
|  | using System.Net; | ||||||
|  | using System.Net.Sockets; | ||||||
| using System.Text.Json.Serialization; | using System.Text.Json.Serialization; | ||||||
|  |  | ||||||
| namespace linker.tun | namespace linker.tun | ||||||
| @@ -118,18 +121,6 @@ namespace linker.tun | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public struct LinkerTunDevicPacket |     public struct LinkerTunDevicPacket | ||||||
|     { |     { | ||||||
|         /// <summary> |  | ||||||
|         /// 协议版本,4或者6 |  | ||||||
|         /// </summary> |  | ||||||
|         public byte Version; |  | ||||||
|         /// <summary> |  | ||||||
|         /// 源IP |  | ||||||
|         /// </summary> |  | ||||||
|         public ReadOnlyMemory<byte> SourceIPAddress; |  | ||||||
|         /// <summary> |  | ||||||
|         /// 目标IP |  | ||||||
|         /// </summary> |  | ||||||
|         public ReadOnlyMemory<byte> DistIPAddress; |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// 带4字节头的包 |         /// 带4字节头的包 | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -139,21 +130,72 @@ namespace linker.tun | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public ReadOnlyMemory<byte> IPPacket; |         public ReadOnlyMemory<byte> IPPacket; | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 协议版本,4或者6 | ||||||
|  |         /// </summary> | ||||||
|  |         public byte Version; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 协议 | ||||||
|  |         /// </summary> | ||||||
|  |         public ProtocolType ProtocolType; | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 源IP | ||||||
|  |         /// </summary> | ||||||
|  |         public ReadOnlyMemory<byte> SourceIPAddress; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 源端口 | ||||||
|  |         /// </summary> | ||||||
|  |         public ushort SourcePort; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 源 | ||||||
|  |         /// </summary> | ||||||
|  |         public readonly IPEndPoint Source => new IPEndPoint(new IPAddress(SourceIPAddress.Span), SourcePort); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// 目标IP | ||||||
|  |         /// </summary> | ||||||
|  |         public ReadOnlyMemory<byte> DistIPAddress; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 目标端口 | ||||||
|  |         /// </summary> | ||||||
|  |         public ushort DistPort; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 目标 | ||||||
|  |         /// </summary> | ||||||
|  |         public readonly IPEndPoint Dist => new IPEndPoint(new IPAddress(DistIPAddress.Span), DistPort); | ||||||
|  |  | ||||||
|         public void Unpacket(ReadOnlyMemory<byte> buffer) |         public void Unpacket(ReadOnlyMemory<byte> buffer) | ||||||
|         { |         { | ||||||
|             Packet = buffer; |             Packet = buffer; | ||||||
|             IPPacket = buffer.Slice(4); |             IPPacket = buffer.Slice(4); | ||||||
|             Version = (byte)(IPPacket.Span[0] >> 4 & 0b1111); |             Version = (byte)(IPPacket.Span[0] >> 4 & 0b1111); | ||||||
|  |  | ||||||
|  |  | ||||||
|             if (Version == 4) |             if (Version == 4) | ||||||
|             { |             { | ||||||
|                 SourceIPAddress = IPPacket.Slice(12, 4); |                 SourceIPAddress = IPPacket.Slice(12, 4); | ||||||
|                 DistIPAddress = IPPacket.Slice(16, 4); |                 DistIPAddress = IPPacket.Slice(16, 4); | ||||||
|  |  | ||||||
|  |                 ProtocolType = (ProtocolType)IPPacket.Span[9]; | ||||||
|  |                 if (ProtocolType == ProtocolType.Tcp || ProtocolType == ProtocolType.Udp) | ||||||
|  |                 { | ||||||
|  |                     SourcePort = BinaryPrimitives.ReverseEndianness(IPPacket.Slice(20, 2).ToUInt16()); | ||||||
|  |                     DistPort = BinaryPrimitives.ReverseEndianness(IPPacket.Slice(22, 2).ToUInt16()); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             else if (Version == 6) |             else if (Version == 6) | ||||||
|             { |             { | ||||||
|                 SourceIPAddress = IPPacket.Slice(8, 16); |                 SourceIPAddress = IPPacket.Slice(8, 16); | ||||||
|                 DistIPAddress = IPPacket.Slice(24, 16); |                 DistIPAddress = IPPacket.Slice(24, 16); | ||||||
|  |  | ||||||
|  |                 ProtocolType = (ProtocolType)IPPacket.Span[6]; | ||||||
|  |  | ||||||
|  |                 if (ProtocolType == ProtocolType.Tcp || ProtocolType == ProtocolType.Udp) | ||||||
|  |                 { | ||||||
|  |                     SourcePort = BinaryPrimitives.ReverseEndianness(IPPacket.Slice(42, 2).ToUInt16()); | ||||||
|  |                     DistPort = BinaryPrimitives.ReverseEndianness(IPPacket.Slice(24, 2).ToUInt16()); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -53,10 +53,13 @@ namespace linker.tun | |||||||
|         { |         { | ||||||
|             error = string.Empty; |             error = string.Empty; | ||||||
|  |  | ||||||
|  |             byte[] ipv6 = IPAddress.Parse("fe80::1818:1818:1818:1818").GetAddressBytes(); | ||||||
|  |             address.GetAddressBytes().CopyTo(ipv6, ipv6.Length - 4); | ||||||
|  |  | ||||||
|             CommandHelper.Linux(string.Empty, new string[] { |             CommandHelper.Linux(string.Empty, new string[] { | ||||||
|                 $"ip tuntap add mode tun dev {Name}", |                 $"ip tuntap add mode tun dev {Name}", | ||||||
|                 $"ip addr del {address}/{prefixLength} dev {Name}", |  | ||||||
|                 $"ip addr add {address}/{prefixLength} dev {Name}", |                 $"ip addr add {address}/{prefixLength} dev {Name}", | ||||||
|  |                 $"ip addr add {new IPAddress(ipv6)}/64 dev {Name}", | ||||||
|                 $"ip link set dev {Name} up" |                 $"ip link set dev {Name} up" | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -64,49 +64,60 @@ namespace linker.tun | |||||||
|             { |             { | ||||||
|                 try |                 try | ||||||
|                 { |                 { | ||||||
|                     WinTun.WintunGetAdapterLUID(adapter, out ulong luid); |                     AddIPV4(); | ||||||
|                     { |                     AddIPV6(); | ||||||
|                         WinTun.MIB_UNICASTIPADDRESS_ROW AddressRow = default; |  | ||||||
|                         WinTun.InitializeUnicastIpAddressEntry(ref AddressRow); |  | ||||||
|                         AddressRow.sin_family = 2; |  | ||||||
|                         AddressRow.sin_addr = BinaryPrimitives.ReadUInt32LittleEndian(address.GetAddressBytes()); |  | ||||||
|                         AddressRow.OnLinkPrefixLength = prefixLength; |  | ||||||
|                         AddressRow.DadState = 4; |  | ||||||
|                         AddressRow.InterfaceLuid = luid; |  | ||||||
|                         uint LastError = WinTun.CreateUnicastIpAddressEntry(ref AddressRow); |  | ||||||
|                         if (LastError != 0) throw new InvalidOperationException(); |  | ||||||
|                     } |  | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 catch (Exception) |                 catch (Exception) | ||||||
|                 { |                 { | ||||||
|                     Thread.Sleep(1000); |                     Thread.Sleep(1000); | ||||||
|                 } |                 } | ||||||
|                 if(i == 4) |                 if (i == 4) | ||||||
|                 { |                 { | ||||||
|                     error = ($"Failed to set adapter ip {Marshal.GetLastWin32Error():x2}"); |                     error = ($"Failed to set adapter ip {Marshal.GetLastWin32Error():x2}"); | ||||||
|                     Shutdown(); |                     Shutdown(); | ||||||
|                     return false; |                     return false; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             /* |  | ||||||
|             { |  | ||||||
|                 MIB_IPFORWARD_ROW2 row = default; |  | ||||||
|                 InitializeIpForwardEntry(ref row); |  | ||||||
|                 row.InterfaceLuid = luid; |  | ||||||
|                 row.PrefixLength = 0; |  | ||||||
|                 row.si_family = 2; |  | ||||||
|                 row.NextHop_si_family = 2; |  | ||||||
|                 row.sin_addr = 0; |  | ||||||
|                 row.NextHop_sin_addr = BinaryPrimitives.ReadUInt32LittleEndian(gateway.GetAddressBytes()); |  | ||||||
|                 uint LastError = CreateIpForwardEntry2(ref row); |  | ||||||
|                 if (LastError != 0) throw new InvalidOperationException(); |  | ||||||
|             } |  | ||||||
|             */ |  | ||||||
|             GetWindowsInterfaceNum(); |             GetWindowsInterfaceNum(); | ||||||
|             tokenSource = new CancellationTokenSource(); |             tokenSource = new CancellationTokenSource(); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         private void AddIPV4() | ||||||
|  |         { | ||||||
|  |             WinTun.WintunGetAdapterLUID(adapter, out ulong luid); | ||||||
|  |             { | ||||||
|  |                 WinTun.MIB_UNICASTIPADDRESS_ROW AddressRow = default; | ||||||
|  |                 WinTun.InitializeUnicastIpAddressEntry(ref AddressRow); | ||||||
|  |                 AddressRow.sin_family = 2; | ||||||
|  |                 AddressRow.sin_addr = BinaryPrimitives.ReadUInt32LittleEndian(address.GetAddressBytes()); | ||||||
|  |                 AddressRow.OnLinkPrefixLength = prefixLength; | ||||||
|  |                 AddressRow.DadState = 4; | ||||||
|  |                 AddressRow.InterfaceLuid = luid; | ||||||
|  |                 uint LastError = WinTun.CreateUnicastIpAddressEntry(ref AddressRow); | ||||||
|  |                 if (LastError != 0) throw new InvalidOperationException(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         private void AddIPV6() | ||||||
|  |         { | ||||||
|  |             NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == Name); | ||||||
|  |             if (networkInterface != null) | ||||||
|  |             { | ||||||
|  |                 var commands = networkInterface.GetIPProperties() | ||||||
|  |                     .UnicastAddresses | ||||||
|  |                     .Where(c => c.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) | ||||||
|  |                     .Select(c => new IPAddress(c.Address.GetAddressBytes(), 0)) | ||||||
|  |                     .Select(c => $"netsh interface ipv6 delete address \"{Name}\" address=\"{c}\"").ToList(); | ||||||
|  |  | ||||||
|  |                 byte[] ipv6 = IPAddress.Parse("fe80::1818:1818:1818:1818").GetAddressBytes(); | ||||||
|  |                 address.GetAddressBytes().CopyTo(ipv6, ipv6.Length - 4); | ||||||
|  |                 commands.Add($"netsh interface ipv6 add address \"{Name}\" address=\"{new IPAddress(ipv6)}\""); | ||||||
|  |                 CommandHelper.Windows(string.Empty, [.. commands]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         public void Shutdown() |         public void Shutdown() | ||||||
|         { |         { | ||||||
|             tokenSource?.Cancel(); |             tokenSource?.Cancel(); | ||||||
| @@ -341,3 +352,5 @@ namespace linker.tun | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ namespace linker.tun | |||||||
| { | { | ||||||
|     internal static class WinTun |     internal static class WinTun | ||||||
|     { |     { | ||||||
|  |         | ||||||
|  |  | ||||||
|         [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 80)] |         [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 80)] | ||||||
|         internal struct MIB_UNICASTIPADDRESS_ROW |         internal struct MIB_UNICASTIPADDRESS_ROW | ||||||
| @@ -19,6 +20,7 @@ namespace linker.tun | |||||||
|             [FieldOffset(64)] |             [FieldOffset(64)] | ||||||
|             public int DadState; |             public int DadState; | ||||||
|         } |         } | ||||||
|  |         | ||||||
|  |  | ||||||
|         [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 104)] |         [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 104)] | ||||||
|         internal struct MIB_IPFORWARD_ROW2 |         internal struct MIB_IPFORWARD_ROW2 | ||||||
| @@ -43,6 +45,7 @@ namespace linker.tun | |||||||
|         [DllImport("iphlpapi.dll", SetLastError = true)] |         [DllImport("iphlpapi.dll", SetLastError = true)] | ||||||
|         internal static extern uint CreateUnicastIpAddressEntry(ref MIB_UNICASTIPADDRESS_ROW Row); |         internal static extern uint CreateUnicastIpAddressEntry(ref MIB_UNICASTIPADDRESS_ROW Row); | ||||||
|  |  | ||||||
|  |  | ||||||
|         [DllImport("iphlpapi.dll", SetLastError = true)] |         [DllImport("iphlpapi.dll", SetLastError = true)] | ||||||
|         internal static extern void InitializeIpForwardEntry(ref MIB_IPFORWARD_ROW2 Row); |         internal static extern void InitializeIpForwardEntry(ref MIB_IPFORWARD_ROW2 Row); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ export default { | |||||||
|  |  | ||||||
|         const tuntap = useTuntap(); |         const tuntap = useTuntap(); | ||||||
|         const globalData = injectGlobalData(); |         const globalData = injectGlobalData(); | ||||||
|         const showDelay = computed(()=>(globalData.value.config.Running.Tuntap.Switch & 2) == 2); |         const showDelay = computed(()=>((globalData.value.config.Running.Tuntap || {Switch:0}).Switch & 2) == 2); | ||||||
|         const handleTuntap = (tuntap) => { |         const handleTuntap = (tuntap) => { | ||||||
|             const fn = tuntap.running ? stopTuntap (tuntap.MachineId) : runTuntap(tuntap.MachineId); |             const fn = tuntap.running ? stopTuntap (tuntap.MachineId) : runTuntap(tuntap.MachineId); | ||||||
|             tuntap.loading = true; |             tuntap.loading = true; | ||||||
|   | |||||||
| @@ -78,41 +78,41 @@ namespace linker.plugins.tuntap.proxy | |||||||
|  |  | ||||||
|         public async Task Callback(LinkerTunDevicPacket packet) |         public async Task Callback(LinkerTunDevicPacket packet) | ||||||
|         { |         { | ||||||
|  |             //IPV4 | ||||||
|             if (packet.Version == 4) |             if (packet.Version == 4) | ||||||
|             { |             { | ||||||
|                 uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DistIPAddress.Span); |                 // 广播组播 | ||||||
|                 if (packet.DistIPAddress.GetIsBroadcastAddress()) |                 if (packet.DistIPAddress.GetIsBroadcastAddress()) | ||||||
|                 { |                 { | ||||||
|                     if (connections.IsEmpty == false) |                     if (connections.IsEmpty == false) | ||||||
|                     { |                     { | ||||||
|                         await Task.WhenAll(connections.Values.Where(c => c != null && c.Connected).Select(c => c.SendAsync(packet.Packet))); |                         await Task.WhenAll(connections.Values.Where(c => c != null && c.Connected).Select(c => c.SendAsync(packet.Packet))); | ||||||
|                     } |                     } | ||||||
|  |                     return; | ||||||
|                 } |                 } | ||||||
|                 else |  | ||||||
|  |                 uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DistIPAddress.Span); | ||||||
|  |                 if (ipConnections.TryGetValue(ip, out ITunnelConnection connection) == false || connection == null || connection.Connected == false) | ||||||
|                 { |                 { | ||||||
|                     if (ipConnections.TryGetValue(ip, out ITunnelConnection connection) == false || connection == null || connection.Connected == false) |                     connection = await ConnectTunnel(ip); | ||||||
|                     { |  | ||||||
|                         connection = await ConnectTunnel(ip); |  | ||||||
|                         if (connection != null) |  | ||||||
|                         { |  | ||||||
|                             ipConnections.AddOrUpdate(ip, connection, (a, b) => connection); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     if (connection != null) |                     if (connection != null) | ||||||
|                     { |                     { | ||||||
|                         await connection.SendAsync(packet.Packet); |                         ipConnections.AddOrUpdate(ip, connection, (a, b) => connection); | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 if (connection != null) | ||||||
|  |                 { | ||||||
|  |                     await connection.SendAsync(packet.Packet); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |             //IPV6 多播 | ||||||
|             else if (packet.Version == 6 && (packet.DistIPAddress.Span[0] & 0xFF) == 0xFF) |             else if (packet.Version == 6 && (packet.DistIPAddress.Span[0] & 0xFF) == 0xFF) | ||||||
|             { |             { | ||||||
|                 if (connections.IsEmpty == false) |                 if (connections.IsEmpty == false) | ||||||
|                 { |                 { | ||||||
|                     await Task.WhenAll(connections.Values.Where(c => c != null && c.Connected).Select(c => c.SendAsync(packet.Packet))); |                     await Task.WhenAll(connections.Values.Where(c => c != null && c.Connected).Select(c => c.SendAsync(packet.Packet))); | ||||||
|                 } |                 } | ||||||
|  |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 snltty
					snltty