跳到主要内容

95.5、NAT

说明
  1. 使用nugetlinker.nat,或源码 https://github.com/snltty/linker/tree/master/src/linker.nat
  2. 以下是简单使用示例

95.4.1 网段映射

网段映射,主要用于组网多局域网网段冲突

LinkerDstMapping mapping = new LinkerDstMapping();  
//设置映射列表
mapping.SetDsts(new DstMapInfo[] {
new DstMapInfo {
FakeIP = IPAddress.Parse("192.168.123.0"),
RealIP = IPAddress.Parse("192.168.1.0"),
PrefixLength = 24
}
});
//将TCP/IP包里的目标IP转换为假IP
mapping.ToFakeDst(tcpIpPacket);

//将TCP/IP包里的目标IP转换为原来的真IP
mapping.ToRealDst(tcpIpPacket);

//通过假IP获取到真实的192.168.1.100,这个一般用于端口转发或者代理的,只获取真的去连接就可以
IPAddress realIp = mapping.GetRealDst(IPAddress.Parse("192.168.123.100"));

95.4.2 目标代理

目标代理,类似DNAT,以实现点对网

LinkerDstProxy dstProxy = new LinkerDstProxy();
//代理IP,一般就用虚拟网卡IP,
IPAddress tunIp = IPAddress.Parse("10.18.18.2");
//需要被代理的IP
(IPAddress ip, byte prefix)[] dsts = new [] {
(IPAddress.Parse("192.168.2.0"), 24)
};

//启动代理,当数据包的目标Ip是[192.168.2.0/24]的时候,会被代理到[10.18.18.2:随机端口]
dstProxy.Setup(tunIp,dsts,ref string error);

//收到别人的数据包在写入虚拟网卡之前调用
bool res = dstProxy.Write(tcpIpPacket);
if(res)
{
//true写入虚拟网卡,false就走代理了不需要写入网卡了
}


//在读取虚拟网卡后发送给别人之前调用
dstProxy.Read(tcpIpPacket);

//停止代理
dstProxy.Shutdown();

95.4.3 源代理

源代理,主要解决 TCP over TCP 导致的一系列降速问题,仅适用于虚拟网卡组网并且走TCP隧道时

public sealed class LinkerSrcProxyCallback: ILinkerSrcProxyCallback
{
//产生TCP/IP数据包
public ValueTask<bool> Callback(LinkerSrcProxyReadPacket packet)
{
//发送给对方
}
//检查是否需要代理,小端IP
public bool CheckAvaliable(uint ip)
{
//根据合适的判断决定是否支持代理
return true;
}
}

LinkerSrcProxy srcProxy = new LinkerSrcProxy();
ILinkerSrcProxyCallback callback = LinkerSrcProxyCallback();
//虚拟网卡IP、掩码、回调,错误信息
srcProxy.Setup(IPAddress.Parse("10.18.18.2"), 24,callback, ref string error);

//在读取虚拟网卡后调用
bool res = srcProxy.Read(tcpIpPacket);
if(res)
{
//true就发送,false的话,会Callback,在Callback中发送
}

//originDstIp 是原始IP,因为有可能经过 网段映射改过了, 要改之前的IP
bool res = await srcProxy.WriteAsync(tcpIpPacket, uint originDstIp);
if(res)
{
//true写入虚拟网卡,false就走代理了不需要写入网卡了
}

//停止代理
srcProxy.Shutdown();

95.4.4 UPNP

用于给网关动态设置端口映射,支持UPNP和PMP

//开始发现
PortMappingUtility.StartDiscovery();
//设备列表
PortMappingUtility.GetDevices();
//获取远程映射列表
PortMappingUtility.GetRemote();
//获取本地映射列表(添加的)
PortMappingUtility.GetLocal();
//添加映射
PortMappingUtility.Add(new PortMappingInfo
{
ClientIp = IPAddress.Parse("192.168.2.2"),
PublicPort = 12345,
PrivatePort = 80,
ProtocolType = ProtocolType.Tcp,
Enabled = true,
Description = "测试",
LeaseDuration = 7200

});
//删除映射
PortMappingUtility.Delete(12345, ProtocolType.Tcp);

//停止发现
PortMappingUtility.StopDiscovery();