mirror of
https://github.com/snltty/linker.git
synced 2025-09-26 21:15:57 +08:00
192
This commit is contained in:
@@ -5,6 +5,17 @@ namespace linker.libs
|
||||
{
|
||||
public sealed class ChecksumHelper
|
||||
{
|
||||
public static unsafe void ClearChecksum(ReadOnlyMemory<byte> packet, bool ipHeader = true, bool payload = true)
|
||||
{
|
||||
ClearChecksum(packet.Span, ipHeader, payload);
|
||||
}
|
||||
public static unsafe void ClearChecksum(ReadOnlySpan<byte> packet, bool ipHeader = true, bool payload = true)
|
||||
{
|
||||
fixed (byte* ptr = packet)
|
||||
{
|
||||
ClearChecksum(ptr, ipHeader, payload);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 清空IP包的校验和
|
||||
/// </summary>
|
||||
@@ -79,6 +90,7 @@ namespace linker.libs
|
||||
ProtocolType.Udp => *(ushort*)(packetPtr + 6) == 0,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
if (ipHeader || payload)
|
||||
Checksum(ptr, ipHeader, payload);
|
||||
}
|
||||
|
@@ -91,14 +91,14 @@ namespace linker.messenger.tuntap
|
||||
public async Task InputPacket(LinkerTunDevicPacket packet)
|
||||
{
|
||||
//IPV4广播组播、IPV6 多播
|
||||
if ((packet.IPV4Broadcast /*|| packet.IPV6Multicast*/) && tuntapConfigTransfer.Info.Multicast == false && connections.IsEmpty == false)
|
||||
if ((packet.IPV4Broadcast || packet.IPV6Multicast) && tuntapConfigTransfer.Info.Multicast == false && connections.IsEmpty == false)
|
||||
{
|
||||
await Task.WhenAll(connections.Values.Where(c => c != null && c.Connected).Select(c => c.SendAsync(packet.Buffer, packet.Offset, packet.Length)));
|
||||
return;
|
||||
}
|
||||
|
||||
//IPV4+IPV6 单播
|
||||
uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DistIPAddress.Span[^4..]);
|
||||
uint ip = BinaryPrimitives.ReadUInt32BigEndian(packet.DstIp.Span[^4..]);
|
||||
if (tuntapCidrConnectionManager.TryGet(ip, out ITunnelConnection connection) && connection.Connected)
|
||||
{
|
||||
/*
|
||||
|
@@ -66,7 +66,7 @@ namespace linker.nat
|
||||
public void ToFakeDst(ReadOnlyMemory<byte> packet)
|
||||
{
|
||||
//只支持映射IPV4
|
||||
//if ((byte)(packet.Span[0] >> 4 & 0b1111) != 4) return;
|
||||
if ((byte)(packet.Span[0] >> 4 & 0b1111) != 4) return;
|
||||
//映射表不为空
|
||||
if (natDic.IsEmpty) return;
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace linker.nat
|
||||
public void ToRealDst(ReadOnlyMemory<byte> packet)
|
||||
{
|
||||
//只支持映射IPV4
|
||||
//if ((byte)(packet.Span[0] >> 4 & 0b1111) != 4) return;
|
||||
if ((byte)(packet.Span[0] >> 4 & 0b1111) != 4) return;
|
||||
//映射表不为空
|
||||
if (masks.Length == 0 || mapDic.Count == 0) return;
|
||||
//广播包
|
||||
@@ -122,8 +122,8 @@ namespace linker.nat
|
||||
{
|
||||
//修改目标IP,需要小端写入,IP计算都是按大端的,操作是小端的,所以转换一下
|
||||
*(uint*)(ptr + pos) = BinaryPrimitives.ReverseEndianness(newIP);
|
||||
//清空校验和,等待重新计算
|
||||
*(ushort*)(ptr + 10) = 0;
|
||||
//清除校验和,由于IP头和传输层协议头都修改了,所以都需要重新计算
|
||||
ChecksumHelper.ClearChecksum(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -84,7 +84,6 @@ namespace linker.nat
|
||||
source.SafeClose();
|
||||
continue;
|
||||
}
|
||||
|
||||
Socket dst = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
dst.BeginConnect(new IPEndPoint(NetworkHelper.ToIP(cache.IP), cache.Port), ConnectCallback, new TcpState { Source = source, Target = dst });
|
||||
}
|
||||
@@ -266,7 +265,7 @@ namespace linker.nat
|
||||
fixed (byte* ptr = packet.Span)
|
||||
{
|
||||
DstProxyPacket p = new DstProxyPacket(ptr);
|
||||
if (/*p.Version != 4 ||*/ p.DstAddr == tunIp || p.DstAddrSpan.IsCast()) return true;
|
||||
if (p.Version != 4 || p.DstAddr == tunIp || p.DstAddrSpan.IsCast()) return true;
|
||||
|
||||
if (lans.Any(c => p.DstAddr >= c.Item1 && p.DstAddr <= c.Item2) == false)
|
||||
{
|
||||
|
@@ -355,7 +355,7 @@ namespace linker.nat
|
||||
fixed (byte* ptr = packet.Span)
|
||||
{
|
||||
FakeAckPacket originPacket = new(ptr);
|
||||
if (/*originPacket.Version != 4 ||*/ originPacket.Protocol != ProtocolType.Tcp)
|
||||
if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -376,7 +376,7 @@ namespace linker.nat
|
||||
fixed (byte* ptr = packet.Span)
|
||||
{
|
||||
FakeAckPacket originPacket = new(ptr);
|
||||
if (/*originPacket.Version != 4 ||*/ originPacket.Protocol != ProtocolType.Tcp)
|
||||
if (originPacket.Version != 4 || originPacket.Protocol != ProtocolType.Tcp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@@ -128,7 +128,7 @@ namespace linker.nat
|
||||
if (state != LinkerFirewallState.Enabled) return;
|
||||
|
||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
||||
if (/*ipv4.Version == 4 &&*/ (ipv4.Protocol == ProtocolType.Udp || ipv4.Protocol == ProtocolType.Tcp))
|
||||
if (ipv4.Version == 4 && (ipv4.Protocol == ProtocolType.Udp || ipv4.Protocol == ProtocolType.Tcp))
|
||||
{
|
||||
(uint src, ushort srcPort, uint dst, ushort dstPort, ProtocolType pro) key = (ipv4.SrcAddr, ipv4.SrcPort, ipv4.DstAddr, ipv4.DstPort, ipv4.Protocol);
|
||||
if (cacheSrcMap.TryGetValue(key, out SrcCacheInfo cache) == false)
|
||||
@@ -176,7 +176,7 @@ namespace linker.nat
|
||||
|
||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
||||
//IPV4 TCP 和 UDP
|
||||
if (/*ipv4.Version == 4 &&*/ (ipv4.Protocol == ProtocolType.Udp || ipv4.Protocol == ProtocolType.Tcp))
|
||||
if (ipv4.Version == 4 && (ipv4.Protocol == ProtocolType.Udp || ipv4.Protocol == ProtocolType.Tcp))
|
||||
{
|
||||
//连接状态
|
||||
(uint src, ushort srcPort, uint dst, ushort dstPort, ProtocolType pro) key = (ipv4.DstAddr, ipv4.DstPort, ipv4.SrcAddr, ipv4.SrcPort, ipv4.Protocol);
|
||||
|
@@ -196,7 +196,7 @@ namespace linker.nat
|
||||
|
||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
||||
//不是 ipv4,是虚拟网卡ip,是广播,不nat
|
||||
if (/*ipv4.Version != 4 ||*/ ipv4.DstAddr == srcIp || ipv4.DstAddrSpan.IsCast())
|
||||
if (ipv4.Version != 4 || ipv4.DstAddr == srcIp || ipv4.DstAddrSpan.IsCast())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@@ -43,8 +43,8 @@ namespace linker.tun
|
||||
//6tcp 17udp
|
||||
if (ptr[9] == 6 || ptr[9] == 17)
|
||||
{
|
||||
IPAddress sourceIP = new IPAddress(packet.SourceIPAddress.Span);
|
||||
IPAddress distIP = new IPAddress(packet.DistIPAddress.Span);
|
||||
IPAddress sourceIP = new IPAddress(packet.SrcIp.Span);
|
||||
IPAddress distIP = new IPAddress(packet.DstIp.Span);
|
||||
|
||||
ushort sourcePort = *(ushort*)(ptr + 20);
|
||||
ushort distPort = *(ushort*)(ptr + 22);
|
||||
|
@@ -2,7 +2,9 @@
|
||||
using linker.libs.timer;
|
||||
using linker.tun.device;
|
||||
using linker.tun.hook;
|
||||
using System.Buffers.Binary;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using static linker.nat.LinkerDstMapping;
|
||||
|
||||
namespace linker.tun
|
||||
@@ -49,7 +51,10 @@ namespace linker.tun
|
||||
|
||||
public LinkerTunDeviceAdapter()
|
||||
{
|
||||
hooks = new ILinkerTunPacketHook[] { lanMap, lanDnat };
|
||||
hooks = new ILinkerTunPacketHook[] {
|
||||
lanMap,
|
||||
lanDnat
|
||||
};
|
||||
hooks1 = hooks.OrderByDescending(c => c.Level).ToArray();
|
||||
}
|
||||
|
||||
@@ -298,10 +303,10 @@ namespace linker.tun
|
||||
}
|
||||
|
||||
packet.Unpacket(buffer, 0, length);
|
||||
if (packet.DistIPAddress.Length == 0 || packet.Version != 4) continue;
|
||||
if (packet.DstIp.Length == 0 || packet.Version != 4) continue;
|
||||
|
||||
for (int i = 0; i < hooks1.Length; i++) if (hooks1[i].Read(packet.IPPacket) == false) goto end;
|
||||
ChecksumHelper.ChecksumWithZero(packet.IPPacket);
|
||||
for (int i = 0; i < hooks1.Length; i++) if (hooks1[i].Read(packet.RawPacket) == false) goto end;
|
||||
ChecksumHelper.ChecksumWithZero(packet.RawPacket);
|
||||
|
||||
await linkerTunDeviceCallback.Callback(packet).ConfigureAwait(false);
|
||||
|
||||
@@ -322,14 +327,17 @@ namespace linker.tun
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <returns></returns>
|
||||
public bool Write(string srcId, ReadOnlyMemory<byte> buffer)
|
||||
public unsafe bool Write(string srcId, ReadOnlyMemory<byte> buffer)
|
||||
{
|
||||
if (linkerTunDevice == null || Status != LinkerTunDeviceStatus.Running || new LinkerTunDevicValidatePacket(buffer).IsValid == false) return false;
|
||||
fixed (byte* ptr = buffer.Span)
|
||||
{
|
||||
if (Status != LinkerTunDeviceStatus.Running || BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + 2)) != buffer.Length) return false;
|
||||
|
||||
for (int i = 0; i < hooks.Length; i++) if (hooks[i].Write(srcId, buffer) == false) return false;
|
||||
ChecksumHelper.ChecksumWithZero(buffer);
|
||||
for (int i = 0; i < hooks.Length; i++) if (hooks[i].Write(srcId, buffer) == false) return false;
|
||||
ChecksumHelper.ChecksumWithZero(buffer);
|
||||
|
||||
return linkerTunDevice.Write(buffer);
|
||||
return linkerTunDevice.Write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -173,7 +173,7 @@ namespace linker.tun.device
|
||||
public int Offset { get; private set; }
|
||||
public int Length { get; private set; }
|
||||
|
||||
public Memory<byte> IPPacket => Buffer.AsMemory(Offset + 4, Length - 4);
|
||||
public Memory<byte> RawPacket => Buffer.AsMemory(Offset + 4, Length - 4);
|
||||
|
||||
/// <summary>
|
||||
/// 协议版本,4或者6
|
||||
@@ -188,95 +188,68 @@ namespace linker.tun.device
|
||||
/// <summary>
|
||||
/// 源IP
|
||||
/// </summary>
|
||||
public ReadOnlyMemory<byte> SourceIPAddress { get; private set; }
|
||||
public ReadOnlyMemory<byte> SrcIp { get; private set; }
|
||||
/// <summary>
|
||||
/// 源端口
|
||||
/// </summary>
|
||||
public ushort SourcePort { get; private set; }
|
||||
public ushort SrcPort { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标IP
|
||||
/// </summary>
|
||||
public ReadOnlyMemory<byte> DistIPAddress { get; private set; }
|
||||
public ReadOnlyMemory<byte> DstIp { get; private set; }
|
||||
/// <summary>
|
||||
/// 目标端口
|
||||
/// </summary>
|
||||
public ushort DistPort { get; private set; }
|
||||
public ushort DstPort { get; private set; }
|
||||
|
||||
public bool IPV4Broadcast => Version == 4 && DistIPAddress.IsCast();
|
||||
public bool IPV6Multicast => Version == 6 && (DistIPAddress.Span[0] & 0xFF) == 0xFF;
|
||||
public bool IPV4Broadcast => Version == 4 && DstIp.IsCast();
|
||||
public bool IPV6Multicast => Version == 6 && (DstIp.Span[0] & 0xFF) == 0xFF;
|
||||
|
||||
public LinkerTunDevicPacket()
|
||||
{
|
||||
}
|
||||
public void Unpacket(byte[] buffer, int offset, int length)
|
||||
public void Unpacket(byte[] buffer, int offset, int length, int pad = 4)
|
||||
{
|
||||
Buffer = buffer;
|
||||
Offset = offset;
|
||||
Length = length;
|
||||
|
||||
ReadOnlyMemory<byte> ipPacket = Buffer.AsMemory(Offset + 4, Length - 4);
|
||||
ReadOnlyMemory<byte> ipPacket = Buffer.AsMemory(Offset + pad, Length - pad);
|
||||
Version = (byte)(ipPacket.Span[0] >> 4 & 0b1111);
|
||||
|
||||
SourceIPAddress = Helper.EmptyArray;
|
||||
DistIPAddress = Helper.EmptyArray;
|
||||
SrcIp = Helper.EmptyArray;
|
||||
DstIp = Helper.EmptyArray;
|
||||
|
||||
if (Version == 4)
|
||||
{
|
||||
SourceIPAddress = ipPacket.Slice(12, 4);
|
||||
DistIPAddress = ipPacket.Slice(16, 4);
|
||||
SrcIp = ipPacket.Slice(12, 4);
|
||||
DstIp = 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());
|
||||
SrcPort = BinaryPrimitives.ReverseEndianness(ipPacket.Slice(20, 2).ToUInt16());
|
||||
DstPort = BinaryPrimitives.ReverseEndianness(ipPacket.Slice(22, 2).ToUInt16());
|
||||
}
|
||||
}
|
||||
else if (Version == 6)
|
||||
{
|
||||
SourceIPAddress = ipPacket.Slice(8, 16);
|
||||
DistIPAddress = ipPacket.Slice(24, 16);
|
||||
SrcIp = ipPacket.Slice(8, 16);
|
||||
DstIp = 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(44, 2).ToUInt16());
|
||||
SrcPort = BinaryPrimitives.ReverseEndianness(ipPacket.Slice(42, 2).ToUInt16());
|
||||
DstPort = BinaryPrimitives.ReverseEndianness(ipPacket.Slice(44, 2).ToUInt16());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public struct LinkerTunDevicValidatePacket
|
||||
{
|
||||
public bool IsValid { get; private set; }
|
||||
public LinkerTunDevicValidatePacket(ReadOnlyMemory<byte> packet)
|
||||
{
|
||||
if (packet.Length >= 1)
|
||||
{
|
||||
byte version = (byte)(packet.Span[0] >> 4 & 0b1111);
|
||||
int headLength = /*version == 4 ?*/ (packet.Span[0] & 0b1111) * 4 /*: 40*/;
|
||||
if (packet.Length < headLength) return;
|
||||
|
||||
ProtocolType protocolType = version switch
|
||||
{
|
||||
4 => (ProtocolType)packet.Span[9],
|
||||
6 => (ProtocolType)packet.Span[6],
|
||||
_ => ProtocolType.Unknown
|
||||
};
|
||||
IsValid = protocolType switch
|
||||
{
|
||||
ProtocolType.Tcp => packet.Length >= headLength + 20,
|
||||
ProtocolType.Udp => packet.Length >= headLength + 8,
|
||||
ProtocolType.Icmp => packet.Length >= headLength + 8,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加路由项
|
||||
|
@@ -1,7 +1,4 @@
|
||||
|
||||
using linker.tun.device;
|
||||
|
||||
namespace linker.tun.hook
|
||||
namespace linker.tun.hook
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据包钩子
|
||||
|
@@ -1,5 +1,5 @@
|
||||
v1.9.2
|
||||
2025-09-23 16:48:18
|
||||
2025-09-24 20:19:20
|
||||
1. 一些累计更新,一些BUG修复
|
||||
2. 使用代理方式重写应用层NAT
|
||||
3. 新增服务端webapi,对外提供公开数据,监听1803端口,设置为0则不监听
|
||||
|
Reference in New Issue
Block a user