mirror of
https://github.com/snltty/linker.git
synced 2025-09-27 13:32:14 +08:00
池化
This commit is contained in:
1
src/linker.app/public/web/css/802.c74979de.css
Normal file
1
src/linker.app/public/web/css/802.c74979de.css
Normal file
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.e9b4f2f4.js"></script><script defer="defer" src="js/app.f1b9356d.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.e16885f2.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.e9b4f2f4.js"></script><script defer="defer" src="js/app.166579fa.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.e16885f2.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
1
src/linker.app/public/web/js/331.65eaa49b.js
Normal file
1
src/linker.app/public/web/js/331.65eaa49b.js
Normal file
File diff suppressed because one or more lines are too long
1
src/linker.app/public/web/js/802.f63dc734.js
Normal file
1
src/linker.app/public/web/js/802.f63dc734.js
Normal file
File diff suppressed because one or more lines are too long
1
src/linker.app/public/web/js/app.166579fa.js
Normal file
1
src/linker.app/public/web/js/app.166579fa.js
Normal file
File diff suppressed because one or more lines are too long
@@ -11,37 +11,42 @@ namespace linker.libs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="packet">一个完整的IP包</param>
|
/// <param name="packet">一个完整的IP包</param>
|
||||||
/// <param name="payload">是否计算荷载协议校验和</param>
|
/// <param name="payload">是否计算荷载协议校验和</param>
|
||||||
public static unsafe void Checksum(ReadOnlyMemory<byte> packet,bool payload = true)
|
public static unsafe void Checksum(ReadOnlyMemory<byte> packet, bool ipHeader = true, bool payload = true)
|
||||||
{
|
{
|
||||||
fixed (byte* ptr = packet.Span)
|
Checksum(packet.Span, ipHeader, payload);
|
||||||
{
|
|
||||||
Checksum(ptr, packet.Length, payload);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计算IP包的校验和
|
/// 计算IP包的校验和
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="packet">一个完整的IP包</param>
|
/// <param name="packet">一个完整的IP包</param>
|
||||||
/// <param name="payload">是否计算荷载协议校验和</param>
|
/// <param name="payload">是否计算荷载协议校验和</param>
|
||||||
public static unsafe void Checksum(ReadOnlySpan<byte> packet, bool payload = true)
|
public static unsafe void Checksum(ReadOnlySpan<byte> packet, bool ipHeader = true, bool payload = true)
|
||||||
{
|
{
|
||||||
fixed (byte* ptr = packet)
|
fixed (byte* ptr = packet)
|
||||||
{
|
{
|
||||||
Checksum(ptr, packet.Length, payload);
|
Checksum(ptr, ipHeader, payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计算IP包的校验和
|
/// 计算IP包的校验和
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ptr">IP包指针</param>
|
/// <param name="ptr">IP包指针</param>
|
||||||
/// <param name="length">IP包长度</param>
|
/// <param name="ipHeader">是否计算IP校验和</param>
|
||||||
/// <param name="payload">是否计算荷载协议校验和</param>
|
/// <param name="payload">是否计算荷载协议校验和</param>
|
||||||
public static unsafe void Checksum(byte* ptr, int length, bool payload = true)
|
public static unsafe void Checksum(byte* ptr, bool ipHeader = true, bool payload = true)
|
||||||
{
|
{
|
||||||
byte ipHeaderLength = (byte)((*ptr & 0b1111) * 4);
|
byte ipHeaderLength = (byte)((*ptr & 0b1111) * 4);
|
||||||
|
byte* packetPtr = ptr + ipHeaderLength;
|
||||||
|
uint totalLength = BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + 2));
|
||||||
|
uint packetLength = totalLength - ipHeaderLength;
|
||||||
|
|
||||||
|
if (ipHeader)
|
||||||
|
{
|
||||||
//重新计算IP头校验和
|
//重新计算IP头校验和
|
||||||
*(ushort*)(ptr + 10) = 0;
|
*(ushort*)(ptr + 10) = 0;
|
||||||
*(ushort*)(ptr + 10) = Checksum((ushort*)ptr, ipHeaderLength);
|
*(ushort*)(ptr + 10) = Checksum((ushort*)ptr, ipHeaderLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (payload)
|
if (payload)
|
||||||
{
|
{
|
||||||
@@ -50,22 +55,22 @@ namespace linker.libs
|
|||||||
{
|
{
|
||||||
case ProtocolType.Tcp:
|
case ProtocolType.Tcp:
|
||||||
{
|
{
|
||||||
*(ushort*)(ptr + ipHeaderLength + 16) = 0;
|
*(ushort*)(packetPtr + 16) = 0;
|
||||||
ulong sum = PseudoHeaderSum(ptr, (uint)(length - ipHeaderLength));
|
ulong sum = PseudoHeaderSum(ptr, packetLength);
|
||||||
*(ushort*)(ptr + ipHeaderLength + 16) = Checksum((ushort*)(ptr + ipHeaderLength), (uint)length - ipHeaderLength, sum);
|
*(ushort*)(packetPtr + 16) = Checksum((ushort*)(packetPtr), packetLength, sum);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProtocolType.Udp:
|
case ProtocolType.Udp:
|
||||||
{
|
{
|
||||||
*(ushort*)(ptr + ipHeaderLength + 6) = 0;
|
*(ushort*)(packetPtr + 6) = 0;
|
||||||
ulong sum = PseudoHeaderSum(ptr, (uint)(length - ipHeaderLength));
|
ulong sum = PseudoHeaderSum(ptr, packetLength);
|
||||||
*(ushort*)(ptr + ipHeaderLength + 6) = Checksum((ushort*)(ptr + ipHeaderLength), (uint)length - ipHeaderLength, sum);
|
*(ushort*)(packetPtr + 6) = Checksum((ushort*)(packetPtr), packetLength, sum);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ProtocolType.Icmp:
|
case ProtocolType.Icmp:
|
||||||
{
|
{
|
||||||
*(ushort*)(ptr + ipHeaderLength + 2) = 0;
|
*(ushort*)(packetPtr + 2) = 0;
|
||||||
*(ushort*)(ptr + ipHeaderLength + 2) = Checksum((ushort*)(ptr + ipHeaderLength), (uint)length - ipHeaderLength);
|
*(ushort*)(packetPtr + 2) = Checksum((ushort*)(packetPtr), packetLength);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,6 @@ using linker.messenger.relay.client;
|
|||||||
using linker.messenger.signin;
|
using linker.messenger.signin;
|
||||||
using linker.messenger.pcp;
|
using linker.messenger.pcp;
|
||||||
using linker.messenger.tuntap.cidr;
|
using linker.messenger.tuntap.cidr;
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
namespace linker.messenger.tuntap
|
namespace linker.messenger.tuntap
|
||||||
{
|
{
|
||||||
@@ -45,11 +44,12 @@ namespace linker.messenger.tuntap
|
|||||||
|
|
||||||
protected override void Connected(ITunnelConnection connection)
|
protected override void Connected(ITunnelConnection connection)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (connection.ProtocolType == TunnelProtocolType.Tcp && tuntapConfigTransfer.Info.FakeAck && tuntapDecenter.HasSwitchFlag(connection.RemoteMachineId, TuntapSwitch.FakeAck))
|
if (connection.ProtocolType == TunnelProtocolType.Tcp && tuntapConfigTransfer.Info.FakeAck && tuntapDecenter.HasSwitchFlag(connection.RemoteMachineId, TuntapSwitch.FakeAck))
|
||||||
{
|
{
|
||||||
connection.PacketBuffer = new byte[4096];
|
connection.PacketBuffer = new byte[1];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
Add(connection);
|
Add(connection);
|
||||||
connection.BeginReceive(this, null);
|
connection.BeginReceive(this, null);
|
||||||
//有哪些目标IP用了相同目标隧道,更新一下
|
//有哪些目标IP用了相同目标隧道,更新一下
|
||||||
@@ -67,7 +67,7 @@ namespace linker.messenger.tuntap
|
|||||||
public async Task Receive(ITunnelConnection connection, ReadOnlyMemory<byte> buffer, object state)
|
public async Task Receive(ITunnelConnection connection, ReadOnlyMemory<byte> buffer, object state)
|
||||||
#pragma warning restore CS1998 // 异步方法缺少 "await" 运算符,将以同步方式运行
|
#pragma warning restore CS1998 // 异步方法缺少 "await" 运算符,将以同步方式运行
|
||||||
{
|
{
|
||||||
if (connection.PacketBuffer.Length > 0) fakeAckTransfer.Write(buffer);
|
//if (connection.PacketBuffer.Length > 0) fakeAckTransfer.Write(buffer, connection.SendBufferFree);
|
||||||
Callback.Receive(connection, buffer);
|
Callback.Receive(connection, buffer);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -101,14 +101,23 @@ namespace linker.messenger.tuntap
|
|||||||
|
|
||||||
//IPV4+IPV6 单播
|
//IPV4+IPV6 单播
|
||||||
uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DistIPAddress.Span[^4..]);
|
uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DistIPAddress.Span[^4..]);
|
||||||
if (tuntapCidrConnectionManager.TryGet(ip, out ITunnelConnection connection) == false || connection == null || connection.Connected == false)
|
if (tuntapCidrConnectionManager.TryGet(ip, out ITunnelConnection connection) && connection.Connected)
|
||||||
{
|
{
|
||||||
|
await connection.SendAsync(packet.Buffer, packet.Offset, packet.Length).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (connection.PacketBuffer.Length > 0)
|
||||||
|
{
|
||||||
|
fakeAckTransfer.Read(packet.IPPacket);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//开始操作,开始失败直接丢包
|
//开始操作,开始失败直接丢包
|
||||||
if (operatingMultipleManager.StartOperation(ip) == false)
|
if (operatingMultipleManager.StartOperation(ip) == false)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = ConnectTunnel(ip).ContinueWith((result, state) =>
|
_ = ConnectTunnel(ip).ContinueWith((result, state) =>
|
||||||
{
|
{
|
||||||
//结束操作
|
//结束操作
|
||||||
@@ -119,13 +128,6 @@ namespace linker.messenger.tuntap
|
|||||||
tuntapCidrConnectionManager.Add((uint)state, result.Result);
|
tuntapCidrConnectionManager.Add((uint)state, result.Result);
|
||||||
}
|
}
|
||||||
}, ip);
|
}, ip);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ushort ackLength = 0;
|
|
||||||
if (connection.PacketBuffer.Length > 0 && fakeAckTransfer.Read(packet.IPPacket, connection.PacketBuffer, connection.SendBufferFree, out ackLength)) return;
|
|
||||||
await connection.SendAsync(packet.Buffer, packet.Offset, packet.Length).ConfigureAwait(false);
|
|
||||||
if (ackLength > 0) Callback.Receive(connection, connection.PacketBuffer.AsMemory(0, ackLength));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.extends;
|
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
@@ -126,7 +126,7 @@ namespace linker.snat
|
|||||||
if (checksum)
|
if (checksum)
|
||||||
{
|
{
|
||||||
//计算校验和
|
//计算校验和
|
||||||
ChecksumHelper.Checksum(ptr, packet.Length);
|
ChecksumHelper.Checksum(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -83,7 +83,7 @@ namespace linker.tun
|
|||||||
//response
|
//response
|
||||||
*(ushort*)(ptr + 20) = 0;
|
*(ushort*)(ptr + 20) = 0;
|
||||||
|
|
||||||
ChecksumHelper.Checksum(ptr, writableMemory.Length);
|
ChecksumHelper.Checksum(ptr);
|
||||||
Program.linkerTunDeviceAdapter.Write(string.Empty, writableMemory);
|
Program.linkerTunDeviceAdapter.Write(string.Empty, writableMemory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
||||||
namespace linker.tun
|
namespace linker.tun
|
||||||
@@ -11,60 +10,35 @@ namespace linker.tun
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe sealed class FakeAckTransfer
|
public unsafe sealed class FakeAckTransfer
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<FaceAckKey, FackAckState> dic = new(new FackAckKeyComparer());
|
private readonly ConcurrentDictionary<FaceAckKey, int> dic = new(new FackAckKeyComparer());
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发起方
|
/// 发起方
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="packet">一个完整的TCP/IP包</param>
|
/// <param name="packet">一个完整的TCP/IP包</param>
|
||||||
/// <param name="fakeBuffer">一个能容纳ACK包的缓冲区,如果需要伪造ACK则写入到这里</param>
|
/// <returns></returns>
|
||||||
/// <param name="bufferFree">缓冲区可用字节数,会根据这个来计算ack的窗口大小</param>
|
public void Read(ReadOnlyMemory<byte> packet)
|
||||||
/// <param name="fakeLength">ack包长度</param>
|
|
||||||
/// <returns>是否丢包</returns>
|
|
||||||
public bool Read(ReadOnlyMemory<byte> packet, ReadOnlyMemory<byte> fakeBuffer, long bufferFree, out ushort fakeLength)
|
|
||||||
{
|
{
|
||||||
fakeLength = 0;
|
|
||||||
|
|
||||||
fixed (byte* ptr = packet.Span)
|
fixed (byte* ptr = packet.Span)
|
||||||
{
|
{
|
||||||
FakeAckPacket originPacket = new(ptr);
|
FakeAckPacket originPacket = new(ptr);
|
||||||
if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
|
if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
|
||||||
{
|
{
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
|
||||||
|
{
|
||||||
FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
|
FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
|
||||||
|
|
||||||
if ((originPacket.IsOnlyAck || originPacket.IsPshAck) && dic.TryGetValue(key, out FackAckState state))
|
|
||||||
{
|
|
||||||
if (originPacket.TcpPayloadLength == 0)
|
|
||||||
{
|
|
||||||
return state.Ack++ > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fixed (byte* pptr = fakeBuffer.Span)
|
|
||||||
{
|
|
||||||
ushort win = (ushort)Math.Max(Math.Min(bufferFree*0.8 / state.WindowScale, 32*1024), 4);
|
|
||||||
fakeLength = originPacket.ToAck(state.Seq, win, pptr);
|
|
||||||
if (new FakeAckPacket(pptr).Cq <= state.Cq)
|
|
||||||
{
|
|
||||||
fakeLength = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
|
|
||||||
{
|
|
||||||
dic.TryRemove(key, out _);
|
dic.TryRemove(key, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 接收方
|
/// 接收方
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="packet">一个完整的TCP/IP包</param>
|
/// <param name="packet">一个完整的TCP/IP包</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void Write(ReadOnlyMemory<byte> packet)
|
public void Write(ReadOnlyMemory<byte> packet, long bufferFree)
|
||||||
{
|
{
|
||||||
fixed (byte* ptr = packet.Span)
|
fixed (byte* ptr = packet.Span)
|
||||||
{
|
{
|
||||||
@@ -75,27 +49,20 @@ namespace linker.tun
|
|||||||
}
|
}
|
||||||
FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
|
FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
|
||||||
|
|
||||||
/*
|
if (originPacket.IsPshAck || originPacket.IsOnlyAck)
|
||||||
//更新序列号
|
|
||||||
if (originPacket.TcpFlagAck && dic.TryGetValue(key, out FackAckState state))
|
|
||||||
{
|
{
|
||||||
state.Cq = originPacket.Cq;
|
|
||||||
|
|
||||||
if (originPacket.TcpPayloadLength > 0)
|
if (dic.TryGetValue(key, out int wins) && originPacket.Window > 0)
|
||||||
{
|
{
|
||||||
state.Seq = originPacket.Seq + (uint)originPacket.TcpPayloadLength;
|
ushort win = (ushort)Math.Max(Math.Min(bufferFree / wins, 65535), 4);
|
||||||
|
originPacket.WriteWindow(ptr, win);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else*/
|
else if (originPacket.IsOnlySyn || originPacket.IsSynAck)
|
||||||
if (originPacket.IsOnlySyn || originPacket.IsSynAck)
|
|
||||||
{
|
{
|
||||||
FackAckState state = new()
|
int windowScale = originPacket.FindWindowScale(ptr);
|
||||||
{
|
dic.AddOrUpdate(key, windowScale, (a, b) => windowScale);
|
||||||
Ack = (ulong)(originPacket.IsOnlySyn ? 1 : 0),
|
|
||||||
Seq = originPacket.Seq + 1,
|
|
||||||
WindowScale = originPacket.FindOptionWindowScale(ptr + originPacket.IPHeadLength)
|
|
||||||
};
|
|
||||||
dic.AddOrUpdate(key, state, (a, b) => state);
|
|
||||||
}
|
}
|
||||||
else if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
|
else if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
|
||||||
{
|
{
|
||||||
@@ -104,17 +71,6 @@ namespace linker.tun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 状态
|
|
||||||
/// </summary>
|
|
||||||
sealed class FackAckState
|
|
||||||
{
|
|
||||||
public ulong Ack { get; set; }
|
|
||||||
public uint Seq { get; set; }
|
|
||||||
public uint Cq { get; set; }
|
|
||||||
public int WindowScale { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 四元组缓存key
|
/// 四元组缓存key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -172,33 +128,14 @@ namespace linker.tun
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly ushort DstPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 2));
|
public readonly ushort DstPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 2));
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IP头长度
|
/// IP头长度
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
|
public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 序列号
|
/// 窗口大小
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly uint Seq => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + IPHeadLength + 4));
|
public readonly ushort Window => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 14));
|
||||||
/// <summary>
|
|
||||||
/// 确认号
|
|
||||||
/// </summary>
|
|
||||||
public readonly uint Cq => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + IPHeadLength + 8));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// TCP负载长度
|
|
||||||
/// </summary>
|
|
||||||
public readonly int TcpPayloadLength
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
int ipHeadLength = (*ptr & 0b1111) * 4;
|
|
||||||
int tcpHeaderLength = (*(ptr + ipHeadLength + 12) >> 4) * 4;
|
|
||||||
return BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + 2)) - ipHeadLength - tcpHeaderLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TCP Flag
|
/// TCP Flag
|
||||||
@@ -225,70 +162,7 @@ namespace linker.tun
|
|||||||
this.ptr = ptr;
|
this.ptr = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public int FindWindowScale(byte* ipPtr)
|
||||||
/// 制作一个ACK包
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="seq">给定一个序列号,可以从syn+ack包中+1获得</param>
|
|
||||||
/// <param name="winSize">窗口大小</param>
|
|
||||||
/// <param name="ipPtr">目标内存</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public readonly unsafe ushort ToAck(uint seq, ushort winSize, byte* ipPtr)
|
|
||||||
{
|
|
||||||
//复制一份IP+TCP头部
|
|
||||||
int ipHeaderLength = (*ptr & 0b1111) * 4;
|
|
||||||
int tcpHeaderLength = (*(ptr + ipHeaderLength + 12) >> 4) * 4;
|
|
||||||
ushort totalLength = BinaryPrimitives.ReverseEndianness(*(ushort*)(ipPtr + 2));
|
|
||||||
uint payloadLength = (uint)(totalLength - ipHeaderLength - tcpHeaderLength);
|
|
||||||
|
|
||||||
new Span<byte>(ptr, ipHeaderLength + tcpHeaderLength).CopyTo(new Span<byte>(ipPtr, ipHeaderLength + tcpHeaderLength));
|
|
||||||
|
|
||||||
//TCP头指针
|
|
||||||
byte* tcpPtr = ipPtr + ipHeaderLength;
|
|
||||||
|
|
||||||
//如果有时间戳,就填充时间戳选项
|
|
||||||
//FullOptionTimestamp(tcpPtr);
|
|
||||||
*(tcpPtr + 12) = 0b01010000;
|
|
||||||
//重新计算头部长度
|
|
||||||
tcpHeaderLength = (*(tcpPtr + 12) >> 4) * 4;
|
|
||||||
totalLength = (ushort)(ipHeaderLength + tcpHeaderLength);
|
|
||||||
|
|
||||||
//交换地址和端口
|
|
||||||
(*(uint*)(ipPtr + 16), *(uint*)(ipPtr + 12)) = (*(uint*)(ipPtr + 12), *(uint*)(ipPtr + 16));
|
|
||||||
(*(ushort*)(tcpPtr + 2), *(ushort*)(tcpPtr)) = (*(ushort*)(tcpPtr), *(ushort*)(tcpPtr + 2));
|
|
||||||
|
|
||||||
//设置总长度
|
|
||||||
*(ushort*)(ipPtr + 2) = BinaryPrimitives.ReverseEndianness(totalLength);
|
|
||||||
|
|
||||||
//重置分片相关信息
|
|
||||||
*(ushort*)(ipPtr + 4) = 0; // 清除分片偏移和标志
|
|
||||||
*(ushort*)(ipPtr + 6) = 0; // 清除更多分片标志
|
|
||||||
|
|
||||||
//源序列号
|
|
||||||
uint _seq = BinaryPrimitives.ReverseEndianness(*(uint*)(tcpPtr + 4));
|
|
||||||
//设置序列号
|
|
||||||
*(uint*)(tcpPtr + 4) = BinaryPrimitives.ReverseEndianness(seq);
|
|
||||||
//设置确认号
|
|
||||||
*(uint*)(tcpPtr + 8) = BinaryPrimitives.ReverseEndianness(_seq + payloadLength);
|
|
||||||
|
|
||||||
//设置TCP标志位为ACK,其他标志位清除
|
|
||||||
*(tcpPtr + 13) = 0b00010000;
|
|
||||||
|
|
||||||
//设置窗口大小
|
|
||||||
*(ushort*)(tcpPtr + 14) = BinaryPrimitives.ReverseEndianness(Math.Max(winSize, (ushort)8));
|
|
||||||
|
|
||||||
//计算校验和
|
|
||||||
ChecksumHelper.Checksum(ipPtr, totalLength);
|
|
||||||
|
|
||||||
//只需要IP头+TCP头
|
|
||||||
return totalLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从TCP的SYN包或SYN+ACK包中,获取窗口缩放比例
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ipPtr">一个完整TCP/IP包</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public int FindOptionWindowScale(byte* ipPtr)
|
|
||||||
{
|
{
|
||||||
//指针移动到TCP头开始位置
|
//指针移动到TCP头开始位置
|
||||||
byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
|
byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
|
||||||
@@ -316,51 +190,55 @@ namespace linker.tun
|
|||||||
//Window Scale 1kind 1length 1shiftCount
|
//Window Scale 1kind 1length 1shiftCount
|
||||||
else if (kind == 3 && length == 3)
|
else if (kind == 3 && length == 3)
|
||||||
{
|
{
|
||||||
byte shiftCount = *(tcpPtr + index + 2);
|
return *(tcpPtr + index + 2);
|
||||||
return shiftCount > 14 ? 1 : 1 << shiftCount;
|
|
||||||
}
|
}
|
||||||
index += length;
|
index += length;
|
||||||
}
|
}
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
private void FullOptionTimestamp(byte* tcpPtr)
|
public int WriteWindowScale(byte* ipPtr, byte windowScale = 7)
|
||||||
{
|
{
|
||||||
int index = 20, end = (*(tcpPtr + 12) >> 4) * 4;
|
//指针移动到TCP头开始位置
|
||||||
//找时间戳
|
byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
|
||||||
uint timestampValue = 0;
|
|
||||||
|
//tcp头固定20,所以option从这里开始
|
||||||
|
int index = 20;
|
||||||
|
//tcp头结束位置,就是option结束位置
|
||||||
|
int end = (*(tcpPtr + 12) >> 4) * 4;
|
||||||
while (index < end)
|
while (index < end)
|
||||||
{
|
{
|
||||||
byte kind = *(tcpPtr + index);
|
byte kind = *(tcpPtr + index);
|
||||||
if (kind == 0) break;
|
//EOF结束符
|
||||||
|
if (kind == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
byte length = *(tcpPtr + index + 1);
|
byte length = *(tcpPtr + index + 1);
|
||||||
|
//NOP 空选项
|
||||||
if (kind == 1)
|
if (kind == 1)
|
||||||
{
|
{
|
||||||
index++;
|
index++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (kind == 8 && length == 10)
|
//Window Scale 1kind 1length 1shiftCount
|
||||||
|
else if (kind == 3 && length == 3)
|
||||||
{
|
{
|
||||||
timestampValue = *(uint*)(tcpPtr + index + 2);
|
if (*(tcpPtr + index + 2) < windowScale)
|
||||||
break;
|
{
|
||||||
|
*(tcpPtr + index + 2) = windowScale;
|
||||||
|
ChecksumHelper.Checksum(ipPtr, false, true);
|
||||||
|
}
|
||||||
|
return *(tcpPtr + index + 2);
|
||||||
}
|
}
|
||||||
index += length;
|
index += length;
|
||||||
}
|
}
|
||||||
// TCP头长度
|
return 0;
|
||||||
if (timestampValue > 0) //有时间戳选项,有选项,8个32位字,32字节,12字节OPTIONS
|
|
||||||
{
|
|
||||||
*(tcpPtr + 12) = 0b10000000;
|
|
||||||
*(tcpPtr + 20) = 0x01; //NOP
|
|
||||||
*(tcpPtr + 21) = 0x01; //NOP
|
|
||||||
*(tcpPtr + 22) = 0x08; //kind timestamp
|
|
||||||
*(tcpPtr + 23) = 0x0A; //length 10
|
|
||||||
*(uint*)(tcpPtr + 24) = (uint)(Stopwatch.GetTimestamp() / (Stopwatch.Frequency / 1000)); //val
|
|
||||||
*(uint*)(tcpPtr + 28) = timestampValue; //ecr 10
|
|
||||||
}
|
}
|
||||||
else //没有时间戳,就没有选项,5个32位字,20字节
|
public void WriteWindow(byte* ipPtr, ushort window)
|
||||||
{
|
{
|
||||||
*(tcpPtr + 12) = 0b01010000;
|
*(ushort*)(ipPtr + ((*ipPtr & 0b1111) * 4) + 14) = BinaryPrimitives.ReverseEndianness(Math.Max(window, (ushort)8));
|
||||||
}
|
ChecksumHelper.Checksum(ipPtr, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -326,7 +326,7 @@ namespace linker.tun
|
|||||||
Span<byte> ipPacket = Buffer.AsSpan(Offset + 4);
|
Span<byte> ipPacket = Buffer.AsSpan(Offset + 4);
|
||||||
if (Version == 4) TTL = --ipPacket[8];
|
if (Version == 4) TTL = --ipPacket[8];
|
||||||
else if (Version == 6) TTL = --ipPacket[7];
|
else if (Version == 6) TTL = --ipPacket[7];
|
||||||
ChecksumHelper.Checksum(ipPacket, false);
|
ChecksumHelper.Checksum(ipPacket, true, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@@ -157,6 +157,15 @@ namespace linker.tunnel.connection
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public long SendBufferFree { get; }
|
public long SendBufferFree { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送缓冲区剩余大小
|
||||||
|
/// </summary>
|
||||||
|
public long RecvBufferRemaining { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 发送缓冲区剩余比例
|
||||||
|
/// </summary>
|
||||||
|
public long RecvBufferFree { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 最后通信时间
|
/// 最后通信时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -41,6 +41,8 @@ namespace linker.tunnel.connection
|
|||||||
public long ReceiveBytes { get; private set; }
|
public long ReceiveBytes { get; private set; }
|
||||||
public long SendBufferRemaining { get; }
|
public long SendBufferRemaining { get; }
|
||||||
public long SendBufferFree { get; } = 512 * 1024;
|
public long SendBufferFree { get; } = 512 * 1024;
|
||||||
|
public long RecvBufferRemaining { get; }
|
||||||
|
public long RecvBufferFree { get; } = 512 * 1024;
|
||||||
|
|
||||||
public LastTicksManager LastTicks { get; private set; } = new LastTicksManager();
|
public LastTicksManager LastTicks { get; private set; } = new LastTicksManager();
|
||||||
|
|
||||||
|
@@ -40,8 +40,12 @@ namespace linker.tunnel.connection
|
|||||||
|
|
||||||
private long sendRemaining = 0;
|
private long sendRemaining = 0;
|
||||||
public long SendBufferRemaining { get => sendRemaining; }
|
public long SendBufferRemaining { get => sendRemaining; }
|
||||||
public long SendBufferFree { get => maxSendRemaining - sendRemaining; }
|
public long SendBufferFree { get => maxRemaining - sendRemaining; }
|
||||||
private const long maxSendRemaining = 1 * 1024 * 1024;
|
private const long maxRemaining = 1 * 1024 * 1024;
|
||||||
|
|
||||||
|
private long recvRemaining = 0;
|
||||||
|
public long RecvBufferRemaining { get => recvRemaining; }
|
||||||
|
public long RecvBufferFree { get => maxRemaining - recvRemaining; }
|
||||||
|
|
||||||
public LastTicksManager LastTicks { get; private set; } = new LastTicksManager();
|
public LastTicksManager LastTicks { get; private set; } = new LastTicksManager();
|
||||||
|
|
||||||
@@ -80,8 +84,8 @@ namespace linker.tunnel.connection
|
|||||||
|
|
||||||
cancellationTokenSource = new CancellationTokenSource();
|
cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
pipeSender = new Pipe(new PipeOptions(pauseWriterThreshold: maxSendRemaining, resumeWriterThreshold: (maxSendRemaining / 2), useSynchronizationContext: false));
|
pipeSender = new Pipe(new PipeOptions(pauseWriterThreshold: maxRemaining, resumeWriterThreshold: (maxRemaining / 2), useSynchronizationContext: false));
|
||||||
pipeWriter = new Pipe(new PipeOptions(pauseWriterThreshold: maxSendRemaining, resumeWriterThreshold: (maxSendRemaining / 2), useSynchronizationContext: false));
|
pipeWriter = new Pipe(new PipeOptions(pauseWriterThreshold: maxRemaining, resumeWriterThreshold: (maxRemaining / 2), useSynchronizationContext: false));
|
||||||
_ = ProcessWrite();
|
_ = ProcessWrite();
|
||||||
_ = Sender();
|
_ = Sender();
|
||||||
_ = Recver();
|
_ = Recver();
|
||||||
@@ -99,10 +103,8 @@ namespace linker.tunnel.connection
|
|||||||
{
|
{
|
||||||
Memory<byte> memory = pipeWriter.Writer.GetMemory(8 * 1024);
|
Memory<byte> memory = pipeWriter.Writer.GetMemory(8 * 1024);
|
||||||
length = await Stream.ReadAsync(memory).ConfigureAwait(false);
|
length = await Stream.ReadAsync(memory).ConfigureAwait(false);
|
||||||
if (length == 0)
|
if (length == 0) break;
|
||||||
{
|
Interlocked.Add(ref recvRemaining, length);
|
||||||
break;
|
|
||||||
}
|
|
||||||
pipeWriter.Writer.Advance(length);
|
pipeWriter.Writer.Advance(length);
|
||||||
await pipeWriter.Writer.FlushAsync().ConfigureAwait(false);
|
await pipeWriter.Writer.FlushAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -111,6 +113,7 @@ namespace linker.tunnel.connection
|
|||||||
Memory<byte> memory = pipeWriter.Writer.GetMemory(8 * 1024);
|
Memory<byte> memory = pipeWriter.Writer.GetMemory(8 * 1024);
|
||||||
length = await Socket.ReceiveAsync(memory, SocketFlags.None).ConfigureAwait(false);
|
length = await Socket.ReceiveAsync(memory, SocketFlags.None).ConfigureAwait(false);
|
||||||
if (length == 0) break;
|
if (length == 0) break;
|
||||||
|
Interlocked.Add(ref recvRemaining, length);
|
||||||
pipeWriter.Writer.Advance(length);
|
pipeWriter.Writer.Advance(length);
|
||||||
await pipeWriter.Writer.FlushAsync().ConfigureAwait(false);
|
await pipeWriter.Writer.FlushAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -173,6 +176,7 @@ namespace linker.tunnel.connection
|
|||||||
temp.CopyTo(packetBuffer.Memory.Span);
|
temp.CopyTo(packetBuffer.Memory.Span);
|
||||||
//处理数据包
|
//处理数据包
|
||||||
await WritePacket(packetBuffer.Memory.Slice(0, packetLength)).ConfigureAwait(false);
|
await WritePacket(packetBuffer.Memory.Slice(0, packetLength)).ConfigureAwait(false);
|
||||||
|
Interlocked.Add(ref recvRemaining, -(packetLength + 4));
|
||||||
|
|
||||||
//移动位置
|
//移动位置
|
||||||
offset += 4 + packetLength;
|
offset += 4 + packetLength;
|
||||||
@@ -303,6 +307,7 @@ namespace linker.tunnel.connection
|
|||||||
} while (sendt < memoryBlock.Length);
|
} while (sendt < memoryBlock.Length);
|
||||||
}
|
}
|
||||||
Interlocked.Add(ref sendRemaining, -memoryBlock.Length);
|
Interlocked.Add(ref sendRemaining, -memoryBlock.Length);
|
||||||
|
SendBytes += memoryBlock.Length;
|
||||||
}
|
}
|
||||||
pipeSender.Reader.AdvanceTo(buffer.End);
|
pipeSender.Reader.AdvanceTo(buffer.End);
|
||||||
LastTicks.Update();
|
LastTicks.Update();
|
||||||
|
@@ -39,6 +39,9 @@ namespace linker.tunnel.connection
|
|||||||
public long ReceiveBytes { get; private set; }
|
public long ReceiveBytes { get; private set; }
|
||||||
public long SendBufferRemaining { get; }
|
public long SendBufferRemaining { get; }
|
||||||
public long SendBufferFree { get; } = 512 * 1024;
|
public long SendBufferFree { get; } = 512 * 1024;
|
||||||
|
public long RecvBufferRemaining { get; }
|
||||||
|
public long RecvBufferFree { get; } = 512 * 1024;
|
||||||
|
|
||||||
public LastTicksManager LastTicks { get; private set; } = new LastTicksManager();
|
public LastTicksManager LastTicks { get; private set; } = new LastTicksManager();
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div>
|
<div>
|
||||||
<p>{{ scope.row.TransportName }}({{ state.protocolTypes[scope.row.ProtocolType] }})</p>
|
<p>{{ scope.row.TransportName }}({{ state.protocolTypes[scope.row.ProtocolType] }})</p>
|
||||||
<p>{{ state.types[scope.row.Type] }} - {{ scope.row.SendBufferRemainingText }}</p>
|
<p>{{ state.types[scope.row.Type] }} - {{ scope.row.SendBufferRemainingText }} - {{ scope.row.RecvBufferRemainingText }}</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@@ -102,6 +102,7 @@ export const provideConnections = () => {
|
|||||||
connection.SendBytesText = parseSpeed(connection.SendBytes - cache.SendBytes,'/s');
|
connection.SendBytesText = parseSpeed(connection.SendBytes - cache.SendBytes,'/s');
|
||||||
connection.ReceiveBytesText = parseSpeed(connection.ReceiveBytes - cache.ReceiveBytes,'/s');
|
connection.ReceiveBytesText = parseSpeed(connection.ReceiveBytes - cache.ReceiveBytes,'/s');
|
||||||
connection.SendBufferRemainingText = parseSpeed(connection.SendBufferRemaining,'');
|
connection.SendBufferRemainingText = parseSpeed(connection.SendBufferRemaining,'');
|
||||||
|
connection.RecvBufferRemainingText = parseSpeed(connection.RecvBufferRemaining || 0,'');
|
||||||
|
|
||||||
cache.SendBytes = connection.SendBytes;
|
cache.SendBytes = connection.SendBytes;
|
||||||
cache.ReceiveBytes = connection.ReceiveBytes;
|
cache.ReceiveBytes = connection.ReceiveBytes;
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
<el-checkbox class="mgr-1" v-model="state.ruleForm.DisableNat" label="禁用NAT" size="large" />
|
<el-checkbox class="mgr-1" v-model="state.ruleForm.DisableNat" label="禁用NAT" size="large" />
|
||||||
<!-- <el-checkbox class="mgr-1" v-model="state.ruleForm.TcpMerge" label="TCP包合并" size="large" /> -->
|
<!-- <el-checkbox class="mgr-1" v-model="state.ruleForm.TcpMerge" label="TCP包合并" size="large" /> -->
|
||||||
<el-checkbox class="mgr-1" v-model="state.ruleForm.InterfaceOrder" label="网卡顺序" size="large" />
|
<el-checkbox class="mgr-1" v-model="state.ruleForm.InterfaceOrder" label="网卡顺序" size="large" />
|
||||||
<el-checkbox v-model="state.ruleForm.FakeAck" label="伪ACK" size="large" />
|
<!-- <el-checkbox v-model="state.ruleForm.FakeAck" label="伪ACK" size="large" /> -->
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
v1.9.1
|
v1.9.1
|
||||||
2025-09-17 18:03:28
|
2025-09-19 16:42:33
|
||||||
1. 一些累计更新
|
1. 一些累计更新
|
||||||
2. 服务器转发多节点
|
2. 服务器转发多节点
|
||||||
3. 虚拟网卡下伪造ACK为TCP-in-TCP隧道提速
|
3. 虚拟网卡下伪造ACK为TCP-in-TCP隧道提速
|
||||||
|
Reference in New Issue
Block a user