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; | ||||
|  | ||||
| namespace linker.tun | ||||
| @@ -118,18 +121,6 @@ namespace linker.tun | ||||
|     /// </summary> | ||||
|     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> | ||||
|         /// 带4字节头的包 | ||||
|         /// </summary> | ||||
| @@ -139,21 +130,72 @@ namespace linker.tun | ||||
|         /// </summary> | ||||
|         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) | ||||
|         { | ||||
|             Packet = buffer; | ||||
|             IPPacket = buffer.Slice(4); | ||||
|             Version = (byte)(IPPacket.Span[0] >> 4 & 0b1111); | ||||
|  | ||||
|  | ||||
|             if (Version == 4) | ||||
|             { | ||||
|                 SourceIPAddress = IPPacket.Slice(12, 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) | ||||
|             { | ||||
|                 SourceIPAddress = IPPacket.Slice(8, 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; | ||||
|  | ||||
|             byte[] ipv6 = IPAddress.Parse("fe80::1818:1818:1818:1818").GetAddressBytes(); | ||||
|             address.GetAddressBytes().CopyTo(ipv6, ipv6.Length - 4); | ||||
|  | ||||
|             CommandHelper.Linux(string.Empty, new string[] { | ||||
|                 $"ip tuntap add mode tun dev {Name}", | ||||
|                 $"ip addr del {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" | ||||
|             }); | ||||
|  | ||||
|   | ||||
| @@ -63,6 +63,28 @@ namespace linker.tun | ||||
|             for (int i = 0; i < 5; i++) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     AddIPV4(); | ||||
|                     AddIPV6(); | ||||
|                     break; | ||||
|                 } | ||||
|                 catch (Exception) | ||||
|                 { | ||||
|                     Thread.Sleep(1000); | ||||
|                 } | ||||
|                 if (i == 4) | ||||
|                 { | ||||
|                     error = ($"Failed to set adapter ip {Marshal.GetLastWin32Error():x2}"); | ||||
|                     Shutdown(); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|             GetWindowsInterfaceNum(); | ||||
|             tokenSource = new CancellationTokenSource(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         private void AddIPV4() | ||||
|         { | ||||
|             WinTun.WintunGetAdapterLUID(adapter, out ulong luid); | ||||
|             { | ||||
| @@ -76,37 +98,26 @@ namespace linker.tun | ||||
|                 uint LastError = WinTun.CreateUnicastIpAddressEntry(ref AddressRow); | ||||
|                 if (LastError != 0) throw new InvalidOperationException(); | ||||
|             } | ||||
|                     break; | ||||
|         } | ||||
|                 catch (Exception) | ||||
|         private void AddIPV6() | ||||
|         { | ||||
|                     Thread.Sleep(1000); | ||||
|                 } | ||||
|                 if(i == 4) | ||||
|             NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == Name); | ||||
|             if (networkInterface != null) | ||||
|             { | ||||
|                     error = ($"Failed to set adapter ip {Marshal.GetLastWin32Error():x2}"); | ||||
|                     Shutdown(); | ||||
|                     return false; | ||||
|                 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]); | ||||
|             } | ||||
|         } | ||||
|             /* | ||||
|             { | ||||
|                 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(); | ||||
|             tokenSource = new CancellationTokenSource(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public void Shutdown() | ||||
|         { | ||||
|             tokenSource?.Cancel(); | ||||
| @@ -341,3 +352,5 @@ namespace linker.tun | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ namespace linker.tun | ||||
|     internal static class WinTun | ||||
|     { | ||||
|         | ||||
|  | ||||
|         [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 80)] | ||||
|         internal struct MIB_UNICASTIPADDRESS_ROW | ||||
|         { | ||||
| @@ -20,6 +21,7 @@ namespace linker.tun | ||||
|             public int DadState; | ||||
|         } | ||||
|         | ||||
|  | ||||
|         [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 104)] | ||||
|         internal struct MIB_IPFORWARD_ROW2 | ||||
|         { | ||||
| @@ -43,6 +45,7 @@ namespace linker.tun | ||||
|         [DllImport("iphlpapi.dll", SetLastError = true)] | ||||
|         internal static extern uint CreateUnicastIpAddressEntry(ref MIB_UNICASTIPADDRESS_ROW Row); | ||||
|  | ||||
|  | ||||
|         [DllImport("iphlpapi.dll", SetLastError = true)] | ||||
|         internal static extern void InitializeIpForwardEntry(ref MIB_IPFORWARD_ROW2 Row); | ||||
|  | ||||
|   | ||||
| @@ -82,7 +82,7 @@ export default { | ||||
|  | ||||
|         const tuntap = useTuntap(); | ||||
|         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 fn = tuntap.running ? stopTuntap (tuntap.MachineId) : runTuntap(tuntap.MachineId); | ||||
|             tuntap.loading = true; | ||||
|   | ||||
| @@ -78,18 +78,20 @@ namespace linker.plugins.tuntap.proxy | ||||
|  | ||||
|         public async Task Callback(LinkerTunDevicPacket packet) | ||||
|         { | ||||
|             //IPV4 | ||||
|             if (packet.Version == 4) | ||||
|             { | ||||
|                 uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DistIPAddress.Span); | ||||
|                 // 广播组播 | ||||
|                 if (packet.DistIPAddress.GetIsBroadcastAddress()) | ||||
|                 { | ||||
|                     if (connections.IsEmpty == false) | ||||
|                     { | ||||
|                         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) | ||||
|                 { | ||||
|                     connection = await ConnectTunnel(ip); | ||||
| @@ -102,17 +104,15 @@ namespace linker.plugins.tuntap.proxy | ||||
|                 { | ||||
|                     await connection.SendAsync(packet.Packet); | ||||
|                 } | ||||
|                     else | ||||
|                     { | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             //IPV6 多播 | ||||
|             else if (packet.Version == 6 && (packet.DistIPAddress.Span[0] & 0xFF) == 0xFF) | ||||
|             { | ||||
|                 if (connections.IsEmpty == false) | ||||
|                 { | ||||
|                     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