mirror of
https://github.com/snltty/linker.git
synced 2025-11-01 21:13:04 +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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,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
|
||||||
{
|
{
|
||||||
@@ -20,6 +21,7 @@ namespace linker.tun
|
|||||||
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