ack欺骗

This commit is contained in:
snltty
2025-08-30 20:51:10 +08:00
parent d91fff813a
commit 8b6d1c471e
5 changed files with 41 additions and 37 deletions

View File

@@ -220,16 +220,6 @@ jobs:
asset_path: ./public/publish-zip/linker-linux-musl-arm64.zip asset_path: ./public/publish-zip/linker-linux-musl-arm64.zip
asset_name: linker-linux-musl-arm64.zip asset_name: linker-linux-musl-arm64.zip
asset_content_type: application/zip asset_content_type: application/zip
- name: upload-version-oss
id: upload-version-oss
uses: tvrcgo/oss-action@v0.1.1
with:
region: oss-cn-shenzhen
key-id: ${{ secrets.ALIYUN_OSS_ID }}
key-secret: ${{ secrets.ALIYUN_OSS_SECRET }}
bucket: ide-qbcode
asset-path: ./public/version.txt
target-path: /downloads/linker/version.txt
- name: upload-install-service-oss - name: upload-install-service-oss
id: upload-install-service-oss id: upload-install-service-oss
uses: tvrcgo/oss-action@v0.1.1 uses: tvrcgo/oss-action@v0.1.1

View File

@@ -48,6 +48,7 @@
- **服务器穿透:** 使用端口或域名访问内网服务(支持`计划任务`定时定长自动开启关闭例如每天在上9点自动开启穿透1小时后自动关闭穿透)。 - **服务器穿透:** 使用端口或域名访问内网服务(支持`计划任务`定时定长自动开启关闭例如每天在上9点自动开启穿透1小时后自动关闭穿透)。
##### 特色功能 ##### 特色功能
- **TCP-in-TCP优化** 伪造ACK包优化TCP-in-TCP隧道
- **网段映射:** 当多个设备不同的局域网使用相同的内网网段(如`192.168.1.0/24`)存在冲突时,网段映射可以让你继续顺利的使用点对网和网对网,例如配置`192.168.188.0/24->192.168.1.0/24`,就可以使用`192.168.188.2`访问`192.168.1.2` - **网段映射:** 当多个设备不同的局域网使用相同的内网网段(如`192.168.1.0/24`)存在冲突时,网段映射可以让你继续顺利的使用点对网和网对网,例如配置`192.168.188.0/24->192.168.1.0/24`,就可以使用`192.168.188.2`访问`192.168.1.2`
- **应用层NAT** 内置了使用`WinDivert`实现的应用层NAT即使在`win7/8win server2008/2012`这样的老系统无法使用系统NAT时也可以顺利使用点对网和网对网。 - **应用层NAT** 内置了使用`WinDivert`实现的应用层NAT即使在`win7/8win server2008/2012`这样的老系统无法使用系统NAT时也可以顺利使用点对网和网对网。
- **应用层防火墙:** 内置了防火墙功能应用于虚拟网卡、端口转发、socks5可以精细控制客户端的访问权限例如只允许A访问B的3389其它客户端无法访问 - **应用层防火墙:** 内置了防火墙功能应用于虚拟网卡、端口转发、socks5可以精细控制客户端的访问权限例如只允许A访问B的3389其它客户端无法访问

View File

@@ -87,7 +87,7 @@ function writeUpload(data, tagName) {
}; };
} }
/*
data.jobs.build.steps.push({ data.jobs.build.steps.push({
name: `upload-version-oss`, name: `upload-version-oss`,
id: `upload-version-oss`, id: `upload-version-oss`,
@@ -101,7 +101,7 @@ function writeUpload(data, tagName) {
'target-path': `/downloads/linker/version.txt` 'target-path': `/downloads/linker/version.txt`
} }
}); });
*/
data.jobs.build.steps.push({ data.jobs.build.steps.push({
name: `upload-install-service-oss`, name: `upload-install-service-oss`,

View File

@@ -5,7 +5,9 @@ using System.Net.Sockets;
namespace linker.tun namespace linker.tun
{ {
/// <summary>
/// 伪造ACK操作类
/// </summary>
public unsafe sealed class FakeAckTransfer public unsafe sealed class FakeAckTransfer
{ {
private readonly ConcurrentDictionary<FackAckKey, FackAckState> dic = new(new FackAckKeyComparer()); private readonly ConcurrentDictionary<FackAckKey, FackAckState> dic = new(new FackAckKeyComparer());
@@ -23,7 +25,7 @@ namespace linker.tun
fixed (byte* ptr = packet.Span) fixed (byte* ptr = packet.Span)
{ {
FakeAckPacket originPacket = new FakeAckPacket(ptr); FakeAckPacket originPacket = new(ptr);
if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp || originPacket.IsOnlySyn) if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp || originPacket.IsOnlySyn)
{ {
return false; return false;
@@ -73,26 +75,29 @@ namespace linker.tun
{ {
fixed (byte* ptr = packet.Span) fixed (byte* ptr = packet.Span)
{ {
FakeAckPacket fakeAckTCPPacket = new FakeAckPacket(ptr); FakeAckPacket originPacket = new(ptr);
if (fakeAckTCPPacket.Version != 4 || fakeAckTCPPacket.Protocol != ProtocolType.Tcp || fakeAckTCPPacket.IsOnlySyn) if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp || originPacket.IsOnlySyn)
{ {
return; return;
} }
FackAckKey key = new() { srcAddr = fakeAckTCPPacket.SrcAddr, srcPort = fakeAckTCPPacket.SrcPort, dstAddr = fakeAckTCPPacket.DstAddr, dstPort = fakeAckTCPPacket.DstPort }; FackAckKey key = new() { srcAddr = originPacket.SrcAddr, srcPort = originPacket.SrcPort, dstAddr = originPacket.DstAddr, dstPort = originPacket.DstPort };
//收到连接连接 //收到连接连接
if (fakeAckTCPPacket.TcpFlagSyn && fakeAckTCPPacket.TcpFlagAck) if (originPacket.TcpFlagSyn && originPacket.TcpFlagAck)
{ {
FackAckState state = new() { Seq = fakeAckTCPPacket.Seq + 1 }; FackAckState state = new() { Seq = originPacket.Seq + 1 };
dic.AddOrUpdate(key, state, (a, b) => state); dic.AddOrUpdate(key, state, (a, b) => state);
} }
//断开连接 //断开连接
else if (fakeAckTCPPacket.TcpFlagFin || fakeAckTCPPacket.TcpFlagRst) else if (originPacket.TcpFlagFin || originPacket.TcpFlagRst)
{ {
dic.TryRemove(key, out _); dic.TryRemove(key, out _);
} }
} }
} }
/// <summary>
/// 状态
/// </summary>
sealed class FackAckState sealed class FackAckState
{ {
public uint Seq { get; set; } public uint Seq { get; set; }
@@ -104,6 +109,9 @@ namespace linker.tun
return drop; return drop;
} }
} }
/// <summary>
/// 四元组缓存key
/// </summary>
struct FackAckKey struct FackAckKey
{ {
public uint srcAddr; public uint srcAddr;
@@ -111,6 +119,9 @@ namespace linker.tun
public uint dstAddr; public uint dstAddr;
public ushort dstPort; public ushort dstPort;
} }
/// <summary>
/// 四元组缓存key比较器
/// </summary>
sealed class FackAckKeyComparer : IEqualityComparer<FackAckKey> sealed class FackAckKeyComparer : IEqualityComparer<FackAckKey>
{ {
public bool Equals(FackAckKey x, FackAckKey y) public bool Equals(FackAckKey x, FackAckKey y)
@@ -125,6 +136,9 @@ namespace linker.tun
} }
} }
/// <summary>
/// 数据包解析
/// </summary>
readonly unsafe struct FakeAckPacket readonly unsafe struct FakeAckPacket
{ {
private readonly byte* ptr; private readonly byte* ptr;
@@ -200,44 +214,43 @@ namespace linker.tun
/// 制作一个ACK包 /// 制作一个ACK包
/// </summary> /// </summary>
/// <param name="seq">给定一个序列号可以从syn+ack包中+1获得</param> /// <param name="seq">给定一个序列号可以从syn+ack包中+1获得</param>
/// <param name="dstPtr">目标内存</param> /// <param name="ipPtr">目标内存</param>
/// <returns></returns> /// <returns></returns>
public readonly unsafe ushort ToAck(uint seq, byte* dstPtr) public readonly unsafe ushort ToAck(uint seq, byte* ipPtr)
{ {
//复制一份IP+TCP头部
int _ipHeadLength = (*ptr & 0b1111) * 4; int _ipHeadLength = (*ptr & 0b1111) * 4;
int _tcpHeaderLength = (*(ptr + _ipHeadLength + 12) >> 4) * 4; int _tcpHeaderLength = (*(ptr + _ipHeadLength + 12) >> 4) * 4;
int _headerLength = _ipHeadLength + _tcpHeaderLength; int _headerLength = _ipHeadLength + _tcpHeaderLength;
new Span<byte>(ptr, _headerLength).CopyTo(new Span<byte>(dstPtr, _headerLength)); new Span<byte>(ptr, _headerLength).CopyTo(new Span<byte>(ipPtr, _headerLength));
byte* tcpPtr = dstPtr + _ipHeadLength; //TCP头指针
byte* tcpPtr = ipPtr + _ipHeadLength;
ushort totalLength = BinaryPrimitives.ReverseEndianness(*(ushort*)(dstPtr + 2)); ushort totalLength = BinaryPrimitives.ReverseEndianness(*(ushort*)(ipPtr + 2));
int ipHeaderLength = (*dstPtr & 0b1111) * 4; int ipHeaderLength = (*ipPtr & 0b1111) * 4;
int tcpHeaderLength = (*(tcpPtr + 12) >> 4) * 4; int tcpHeaderLength = (*(tcpPtr + 12) >> 4) * 4;
uint payloadLength = (uint)(totalLength - ipHeaderLength - tcpHeaderLength); uint payloadLength = (uint)(totalLength - ipHeaderLength - tcpHeaderLength);
totalLength = (ushort)(ipHeaderLength + tcpHeaderLength); totalLength = (ushort)(ipHeaderLength + tcpHeaderLength);
//交换地址和端口 //交换地址和端口
(*(uint*)(dstPtr + 16), *(uint*)(dstPtr + 12)) = (*(uint*)(dstPtr + 12), *(uint*)(dstPtr + 16)); (*(uint*)(ipPtr + 16), *(uint*)(ipPtr + 12)) = (*(uint*)(ipPtr + 12), *(uint*)(ipPtr + 16));
(*(ushort*)(tcpPtr + 2), *(ushort*)(tcpPtr)) = (*(ushort*)(tcpPtr), *(ushort*)(tcpPtr + 2)); (*(ushort*)(tcpPtr + 2), *(ushort*)(tcpPtr)) = (*(ushort*)(tcpPtr), *(ushort*)(tcpPtr + 2));
//设置总长度 = IP头长度 + TCP头长度 //设置总长度
*(ushort*)(dstPtr + 2) = BinaryPrimitives.ReverseEndianness(totalLength); *(ushort*)(ipPtr + 2) = BinaryPrimitives.ReverseEndianness(totalLength);
//重置分片相关信息 //重置分片相关信息
*(ushort*)(dstPtr + 4) = 0; // 清除分片偏移和标志 *(ushort*)(ipPtr + 4) = 0; // 清除分片偏移和标志
*(ushort*)(dstPtr + 6) = 0; // 清除更多分片标志 *(ushort*)(ipPtr + 6) = 0; // 清除更多分片标志
//源序列号 //源序列号
uint _seq = BinaryPrimitives.ReverseEndianness(*(uint*)(tcpPtr + 4)); uint _seq = BinaryPrimitives.ReverseEndianness(*(uint*)(tcpPtr + 4));
//新确认号 = 序列号+ 数据长度
uint cq = _seq + payloadLength;
//设置序列号 //设置序列号
*(uint*)(tcpPtr + 4) = BinaryPrimitives.ReverseEndianness(seq); *(uint*)(tcpPtr + 4) = BinaryPrimitives.ReverseEndianness(seq);
//设置确认号 //设置确认号
*(uint*)(tcpPtr + 8) = BinaryPrimitives.ReverseEndianness(cq); *(uint*)(tcpPtr + 8) = BinaryPrimitives.ReverseEndianness(_seq + payloadLength);
//设置TCP标志位为ACK其他标志位清除 //设置TCP标志位为ACK其他标志位清除
*(tcpPtr + 13) = 0b00010000; *(tcpPtr + 13) = 0b00010000;
@@ -246,7 +259,7 @@ namespace linker.tun
*(ushort*)(tcpPtr + 14) = BinaryPrimitives.ReverseEndianness((ushort)65535); *(ushort*)(tcpPtr + 14) = BinaryPrimitives.ReverseEndianness((ushort)65535);
//计算校验和 //计算校验和
ChecksumHelper.Checksum(dstPtr, totalLength); ChecksumHelper.Checksum(ipPtr, totalLength);
//只需要IP头+TCP头 //只需要IP头+TCP头
return totalLength; return totalLength;

View File

@@ -1,5 +1,5 @@
v1.9.0 v1.9.0
2025-08-30 15:59:20 2025-08-30 20:51:10
1. 一些累计更新 1. 一些累计更新
2. 服务器转发多节点 2. 服务器转发多节点
3. 虚拟网卡下伪造ACK为TCP-in-TCP隧道提速 3. 虚拟网卡下伪造ACK为TCP-in-TCP隧道提速