mirror of
https://github.com/snltty/linker.git
synced 2025-09-26 21:15:57 +08:00
192
This commit is contained in:
@@ -5,48 +5,6 @@ namespace linker.libs
|
|||||||
{
|
{
|
||||||
public sealed class ChecksumHelper
|
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>
|
|
||||||
/// <param name="ptr"></param>
|
|
||||||
/// <param name="ipHeader">是否情况IP头校验和</param>
|
|
||||||
/// <param name="payload">是否清空荷载协议校验和</param>
|
|
||||||
public static unsafe void ClearChecksum(byte* ptr, bool ipHeader = true, bool payload = true)
|
|
||||||
{
|
|
||||||
byte ipHeaderLength = (byte)((*ptr & 0b1111) * 4);
|
|
||||||
byte* packetPtr = ptr + ipHeaderLength;
|
|
||||||
|
|
||||||
if (ipHeader)
|
|
||||||
{
|
|
||||||
*(ushort*)(ptr + 10) = 0;
|
|
||||||
}
|
|
||||||
if (payload)
|
|
||||||
{
|
|
||||||
int index = (ProtocolType)(*(ptr + 9)) switch
|
|
||||||
{
|
|
||||||
ProtocolType.Icmp => 2,
|
|
||||||
ProtocolType.Tcp => 16,
|
|
||||||
ProtocolType.Udp => 6,
|
|
||||||
_ => -1,
|
|
||||||
};
|
|
||||||
if (index > 0)
|
|
||||||
{
|
|
||||||
*(ushort*)(packetPtr + index) = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计算IP包的校验和,当校验和为0时才计算
|
/// 计算IP包的校验和,当校验和为0时才计算
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
|
using linker.libs.extends;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
namespace linker.nat
|
namespace linker.nat
|
||||||
{
|
{
|
||||||
@@ -62,70 +64,60 @@ namespace linker.nat
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换为假IP
|
/// 转换为假IP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="packet">TCP/IP</param>
|
/// <param name="buffer">TCP/IP</param>
|
||||||
public void ToFakeDst(ReadOnlyMemory<byte> packet)
|
public unsafe void ToFakeDst(ReadOnlyMemory<byte> buffer)
|
||||||
{
|
{
|
||||||
//只支持映射IPV4
|
|
||||||
if ((byte)(packet.Span[0] >> 4 & 0b1111) != 4) return;
|
|
||||||
//映射表不为空
|
//映射表不为空
|
||||||
if (natDic.IsEmpty) return;
|
if (natDic.IsEmpty) return;
|
||||||
|
|
||||||
//源IP
|
fixed (byte* ptr = buffer.Span)
|
||||||
uint realDist = NetworkHelper.ToValue(packet.Span.Slice(12, 4));
|
|
||||||
if (natDic.TryGetValue(realDist, out uint fakeDist))
|
|
||||||
{
|
{
|
||||||
//修改源IP
|
MapPacket packet = new MapPacket(ptr);
|
||||||
ReWriteIP(packet, fakeDist, 12);
|
//只支持映射IPV4
|
||||||
|
if (packet.Version != 4) return;
|
||||||
|
|
||||||
|
if (natDic.TryGetValue(packet.SrcAddr, out uint fakeDist))
|
||||||
|
{
|
||||||
|
packet.SrcAddr = fakeDist;
|
||||||
|
packet.IPChecksum = 0;
|
||||||
|
packet.PayloadChecksum = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换为真IP
|
/// 转换为真IP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="packet">TCP/IP</param>
|
/// <param name="packet">TCP/IP</param>
|
||||||
/// <param name="checksum">是否计算校验和,如果使用了应用层NAT,可以交给应用层NAT去计算校验和</param>
|
/// <param name="checksum">是否计算校验和,如果使用了应用层NAT,可以交给应用层NAT去计算校验和</param>
|
||||||
public void ToRealDst(ReadOnlyMemory<byte> packet)
|
public unsafe void ToRealDst(ReadOnlyMemory<byte> buffer)
|
||||||
{
|
{
|
||||||
//只支持映射IPV4
|
|
||||||
if ((byte)(packet.Span[0] >> 4 & 0b1111) != 4) return;
|
|
||||||
//映射表不为空
|
//映射表不为空
|
||||||
if (masks.Length == 0 || mapDic.Count == 0) return;
|
if (masks.Length == 0 || mapDic.Count == 0) return;
|
||||||
//广播包
|
|
||||||
if (packet.Span[19] == 255) return;
|
|
||||||
|
|
||||||
uint fakeDist = NetworkHelper.ToValue(packet.Span.Slice(16, 4));
|
fixed (byte* ptr = buffer.Span)
|
||||||
|
|
||||||
for (int i = 0; i < masks.Length; i++)
|
|
||||||
{
|
{
|
||||||
//目标IP网络号存在映射表中,找到映射后的真实网络号,替换网络号得到最终真实的IP
|
MapPacket packet = new MapPacket(ptr);
|
||||||
if (mapDic.TryGetValue(fakeDist & masks[i], out uint realNetwork))
|
//只支持映射IPV4
|
||||||
|
if (packet.Version != 4 || packet.DstAddrSpan.IsCast()) return;
|
||||||
|
|
||||||
|
uint fakeDist = packet.DstAddr;
|
||||||
|
for (int i = 0; i < masks.Length; i++)
|
||||||
{
|
{
|
||||||
uint realDist = realNetwork | (fakeDist & ~masks[i]);
|
//目标IP网络号存在映射表中,找到映射后的真实网络号,替换网络号得到最终真实的IP
|
||||||
//修改目标IP
|
if (mapDic.TryGetValue(fakeDist & masks[i], out uint realNetwork))
|
||||||
ReWriteIP(packet, realDist, 16);
|
|
||||||
if (natDic.TryGetValue(realDist, out uint value) == false || value != fakeDist)
|
|
||||||
{
|
{
|
||||||
natDic.AddOrUpdate(realDist, fakeDist, (a, b) => fakeDist);
|
uint realDist = realNetwork | (fakeDist & ~masks[i]);
|
||||||
|
packet.DstAddr = realDist;
|
||||||
|
if (natDic.TryGetValue(realDist, out uint value) == false || value != fakeDist)
|
||||||
|
{
|
||||||
|
natDic.AddOrUpdate(realDist, fakeDist, (a, b) => fakeDist);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// 写入新IP
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="packet">IP包</param>
|
|
||||||
/// <param name="newIP">大端IP</param>
|
|
||||||
/// <param name="pos">写入位置,源12,目的16</param>
|
|
||||||
private unsafe void ReWriteIP(ReadOnlyMemory<byte> packet, uint newIP, int pos)
|
|
||||||
{
|
|
||||||
fixed (byte* ptr = packet.Span)
|
|
||||||
{
|
|
||||||
//修改目标IP,需要小端写入,IP计算都是按大端的,操作是小端的,所以转换一下
|
|
||||||
*(uint*)(ptr + pos) = BinaryPrimitives.ReverseEndianness(newIP);
|
|
||||||
//清除校验和,由于IP头和传输层协议头都修改了,所以都需要重新计算
|
|
||||||
ChecksumHelper.ClearChecksum(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 映射对象
|
/// 映射对象
|
||||||
@@ -145,5 +137,104 @@ namespace linker.nat
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public byte PrefixLength { get; set; }
|
public byte PrefixLength { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly unsafe struct MapPacket
|
||||||
|
{
|
||||||
|
private readonly byte* ptr;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议版本
|
||||||
|
/// </summary>
|
||||||
|
public readonly byte Version => (byte)((*ptr >> 4) & 0b1111);
|
||||||
|
public readonly ProtocolType Protocol => (ProtocolType)(*(ptr + 9));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IP头长度
|
||||||
|
/// </summary>
|
||||||
|
public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
|
||||||
|
/// <summary>
|
||||||
|
/// IP包荷载数据指针,也就是TCP/UDP头指针
|
||||||
|
/// </summary>
|
||||||
|
public readonly byte* PayloadPtr => ptr + IPHeadLength;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 源地址
|
||||||
|
/// </summary>
|
||||||
|
public readonly uint SrcAddr
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 12));
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
*(uint*)(ptr + 12) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 目的地址
|
||||||
|
/// </summary>
|
||||||
|
public readonly uint DstAddr
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
*(uint*)(ptr + 16) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ReadOnlySpan<byte> DstAddrSpan => new Span<byte>((ptr + 16), 4);
|
||||||
|
|
||||||
|
public readonly ushort IPChecksum
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + 10));
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
*(ushort*)(ptr + 10) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public readonly ushort PayloadChecksum
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Protocol switch
|
||||||
|
{
|
||||||
|
ProtocolType.Icmp => BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr + 2)),
|
||||||
|
ProtocolType.Tcp => BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr + 16)),
|
||||||
|
ProtocolType.Udp => BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr + 6)),
|
||||||
|
_ => (ushort)0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (Protocol)
|
||||||
|
{
|
||||||
|
case ProtocolType.Icmp:
|
||||||
|
*(ushort*)(PayloadPtr + 2) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
break;
|
||||||
|
case ProtocolType.Tcp:
|
||||||
|
*(ushort*)(PayloadPtr + 16) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
break;
|
||||||
|
case ProtocolType.Udp:
|
||||||
|
*(ushort*)(PayloadPtr + 6) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载TCP/IP包,必须是一个完整的TCP/IP包
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ptr">一个完整的TCP/IP包</param>
|
||||||
|
public MapPacket(byte* ptr)
|
||||||
|
{
|
||||||
|
this.ptr = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.timer;
|
using linker.libs.timer;
|
||||||
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using static linker.nat.LinkerSrcNat;
|
|
||||||
namespace linker.nat
|
namespace linker.nat
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -123,20 +123,23 @@ namespace linker.nat
|
|||||||
/// 添加一个允许,比如 192.168.1.1:12345->192.168.100.100:80,等下192.168.100.100:80->192.168.1.1:12345时要允许,越过防火墙
|
/// 添加一个允许,比如 192.168.1.1:12345->192.168.100.100:80,等下192.168.100.100:80->192.168.1.1:12345时要允许,越过防火墙
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="packet">一个TCP/IP包</param>
|
/// <param name="packet">一个TCP/IP包</param>
|
||||||
public void AddAllow(ReadOnlyMemory<byte> packet)
|
public unsafe void AddAllow(ReadOnlyMemory<byte> packet)
|
||||||
{
|
{
|
||||||
if (state != LinkerFirewallState.Enabled) return;
|
if (state != LinkerFirewallState.Enabled) return;
|
||||||
|
|
||||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
fixed (byte* ptr = packet.Span)
|
||||||
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);
|
FirewallPacket ipv4 = new FirewallPacket(ptr);
|
||||||
if (cacheSrcMap.TryGetValue(key, out SrcCacheInfo cache) == false)
|
if (ipv4.Version == 4 && (ipv4.Protocol == ProtocolType.Udp || ipv4.Protocol == ProtocolType.Tcp))
|
||||||
{
|
{
|
||||||
cache = new SrcCacheInfo { Type = SrcCacheType.Out };
|
(uint src, ushort srcPort, uint dst, ushort dstPort, ProtocolType pro) key = (ipv4.SrcAddr, ipv4.SrcPort, ipv4.DstAddr, ipv4.DstPort, ipv4.Protocol);
|
||||||
cacheSrcMap.TryAdd(key, cache);
|
if (cacheSrcMap.TryGetValue(key, out SrcCacheInfo cache) == false)
|
||||||
|
{
|
||||||
|
cache = new SrcCacheInfo { Type = SrcCacheType.Out };
|
||||||
|
cacheSrcMap.TryAdd(key, cache);
|
||||||
|
}
|
||||||
|
cache.LastTime = Environment.TickCount64;
|
||||||
}
|
}
|
||||||
cache.LastTime = Environment.TickCount64;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +160,7 @@ namespace linker.nat
|
|||||||
|
|
||||||
return Check(srcId, dst, dstPort, protocol);
|
return Check(srcId, dst, dstPort, protocol);
|
||||||
}
|
}
|
||||||
public bool Check(string srcId, (uint ip,ushort port) dstEP, ProtocolType protocol)
|
public bool Check(string srcId, (uint ip, ushort port) dstEP, ProtocolType protocol)
|
||||||
{
|
{
|
||||||
if (this.state != LinkerFirewallState.Enabled) return true;
|
if (this.state != LinkerFirewallState.Enabled) return true;
|
||||||
return Check(srcId, dstEP.ip, dstEP.port, protocol);
|
return Check(srcId, dstEP.ip, dstEP.port, protocol);
|
||||||
@@ -170,29 +173,32 @@ namespace linker.nat
|
|||||||
/// <param name="srcId">客户端Id</param>
|
/// <param name="srcId">客户端Id</param>
|
||||||
/// <param name="packet">TCP/IP数据包</param>
|
/// <param name="packet">TCP/IP数据包</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool Check(string srcId, ReadOnlyMemory<byte> packet)
|
public unsafe bool Check(string srcId, ReadOnlyMemory<byte> packet)
|
||||||
{
|
{
|
||||||
if (state != LinkerFirewallState.Enabled) return true;
|
if (state != LinkerFirewallState.Enabled) return true;
|
||||||
|
|
||||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
fixed (byte* ptr = packet.Span)
|
||||||
//IPV4 TCP 和 UDP
|
|
||||||
if (ipv4.Version == 4 && (ipv4.Protocol == ProtocolType.Udp || ipv4.Protocol == ProtocolType.Tcp))
|
|
||||||
{
|
{
|
||||||
//连接状态
|
FirewallPacket ipv4 = new FirewallPacket(ptr);
|
||||||
(uint src, ushort srcPort, uint dst, ushort dstPort, ProtocolType pro) key = (ipv4.DstAddr, ipv4.DstPort, ipv4.SrcAddr, ipv4.SrcPort, ipv4.Protocol);
|
//IPV4 TCP 和 UDP
|
||||||
if (cacheSrcMap.TryGetValue(key, out SrcCacheInfo cache) == false)
|
if (ipv4.Version == 4 && (ipv4.Protocol == ProtocolType.Udp || ipv4.Protocol == ProtocolType.Tcp))
|
||||||
{
|
{
|
||||||
cache = new SrcCacheInfo { Type = SrcCacheType.In };
|
//连接状态
|
||||||
cacheSrcMap.TryAdd(key, cache);
|
(uint src, ushort srcPort, uint dst, ushort dstPort, ProtocolType pro) key = (ipv4.DstAddr, ipv4.DstPort, ipv4.SrcAddr, ipv4.SrcPort, ipv4.Protocol);
|
||||||
|
if (cacheSrcMap.TryGetValue(key, out SrcCacheInfo cache) == false)
|
||||||
|
{
|
||||||
|
cache = new SrcCacheInfo { Type = SrcCacheType.In };
|
||||||
|
cacheSrcMap.TryAdd(key, cache);
|
||||||
|
}
|
||||||
|
cache.LastTime = Environment.TickCount64;
|
||||||
|
|
||||||
|
//有出站标记 或 通过检查
|
||||||
|
return cache.Type == SrcCacheType.Out
|
||||||
|
|| Check(srcId, ipv4.SrcAddr, ipv4.SrcPort, ipv4.Protocol);
|
||||||
}
|
}
|
||||||
cache.LastTime = Environment.TickCount64;
|
|
||||||
|
|
||||||
//有出站标记 或 通过检查
|
return true;
|
||||||
return cache.Type == SrcCacheType.Out
|
|
||||||
|| Check(srcId, ipv4.SrcAddr, ipv4.SrcPort, ipv4.Protocol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool Check(string srcId, uint ip, ushort port, ProtocolType protocol)
|
private bool Check(string srcId, uint ip, ushort port, ProtocolType protocol)
|
||||||
@@ -255,7 +261,104 @@ namespace linker.nat
|
|||||||
public LinkerFirewallProtocolType Protocol { get; set; }
|
public LinkerFirewallProtocolType Protocol { get; set; }
|
||||||
public LinkerFirewallAction Action { get; set; }
|
public LinkerFirewallAction Action { get; set; }
|
||||||
}
|
}
|
||||||
|
sealed class SrcCacheInfo
|
||||||
|
{
|
||||||
|
public long LastTime { get; set; } = Environment.TickCount64;
|
||||||
|
public SrcCacheType Type { get; set; }
|
||||||
|
}
|
||||||
|
enum SrcCacheType
|
||||||
|
{
|
||||||
|
In = 0,
|
||||||
|
Out = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly unsafe struct FirewallPacket
|
||||||
|
{
|
||||||
|
private readonly byte* ptr;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 协议版本
|
||||||
|
/// </summary>
|
||||||
|
public readonly byte Version => (byte)((*ptr >> 4) & 0b1111);
|
||||||
|
public readonly ProtocolType Protocol => (ProtocolType)(*(ptr + 9));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IP头长度
|
||||||
|
/// </summary>
|
||||||
|
public readonly int IPHeadLength => (*ptr & 0b1111) * 4;
|
||||||
|
/// <summary>
|
||||||
|
/// IP包荷载数据指针,也就是TCP/UDP头指针
|
||||||
|
/// </summary>
|
||||||
|
public readonly byte* PayloadPtr => ptr + IPHeadLength;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 源地址
|
||||||
|
/// </summary>
|
||||||
|
public readonly uint SrcAddr
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 12));
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
*(uint*)(ptr + 12) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 源端口
|
||||||
|
/// </summary>
|
||||||
|
public readonly ushort SrcPort
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr));
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
*(ushort*)(PayloadPtr) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 目的地址
|
||||||
|
/// </summary>
|
||||||
|
public readonly uint DstAddr
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
*(uint*)(ptr + 16) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 目标端口
|
||||||
|
/// </summary>
|
||||||
|
public readonly ushort DstPort
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return BinaryPrimitives.ReverseEndianness(*(ushort*)(PayloadPtr + 2));
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
*(ushort*)(PayloadPtr + 2) = BinaryPrimitives.ReverseEndianness(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载TCP/IP包,必须是一个完整的TCP/IP包
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ptr">一个完整的TCP/IP包</param>
|
||||||
|
public FirewallPacket(byte* ptr)
|
||||||
|
{
|
||||||
|
this.ptr = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LinkerFirewallRuleInfo
|
public class LinkerFirewallRuleInfo
|
||||||
{
|
{
|
||||||
public string SrcId { get; set; } = string.Empty;
|
public string SrcId { get; set; } = string.Empty;
|
||||||
@@ -266,7 +369,6 @@ namespace linker.nat
|
|||||||
public LinkerFirewallProtocolType Protocol { get; set; }
|
public LinkerFirewallProtocolType Protocol { get; set; }
|
||||||
public LinkerFirewallAction Action { get; set; }
|
public LinkerFirewallAction Action { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum LinkerFirewallProtocolType : byte
|
public enum LinkerFirewallProtocolType : byte
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
@@ -286,15 +388,9 @@ namespace linker.nat
|
|||||||
Disabled = 1
|
Disabled = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SrcCacheInfo
|
|
||||||
{
|
|
||||||
public long LastTime { get; set; } = Environment.TickCount64;
|
|
||||||
public SrcCacheType Type { get; set; }
|
|
||||||
}
|
|
||||||
public enum SrcCacheType
|
|
||||||
{
|
|
||||||
In = 0,
|
|
||||||
Out = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -194,7 +194,7 @@ namespace linker.nat
|
|||||||
{
|
{
|
||||||
if (winDivert == null) return false;
|
if (winDivert == null) return false;
|
||||||
|
|
||||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
SrcNatPacket ipv4 = new SrcNatPacket(packet.Span);
|
||||||
//不是 ipv4,是虚拟网卡ip,是广播,不nat
|
//不是 ipv4,是虚拟网卡ip,是广播,不nat
|
||||||
if (ipv4.Version != 4 || ipv4.DstAddr == srcIp || ipv4.DstAddrSpan.IsCast())
|
if (ipv4.Version != 4 || ipv4.DstAddr == srcIp || ipv4.DstAddrSpan.IsCast())
|
||||||
{
|
{
|
||||||
@@ -241,7 +241,7 @@ namespace linker.nat
|
|||||||
//只操作response 和 request
|
//只操作response 和 request
|
||||||
if (p.ICMPv4Hdr->Type != 0 && p.ICMPv4Hdr->Type != 8) return false;
|
if (p.ICMPv4Hdr->Type != 0 && p.ICMPv4Hdr->Type != 8) return false;
|
||||||
|
|
||||||
IPV4Packet ipv4 = new IPV4Packet(ptr);
|
SrcNatPacket ipv4 = new SrcNatPacket(ptr);
|
||||||
if (ipv4.IsFragment) return false;
|
if (ipv4.IsFragment) return false;
|
||||||
|
|
||||||
//原标识符,两个字节
|
//原标识符,两个字节
|
||||||
@@ -287,7 +287,7 @@ namespace linker.nat
|
|||||||
//只操作response 和 request
|
//只操作response 和 request
|
||||||
if (p.ICMPv4Hdr->Type != 0 && p.ICMPv4Hdr->Type != 8) return false;
|
if (p.ICMPv4Hdr->Type != 0 && p.ICMPv4Hdr->Type != 8) return false;
|
||||||
|
|
||||||
IPV4Packet ipv4 = new IPV4Packet(ptr);
|
SrcNatPacket ipv4 = new SrcNatPacket(ptr);
|
||||||
|
|
||||||
//标识符,两个字节
|
//标识符,两个字节
|
||||||
byte* ptr0 = ipv4.IcmpIdentifier0;
|
byte* ptr0 = ipv4.IcmpIdentifier0;
|
||||||
@@ -316,7 +316,7 @@ namespace linker.nat
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private unsafe bool InjectTcp(WinDivertParseResult p, byte* ptr, NetworkIPv4Addr interfaceAddr)
|
private unsafe bool InjectTcp(WinDivertParseResult p, byte* ptr, NetworkIPv4Addr interfaceAddr)
|
||||||
{
|
{
|
||||||
IPV4Packet ipv4 = new IPV4Packet(ptr);
|
SrcNatPacket ipv4 = new SrcNatPacket(ptr);
|
||||||
|
|
||||||
//新端口
|
//新端口
|
||||||
ValueTuple<uint, ushort> portKey = (p.IPv4Hdr->SrcAddr.Raw, p.TCPHdr->SrcPort);
|
ValueTuple<uint, ushort> portKey = (p.IPv4Hdr->SrcAddr.Raw, p.TCPHdr->SrcPort);
|
||||||
@@ -358,7 +358,7 @@ namespace linker.nat
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private unsafe bool RecvTcp(WinDivertParseResult p, byte* ptr)
|
private unsafe bool RecvTcp(WinDivertParseResult p, byte* ptr)
|
||||||
{
|
{
|
||||||
IPV4Packet ipv4 = new IPV4Packet(ptr);
|
SrcNatPacket ipv4 = new SrcNatPacket(ptr);
|
||||||
|
|
||||||
ValueTuple<uint, ushort, uint, ushort, ProtocolType> key = (p.IPv4Hdr->DstAddr.Raw, p.TCPHdr->DstPort, p.IPv4Hdr->SrcAddr.Raw, p.TCPHdr->SrcPort, ProtocolType.Tcp);
|
ValueTuple<uint, ushort, uint, ushort, ProtocolType> key = (p.IPv4Hdr->DstAddr.Raw, p.TCPHdr->DstPort, p.IPv4Hdr->SrcAddr.Raw, p.TCPHdr->SrcPort, ProtocolType.Tcp);
|
||||||
if (natMap.TryGetValue(key, out NatMapInfo natMapInfo))
|
if (natMap.TryGetValue(key, out NatMapInfo natMapInfo))
|
||||||
@@ -541,7 +541,7 @@ namespace linker.nat
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// IPV4 包
|
/// IPV4 包
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe struct IPV4Packet
|
public unsafe struct SrcNatPacket
|
||||||
{
|
{
|
||||||
byte* ptr;
|
byte* ptr;
|
||||||
|
|
||||||
@@ -549,25 +549,11 @@ namespace linker.nat
|
|||||||
/// 协议版本
|
/// 协议版本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte Version => (byte)((*ptr >> 4) & 0b1111);
|
public byte Version => (byte)((*ptr >> 4) & 0b1111);
|
||||||
public ProtocolType Protocol => (ProtocolType)(*(ptr + 9));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 源地址
|
|
||||||
/// </summary>
|
|
||||||
public uint SrcAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 12));
|
|
||||||
/// <summary>
|
|
||||||
/// 源端口
|
|
||||||
/// </summary>
|
|
||||||
public ushort SrcPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength));
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 目的地址
|
/// 目的地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint DstAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
|
public uint DstAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 目标端口
|
|
||||||
/// </summary>
|
|
||||||
public ushort DstPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 2));
|
|
||||||
/// <summary>
|
|
||||||
/// 源地址
|
/// 源地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ReadOnlySpan<byte> SrcAddrSpan => new Span<byte>((ptr + 12), 4);
|
public ReadOnlySpan<byte> SrcAddrSpan => new Span<byte>((ptr + 12), 4);
|
||||||
@@ -586,10 +572,6 @@ namespace linker.nat
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public byte Flag => (byte)(*(ptr + 6) >> 5);
|
public byte Flag => (byte)(*(ptr + 6) >> 5);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 不分片
|
|
||||||
/// </summary>
|
|
||||||
public bool DontFragment => (Flag & 0x02) == 2;
|
|
||||||
/// <summary>
|
|
||||||
/// 更多分片
|
/// 更多分片
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool MoreFragment => (Flag & 0x01) == 1;
|
public bool MoreFragment => (Flag & 0x01) == 1;
|
||||||
@@ -622,11 +604,11 @@ namespace linker.nat
|
|||||||
public bool TcpFlagAck => (TcpFlag & 0b010000) != 0;
|
public bool TcpFlagAck => (TcpFlag & 0b010000) != 0;
|
||||||
public bool TcpFlagUrg => (TcpFlag & 0b100000) != 0;
|
public bool TcpFlagUrg => (TcpFlag & 0b100000) != 0;
|
||||||
|
|
||||||
public IPV4Packet(byte* ptr)
|
public SrcNatPacket(byte* ptr)
|
||||||
{
|
{
|
||||||
this.ptr = ptr;
|
this.ptr = ptr;
|
||||||
}
|
}
|
||||||
public IPV4Packet(ReadOnlySpan<byte> span)
|
public SrcNatPacket(ReadOnlySpan<byte> span)
|
||||||
{
|
{
|
||||||
fixed (byte* ptr = span)
|
fixed (byte* ptr = span)
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
v1.9.2
|
v1.9.2
|
||||||
2025-09-24 20:19:20
|
2025-09-24 20:55:51
|
||||||
1. 一些累计更新,一些BUG修复
|
1. 一些累计更新,一些BUG修复
|
||||||
2. 使用代理方式重写应用层NAT
|
2. 使用代理方式重写应用层NAT
|
||||||
3. 新增服务端webapi,对外提供公开数据,监听1803端口,设置为0则不监听
|
3. 新增服务端webapi,对外提供公开数据,监听1803端口,设置为0则不监听
|
||||||
|
Reference in New Issue
Block a user