应用层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-%%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\\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\\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 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; tuntapProxy.Callback = this;
tuntapDecenter = LinkerMessengerEntry.GetService<TuntapDecenter>(); tuntapDecenter = LinkerMessengerEntry.GetService<TuntapDecenter>();
tuntapTransfer.Init(new LinkerVpnDevice(this), this); tuntapTransfer.Initialize(new LinkerVpnDevice(this), this);
} }
public override void OnCreate() public override void OnCreate()
{ {
@@ -294,7 +294,7 @@ namespace linker.app
this.vpnService = vpnService; 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; error = string.Empty;
if (address.Equals(IPAddress.Any)) return false; if (address.Equals(IPAddress.Any)) return false;
@@ -374,7 +374,11 @@ namespace linker.app
public void SetMtu(int value) 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; error = string.Empty;
} }
@@ -395,10 +399,10 @@ namespace linker.app
return new List<LinkerTunDeviceForwardItem>(); 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) 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)); 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) public static uint ToBroadcastValue(uint ip, uint prefixIP)
{ {
return ip | ~prefixIP; return ip | ~prefixIP;

View File

@@ -4,6 +4,7 @@ using linker.libs.timer;
using linker.tunnel.connection; using linker.tunnel.connection;
using LiteDB; using LiteDB;
using System.Net; using System.Net;
using System.Runtime.ExceptionServices;
namespace linker.messenger.store.file namespace linker.messenger.store.file
{ {
@@ -14,7 +15,14 @@ namespace linker.messenger.store.file
public sealed class Storefactory public sealed class Storefactory
{ {
LiteDatabase database; LiteDatabase database;
public Storefactory() public Storefactory()
{
Init();
}
private void Init()
{ {
BsonMapper bsonMapper = new BsonMapper(); BsonMapper bsonMapper = new BsonMapper();
bsonMapper.RegisterType<IPEndPoint>(serialize: (a) => a.ToString(), deserialize: (a) => IPEndPoint.Parse(a.AsString)); 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); bsonMapper.RegisterType<IConnection>(serialize: (a) => string.Empty, deserialize: (a) => null);
string db = Path.Join(Helper.currentDirectory, "./configs/db.db"); 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)); 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) if (OperatingSystem.IsAndroid() == false)
{ {

View File

@@ -5,7 +5,6 @@ using linker.messenger.exroute;
using linker.messenger.signin; using linker.messenger.signin;
using linker.tun; using linker.tun;
using linker.tunnel.connection; using linker.tunnel.connection;
using System.Linq;
using System.Net; using System.Net;
namespace linker.messenger.tuntap namespace linker.messenger.tuntap
@@ -38,7 +37,7 @@ namespace linker.messenger.tuntap
signInClientState.OnSignInSuccess += (times) => tuntapConfigTransfer.RefreshIP(); signInClientState.OnSignInSuccess += (times) => tuntapConfigTransfer.RefreshIP();
//初始化网卡 //初始化网卡
tuntapTransfer.Init(this); tuntapTransfer.Initialize(this);
//网卡状态发生变化,同步一下信息 //网卡状态发生变化,同步一下信息
tuntapTransfer.OnSetupBefore += () => tuntapTransfer.OnSetupBefore += () =>
{ {
@@ -56,6 +55,7 @@ namespace linker.messenger.tuntap
tuntapTransfer.OnSetupSuccess += () => tuntapTransfer.OnSetupSuccess += () =>
{ {
SetMaps(); SetMaps();
SetAppNat();
AddForward(); AddForward();
}; };
tuntapTransfer.OnShutdownBefore += () => tuntapTransfer.OnShutdownBefore += () =>
@@ -130,7 +130,6 @@ namespace linker.messenger.tuntap
tuntapTransfer.Write(buffer); tuntapTransfer.Write(buffer);
} }
/// <summary> /// <summary>
/// 重启网卡 /// 重启网卡
/// </summary> /// </summary>
@@ -153,6 +152,9 @@ namespace linker.messenger.tuntap
tuntapTransfer.Shutdown(); tuntapTransfer.Shutdown();
} }
/// <summary>
/// 设置映射
/// </summary>
private void SetMaps() private void SetMaps()
{ {
var maps = tuntapConfigTransfer.Info.Lans 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(); .Select(c => new LanMapInfo { IP = c.IP, ToIP = c.MapIP, PrefixLength = c.MapPrefixLength }).ToArray();
tuntapTransfer.SetMap(maps); 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>
/// 添加端口转发 /// 添加端口转发
/// </summary> /// </summary>

View File

@@ -101,9 +101,9 @@ namespace linker.messenger.tuntap
var removeItems = routeItems.Except(_routeItems, new LinkerTunDeviceRouteItemComparer()).ToArray(); var removeItems = routeItems.Except(_routeItems, new LinkerTunDeviceRouteItemComparer()).ToArray();
if (removeItems.Length > 0) if (removeItems.Length > 0)
tuntapTransfer.DelRoute(removeItems); tuntapTransfer.RemoveRoute(removeItems);
tuntapTransfer.AddRoute(_routeItems, tuntapConfigTransfer.Info.IP); tuntapTransfer.AddRoute(_routeItems);
tuntapProxy.SetIPs(ips); tuntapProxy.SetIPs(ips);
foreach (var item in Infos.Values) foreach (var item in Infos.Values)
@@ -120,7 +120,7 @@ namespace linker.messenger.tuntap
private List<TuntapVeaLanIPAddressList> ParseIPs(List<TuntapInfo> infos) private List<TuntapVeaLanIPAddressList> ParseIPs(List<TuntapInfo> infos)
{ {
//排除的IP //排除的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) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Warning($"tuntap route ex ips : {string.Join(",", excludeIps.Select(c => NetworkHelper.ToIP(c)).ToList())}"); 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)) 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; item.Exists = true;
} }

View File

@@ -2,7 +2,6 @@
using System.Net; using System.Net;
using linker.tun; using linker.tun;
using linker.libs.timer; using linker.libs.timer;
using System.ComponentModel;
namespace linker.messenger.tuntap 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); linkerTunDeviceAdapter.Initialize(linkerTunDeviceCallback);
} }
public void Init(ILinkerTunDevice linkerTunDevice, ILinkerTunDeviceCallback linkerTunDeviceCallback) public void Initialize(ILinkerTunDevice linkerTunDevice, ILinkerTunDeviceCallback linkerTunDeviceCallback)
{ {
linkerTunDeviceAdapter.Initialize(linkerTunDevice, linkerTunDeviceCallback); linkerTunDeviceAdapter.Initialize(linkerTunDevice, linkerTunDeviceCallback);
} }
@@ -72,11 +71,14 @@ namespace linker.messenger.tuntap
return; return;
} }
if (nat) 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(); OnSetupSuccess();
} }
catch (Exception ex) 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>
/// 刷新网卡 /// 刷新网卡
/// </summary> /// </summary>
@@ -123,64 +154,64 @@ namespace linker.messenger.tuntap
} }
}); });
} }
/// <summary> /// <summary>
/// 停止网卡 /// 设置应用层NAT
/// </summary> /// </summary>
public void Shutdown(bool notify = true) /// <param name="items"></param>
public void SetAppNat(LinkerTunAppNatItemInfo[] items)
{ {
if (operatingManager.StartOperation() == false) if (string.IsNullOrWhiteSpace(NatError) == false)
{ linkerTunDeviceAdapter.SetAppNat(items);
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();
}
} }
/// <summary>
/// 添加转发
/// </summary>
/// <param name="forward"></param>
public void AddForward(List<LinkerTunDeviceForwardItem> forward) public void AddForward(List<LinkerTunDeviceForwardItem> forward)
{ {
linkerTunDeviceAdapter.AddForward(forward); linkerTunDeviceAdapter.AddForward(forward);
} }
/// <summary>
/// 移除转发
/// </summary>
/// <param name="forward"></param>
public void RemoveForward(List<LinkerTunDeviceForwardItem> forward) public void RemoveForward(List<LinkerTunDeviceForwardItem> forward)
{ {
linkerTunDeviceAdapter.RemoveForward(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) public void SetMap(LanMapInfo[] maps)
{ {
linkerTunDeviceAdapter.SetMap(maps); linkerTunDeviceAdapter.SetMap(maps);
} }
/// <summary>
/// 检查网卡是否可用
/// </summary>
/// <param name="order"></param>
/// <returns></returns>
public async Task<bool> CheckAvailable(bool order = false) public async Task<bool> CheckAvailable(bool order = false)
{ {
return await linkerTunDeviceAdapter.CheckAvailable(order).ConfigureAwait(false); return await linkerTunDeviceAdapter.CheckAvailable(order).ConfigureAwait(false);

View File

@@ -25,16 +25,18 @@ namespace linker.tun
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="address"></param> /// <param name="address"></param>
/// <param name="gateway"></param>
/// <param name="prefixLength"></param> /// <param name="prefixLength"></param>
/// <param name="error"></param> /// <param name="error"></param>
/// <returns></returns> /// <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>
/// 关闭 /// 关闭
/// </summary> /// </summary>
public void Shutdown(); public void Shutdown();
/// <summary>
/// 刷新网卡
/// </summary>
public void Refresh(); public void Refresh();
/// <summary> /// <summary>
@@ -43,9 +45,14 @@ namespace linker.tun
/// <param name="value"></param> /// <param name="value"></param>
public void SetMtu(int value); public void SetMtu(int value);
/// <summary> /// <summary>
/// 设置NAT转发 /// 设置系统NAT转发
/// </summary> /// </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> /// <summary>
/// 移除NAT转发 /// 移除NAT转发
/// </summary> /// </summary>
@@ -72,15 +79,12 @@ namespace linker.tun
/// 添加路由 /// 添加路由
/// </summary> /// </summary>
/// <param name="ips"></param> /// <param name="ips"></param>
/// <param name="ip"></param> public void AddRoute(LinkerTunDeviceRouteItem[] ips);
/// <param name="gateway">是不是网关是网关将使用NAT转发不是网关将添加路由</param>
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip);
/// <summary> /// <summary>
/// 删除路由 /// 删除路由
/// </summary> /// </summary>
/// <param name="ip"></param> /// <param name="ips"></param>
/// <param name="gateway">是不是网关是网关将删除NAT转发不是网关将删除路由</param> public void RemoveRoute(LinkerTunDeviceRouteItem[] ips);
public void DelRoute(LinkerTunDeviceRouteItem[] ip);
/// <summary> /// <summary>
/// 读取数据包 /// 读取数据包
@@ -260,4 +264,10 @@ namespace linker.tun
/// </summary> /// </summary>
Running = 2 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; error = string.Empty;
@@ -149,7 +149,7 @@ namespace linker.tun
{ {
return CommandHelper.Linux(string.Empty, ["ip route show default | awk '{print $5}'"]); 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; error = string.Empty;
if (address == null || address.Equals(IPAddress.Any)) return; if (address == null || address.Equals(IPAddress.Any)) return;
@@ -182,6 +182,10 @@ namespace linker.tun
error = ex.Message; error = ex.Message;
} }
} }
public void SetAppNat(LinkerTunAppNatItemInfo[] items,out string error)
{
error = string.Empty;
}
public void RemoveNat(out string error) public void RemoveNat(out string error)
{ {
error = string.Empty; 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 => string[] commands = ips.Select(item =>
{ {
uint prefixValue = NetworkHelper.ToPrefixValue(item.PrefixLength); uint prefixValue = NetworkHelper.ToPrefixValue(item.PrefixLength);
IPAddress network = NetworkHelper.ToNetworkIP(item.Address, prefixValue); 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(); }).ToArray();
if (commands.Length > 0) if (commands.Length > 0)
{ {
@@ -291,7 +295,7 @@ namespace linker.tun
CommandHelper.Linux(string.Empty, commands); CommandHelper.Linux(string.Empty, commands);
} }
} }
public void DelRoute(LinkerTunDeviceRouteItem[] ip) public void RemoveRoute(LinkerTunDeviceRouteItem[] ip)
{ {
string[] commands = ip.Select(item => 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; this.name = name;
error = string.Empty; 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 => string[] commands = ips.Select(item =>
{ {
IPAddress _ip = NetworkHelper.ToNetworkIP(item.Address, item.PrefixLength); 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(); }).ToArray();
if (commands.Length > 0) if (commands.Length > 0)
{ {
CommandHelper.Osx(string.Empty, commands.ToArray()); 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); IPAddress _ip = NetworkHelper.ToNetworkIP(item.Address, item.PrefixLength);
return $"route delete -net {_ip}/{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}" }); 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; 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) public void RemoveNat(out string error)
{ {
error = string.Empty; error = string.Empty;

View File

@@ -77,6 +77,12 @@ namespace linker.tun
} }
return false; return false;
} }
/// <summary>
/// 初始化
/// </summary>
/// <param name="linkerTunDevice">网卡实现</param>
/// <param name="linkerTunDeviceCallback">读取数据回调</param>
/// <returns></returns>
public bool Initialize(ILinkerTunDevice linkerTunDevice, ILinkerTunDeviceCallback linkerTunDeviceCallback) public bool Initialize(ILinkerTunDevice linkerTunDevice, ILinkerTunDeviceCallback linkerTunDeviceCallback)
{ {
this.linkerTunDevice = linkerTunDevice; this.linkerTunDevice = linkerTunDevice;
@@ -105,7 +111,7 @@ namespace linker.tun
setupError = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} not support"; setupError = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} not support";
return false; 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) if (string.IsNullOrWhiteSpace(setupError) == false)
{ {
return false; return false;
@@ -126,7 +132,6 @@ namespace linker.tun
} }
return false; return false;
} }
/// <summary> /// <summary>
/// 关闭网卡 /// 关闭网卡
/// </summary> /// </summary>
@@ -141,6 +146,7 @@ namespace linker.tun
{ {
cancellationTokenSource?.Cancel(); cancellationTokenSource?.Cancel();
linkerTunDevice?.Shutdown(); linkerTunDevice?.Shutdown();
linkerTunDevice?.RemoveNat(out string error);
} }
catch (Exception) catch (Exception)
{ {
@@ -152,8 +158,6 @@ namespace linker.tun
setupError = string.Empty; setupError = string.Empty;
return true; return true;
} }
/// <summary> /// <summary>
/// 刷新网卡 /// 刷新网卡
/// </summary> /// </summary>
@@ -163,19 +167,26 @@ namespace linker.tun
} }
/// <summary> /// <summary>
/// 添加NAT转发,这会将来到本网卡且目标IP不是本网卡IP的包转发到其它网卡 /// 设置系统层NAT
/// </summary> /// </summary>
public void SetNat() public void SetSystemNat()
{ {
linkerTunDevice?.RemoveNat(out string error); linkerTunDevice?.SetSystemNat(out natError);
linkerTunDevice?.SetNat(out natError);
} }
/// <summary> /// <summary>
/// 移除NAT转发 /// 设置应用层NAT
/// </summary>
/// <param name="items"></param>
public void SetAppNat(LinkerTunAppNatItemInfo[] items)
{
linkerTunDevice?.SetAppNat(items, out natError);
}
/// <summary>
/// 移除NAT
/// </summary> /// </summary>
public void RemoveNat() public void RemoveNat()
{ {
linkerTunDevice?.RemoveNat(out string error); linkerTunDevice.RemoveNat(out string error);
} }
/// <summary> /// <summary>
@@ -208,17 +219,17 @@ namespace linker.tun
/// </summary> /// </summary>
/// <param name="ips"></param> /// <param name="ips"></param>
/// <param name="ip"></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>
/// 删除路由 /// 删除路由
/// </summary> /// </summary>
/// <param name="ips"></param> /// <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> /// </summary>
/// <param name="buffer"></param> /// <param name="buffer"></param>
/// <returns></returns> /// <returns></returns>
public unsafe bool Write(ReadOnlyMemory<byte> buffer) public bool Write(ReadOnlyMemory<byte> buffer)
{ {
if (linkerTunDevice != null && Status == LinkerTunDeviceStatus.Running) if (linkerTunDevice != null && Status == LinkerTunDeviceStatus.Running)
{ {
@@ -272,6 +283,40 @@ namespace linker.tun
return false; 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) private unsafe void ReWriteIP(ReadOnlyMemory<byte> buffer, uint newIP, int pos)
{ {
fixed (byte* ptr = buffer.Span) 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> /// <summary>
/// 设置IP映射列表 /// 设置IP映射列表
/// </summary> /// </summary>
@@ -397,7 +409,6 @@ namespace linker.tun
return sum; return sum;
} }
public async Task<bool> CheckAvailable(bool order = false) public async Task<bool> CheckAvailable(bool order = false)
{ {
return await linkerTunDevice.CheckAvailable(order); return await linkerTunDevice.CheckAvailable(order);

View File

@@ -27,14 +27,13 @@ namespace linker.tun
private CancellationTokenSource tokenSource; private CancellationTokenSource tokenSource;
private WinDivert winDivert; private WinDivertNAT winDivertNAT;
public LinkerWinTunDevice() 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.name = name;
this.address = address; this.address = address;
@@ -184,9 +183,9 @@ namespace linker.tun
$"netsh interface ipv6 set subinterface {interfaceNumber} mtu={value} store=persistent" $"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; error = string.Empty;
if (address == null || address.Equals(IPAddress.Any)) return; if (address == null || address.Equals(IPAddress.Any)) return;
@@ -194,31 +193,33 @@ namespace linker.tun
{ {
CommandHelper.PowerShell($"start-service WinNat", [], out error); CommandHelper.PowerShell($"start-service WinNat", [], out error);
CommandHelper.PowerShell($"Install-WindowsFeature -Name Routing -IncludeManagementTools", [], 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); 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)); IPAddress network = NetworkHelper.ToNetworkIP(this.address, NetworkHelper.ToPrefixValue(prefixLength));
CommandHelper.PowerShell($"Remove-NetNat -Name {Name} -Confirm:$false", [], out error); CommandHelper.PowerShell($"Remove-NetNat -Name {Name} -Confirm:$false", [], out error);
CommandHelper.PowerShell($"New-NetNat -Name {Name} -InternalIPInterfaceAddressPrefix {network}/{prefixLength}", [], 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; return;
} }
/* error = $"NetNat and ICS not supported,{error}";
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";
} }
catch (Exception ex) catch (Exception ex)
{ {
error = ex.Message; 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) public void RemoveNat(out string error)
{ {
error = string.Empty; error = string.Empty;
@@ -228,12 +229,19 @@ namespace linker.tun
{ {
CommandHelper.PowerShell($"start-service WinNat", [], out error); CommandHelper.PowerShell($"start-service WinNat", [], out error);
CommandHelper.PowerShell($"Remove-NetNat -Name {Name} -Confirm:$false", [], 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) catch (Exception ex)
{ {
error = ex.Message; 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) if (interfaceNumber > 0)
{ {
@@ -281,7 +289,7 @@ namespace linker.tun
IPAddress mask = NetworkHelper.ToIP(maskValue); IPAddress mask = NetworkHelper.ToIP(maskValue);
IPAddress _ip = NetworkHelper.ToNetworkIP(item.Address, 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(); }).ToArray();
if (commands.Length > 0) 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); uint maskValue = NetworkHelper.ToPrefixValue(item.PrefixLength);
IPAddress mask = NetworkHelper.ToIP(maskValue); IPAddress mask = NetworkHelper.ToIP(maskValue);

View File

@@ -1,23 +1,40 @@
using System; using linker.libs;
using System.Collections.Generic; using linker.libs.timer;
using System.Linq; using System.Buffers.Binary;
using System.Runtime.InteropServices; using System.Collections.Frozen;
using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks;
using static linker.libs.winapis.SECUR32;
using static System.Collections.Specialized.BitVector32;
namespace linker.tun namespace linker.tun
{ {
/// <summary> /// <summary>
/// 应用层NAT /// 应用层NAT
/// </summary> /// </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)
{ {
/* this.src = src;
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.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 packet = new Memory<byte>(new byte[WinDivert.MTUMax]);
var abuf = new Memory<WinDivertAddress>(new WinDivertAddress[1]); var abuf = new Memory<WinDivertAddress>(new WinDivertAddress[1]);
TimerHelper.Async(() => 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) 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); //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.ServiceProcess;
using System.Diagnostics; using System.Diagnostics;
using linker.messenger.entry; using linker.messenger.entry;
using linker.libs.extends;
using System.Text;
using System.Text.Json;
namespace linker namespace linker
{ {

Binary file not shown.

View File

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