mirror of
https://github.com/snltty/linker.git
synced 2025-10-30 20:16:53 +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"
|
||||
});
|
||||
|
||||
|
||||
@@ -64,49 +64,60 @@ namespace linker.tun
|
||||
{
|
||||
try
|
||||
{
|
||||
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();
|
||||
}
|
||||
AddIPV4();
|
||||
AddIPV6();
|
||||
break;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
if(i == 4)
|
||||
if (i == 4)
|
||||
{
|
||||
error = ($"Failed to set adapter ip {Marshal.GetLastWin32Error():x2}");
|
||||
Shutdown();
|
||||
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();
|
||||
tokenSource = new CancellationTokenSource();
|
||||
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()
|
||||
{
|
||||
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,41 +78,41 @@ 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)
|
||||
{
|
||||
if (ipConnections.TryGetValue(ip, out ITunnelConnection connection) == false || connection == null || connection.Connected == false)
|
||||
{
|
||||
connection = await ConnectTunnel(ip);
|
||||
if (connection != null)
|
||||
{
|
||||
ipConnections.AddOrUpdate(ip, connection, (a, b) => connection);
|
||||
}
|
||||
}
|
||||
connection = await ConnectTunnel(ip);
|
||||
if (connection != null)
|
||||
{
|
||||
await connection.SendAsync(packet.Packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
ipConnections.AddOrUpdate(ip, connection, (a, b) => connection);
|
||||
}
|
||||
}
|
||||
if (connection != null)
|
||||
{
|
||||
await connection.SendAsync(packet.Packet);
|
||||
}
|
||||
}
|
||||
//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