mirror of
https://github.com/snltty/linker.git
synced 2025-09-27 05:25:57 +08:00
ack欺骗
This commit is contained in:
10
.github/workflows/dotnet.yml
vendored
10
.github/workflows/dotnet.yml
vendored
@@ -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
|
||||||
|
@@ -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/8,win server2008/2012`这样的老系统无法使用系统NAT时也可以顺利使用点对网和网对网。
|
- **应用层NAT:** 内置了使用`WinDivert`实现的应用层NAT,即使在`win7/8,win server2008/2012`这样的老系统无法使用系统NAT时也可以顺利使用点对网和网对网。
|
||||||
- **应用层防火墙:** 内置了防火墙功能,应用于虚拟网卡、端口转发、socks5,可以精细控制客户端的访问权限,例如只允许A访问B的3389,其它客户端无法访问
|
- **应用层防火墙:** 内置了防火墙功能,应用于虚拟网卡、端口转发、socks5,可以精细控制客户端的访问权限,例如只允许A访问B的3389,其它客户端无法访问
|
||||||
|
@@ -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`,
|
||||||
|
@@ -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;
|
||||||
|
@@ -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隧道提速
|
||||||
|
Reference in New Issue
Block a user