mirror of
https://github.com/snltty/linker.git
synced 2025-09-26 21:15:57 +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>
|
||||
/// <param name="packet">一个完整的IP包</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(ptr, packet.Length, payload);
|
||||
}
|
||||
Checksum(packet.Span, ipHeader, payload);
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算IP包的校验和
|
||||
/// </summary>
|
||||
/// <param name="packet">一个完整的IP包</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)
|
||||
{
|
||||
Checksum(ptr, packet.Length, payload);
|
||||
Checksum(ptr, ipHeader, payload);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算IP包的校验和
|
||||
/// </summary>
|
||||
/// <param name="ptr">IP包指针</param>
|
||||
/// <param name="length">IP包长度</param>
|
||||
/// <param name="ipHeader">是否计算IP校验和</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);
|
||||
//重新计算IP头校验和
|
||||
*(ushort*)(ptr + 10) = 0;
|
||||
*(ushort*)(ptr + 10) = Checksum((ushort*)ptr, ipHeaderLength);
|
||||
byte* packetPtr = ptr + ipHeaderLength;
|
||||
uint totalLength = BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + 2));
|
||||
uint packetLength = totalLength - ipHeaderLength;
|
||||
|
||||
if (ipHeader)
|
||||
{
|
||||
//重新计算IP头校验和
|
||||
*(ushort*)(ptr + 10) = 0;
|
||||
*(ushort*)(ptr + 10) = Checksum((ushort*)ptr, ipHeaderLength);
|
||||
}
|
||||
|
||||
|
||||
if (payload)
|
||||
{
|
||||
@@ -50,22 +55,22 @@ namespace linker.libs
|
||||
{
|
||||
case ProtocolType.Tcp:
|
||||
{
|
||||
*(ushort*)(ptr + ipHeaderLength + 16) = 0;
|
||||
ulong sum = PseudoHeaderSum(ptr, (uint)(length - ipHeaderLength));
|
||||
*(ushort*)(ptr + ipHeaderLength + 16) = Checksum((ushort*)(ptr + ipHeaderLength), (uint)length - ipHeaderLength, sum);
|
||||
*(ushort*)(packetPtr + 16) = 0;
|
||||
ulong sum = PseudoHeaderSum(ptr, packetLength);
|
||||
*(ushort*)(packetPtr + 16) = Checksum((ushort*)(packetPtr), packetLength, sum);
|
||||
}
|
||||
break;
|
||||
case ProtocolType.Udp:
|
||||
{
|
||||
*(ushort*)(ptr + ipHeaderLength + 6) = 0;
|
||||
ulong sum = PseudoHeaderSum(ptr, (uint)(length - ipHeaderLength));
|
||||
*(ushort*)(ptr + ipHeaderLength + 6) = Checksum((ushort*)(ptr + ipHeaderLength), (uint)length - ipHeaderLength, sum);
|
||||
*(ushort*)(packetPtr + 6) = 0;
|
||||
ulong sum = PseudoHeaderSum(ptr, packetLength);
|
||||
*(ushort*)(packetPtr + 6) = Checksum((ushort*)(packetPtr), packetLength, sum);
|
||||
}
|
||||
break;
|
||||
case ProtocolType.Icmp:
|
||||
{
|
||||
*(ushort*)(ptr + ipHeaderLength + 2) = 0;
|
||||
*(ushort*)(ptr + ipHeaderLength + 2) = Checksum((ushort*)(ptr + ipHeaderLength), (uint)length - ipHeaderLength);
|
||||
*(ushort*)(packetPtr + 2) = 0;
|
||||
*(ushort*)(packetPtr + 2) = Checksum((ushort*)(packetPtr), packetLength);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ using linker.messenger.relay.client;
|
||||
using linker.messenger.signin;
|
||||
using linker.messenger.pcp;
|
||||
using linker.messenger.tuntap.cidr;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace linker.messenger.tuntap
|
||||
{
|
||||
@@ -45,11 +44,12 @@ namespace linker.messenger.tuntap
|
||||
|
||||
protected override void Connected(ITunnelConnection connection)
|
||||
{
|
||||
/*
|
||||
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);
|
||||
connection.BeginReceive(this, null);
|
||||
//有哪些目标IP用了相同目标隧道,更新一下
|
||||
@@ -67,7 +67,7 @@ namespace linker.messenger.tuntap
|
||||
public async Task Receive(ITunnelConnection connection, ReadOnlyMemory<byte> buffer, object state)
|
||||
#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);
|
||||
}
|
||||
/// <summary>
|
||||
@@ -101,31 +101,33 @@ namespace linker.messenger.tuntap
|
||||
|
||||
//IPV4+IPV6 单播
|
||||
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)
|
||||
{
|
||||
//开始操作,开始失败直接丢包
|
||||
if (operatingMultipleManager.StartOperation(ip) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_ = ConnectTunnel(ip).ContinueWith((result, state) =>
|
||||
{
|
||||
//结束操作
|
||||
operatingMultipleManager.StopOperation((uint)state);
|
||||
//连接成功就缓存隧道
|
||||
if (result.Result != null)
|
||||
{
|
||||
tuntapCidrConnectionManager.Add((uint)state, result.Result);
|
||||
}
|
||||
}, ip);
|
||||
await connection.SendAsync(packet.Buffer, packet.Offset, packet.Length).ConfigureAwait(false);
|
||||
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));
|
||||
/*
|
||||
if (connection.PacketBuffer.Length > 0)
|
||||
{
|
||||
fakeAckTransfer.Read(packet.IPPacket);
|
||||
}
|
||||
*/
|
||||
|
||||
//开始操作,开始失败直接丢包
|
||||
if (operatingMultipleManager.StartOperation(ip) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_ = ConnectTunnel(ip).ContinueWith((result, state) =>
|
||||
{
|
||||
//结束操作
|
||||
operatingMultipleManager.StopOperation((uint)state);
|
||||
//连接成功就缓存隧道
|
||||
if (result.Result != null)
|
||||
{
|
||||
tuntapCidrConnectionManager.Add((uint)state, result.Result);
|
||||
}
|
||||
}, ip);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using linker.libs;
|
||||
using linker.libs.extends;
|
||||
using System.Buffers;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@@ -126,7 +126,7 @@ namespace linker.snat
|
||||
if (checksum)
|
||||
{
|
||||
//计算校验和
|
||||
ChecksumHelper.Checksum(ptr, packet.Length);
|
||||
ChecksumHelper.Checksum(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -83,7 +83,7 @@ namespace linker.tun
|
||||
//response
|
||||
*(ushort*)(ptr + 20) = 0;
|
||||
|
||||
ChecksumHelper.Checksum(ptr, writableMemory.Length);
|
||||
ChecksumHelper.Checksum(ptr);
|
||||
Program.linkerTunDeviceAdapter.Write(string.Empty, writableMemory);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using linker.libs;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace linker.tun
|
||||
@@ -11,60 +10,35 @@ namespace linker.tun
|
||||
/// </summary>
|
||||
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>
|
||||
/// <param name="packet">一个完整的TCP/IP包</param>
|
||||
/// <param name="fakeBuffer">一个能容纳ACK包的缓冲区,如果需要伪造ACK则写入到这里</param>
|
||||
/// <param name="bufferFree">缓冲区可用字节数,会根据这个来计算ack的窗口大小</param>
|
||||
/// <param name="fakeLength">ack包长度</param>
|
||||
/// <returns>是否丢包</returns>
|
||||
public bool Read(ReadOnlyMemory<byte> packet, ReadOnlyMemory<byte> fakeBuffer, long bufferFree, out ushort fakeLength)
|
||||
/// <returns></returns>
|
||||
public void Read(ReadOnlyMemory<byte> packet)
|
||||
{
|
||||
fakeLength = 0;
|
||||
|
||||
fixed (byte* ptr = packet.Span)
|
||||
{
|
||||
FakeAckPacket originPacket = new(ptr);
|
||||
if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
|
||||
{
|
||||
FaceAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
|
||||
dic.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 接收方
|
||||
/// </summary>
|
||||
/// <param name="packet">一个完整的TCP/IP包</param>
|
||||
/// <returns></returns>
|
||||
public void Write(ReadOnlyMemory<byte> packet)
|
||||
public void Write(ReadOnlyMemory<byte> packet, long bufferFree)
|
||||
{
|
||||
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 };
|
||||
|
||||
/*
|
||||
//更新序列号
|
||||
if (originPacket.TcpFlagAck && dic.TryGetValue(key, out FackAckState state))
|
||||
if (originPacket.IsPshAck || originPacket.IsOnlyAck)
|
||||
{
|
||||
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*/
|
||||
if (originPacket.IsOnlySyn || originPacket.IsSynAck)
|
||||
else if (originPacket.IsOnlySyn || originPacket.IsSynAck)
|
||||
{
|
||||
FackAckState state = new()
|
||||
{
|
||||
Ack = (ulong)(originPacket.IsOnlySyn ? 1 : 0),
|
||||
Seq = originPacket.Seq + 1,
|
||||
WindowScale = originPacket.FindOptionWindowScale(ptr + originPacket.IPHeadLength)
|
||||
};
|
||||
dic.AddOrUpdate(key, state, (a, b) => state);
|
||||
int windowScale = originPacket.FindWindowScale(ptr);
|
||||
dic.AddOrUpdate(key, windowScale, (a, b) => windowScale);
|
||||
}
|
||||
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>
|
||||
/// 四元组缓存key
|
||||
/// </summary>
|
||||
@@ -172,33 +128,14 @@ namespace linker.tun
|
||||
/// </summary>
|
||||
public readonly ushort DstPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 2));
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// IP头长度
|
||||
/// </summary>
|
||||
public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
|
||||
|
||||
/// <summary>
|
||||
/// 序列号
|
||||
/// 窗口大小
|
||||
/// </summary>
|
||||
public readonly uint Seq => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + IPHeadLength + 4));
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
public readonly ushort Window => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 14));
|
||||
|
||||
/// <summary>
|
||||
/// TCP Flag
|
||||
@@ -225,70 +162,7 @@ namespace linker.tun
|
||||
this.ptr = ptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 制作一个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)
|
||||
public int FindWindowScale(byte* ipPtr)
|
||||
{
|
||||
//指针移动到TCP头开始位置
|
||||
byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
|
||||
@@ -316,51 +190,55 @@ namespace linker.tun
|
||||
//Window Scale 1kind 1length 1shiftCount
|
||||
else if (kind == 3 && length == 3)
|
||||
{
|
||||
byte shiftCount = *(tcpPtr + index + 2);
|
||||
return shiftCount > 14 ? 1 : 1 << shiftCount;
|
||||
return *(tcpPtr + index + 2);
|
||||
}
|
||||
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;
|
||||
//找时间戳
|
||||
uint timestampValue = 0;
|
||||
//指针移动到TCP头开始位置
|
||||
byte* tcpPtr = ipPtr + ((*ipPtr & 0b1111) * 4);
|
||||
|
||||
//tcp头固定20,所以option从这里开始
|
||||
int index = 20;
|
||||
//tcp头结束位置,就是option结束位置
|
||||
int end = (*(tcpPtr + 12) >> 4) * 4;
|
||||
while (index < end)
|
||||
{
|
||||
byte kind = *(tcpPtr + index);
|
||||
if (kind == 0) break;
|
||||
//EOF结束符
|
||||
if (kind == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
byte length = *(tcpPtr + index + 1);
|
||||
//NOP 空选项
|
||||
if (kind == 1)
|
||||
{
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
else if (kind == 8 && length == 10)
|
||||
//Window Scale 1kind 1length 1shiftCount
|
||||
else if (kind == 3 && length == 3)
|
||||
{
|
||||
timestampValue = *(uint*)(tcpPtr + index + 2);
|
||||
break;
|
||||
if (*(tcpPtr + index + 2) < windowScale)
|
||||
{
|
||||
*(tcpPtr + index + 2) = windowScale;
|
||||
ChecksumHelper.Checksum(ipPtr, false, true);
|
||||
}
|
||||
return *(tcpPtr + index + 2);
|
||||
}
|
||||
index += length;
|
||||
}
|
||||
// TCP头长度
|
||||
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字节
|
||||
{
|
||||
*(tcpPtr + 12) = 0b01010000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public void WriteWindow(byte* ipPtr, ushort window)
|
||||
{
|
||||
*(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);
|
||||
if (Version == 4) TTL = --ipPacket[8];
|
||||
else if (Version == 6) TTL = --ipPacket[7];
|
||||
ChecksumHelper.Checksum(ipPacket, false);
|
||||
ChecksumHelper.Checksum(ipPacket, true, false);
|
||||
|
||||
return true;
|
||||
|
||||
|
@@ -157,6 +157,15 @@ namespace linker.tunnel.connection
|
||||
/// </summary>
|
||||
public long SendBufferFree { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送缓冲区剩余大小
|
||||
/// </summary>
|
||||
public long RecvBufferRemaining { get; }
|
||||
/// <summary>
|
||||
/// 发送缓冲区剩余比例
|
||||
/// </summary>
|
||||
public long RecvBufferFree { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后通信时间
|
||||
/// </summary>
|
||||
|
@@ -41,6 +41,8 @@ namespace linker.tunnel.connection
|
||||
public long ReceiveBytes { get; private set; }
|
||||
public long SendBufferRemaining { get; }
|
||||
public long SendBufferFree { get; } = 512 * 1024;
|
||||
public long RecvBufferRemaining { get; }
|
||||
public long RecvBufferFree { get; } = 512 * 1024;
|
||||
|
||||
public LastTicksManager LastTicks { get; private set; } = new LastTicksManager();
|
||||
|
||||
|
@@ -40,8 +40,12 @@ namespace linker.tunnel.connection
|
||||
|
||||
private long sendRemaining = 0;
|
||||
public long SendBufferRemaining { get => sendRemaining; }
|
||||
public long SendBufferFree { get => maxSendRemaining - sendRemaining; }
|
||||
private const long maxSendRemaining = 1 * 1024 * 1024;
|
||||
public long SendBufferFree { get => maxRemaining - sendRemaining; }
|
||||
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();
|
||||
|
||||
@@ -80,8 +84,8 @@ namespace linker.tunnel.connection
|
||||
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
pipeSender = new Pipe(new PipeOptions(pauseWriterThreshold: maxSendRemaining, resumeWriterThreshold: (maxSendRemaining / 2), useSynchronizationContext: false));
|
||||
pipeWriter = 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: maxRemaining, resumeWriterThreshold: (maxRemaining / 2), useSynchronizationContext: false));
|
||||
_ = ProcessWrite();
|
||||
_ = Sender();
|
||||
_ = Recver();
|
||||
@@ -99,10 +103,8 @@ namespace linker.tunnel.connection
|
||||
{
|
||||
Memory<byte> memory = pipeWriter.Writer.GetMemory(8 * 1024);
|
||||
length = await Stream.ReadAsync(memory).ConfigureAwait(false);
|
||||
if (length == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (length == 0) break;
|
||||
Interlocked.Add(ref recvRemaining, length);
|
||||
pipeWriter.Writer.Advance(length);
|
||||
await pipeWriter.Writer.FlushAsync().ConfigureAwait(false);
|
||||
}
|
||||
@@ -111,6 +113,7 @@ namespace linker.tunnel.connection
|
||||
Memory<byte> memory = pipeWriter.Writer.GetMemory(8 * 1024);
|
||||
length = await Socket.ReceiveAsync(memory, SocketFlags.None).ConfigureAwait(false);
|
||||
if (length == 0) break;
|
||||
Interlocked.Add(ref recvRemaining, length);
|
||||
pipeWriter.Writer.Advance(length);
|
||||
await pipeWriter.Writer.FlushAsync().ConfigureAwait(false);
|
||||
}
|
||||
@@ -173,6 +176,7 @@ namespace linker.tunnel.connection
|
||||
temp.CopyTo(packetBuffer.Memory.Span);
|
||||
//处理数据包
|
||||
await WritePacket(packetBuffer.Memory.Slice(0, packetLength)).ConfigureAwait(false);
|
||||
Interlocked.Add(ref recvRemaining, -(packetLength + 4));
|
||||
|
||||
//移动位置
|
||||
offset += 4 + packetLength;
|
||||
@@ -303,6 +307,7 @@ namespace linker.tunnel.connection
|
||||
} while (sendt < memoryBlock.Length);
|
||||
}
|
||||
Interlocked.Add(ref sendRemaining, -memoryBlock.Length);
|
||||
SendBytes += memoryBlock.Length;
|
||||
}
|
||||
pipeSender.Reader.AdvanceTo(buffer.End);
|
||||
LastTicks.Update();
|
||||
|
@@ -39,6 +39,9 @@ namespace linker.tunnel.connection
|
||||
public long ReceiveBytes { get; private set; }
|
||||
public long SendBufferRemaining { get; }
|
||||
public long SendBufferFree { get; } = 512 * 1024;
|
||||
public long RecvBufferRemaining { get; }
|
||||
public long RecvBufferFree { get; } = 512 * 1024;
|
||||
|
||||
public LastTicksManager LastTicks { get; private set; } = new LastTicksManager();
|
||||
|
||||
[JsonIgnore]
|
||||
|
@@ -19,7 +19,7 @@
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<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>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@@ -102,6 +102,7 @@ export const provideConnections = () => {
|
||||
connection.SendBytesText = parseSpeed(connection.SendBytes - cache.SendBytes,'/s');
|
||||
connection.ReceiveBytesText = parseSpeed(connection.ReceiveBytes - cache.ReceiveBytes,'/s');
|
||||
connection.SendBufferRemainingText = parseSpeed(connection.SendBufferRemaining,'');
|
||||
connection.RecvBufferRemainingText = parseSpeed(connection.RecvBufferRemaining || 0,'');
|
||||
|
||||
cache.SendBytes = connection.SendBytes;
|
||||
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.TcpMerge" label="TCP包合并" 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>
|
||||
</div>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
v1.9.1
|
||||
2025-09-17 18:03:28
|
||||
2025-09-19 16:42:33
|
||||
1. 一些累计更新
|
||||
2. 服务器转发多节点
|
||||
3. 虚拟网卡下伪造ACK为TCP-in-TCP隧道提速
|
||||
|
Reference in New Issue
Block a user