应用层NAT

This commit is contained in:
snltty
2025-04-18 00:45:38 +08:00
parent 984954ccb6
commit 30488ef9a0
24 changed files with 614 additions and 166 deletions

View File

@@ -28,6 +28,10 @@ for %%r in (win-x86,win-x64,win-arm64) do (
echo F|xcopy "src\\linker\\msquic-%%r.dll" "public\\extends\\%%r\\linker-%%r\\msquic.dll" /s /f /h /y
echo F|xcopy "src\\linker\\msquic-openssl3-%%r.dll" "public\\extends\\%%r\\linker-%%r\\msquic-openssl.dll" /s /f /h /y
echo F|xcopy "src\\linker\\wintun-%%r.dll" "public\\extends\\%%r\\linker-%%r\\wintun.dll" /s /f /h /y
echo F|xcopy "src\\linker\\WinDivert-%%r.dll" "public\\extends\\%%r\\linker-%%r\\WinDivert.dll" /s /f /h /y
echo F|xcopy "src\\linker\\WinDivert-%%r.sys" "public\\extends\\%%r\\linker-%%r\\WinDivert.sys" /s /f /h /y
echo F|xcopy "src\\linker\\WinDivert64-%%r.sys" "public\\extends\\%%r\\linker-%%r\\WinDivert64.sys" /s /f /h /y
)
msbuild "src\\linker.ics\\linker.ics.csproj" -p:Configuration=Release -p:OutputPath=../../public/extends/win-x64/linker-win-x64

View File

@@ -106,7 +106,7 @@ namespace linker.app
tuntapProxy.Callback = this;
tuntapDecenter = LinkerMessengerEntry.GetService<TuntapDecenter>();
tuntapTransfer.Init(new LinkerVpnDevice(this), this);
tuntapTransfer.Initialize(new LinkerVpnDevice(this), this);
}
public override void OnCreate()
{
@@ -294,7 +294,7 @@ namespace linker.app
this.vpnService = vpnService;
}
public bool Setup(string name, IPAddress address, IPAddress gateway, byte prefixLength, out string error)
public bool Setup(string name, IPAddress address, byte prefixLength, out string error)
{
error = string.Empty;
if (address.Equals(IPAddress.Any)) return false;
@@ -374,7 +374,11 @@ namespace linker.app
public void SetMtu(int value)
{
}
public void SetNat(out string error)
public void SetSystemNat(out string error)
{
error = string.Empty;
}
public void SetAppNat(LinkerTunAppNatItemInfo[] items, out string error)
{
error = string.Empty;
}
@@ -395,10 +399,10 @@ namespace linker.app
return new List<LinkerTunDeviceForwardItem>();
}
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip)
public void AddRoute(LinkerTunDeviceRouteItem[] ips)
{
}
public void DelRoute(LinkerTunDeviceRouteItem[] ips)
public void RemoveRoute(LinkerTunDeviceRouteItem[] ips)
{
}
public async Task<bool> CheckAvailable(bool order = false)

View File

@@ -1 +1 @@
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.cfba5739.js"></script><script defer="defer" src="js/app.656481f7.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.3aab4747.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>linker.web</title><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script><script defer="defer" src="js/chunk-vendors.cfba5739.js"></script><script defer="defer" src="js/app.644fc91c.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.3aab4747.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but linker.web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -315,6 +315,11 @@ namespace linker.libs
{
return ToNetworkValue(ip, ToPrefixValue(prefixLength));
}
public static uint ToBroadcastValue(IPAddress ip, byte prefixLength)
{
return ToBroadcastValue(ToValue(ip), ToPrefixValue(prefixLength));
}
public static uint ToBroadcastValue(uint ip, uint prefixIP)
{
return ip | ~prefixIP;

View File

@@ -4,6 +4,7 @@ using linker.libs.timer;
using linker.tunnel.connection;
using LiteDB;
using System.Net;
using System.Runtime.ExceptionServices;
namespace linker.messenger.store.file
{
@@ -14,7 +15,14 @@ namespace linker.messenger.store.file
public sealed class Storefactory
{
LiteDatabase database;
public Storefactory()
{
Init();
}
private void Init()
{
BsonMapper bsonMapper = new BsonMapper();
bsonMapper.RegisterType<IPEndPoint>(serialize: (a) => a.ToString(), deserialize: (a) => IPEndPoint.Parse(a.AsString));
@@ -24,12 +32,21 @@ namespace linker.messenger.store.file
bsonMapper.RegisterType<IConnection>(serialize: (a) => string.Empty, deserialize: (a) => null);
string db = Path.Join(Helper.currentDirectory, "./configs/db.db");
if(Directory.Exists(Path.GetDirectoryName(db)) == false)
if (Directory.Exists(Path.GetDirectoryName(db)) == false)
{
Directory.CreateDirectory(Path.GetDirectoryName(db));
}
database = new LiteDatabase(new ConnectionString($"Filename={db};Password={Helper.GlobalString}"), bsonMapper);
try
{
database = new LiteDatabase(new ConnectionString($"Filename={db};Password={Helper.GlobalString}"), bsonMapper);
}
catch (Exception ex)
{
LoggerHelper.Instance.Error(ex);
//让服务自动重启
Environment.Exit(1);
}
if (OperatingSystem.IsAndroid() == false)
{

View File

@@ -5,7 +5,6 @@ using linker.messenger.exroute;
using linker.messenger.signin;
using linker.tun;
using linker.tunnel.connection;
using System.Linq;
using System.Net;
namespace linker.messenger.tuntap
@@ -38,7 +37,7 @@ namespace linker.messenger.tuntap
signInClientState.OnSignInSuccess += (times) => tuntapConfigTransfer.RefreshIP();
//初始化网卡
tuntapTransfer.Init(this);
tuntapTransfer.Initialize(this);
//网卡状态发生变化,同步一下信息
tuntapTransfer.OnSetupBefore += () =>
{
@@ -56,6 +55,7 @@ namespace linker.messenger.tuntap
tuntapTransfer.OnSetupSuccess += () =>
{
SetMaps();
SetAppNat();
AddForward();
};
tuntapTransfer.OnShutdownBefore += () =>
@@ -130,7 +130,6 @@ namespace linker.messenger.tuntap
tuntapTransfer.Write(buffer);
}
/// <summary>
/// 重启网卡
/// </summary>
@@ -153,6 +152,9 @@ namespace linker.messenger.tuntap
tuntapTransfer.Shutdown();
}
/// <summary>
/// 设置映射
/// </summary>
private void SetMaps()
{
var maps = tuntapConfigTransfer.Info.Lans
@@ -160,6 +162,24 @@ namespace linker.messenger.tuntap
.Select(c => new LanMapInfo { IP = c.IP, ToIP = c.MapIP, PrefixLength = c.MapPrefixLength }).ToArray();
tuntapTransfer.SetMap(maps);
}
/// <summary>
/// 设置应用层NAT
/// </summary>
private void SetAppNat()
{
if (tuntapConfigTransfer.Info.DisableNat == false)
{
var nats = tuntapConfigTransfer.Info.Lans
.Where(c => c.IP != null && c.IP.Equals(IPAddress.Any) == false && c.MapIP != null && c.MapIP.Equals(IPAddress.Any) == false && c.Disabled == false)
.Select(c => new LinkerTunAppNatItemInfo
{
IP = c.MapIP.Equals(IPAddress.Any) ? c.IP : c.MapIP,
PrefixLength = c.MapIP.Equals(IPAddress.Any) ? c.PrefixLength : c.MapPrefixLength,
}).ToArray();
tuntapTransfer.SetAppNat(nats);
}
}
// <summary>
/// 添加端口转发
/// </summary>

View File

@@ -101,9 +101,9 @@ namespace linker.messenger.tuntap
var removeItems = routeItems.Except(_routeItems, new LinkerTunDeviceRouteItemComparer()).ToArray();
if (removeItems.Length > 0)
tuntapTransfer.DelRoute(removeItems);
tuntapTransfer.RemoveRoute(removeItems);
tuntapTransfer.AddRoute(_routeItems, tuntapConfigTransfer.Info.IP);
tuntapTransfer.AddRoute(_routeItems);
tuntapProxy.SetIPs(ips);
foreach (var item in Infos.Values)
@@ -120,7 +120,7 @@ namespace linker.messenger.tuntap
private List<TuntapVeaLanIPAddressList> ParseIPs(List<TuntapInfo> infos)
{
//排除的IP
uint[] excludeIps = exRouteTransfer.Get().Where(c=>c.Equals(IPAddress.Any)==false).Select(NetworkHelper.ToValue).Distinct().ToArray();
uint[] excludeIps = exRouteTransfer.Get().Where(c => c.Equals(IPAddress.Any) == false).Select(NetworkHelper.ToValue).Distinct().ToArray();
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Warning($"tuntap route ex ips : {string.Join(",", excludeIps.Select(c => NetworkHelper.ToIP(c)).ToList())}");
@@ -136,7 +136,7 @@ namespace linker.messenger.tuntap
{
if (wan.Equals(c.Wan))
{
foreach (var item in c.Lans.Where(c=>c.MapIP==null || c.MapIP.Equals(IPAddress.Any)))
foreach (var item in c.Lans.Where(c => c.MapIP == null || c.MapIP.Equals(IPAddress.Any)))
{
item.Exists = true;
}

View File

@@ -2,7 +2,6 @@
using System.Net;
using linker.tun;
using linker.libs.timer;
using System.ComponentModel;
namespace linker.messenger.tuntap
{
@@ -32,12 +31,12 @@ namespace linker.messenger.tuntap
}
}
public void Init(ILinkerTunDeviceCallback linkerTunDeviceCallback)
public void Initialize(ILinkerTunDeviceCallback linkerTunDeviceCallback)
{
linkerTunDeviceAdapter.Initialize(linkerTunDeviceCallback);
}
public void Init(ILinkerTunDevice linkerTunDevice, ILinkerTunDeviceCallback linkerTunDeviceCallback)
public void Initialize(ILinkerTunDevice linkerTunDevice, ILinkerTunDeviceCallback linkerTunDeviceCallback)
{
linkerTunDeviceAdapter.Initialize(linkerTunDevice, linkerTunDeviceCallback);
}
@@ -72,11 +71,14 @@ namespace linker.messenger.tuntap
return;
}
if (nat)
linkerTunDeviceAdapter.SetNat();
if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.NatError) == false)
{
LoggerHelper.Instance.Error(linkerTunDeviceAdapter.NatError);
linkerTunDeviceAdapter.SetSystemNat();
if (string.IsNullOrWhiteSpace(linkerTunDeviceAdapter.NatError) == false)
{
LoggerHelper.Instance.Error(linkerTunDeviceAdapter.NatError);
}
}
OnSetupSuccess();
}
catch (Exception ex)
@@ -95,6 +97,35 @@ namespace linker.messenger.tuntap
});
}
/// <summary>
/// 停止网卡
/// </summary>
public void Shutdown(bool notify = true)
{
if (operatingManager.StartOperation() == false)
{
return;
}
try
{
if (notify) OnShutdownBefore();
linkerTunDeviceAdapter.Shutdown();
if (notify) OnShutdownSuccess();
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
finally
{
if (notify)
OnShutdownAfter();
operatingManager.StopOperation();
}
}
/// <summary>
/// 刷新网卡
/// </summary>
@@ -123,64 +154,64 @@ namespace linker.messenger.tuntap
}
});
}
/// <summary>
/// 停止网卡
/// 设置应用层NAT
/// </summary>
public void Shutdown(bool notify = true)
/// <param name="items"></param>
public void SetAppNat(LinkerTunAppNatItemInfo[] items)
{
if (operatingManager.StartOperation() == false)
{
return;
}
try
{
if (notify)
OnShutdownBefore();
linkerTunDeviceAdapter.Shutdown();
linkerTunDeviceAdapter.RemoveNat();
if (notify)
OnShutdownSuccess();
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
finally
{
if (notify)
OnShutdownAfter();
operatingManager.StopOperation();
}
if (string.IsNullOrWhiteSpace(NatError) == false)
linkerTunDeviceAdapter.SetAppNat(items);
}
/// <summary>
/// 添加转发
/// </summary>
/// <param name="forward"></param>
public void AddForward(List<LinkerTunDeviceForwardItem> forward)
{
linkerTunDeviceAdapter.AddForward(forward);
}
/// <summary>
/// 移除转发
/// </summary>
/// <param name="forward"></param>
public void RemoveForward(List<LinkerTunDeviceForwardItem> forward)
{
linkerTunDeviceAdapter.RemoveForward(forward);
}
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip)
/// <summary>
/// 添加路由
/// </summary>
/// <param name="ips"></param>
public void AddRoute(LinkerTunDeviceRouteItem[] ips)
{
linkerTunDeviceAdapter.AddRoute(ips, ip);
linkerTunDeviceAdapter.AddRoute(ips);
}
public void DelRoute(LinkerTunDeviceRouteItem[] ips)
/// <summary>
/// 移除路由
/// </summary>
/// <param name="ips"></param>
public void RemoveRoute(LinkerTunDeviceRouteItem[] ips)
{
linkerTunDeviceAdapter.DelRoute(ips);
linkerTunDeviceAdapter.RemoveRoute(ips);
}
/// <summary>
/// 添加映射
/// </summary>
/// <param name="maps"></param>
public void SetMap(LanMapInfo[] maps)
{
linkerTunDeviceAdapter.SetMap(maps);
}
/// <summary>
/// 检查网卡是否可用
/// </summary>
/// <param name="order"></param>
/// <returns></returns>
public async Task<bool> CheckAvailable(bool order = false)
{
return await linkerTunDeviceAdapter.CheckAvailable(order).ConfigureAwait(false);

View File

@@ -25,16 +25,18 @@ namespace linker.tun
/// </summary>
/// <param name="name"></param>
/// <param name="address"></param>
/// <param name="gateway"></param>
/// <param name="prefixLength"></param>
/// <param name="error"></param>
/// <returns></returns>
public bool Setup(string name,IPAddress address, IPAddress gateway, byte prefixLength, out string error);
public bool Setup(string name,IPAddress address, byte prefixLength, out string error);
/// <summary>
/// 关闭
/// </summary>
public void Shutdown();
/// <summary>
/// 刷新网卡
/// </summary>
public void Refresh();
/// <summary>
@@ -43,9 +45,14 @@ namespace linker.tun
/// <param name="value"></param>
public void SetMtu(int value);
/// <summary>
/// 设置NAT转发
/// 设置系统NAT转发
/// </summary>
public void SetNat(out string error);
public void SetSystemNat(out string error);
/// <summary>
/// 设置应用层NAT转发
/// </summary>
/// <param name="error"></param>
public void SetAppNat(LinkerTunAppNatItemInfo[] items, out string error);
/// <summary>
/// 移除NAT转发
/// </summary>
@@ -72,15 +79,12 @@ namespace linker.tun
/// 添加路由
/// </summary>
/// <param name="ips"></param>
/// <param name="ip"></param>
/// <param name="gateway">是不是网关是网关将使用NAT转发不是网关将添加路由</param>
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip);
public void AddRoute(LinkerTunDeviceRouteItem[] ips);
/// <summary>
/// 删除路由
/// </summary>
/// <param name="ip"></param>
/// <param name="gateway">是不是网关是网关将删除NAT转发不是网关将删除路由</param>
public void DelRoute(LinkerTunDeviceRouteItem[] ip);
/// <param name="ips"></param>
public void RemoveRoute(LinkerTunDeviceRouteItem[] ips);
/// <summary>
/// 读取数据包
@@ -260,4 +264,10 @@ namespace linker.tun
/// </summary>
Running = 2
}
public sealed class LinkerTunAppNatItemInfo
{
public IPAddress IP { get; set; }
public byte PrefixLength { get; set; }
}
}

View File

@@ -26,7 +26,7 @@ namespace linker.tun
{
}
public bool Setup(string name, IPAddress address, IPAddress gateway, byte prefixLength, out string error)
public bool Setup(string name, IPAddress address, byte prefixLength, out string error)
{
error = string.Empty;
@@ -149,7 +149,7 @@ namespace linker.tun
{
return CommandHelper.Linux(string.Empty, ["ip route show default | awk '{print $5}'"]);
}
public void SetNat(out string error)
public void SetSystemNat(out string error)
{
error = string.Empty;
if (address == null || address.Equals(IPAddress.Any)) return;
@@ -182,6 +182,10 @@ namespace linker.tun
error = ex.Message;
}
}
public void SetAppNat(LinkerTunAppNatItemInfo[] items,out string error)
{
error = string.Empty;
}
public void RemoveNat(out string error)
{
error = string.Empty;
@@ -275,14 +279,14 @@ namespace linker.tun
}
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip)
public void AddRoute(LinkerTunDeviceRouteItem[] ips)
{
string[] commands = ips.Select(item =>
{
uint prefixValue = NetworkHelper.ToPrefixValue(item.PrefixLength);
IPAddress network = NetworkHelper.ToNetworkIP(item.Address, prefixValue);
return $"ip route add {network}/{item.PrefixLength} via {ip} dev {Name} metric 1 ";
return $"ip route add {network}/{item.PrefixLength} via {address} dev {Name} metric 1 ";
}).ToArray();
if (commands.Length > 0)
{
@@ -291,7 +295,7 @@ namespace linker.tun
CommandHelper.Linux(string.Empty, commands);
}
}
public void DelRoute(LinkerTunDeviceRouteItem[] ip)
public void RemoveRoute(LinkerTunDeviceRouteItem[] ip)
{
string[] commands = ip.Select(item =>
{

View File

@@ -25,7 +25,7 @@ namespace linker.tun
}
public bool Setup(string name, IPAddress address, IPAddress gateway, byte prefixLength, out string error)
public bool Setup(string name, IPAddress address, byte prefixLength, out string error)
{
this.name = name;
error = string.Empty;
@@ -65,21 +65,21 @@ namespace linker.tun
}
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip)
public void AddRoute(LinkerTunDeviceRouteItem[] ips)
{
string[] commands = ips.Select(item =>
{
IPAddress _ip = NetworkHelper.ToNetworkIP(item.Address, item.PrefixLength);
return $"route add -net {_ip}/{item.PrefixLength} {ip}";
return $"route add -net {_ip}/{item.PrefixLength} {address}";
}).ToArray();
if (commands.Length > 0)
{
CommandHelper.Osx(string.Empty, commands.ToArray());
}
}
public void DelRoute(LinkerTunDeviceRouteItem[] ip)
public void RemoveRoute(LinkerTunDeviceRouteItem[] ips)
{
string[] commands = ip.Select(item =>
string[] commands = ips.Select(item =>
{
IPAddress _ip = NetworkHelper.ToNetworkIP(item.Address, item.PrefixLength);
return $"route delete -net {_ip}/{item.PrefixLength}";
@@ -95,7 +95,7 @@ namespace linker.tun
CommandHelper.Osx(string.Empty, new string[] { $"ifconfig {Name} mtu {value}" });
}
public void SetNat(out string error)
public void SetSystemNat(out string error)
{
error = string.Empty;
/*
@@ -113,6 +113,10 @@ namespace linker.tun
});
*/
}
public void SetAppNat(LinkerTunAppNatItemInfo[] items, out string error)
{
error = string.Empty;
}
public void RemoveNat(out string error)
{
error = string.Empty;

View File

@@ -77,6 +77,12 @@ namespace linker.tun
}
return false;
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="linkerTunDevice">网卡实现</param>
/// <param name="linkerTunDeviceCallback">读取数据回调</param>
/// <returns></returns>
public bool Initialize(ILinkerTunDevice linkerTunDevice, ILinkerTunDeviceCallback linkerTunDeviceCallback)
{
this.linkerTunDevice = linkerTunDevice;
@@ -105,7 +111,7 @@ namespace linker.tun
setupError = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} not support";
return false;
}
linkerTunDevice.Setup(deviceName, address, NetworkHelper.ToGatewayIP(address, prefixLength), prefixLength, out setupError);
linkerTunDevice.Setup(deviceName, address, prefixLength, out setupError);
if (string.IsNullOrWhiteSpace(setupError) == false)
{
return false;
@@ -126,7 +132,6 @@ namespace linker.tun
}
return false;
}
/// <summary>
/// 关闭网卡
/// </summary>
@@ -141,6 +146,7 @@ namespace linker.tun
{
cancellationTokenSource?.Cancel();
linkerTunDevice?.Shutdown();
linkerTunDevice?.RemoveNat(out string error);
}
catch (Exception)
{
@@ -152,8 +158,6 @@ namespace linker.tun
setupError = string.Empty;
return true;
}
/// <summary>
/// 刷新网卡
/// </summary>
@@ -163,19 +167,26 @@ namespace linker.tun
}
/// <summary>
/// 添加NAT转发,这会将来到本网卡且目标IP不是本网卡IP的包转发到其它网卡
/// 设置系统层NAT
/// </summary>
public void SetNat()
public void SetSystemNat()
{
linkerTunDevice?.RemoveNat(out string error);
linkerTunDevice?.SetNat(out natError);
linkerTunDevice?.SetSystemNat(out natError);
}
/// <summary>
/// 移除NAT转发
/// 设置应用层NAT
/// </summary>
/// <param name="items"></param>
public void SetAppNat(LinkerTunAppNatItemInfo[] items)
{
linkerTunDevice?.SetAppNat(items, out natError);
}
/// <summary>
/// 移除NAT
/// </summary>
public void RemoveNat()
{
linkerTunDevice?.RemoveNat(out string error);
linkerTunDevice.RemoveNat(out string error);
}
/// <summary>
@@ -208,17 +219,17 @@ namespace linker.tun
/// </summary>
/// <param name="ips"></param>
/// <param name="ip"></param>
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip)
public void AddRoute(LinkerTunDeviceRouteItem[] ips)
{
linkerTunDevice?.AddRoute(ips, ip);
linkerTunDevice?.AddRoute(ips);
}
/// <summary>
/// 删除路由
/// </summary>
/// <param name="ips"></param>
public void DelRoute(LinkerTunDeviceRouteItem[] ips)
public void RemoveRoute(LinkerTunDeviceRouteItem[] ips)
{
linkerTunDevice?.DelRoute(ips);
linkerTunDevice?.RemoveRoute(ips);
}
@@ -262,7 +273,7 @@ namespace linker.tun
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
public unsafe bool Write(ReadOnlyMemory<byte> buffer)
public bool Write(ReadOnlyMemory<byte> buffer)
{
if (linkerTunDevice != null && Status == LinkerTunDeviceStatus.Running)
{
@@ -272,6 +283,40 @@ namespace linker.tun
return false;
}
private void ToMapIP(ReadOnlyMemory<byte> buffer)
{
//只支持映射IPV4
if ((byte)(buffer.Span[0] >> 4 & 0b1111) != 4) return;
//映射表不为空
if (natDic.IsEmpty) return;
uint realDist = NetworkHelper.ToValue(buffer.Span.Slice(12, 4));
if (natDic.TryGetValue(realDist, out uint fakeDist))
{
ReWriteIP(buffer, BinaryPrimitives.ReverseEndianness(fakeDist), 12);
}
}
private void MapToRealIP(ReadOnlyMemory<byte> buffer)
{
//只支持映射IPV4
if ((byte)(buffer.Span[0] >> 4 & 0b1111) != 4) return;
//映射表不为空
if (masks.Length == 0 || mapDic.Count == 0) return;
uint fakeDist = NetworkHelper.ToValue(buffer.Span.Slice(16, 4));
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]);
ReWriteIP(buffer, BinaryPrimitives.ReverseEndianness(realDist), 16);
natDic.AddOrUpdate(realDist, fakeDist, (a, b) => fakeDist);
break;
}
}
}
private unsafe void ReWriteIP(ReadOnlyMemory<byte> buffer, uint newIP, int pos)
{
fixed (byte* ptr = buffer.Span)
@@ -306,39 +351,6 @@ namespace linker.tun
}
}
}
private void ToMapIP(ReadOnlyMemory<byte> buffer)
{
//只支持映射IPV4
if ((byte)(buffer.Span[0] >> 4 & 0b1111) != 4) return;
//映射表不为空
if (natDic.IsEmpty) return;
uint realDist = NetworkHelper.ToValue(buffer.Span.Slice(12, 4));
if (natDic.TryGetValue(realDist, out uint fakeDist))
{
ReWriteIP(buffer, BinaryPrimitives.ReverseEndianness( fakeDist), 12);
}
}
private void MapToRealIP(ReadOnlyMemory<byte> buffer)
{
//只支持映射IPV4
if ((byte)(buffer.Span[0] >> 4 & 0b1111) != 4) return;
//映射表不为空
if (masks.Length == 0 || mapDic.Count == 0) return;
uint fakeDist = NetworkHelper.ToValue(buffer.Span.Slice(16, 4));
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]);
ReWriteIP(buffer, BinaryPrimitives.ReverseEndianness(realDist), 16);
natDic.AddOrUpdate(realDist, fakeDist, (a, b) => fakeDist);
break;
}
}
}
/// <summary>
/// 设置IP映射列表
/// </summary>
@@ -397,7 +409,6 @@ namespace linker.tun
return sum;
}
public async Task<bool> CheckAvailable(bool order = false)
{
return await linkerTunDevice.CheckAvailable(order);

View File

@@ -27,14 +27,13 @@ namespace linker.tun
private CancellationTokenSource tokenSource;
private WinDivert winDivert;
private WinDivertNAT winDivertNAT;
public LinkerWinTunDevice()
{
}
public bool Setup(string name, IPAddress address, IPAddress gateway, byte prefixLength, out string error)
public bool Setup(string name, IPAddress address, byte prefixLength, out string error)
{
this.name = name;
this.address = address;
@@ -184,9 +183,9 @@ namespace linker.tun
$"netsh interface ipv6 set subinterface {interfaceNumber} mtu={value} store=persistent"
});
}
public void SetNat(out string error)
{
public void SetSystemNat(out string error)
{
error = string.Empty;
if (address == null || address.Equals(IPAddress.Any)) return;
@@ -194,31 +193,33 @@ namespace linker.tun
{
CommandHelper.PowerShell($"start-service WinNat", [], out error);
CommandHelper.PowerShell($"Install-WindowsFeature -Name Routing -IncludeManagementTools", [], out error);
CommandHelper.PowerShell($"Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All", [], out error);
CommandHelper.PowerShell($"Set-ItemProperty -Path \"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\" -Name \"IPEnableRouter\" -Value 1", [], out error);
IPAddress network = NetworkHelper.ToNetworkIP(this.address, NetworkHelper.ToPrefixValue(prefixLength));
CommandHelper.PowerShell($"Remove-NetNat -Name {Name} -Confirm:$false", [], out error);
CommandHelper.PowerShell($"New-NetNat -Name {Name} -InternalIPInterfaceAddressPrefix {network}/{prefixLength}", [], out error);
if (string.IsNullOrWhiteSpace(error))
string result = CommandHelper.PowerShell($"Get-NetNat", [], out error);
if (string.IsNullOrWhiteSpace(result) == false && result.Contains($"{network}/{prefixLength}"))
{
return;
}
/*
CommandHelper.Windows(string.Empty, [$"net start SharedAccess"]);
string result = CommandHelper.Windows(string.Empty, [$"linker.ics.exe {defaultInterfaceName} {Name} enable"]);
if (result.Contains($"enable success"))
{
return;
}
*/
error = "NetNat and ICS not supported";
error = $"NetNat and ICS not supported,{error}";
}
catch (Exception ex)
{
error = ex.Message;
}
}
public void SetAppNat(LinkerTunAppNatItemInfo[] items, out string error)
{
error = string.Empty;
winDivertNAT?.Dispose();
winDivertNAT = new WinDivertNAT(new WinDivertNAT.AddrInfo(address, prefixLength), items.Select(c => new WinDivertNAT.AddrInfo(c.IP, c.PrefixLength)).ToArray());
//winDivertNAT.Setup();
}
public void RemoveNat(out string error)
{
error = string.Empty;
@@ -228,12 +229,19 @@ namespace linker.tun
{
CommandHelper.PowerShell($"start-service WinNat", [], out error);
CommandHelper.PowerShell($"Remove-NetNat -Name {Name} -Confirm:$false", [], out error);
//CommandHelper.Windows(string.Empty, [$"linker.ics.exe {defaultInterfaceName} {Name} disable"]);
}
catch (Exception ex)
{
error = ex.Message;
}
try
{
winDivertNAT?.Dispose();
}
catch (Exception)
{
}
}
@@ -271,7 +279,7 @@ namespace linker.tun
}
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip)
public void AddRoute(LinkerTunDeviceRouteItem[] ips)
{
if (interfaceNumber > 0)
{
@@ -281,7 +289,7 @@ namespace linker.tun
IPAddress mask = NetworkHelper.ToIP(maskValue);
IPAddress _ip = NetworkHelper.ToNetworkIP(item.Address, maskValue);
return $"route add {_ip} mask {mask} {ip} metric 5 if {interfaceNumber}";
return $"route add {_ip} mask {mask} {address} metric 5 if {interfaceNumber}";
}).ToArray();
if (commands.Length > 0)
{
@@ -291,9 +299,9 @@ namespace linker.tun
}
}
}
public void DelRoute(LinkerTunDeviceRouteItem[] ip)
public void RemoveRoute(LinkerTunDeviceRouteItem[] ips)
{
string[] commands = ip.Select(item =>
string[] commands = ips.Select(item =>
{
uint maskValue = NetworkHelper.ToPrefixValue(item.PrefixLength);
IPAddress mask = NetworkHelper.ToIP(maskValue);

View File

@@ -1,23 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using linker.libs;
using linker.libs.timer;
using System.Buffers.Binary;
using System.Collections.Frozen;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using static linker.libs.winapis.SECUR32;
using static System.Collections.Specialized.BitVector32;
namespace linker.tun
{
/// <summary>
/// 应用层NAT
/// </summary>
internal sealed class WinDivertNAT
public sealed class WinDivertNAT
{
public WinDivertNAT()
WinDivert winDivert;
AddrInfo src;
AddrInfo[] dsts;
NetworkIPv4Addr srcAddr;
//网络号对应网卡IP用来替换源IP
private FrozenDictionary<uint, NetworkIPv4Addr> sourceDic = new Dictionary<uint, NetworkIPv4Addr>().ToFrozenDictionary();
public WinDivertNAT(AddrInfo src, AddrInfo[] dsts)
{
/*
winDivert = new WinDivert("inbound and (( ip.SrcAddr == 10.18.18.0/24 and ip.DstAddr == 192.168.56.0/24) or ( ip.SrcAddr == 192.168.56.0/24))", WinDivert.Layer.Network, 0, WinDivert.Flag.Sniff);
this.src = src;
this.dsts = dsts;
InitializeInterfaceIP();
}
public void Setup()
{
srcAddr = IPv4Addr.Parse(src.IP.ToString());
StringBuilder sb = new StringBuilder("inbound");
sb.Append($" and (ip.SrcAddr >= {src.NetworkIP} and ip.SrcAddr <= {src.BroadcastIP})");
winDivert = new WinDivert(sb.ToString(), WinDivert.Layer.Network, 0, WinDivert.Flag.Sniff);
var packet = new Memory<byte>(new byte[WinDivert.MTUMax]);
var abuf = new Memory<WinDivertAddress>(new WinDivertAddress[1]);
TimerHelper.Async(() =>
@@ -45,16 +62,15 @@ namespace linker.tun
}
});
*/
}
// NetworkIPv4Addr sourceAddr = IPv4Addr.Parse("10.18.18.23");
private unsafe void ModifyPacket(WinDivertParseResult p, ref WinDivertAddress addr)
{
/*
if (p.IPv4Hdr->SrcAddr == sourceAddr)
if (NetworkHelper.ToNetworkValue(BinaryPrimitives.ReverseEndianness(p.IPv4Hdr->SrcAddr.Raw), src.PrefixValue) == src.NetworkValue)
{
Console.WriteLine($"{p.IPv4Hdr->SrcAddr}->{p.IPv4Hdr->DstAddr}");
}*/
Console.WriteLine($"{p.IPv4Hdr->SrcAddr}->{p.IPv4Hdr->DstAddr}================================");
}
//WinDivert.CalcChecksums(p.Packet.Span, ref addr, 0);
}
@@ -79,5 +95,43 @@ namespace linker.tun
}
*/
}
private void InitializeInterfaceIP()
{
}
public void Dispose()
{
winDivert?.Dispose();
}
public sealed class AddrInfo
{
public AddrInfo(IPAddress ip, byte prefixLength)
{
IP = ip;
PrefixLength = prefixLength;
PrefixValue = NetworkHelper.ToPrefixValue(PrefixLength);
NetworkValue = NetworkHelper.ToNetworkValue(IP, PrefixLength);
BroadcastValue = NetworkHelper.ToBroadcastValue(IP, PrefixLength);
NetworkAddr = IPv4Addr.Parse(NetworkHelper.ToIP(NetworkValue).ToString());
NetworkIP = NetworkHelper.ToIP(NetworkValue);
BroadcastIP = NetworkHelper.ToIP(BroadcastValue);
}
public IPAddress IP { get; }
public byte PrefixLength { get; }
public NetworkIPv4Addr NetworkAddr { get; private set; }
public uint PrefixValue { get; private set; }
public uint NetworkValue { get; private set; }
public uint BroadcastValue { get; private set; }
public IPAddress NetworkIP { get; private set; }
public IPAddress BroadcastIP { get; private set; }
}
}
}

View File

@@ -2,9 +2,6 @@
using System.ServiceProcess;
using System.Diagnostics;
using linker.messenger.entry;
using linker.libs.extends;
using System.Text;
using System.Text.Json;
namespace linker
{

Binary file not shown.

View File

@@ -1,5 +1,5 @@
v1.7.3
2025-04-17 12:00:54
2025-04-18 00:45:38
1. 优化自动分配IP
2. 优化网卡,排除不明数据包
3. 虚拟网卡点对网IP映射用于解决网段冲突