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 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>
|
||||
/// 计算IP包的校验和,当校验和为0时才计算
|
||||
|
@@ -1,9 +1,11 @@
|
||||
using linker.libs;
|
||||
using linker.libs.extends;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Frozen;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace linker.nat
|
||||
{
|
||||
@@ -62,46 +64,51 @@ namespace linker.nat
|
||||
/// <summary>
|
||||
/// 转换为假IP
|
||||
/// </summary>
|
||||
/// <param name="packet">TCP/IP</param>
|
||||
public void ToFakeDst(ReadOnlyMemory<byte> packet)
|
||||
/// <param name="buffer">TCP/IP</param>
|
||||
public unsafe void ToFakeDst(ReadOnlyMemory<byte> buffer)
|
||||
{
|
||||
//只支持映射IPV4
|
||||
if ((byte)(packet.Span[0] >> 4 & 0b1111) != 4) return;
|
||||
//映射表不为空
|
||||
if (natDic.IsEmpty) return;
|
||||
|
||||
//源IP
|
||||
uint realDist = NetworkHelper.ToValue(packet.Span.Slice(12, 4));
|
||||
if (natDic.TryGetValue(realDist, out uint fakeDist))
|
||||
fixed (byte* ptr = buffer.Span)
|
||||
{
|
||||
//修改源IP
|
||||
ReWriteIP(packet, fakeDist, 12);
|
||||
MapPacket packet = new MapPacket(ptr);
|
||||
//只支持映射IPV4
|
||||
if (packet.Version != 4) return;
|
||||
|
||||
if (natDic.TryGetValue(packet.SrcAddr, out uint fakeDist))
|
||||
{
|
||||
packet.SrcAddr = fakeDist;
|
||||
packet.IPChecksum = 0;
|
||||
packet.PayloadChecksum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 转换为真IP
|
||||
/// </summary>
|
||||
/// <param name="packet">TCP/IP</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 (packet.Span[19] == 255) return;
|
||||
|
||||
uint fakeDist = NetworkHelper.ToValue(packet.Span.Slice(16, 4));
|
||||
fixed (byte* ptr = buffer.Span)
|
||||
{
|
||||
MapPacket packet = new MapPacket(ptr);
|
||||
//只支持映射IPV4
|
||||
if (packet.Version != 4 || packet.DstAddrSpan.IsCast()) return;
|
||||
|
||||
uint fakeDist = packet.DstAddr;
|
||||
for (int i = 0; i < masks.Length; i++)
|
||||
{
|
||||
//目标IP网络号存在映射表中,找到映射后的真实网络号,替换网络号得到最终真实的IP
|
||||
if (mapDic.TryGetValue(fakeDist & masks[i], out uint realNetwork))
|
||||
{
|
||||
uint realDist = realNetwork | (fakeDist & ~masks[i]);
|
||||
//修改目标IP
|
||||
ReWriteIP(packet, realDist, 16);
|
||||
packet.DstAddr = realDist;
|
||||
if (natDic.TryGetValue(realDist, out uint value) == false || value != fakeDist)
|
||||
{
|
||||
natDic.AddOrUpdate(realDist, fakeDist, (a, b) => fakeDist);
|
||||
@@ -110,21 +117,6 @@ namespace linker.nat
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <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>
|
||||
@@ -145,5 +137,104 @@ namespace linker.nat
|
||||
/// </summary>
|
||||
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.timer;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using static linker.nat.LinkerSrcNat;
|
||||
namespace linker.nat
|
||||
{
|
||||
/// <summary>
|
||||
@@ -123,11 +123,13 @@ namespace linker.nat
|
||||
/// 添加一个允许,比如 192.168.1.1:12345->192.168.100.100:80,等下192.168.100.100:80->192.168.1.1:12345时要允许,越过防火墙
|
||||
/// </summary>
|
||||
/// <param name="packet">一个TCP/IP包</param>
|
||||
public void AddAllow(ReadOnlyMemory<byte> packet)
|
||||
public unsafe void AddAllow(ReadOnlyMemory<byte> packet)
|
||||
{
|
||||
if (state != LinkerFirewallState.Enabled) return;
|
||||
|
||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
||||
fixed (byte* ptr = packet.Span)
|
||||
{
|
||||
FirewallPacket ipv4 = new FirewallPacket(ptr);
|
||||
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);
|
||||
@@ -139,6 +141,7 @@ namespace linker.nat
|
||||
cache.LastTime = Environment.TickCount64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查数据包是否符合规则
|
||||
@@ -157,7 +160,7 @@ namespace linker.nat
|
||||
|
||||
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;
|
||||
return Check(srcId, dstEP.ip, dstEP.port, protocol);
|
||||
@@ -170,11 +173,13 @@ namespace linker.nat
|
||||
/// <param name="srcId">客户端Id</param>
|
||||
/// <param name="packet">TCP/IP数据包</param>
|
||||
/// <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;
|
||||
|
||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
||||
fixed (byte* ptr = packet.Span)
|
||||
{
|
||||
FirewallPacket ipv4 = new FirewallPacket(ptr);
|
||||
//IPV4 TCP 和 UDP
|
||||
if (ipv4.Version == 4 && (ipv4.Protocol == ProtocolType.Udp || ipv4.Protocol == ProtocolType.Tcp))
|
||||
{
|
||||
@@ -194,6 +199,7 @@ namespace linker.nat
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool Check(string srcId, uint ip, ushort port, ProtocolType protocol)
|
||||
{
|
||||
@@ -255,7 +261,104 @@ namespace linker.nat
|
||||
public LinkerFirewallProtocolType Protocol { 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 string SrcId { get; set; } = string.Empty;
|
||||
@@ -266,7 +369,6 @@ namespace linker.nat
|
||||
public LinkerFirewallProtocolType Protocol { get; set; }
|
||||
public LinkerFirewallAction Action { get; set; }
|
||||
}
|
||||
|
||||
public enum LinkerFirewallProtocolType : byte
|
||||
{
|
||||
None = 0,
|
||||
@@ -286,15 +388,9 @@ namespace linker.nat
|
||||
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;
|
||||
|
||||
IPV4Packet ipv4 = new IPV4Packet(packet.Span);
|
||||
SrcNatPacket ipv4 = new SrcNatPacket(packet.Span);
|
||||
//不是 ipv4,是虚拟网卡ip,是广播,不nat
|
||||
if (ipv4.Version != 4 || ipv4.DstAddr == srcIp || ipv4.DstAddrSpan.IsCast())
|
||||
{
|
||||
@@ -241,7 +241,7 @@ namespace linker.nat
|
||||
//只操作response 和 request
|
||||
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;
|
||||
|
||||
//原标识符,两个字节
|
||||
@@ -287,7 +287,7 @@ namespace linker.nat
|
||||
//只操作response 和 request
|
||||
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;
|
||||
@@ -316,7 +316,7 @@ namespace linker.nat
|
||||
/// <returns></returns>
|
||||
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);
|
||||
@@ -358,7 +358,7 @@ namespace linker.nat
|
||||
/// <returns></returns>
|
||||
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);
|
||||
if (natMap.TryGetValue(key, out NatMapInfo natMapInfo))
|
||||
@@ -541,7 +541,7 @@ namespace linker.nat
|
||||
/// <summary>
|
||||
/// IPV4 包
|
||||
/// </summary>
|
||||
public unsafe struct IPV4Packet
|
||||
public unsafe struct SrcNatPacket
|
||||
{
|
||||
byte* ptr;
|
||||
|
||||
@@ -549,25 +549,11 @@ namespace linker.nat
|
||||
/// 协议版本
|
||||
/// </summary>
|
||||
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>
|
||||
public uint DstAddr => BinaryPrimitives.ReverseEndianness(*(uint*)(ptr + 16));
|
||||
/// <summary>
|
||||
/// 目标端口
|
||||
/// </summary>
|
||||
public ushort DstPort => BinaryPrimitives.ReverseEndianness(*(ushort*)(ptr + IPHeadLength + 2));
|
||||
/// <summary>
|
||||
/// 源地址
|
||||
/// </summary>
|
||||
public ReadOnlySpan<byte> SrcAddrSpan => new Span<byte>((ptr + 12), 4);
|
||||
@@ -586,10 +572,6 @@ namespace linker.nat
|
||||
/// </summary>
|
||||
public byte Flag => (byte)(*(ptr + 6) >> 5);
|
||||
/// <summary>
|
||||
/// 不分片
|
||||
/// </summary>
|
||||
public bool DontFragment => (Flag & 0x02) == 2;
|
||||
/// <summary>
|
||||
/// 更多分片
|
||||
/// </summary>
|
||||
public bool MoreFragment => (Flag & 0x01) == 1;
|
||||
@@ -622,11 +604,11 @@ namespace linker.nat
|
||||
public bool TcpFlagAck => (TcpFlag & 0b010000) != 0;
|
||||
public bool TcpFlagUrg => (TcpFlag & 0b100000) != 0;
|
||||
|
||||
public IPV4Packet(byte* ptr)
|
||||
public SrcNatPacket(byte* ptr)
|
||||
{
|
||||
this.ptr = ptr;
|
||||
}
|
||||
public IPV4Packet(ReadOnlySpan<byte> span)
|
||||
public SrcNatPacket(ReadOnlySpan<byte> span)
|
||||
{
|
||||
fixed (byte* ptr = span)
|
||||
{
|
||||
|
@@ -1,5 +1,5 @@
|
||||
v1.9.2
|
||||
2025-09-24 20:19:20
|
||||
2025-09-24 20:55:51
|
||||
1. 一些累计更新,一些BUG修复
|
||||
2. 使用代理方式重写应用层NAT
|
||||
3. 新增服务端webapi,对外提供公开数据,监听1803端口,设置为0则不监听
|
||||
|
Reference in New Issue
Block a user