整理代码

This commit is contained in:
snltty
2024-12-12 17:37:53 +08:00
parent f95926ec81
commit cc4a9ef3f1
42 changed files with 843 additions and 806 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.184" ProductVersion="0.0.0.184" publishDir="/dist/" dstrip="false" local="false" ignored="false">
<project ver="10" name="linker.tray.win" libEmbed="true" icon="..\linker\favicon.ico" ui="win" output="linker.tray.win.exe" CompanyName="snltty" FileDescription="linker.tray.win" LegalCopyright="Copyright (C) snltty 2024" ProductName="linker.tray.win" InternalName="linker.install.win" FileVersion="0.0.0.185" ProductVersion="0.0.0.185" publishDir="/dist/" dstrip="false" local="false" ignored="false">
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
<file name="favicon.ico" path="res\favicon.ico" comment="res\favicon.ico"/>

Binary file not shown.

View File

@@ -1 +1 @@
.table-sort th[data-v-4b2df38c]{border-bottom:0}.dropdown[data-v-6638f97d]{border:1px solid #ddd;padding:.4rem;font-size:1.3rem;border-radius:.4rem;position:relative}.dropdown .el-icon[data-v-6638f97d]{vertical-align:middle}.dropdown .badge[data-v-6638f97d]{position:absolute;right:-1rem;top:-50%;border-radius:10px;background-color:#f1ae05;color:#fff;padding:.2rem .6rem;font-size:1.2rem}a[data-v-6653ef00]{color:#666;text-decoration:underline}a.green[data-v-6653ef00]{color:green;font-weight:700}a.download[data-v-6653ef00]{margin-left:.6rem}a.download .el-icon[data-v-6653ef00]{vertical-align:middle;font-weight:700;margin-left:.3rem}a.download .el-icon.loading[data-v-6653ef00]{animation:loading-6653ef00 1s linear infinite}a.download+a.download[data-v-6653ef00]{margin-left:.2rem}@keyframes loading-6653ef00{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}img.system[data-v-ffd0d512]{height:1.6rem;vertical-align:middle;margin-right:.4rem}.self[data-v-ffd0d512]{color:#d400ff}.self .el-icon[data-v-ffd0d512]{vertical-align:text-bottom}.ipaddress span[data-v-5db71b03]{vertical-align:middle}.el-input[data-v-5db71b03]{width:12rem;margin-right:.6rem}.el-col[data-v-5d52ca48]{text-align:left}.el-icon.loading[data-v-7edec26e],a.loading[data-v-7edec26e]{vertical-align:middle;font-weight:700;animation:loading-7edec26e 1s linear infinite}.el-switch.is-disabled[data-v-7edec26e]{opacity:1}.el-input[data-v-7edec26e]{width:8rem}.delay[data-v-7edec26e]{position:absolute;right:0;bottom:0;line-height:normal}.switch-btn[data-v-7edec26e]{font-size:1.5rem}@keyframes loading-7edec26e{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.wrap[data-v-71a71fe4]{padding-right:1rem}.remark[data-v-71a71fe4]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wrap[data-v-4abaaeaf]{padding-right:1rem}.el-switch.is-disabled[data-v-34275839]{opacity:1}.upgrade-wrap[data-v-34275839]{border:1px solid #ddd;margin-bottom:2rem;padding:0 0 1rem 0}.el-switch.is-disabled[data-v-4a28804a]{opacity:1}.calc span[data-v-4a28804a]{display:inline-block}.calc span.label[data-v-4a28804a]{width:6rem}.el-icon.loading[data-v-c1ea089c],a.loading[data-v-c1ea089c]{vertical-align:middle;font-weight:700;animation:loading-c1ea089c 1s linear infinite}.el-switch.is-disabled[data-v-c1ea089c]{opacity:1}.el-input[data-v-c1ea089c]{width:8rem}.switch-btn[data-v-c1ea089c]{font-size:1.5rem}@keyframes loading-c1ea089c{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-switch.is-disabled[data-v-022e3781]{opacity:1}.upgrade-wrap[data-v-022e3781]{border:1px solid #ddd;margin-bottom:2rem;padding:1rem 0 1rem 0}.lan-item[data-v-022e3781]{margin-bottom:0}.el-switch.is-disabled[data-v-49e16cac]{opacity:1}.green[data-v-49e16cac]{font-weight:700}.el-switch.is-disabled[data-v-6ea047f9]{opacity:1}a[data-v-26b3f87e]{text-decoration:underline}a+a[data-v-26b3f87e]{margin-left:1rem}a.green[data-v-26b3f87e]{font-weight:700}.head[data-v-15b05a01]{padding-bottom:1rem}.green[data-v-15b05a01]{color:green;font-weight:700}.error[data-v-15b05a01]{font-weight:700}.error .el-icon[data-v-15b05a01]{vertical-align:text-bottom}.head[data-v-7eb8e7cc]{padding-bottom:1rem}.error[data-v-7eb8e7cc]{font-weight:700}.error .el-icon[data-v-7eb8e7cc]{vertical-align:text-bottom}.head[data-v-7891b902]{padding-bottom:1rem}.table-sort.el-table th.el-table__cell.is-leaf{border-bottom:0}.table-sort.el-table .el-table__inner-wrapper:before{height:0}.home-list-wrap[data-v-3d1c480c]{padding:1rem}.home-list-wrap .page[data-v-3d1c480c]{padding-top:1rem}.home-list-wrap .page-wrap[data-v-3d1c480c]{display:inline-block}
.table-sort th[data-v-4b2df38c]{border-bottom:0}.dropdown[data-v-6638f97d]{border:1px solid #ddd;padding:.4rem;font-size:1.3rem;border-radius:.4rem;position:relative}.dropdown .el-icon[data-v-6638f97d]{vertical-align:middle}.dropdown .badge[data-v-6638f97d]{position:absolute;right:-1rem;top:-50%;border-radius:10px;background-color:#f1ae05;color:#fff;padding:.2rem .6rem;font-size:1.2rem}a[data-v-6653ef00]{color:#666;text-decoration:underline}a.green[data-v-6653ef00]{color:green;font-weight:700}a.download[data-v-6653ef00]{margin-left:.6rem}a.download .el-icon[data-v-6653ef00]{vertical-align:middle;font-weight:700;margin-left:.3rem}a.download .el-icon.loading[data-v-6653ef00]{animation:loading-6653ef00 1s linear infinite}a.download+a.download[data-v-6653ef00]{margin-left:.2rem}@keyframes loading-6653ef00{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}img.system[data-v-ffd0d512]{height:1.6rem;vertical-align:middle;margin-right:.4rem}.self[data-v-ffd0d512]{color:#d400ff}.self .el-icon[data-v-ffd0d512]{vertical-align:text-bottom}.ipaddress span[data-v-5db71b03]{vertical-align:middle}.el-input[data-v-5db71b03]{width:12rem;margin-right:.6rem}.el-col[data-v-5d52ca48]{text-align:left}.el-icon.loading[data-v-7edec26e],a.loading[data-v-7edec26e]{vertical-align:middle;font-weight:700;animation:loading-7edec26e 1s linear infinite}.el-switch.is-disabled[data-v-7edec26e]{opacity:1}.el-input[data-v-7edec26e]{width:8rem}.delay[data-v-7edec26e]{position:absolute;right:0;bottom:0;line-height:normal}.switch-btn[data-v-7edec26e]{font-size:1.5rem}@keyframes loading-7edec26e{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.wrap[data-v-786fe646]{padding-right:1rem}.remark[data-v-786fe646]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wrap[data-v-4abaaeaf]{padding-right:1rem}.el-switch.is-disabled[data-v-34275839]{opacity:1}.upgrade-wrap[data-v-34275839]{border:1px solid #ddd;margin-bottom:2rem;padding:0 0 1rem 0}.el-switch.is-disabled[data-v-4a28804a]{opacity:1}.calc span[data-v-4a28804a]{display:inline-block}.calc span.label[data-v-4a28804a]{width:6rem}.el-icon.loading[data-v-c1ea089c],a.loading[data-v-c1ea089c]{vertical-align:middle;font-weight:700;animation:loading-c1ea089c 1s linear infinite}.el-switch.is-disabled[data-v-c1ea089c]{opacity:1}.el-input[data-v-c1ea089c]{width:8rem}.switch-btn[data-v-c1ea089c]{font-size:1.5rem}@keyframes loading-c1ea089c{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-switch.is-disabled[data-v-022e3781]{opacity:1}.upgrade-wrap[data-v-022e3781]{border:1px solid #ddd;margin-bottom:2rem;padding:1rem 0 1rem 0}.lan-item[data-v-022e3781]{margin-bottom:0}.el-switch.is-disabled[data-v-49e16cac]{opacity:1}.green[data-v-49e16cac]{font-weight:700}.el-switch.is-disabled[data-v-6ea047f9]{opacity:1}a[data-v-26b3f87e]{text-decoration:underline}a+a[data-v-26b3f87e]{margin-left:1rem}a.green[data-v-26b3f87e]{font-weight:700}.head[data-v-15b05a01]{padding-bottom:1rem}.green[data-v-15b05a01]{color:green;font-weight:700}.error[data-v-15b05a01]{font-weight:700}.error .el-icon[data-v-15b05a01]{vertical-align:text-bottom}.head[data-v-7eb8e7cc]{padding-bottom:1rem}.error[data-v-7eb8e7cc]{font-weight:700}.error .el-icon[data-v-7eb8e7cc]{vertical-align:text-bottom}.head[data-v-7891b902]{padding-bottom:1rem}.table-sort.el-table th.el-table__cell.is-leaf{border-bottom:0}.table-sort.el-table .el-table__inner-wrapper:before{height:0}.home-list-wrap[data-v-3d1c480c]{padding:1rem}.home-list-wrap .page[data-v-3d1c480c]{padding-top:1rem}.home-list-wrap .page-wrap[data-v-3d1c480c]{display:inline-block}

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><script defer="defer" src="js/chunk-vendors.7b81ea90.js"></script><script defer="defer" src="js/app.8e82ca5d.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.e2cbd3ed.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><script defer="defer" src="js/chunk-vendors.7b81ea90.js"></script><script defer="defer" src="js/app.1dbd8a85.js"></script><link href="css/chunk-vendors.d8267b33.css" rel="stylesheet"><link href="css/app.e2cbd3ed.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

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,4 @@
using linker.tunnel.adapter;
using linker.tunnel.connection;
using linker.tunnel.connection;
using linker.tunnel.transport;
using linker.libs;
using linker.libs.extends;
@@ -7,14 +6,63 @@ using System.Collections.Concurrent;
using System.Net.Sockets;
using System.Net;
using linker.tunnel.wanport;
using System.Security.Cryptography.X509Certificates;
namespace linker.tunnel
{
public sealed class TunnelTransfer
{
/// <summary>
/// 本机局域网IP当然你也可以使用0.0.0.0但是使用局域网IP会提高打洞成功率
/// </summary>
public Func<IPAddress> LocalIP { get; set; } = () => IPAddress.Any;
/// <summary>
/// 服务器地址
/// </summary>
public Func<IPEndPoint> ServerHost { get; set; } = () => new IPEndPoint(IPAddress.Any, 0);
/// <summary>
/// ssl加密证书没有证书则无法加密通信
/// </summary>
public Func<X509Certificate2> Certificate { get; set; } = () => null;
/// <summary>
/// 获取打洞协议列表
/// </summary>
/// <returns></returns>
public Func<List<TunnelTransportItemInfo>> GetTunnelTransports { get; set; } = () => new List<TunnelTransportItemInfo>();
/// <summary>
/// 保存打洞协议列表
/// </summary>
/// <param name="transports"></param>
public Action<List<TunnelTransportItemInfo>, bool> SetTunnelTransports { get; set; } = (list, update) => { };
/// <summary>
/// 获取本地网络信息
/// </summary>
/// <returns></returns>
public Func<NetworkInfo> GetLocalConfig { get; set; } = () => new NetworkInfo();
/// <summary>
/// 获取远端的外网信息比如你是A你要获取B的信息可以在B调用 TunnelTransfer.GetWanPort() 发送回来
/// </summary>
public Func<TunnelWanPortProtocolInfo, Task<TunnelTransportWanPortInfo>> GetRemoteWanPort { get; set; } = async (info) => { return await Task.FromResult(new TunnelTransportWanPortInfo()); };
/// <summary>
/// 发送开始打洞
/// </summary>
public Func<TunnelTransportInfo, Task<bool>> SendConnectBegin { get; set; } = async (info) => { return await Task.FromResult(false); };
/// <summary>
/// 发送打洞失败
/// </summary>
public Func<TunnelTransportInfo, Task<bool>> SendConnectFail { get; set; } = async (info) => { return await Task.FromResult(false); };
/// <summary>
/// 发送打洞成功
/// </summary>
public Func<TunnelTransportInfo, Task<bool>> SendConnectSuccess { get; set; } = async (info) => { return await Task.FromResult(false); };
private List<ITunnelTransport> transports;
private TunnelWanPortTransfer compactTransfer;
private ITunnelAdapter tunnelAdapter;
private TunnelWanPortTransfer tunnelWanPortTransfer;
private TunnelUpnpTransfer TunnelUpnpTransfer;
private ConcurrentDictionary<string, bool> connectingDic = new ConcurrentDictionary<string, bool>();
@@ -29,23 +77,22 @@ namespace linker.tunnel
/// 加载打洞协议
/// </summary>
/// <param name="assembs"></param>
public void LoadTransports(TunnelWanPortTransfer compactTransfer, ITunnelAdapter tunnelAdapter, TunnelUpnpTransfer TunnelUpnpTransfer, List<ITunnelTransport> transports)
public void LoadTransports(TunnelWanPortTransfer tunnelWanPortTransfer, TunnelUpnpTransfer TunnelUpnpTransfer, List<ITunnelTransport> transports)
{
this.compactTransfer = compactTransfer;
this.tunnelAdapter = tunnelAdapter;
this.tunnelWanPortTransfer = tunnelWanPortTransfer;
this.transports = transports;
this.TunnelUpnpTransfer = TunnelUpnpTransfer;
foreach (var item in transports)
{
item.OnSendConnectBegin = tunnelAdapter.SendConnectBegin;
item.OnSendConnectFail = tunnelAdapter.SendConnectFail;
item.OnSendConnectSuccess = tunnelAdapter.SendConnectSuccess;
item.OnSendConnectBegin = SendConnectBegin;
item.OnSendConnectFail = SendConnectFail;
item.OnSendConnectSuccess = SendConnectSuccess;
item.OnConnected = _OnConnected;
item.SetAdapter(tunnelAdapter);
item.SetSSL(Certificate());
}
var transportItems = tunnelAdapter.GetTunnelTransports();
var transportItems = GetTunnelTransports();
//有新的协议
var newTransportNames = transports.Select(c => c.Name).Except(transportItems.Select(c => c.Name));
if (newTransportNames.Any())
@@ -96,11 +143,10 @@ namespace linker.tunnel
}
}
tunnelAdapter.SetTunnelTransports(transportItems, true);
SetTunnelTransports(transportItems, true);
LoggerHelper.Instance.Info($"load tunnel transport:{string.Join(",", transports.Select(c => c.Name))}");
}
/// <summary>
/// 设置成功打洞回调
/// </summary>
@@ -154,7 +200,7 @@ namespace linker.tunnel
try
{
foreach (TunnelTransportItemInfo transportItem in tunnelAdapter.GetTunnelTransports().OrderBy(c => c.Order).Where(c => c.Disabled == false))
foreach (TunnelTransportItemInfo transportItem in GetTunnelTransports().OrderBy(c => c.Order).Where(c => c.Disabled == false))
{
ITunnelTransport transport = transports.FirstOrDefault(c => c.Name == transportItem.Name);
//找不到这个打洞协议,或者是不支持的协议
@@ -163,7 +209,7 @@ namespace linker.tunnel
continue;
}
foreach (var wanPortProtocol in compactTransfer.Protocols)
foreach (var wanPortProtocol in tunnelWanPortTransfer.Protocols)
{
//这个打洞协议不支持这个外网端口协议
@@ -182,7 +228,7 @@ namespace linker.tunnel
//获取自己的外网ip
Task<TunnelTransportWanPortInfo> localInfo = GetLocalInfo(wanPortProtocol);
//获取对方的外网ip
Task<TunnelTransportWanPortInfo> remoteInfo = tunnelAdapter.GetRemoteWanPort(new TunnelWanPortProtocolInfo
Task<TunnelTransportWanPortInfo> remoteInfo = GetRemoteWanPort(new TunnelWanPortProtocolInfo
{
MachineId = remoteMachineId,
ProtocolType = wanPortProtocol
@@ -270,7 +316,7 @@ namespace linker.tunnel
try
{
ITunnelTransport _transports = transports.FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.ProtocolType == tunnelTransportInfo.TransportType);
TunnelTransportItemInfo item = tunnelAdapter.GetTunnelTransports().FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.Disabled == false);
TunnelTransportItemInfo item = GetTunnelTransports().FirstOrDefault(c => c.Name == tunnelTransportInfo.TransportName && c.Disabled == false);
if (_transports != null && item != null)
{
OnConnectBegin(tunnelTransportInfo);
@@ -283,7 +329,7 @@ namespace linker.tunnel
else
{
connectingDic.TryRemove(tunnelTransportInfo.Remote.MachineId, out _);
_ = tunnelAdapter.SendConnectFail(tunnelTransportInfo);
_ = SendConnectFail(tunnelTransportInfo);
}
}
catch (Exception ex)
@@ -331,11 +377,11 @@ namespace linker.tunnel
/// <returns></returns>
private async Task<TunnelTransportWanPortInfo> GetLocalInfo(TunnelWanPortProtocolType tunnelWanPortProtocolType)
{
TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP, tunnelWanPortProtocolType).ConfigureAwait(false);
TunnelWanPortEndPoint ip = await tunnelWanPortTransfer.GetWanPortAsync(ServerHost(), LocalIP(), tunnelWanPortProtocolType).ConfigureAwait(false);
if (ip != null)
{
MapInfo portMapInfo = TunnelUpnpTransfer.PortMap ?? new MapInfo { PrivatePort = 0, PublicPort = 0 };
var config = tunnelAdapter.GetLocalConfig();
var config = GetLocalConfig();
return new TunnelTransportWanPortInfo
{
Local = ip.Local,
@@ -492,6 +538,12 @@ namespace linker.tunnel
{
backgroundDic.TryRemove(GetBackgroundKey(remoteMachineId, transactionId), out _);
}
/// <summary>
/// 是否正在后台打洞
/// </summary>
/// <param name="remoteMachineId"></param>
/// <param name="transactionId"></param>
/// <returns></returns>
public bool IsBackground(string remoteMachineId, string transactionId)
{
return backgroundDic.ContainsKey(GetBackgroundKey(remoteMachineId, transactionId));

View File

@@ -1,103 +0,0 @@
using linker.tunnel.wanport;
using linker.tunnel.transport;
using System.Net;
using System.Security.Cryptography.X509Certificates;
namespace linker.tunnel.adapter
{
public interface ITunnelAdapter
{
/// <summary>
/// 本机局域网IP当然你也可以使用0.0.0.0但是使用局域网IP会提高打洞成功率
/// </summary>
public IPAddress LocalIP { get; }
/// <summary>
/// 服务器地址
/// </summary>
public IPEndPoint ServerHost { get; }
/// <summary>
/// ssl加密证书没有证书则无法加密通信
/// </summary>
public X509Certificate2 Certificate { get; }
/// <summary>
/// 获取打洞协议列表
/// </summary>
/// <returns></returns>
public List<TunnelTransportItemInfo> GetTunnelTransports();
/// <summary>
/// 保存打洞协议列表
/// </summary>
/// <param name="transports"></param>
public void SetTunnelTransports(List<TunnelTransportItemInfo> transports, bool updateVersion);
/// <summary>
/// 获取本地网络信息
/// </summary>
/// <returns></returns>
public NetworkInfo GetLocalConfig();
/// <summary>
/// 获取远端的外网信息比如你是A你要获取B的信息可以在B调用 TunnelTransfer.GetWanPort() 发送回来
/// </summary>
/// <param name="remoteMachineId"></param>
/// <returns></returns>
public Task<TunnelTransportWanPortInfo> GetRemoteWanPort(TunnelWanPortProtocolInfo info);
/// <summary>
/// 发送开始打洞
/// </summary>
/// <param name="tunnelTransportInfo"></param>
/// <returns></returns>
public Task<bool> SendConnectBegin(TunnelTransportInfo tunnelTransportInfo);
/// <summary>
/// 发送打洞失败
/// </summary>
/// <param name="tunnelTransportInfo"></param>
/// <returns></returns>
public Task<bool> SendConnectFail(TunnelTransportInfo tunnelTransportInfo);
/// <summary>
/// 发送打洞成功
/// </summary>
/// <param name="tunnelTransportInfo"></param>
/// <returns></returns>
public Task<bool> SendConnectSuccess(TunnelTransportInfo tunnelTransportInfo);
}
public sealed class NetworkInfo
{
/// <summary>
/// 本机局域网IP列表可以通过NetworkHelper.GetRouteLevel 获取
/// </summary>
public IPAddress[] LocalIps { get; set; }
/// <summary>
/// 本机与外网的距离通过多少网关可以通过NetworkHelper.GetRouteLevel 获取
/// </summary>
public int RouteLevel { get; set; }
/// <summary>
/// 本机名
/// </summary>
public string MachineId { get; set; }
}
public sealed class PortMapInfo
{
public int WanPort { get; set; }
public int LanPort { get; set; }
}
public sealed class TunnelWanPortProtocolInfo
{
/// <summary>
/// 协议
/// </summary>
public TunnelWanPortProtocolType ProtocolType { get; set; } = TunnelWanPortProtocolType.Udp;
/// <summary>
/// 对方id
/// </summary>
public string MachineId { get; set; }
}
}

View File

@@ -1,7 +1,7 @@
using linker.tunnel.adapter;
using linker.tunnel.connection;
using linker.tunnel.connection;
using linker.tunnel.wanport;
using System.Net;
using System.Security.Cryptography.X509Certificates;
namespace linker.tunnel.transport
{
@@ -62,7 +62,7 @@ namespace linker.tunnel.transport
/// </summary>
public Action<ITunnelConnection> OnConnected { get; set; }
public void SetAdapter(ITunnelAdapter tunnelAdapter);
public void SetSSL(X509Certificate2 certificate);
/// <summary>
/// 连接对方
@@ -228,4 +228,32 @@ namespace linker.tunnel.transport
}
public sealed class NetworkInfo
{
/// <summary>
/// 本机局域网IP列表可以通过NetworkHelper.GetRouteLevel 获取
/// </summary>
public IPAddress[] LocalIps { get; set; }
/// <summary>
/// 本机与外网的距离通过多少网关可以通过NetworkHelper.GetRouteLevel 获取
/// </summary>
public int RouteLevel { get; set; }
/// <summary>
/// 本机名
/// </summary>
public string MachineId { get; set; }
}
public sealed class TunnelWanPortProtocolInfo
{
/// <summary>
/// 协议
/// </summary>
public TunnelWanPortProtocolType ProtocolType { get; set; } = TunnelWanPortProtocolType.Udp;
/// <summary>
/// 对方id
/// </summary>
public string MachineId { get; set; }
}
}

View File

@@ -1,4 +1,4 @@
using linker.tunnel.adapter;

using linker.tunnel.connection;
using linker.libs;
using linker.libs.extends;
@@ -10,6 +10,7 @@ using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using linker.tunnel.wanport;
using System.Security.Cryptography.X509Certificates;
namespace linker.tunnel.transport
{
@@ -46,15 +47,16 @@ namespace linker.tunnel.transport
private byte[] endBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.end");
private IPEndPoint quicListenEP = null;
private ITunnelAdapter tunnelAdapter;
public TransportMsQuic()
{
_ = QuicListen();
}
public void SetAdapter(ITunnelAdapter tunnelAdapter)
private X509Certificate2 certificate;
public void SetSSL(X509Certificate2 certificate)
{
this.tunnelAdapter = tunnelAdapter;
this.certificate = certificate;
}
/// <summary>
@@ -72,7 +74,7 @@ namespace linker.tunnel.transport
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
return null;
}
if (tunnelAdapter.Certificate == null)
if (certificate == null)
{
LoggerHelper.Instance.Warning($"msquic need ssl");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
@@ -132,7 +134,7 @@ namespace linker.tunnel.transport
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
return;
}
if (tunnelAdapter.Certificate == null)
if (certificate == null)
{
LoggerHelper.Instance.Warning($"msquic need ssl");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
@@ -661,7 +663,7 @@ namespace linker.tunnel.transport
LoggerHelper.Instance.Warning($"msquic not supported, need win11+,or linux, or try to restart linker");
return;
}
if (tunnelAdapter.Certificate == null)
if (certificate == null)
{
LoggerHelper.Instance.Warning($"msquic need ssl");
return;
@@ -683,7 +685,7 @@ namespace linker.tunnel.transport
IdleTimeout = TimeSpan.FromMilliseconds(15000),
ServerAuthenticationOptions = new SslServerAuthenticationOptions
{
ServerCertificate = tunnelAdapter.Certificate,
ServerCertificate = certificate,
EnabledSslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13,
ApplicationProtocols = new List<SslApplicationProtocol> { SslApplicationProtocol.Http3 }
}

View File

@@ -1,4 +1,4 @@
using linker.tunnel.adapter;

using linker.tunnel.connection;
using linker.libs;
using linker.libs.extends;
@@ -54,13 +54,13 @@ namespace linker.tunnel.transport
/// </summary>
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
private ITunnelAdapter tunnelAdapter;
public TunnelTransportTcpNutssb()
{
}
public void SetAdapter(ITunnelAdapter tunnelAdapter)
private X509Certificate2 certificate;
public void SetSSL(X509Certificate2 certificate)
{
this.tunnelAdapter = tunnelAdapter;
this.certificate = certificate;
}
/// <summary>
@@ -114,7 +114,7 @@ namespace linker.tunnel.transport
/// <param name="tunnelTransportInfo"></param>
public async Task OnBegin(TunnelTransportInfo tunnelTransportInfo)
{
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
if (tunnelTransportInfo.SSL && certificate == null)
{
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
@@ -278,7 +278,7 @@ namespace linker.tunnel.transport
SslStream sslStream = null;
if (_state.SSL)
{
if (tunnelAdapter.Certificate == null)
if (certificate == null)
{
LoggerHelper.Instance.Error($"{Name}-> ssl Certificate not found");
socket.SafeClose();
@@ -286,7 +286,7 @@ namespace linker.tunnel.transport
}
sslStream = new SslStream(new NetworkStream(socket, false), false);
await sslStream.AuthenticateAsServerAsync(tunnelAdapter.Certificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
}
TunnelConnectionTcp result = new TunnelConnectionTcp

View File

@@ -1,4 +1,4 @@
using linker.tunnel.adapter;

using linker.tunnel.connection;
using linker.libs;
using linker.libs.extends;
@@ -55,14 +55,14 @@ namespace linker.tunnel.transport
private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl");
private byte[] endBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.end");
private ITunnelAdapter tunnelAdapter;
public TransportTcpP2PNAT()
{
}
public void SetAdapter(ITunnelAdapter tunnelAdapter)
private X509Certificate2 certificate;
public void SetSSL(X509Certificate2 certificate)
{
this.tunnelAdapter = tunnelAdapter;
this.certificate = certificate;
}
/// <summary>
@@ -96,7 +96,7 @@ namespace linker.tunnel.transport
/// <param name="tunnelTransportInfo"></param>
public async Task OnBegin(TunnelTransportInfo tunnelTransportInfo)
{
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
if (tunnelTransportInfo.SSL && certificate == null)
{
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
@@ -217,7 +217,7 @@ namespace linker.tunnel.transport
SslStream sslStream = null;
if (state.SSL)
{
if (tunnelAdapter.Certificate == null)
if (certificate == null)
{
LoggerHelper.Instance.Error($"{Name}-> ssl Certificate not found");
socket.SafeClose();
@@ -225,7 +225,7 @@ namespace linker.tunnel.transport
}
sslStream = new SslStream(new NetworkStream(socket, false), false);
await sslStream.AuthenticateAsServerAsync(tunnelAdapter.Certificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
}
return new TunnelConnectionTcp

View File

@@ -6,7 +6,6 @@ using System.Text;
using linker.libs.extends;
using System.Collections.Concurrent;
using linker.libs;
using linker.tunnel.adapter;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Authentication;
@@ -44,13 +43,14 @@ namespace linker.tunnel.transport
private readonly ConcurrentDictionary<string, TaskCompletionSource<Socket>> distDic = new ConcurrentDictionary<string, TaskCompletionSource<Socket>>();
private ITunnelAdapter tunnelAdapter;
public TransportTcpPortMap()
{
}
public void SetAdapter(ITunnelAdapter tunnelAdapter)
private X509Certificate2 certificate;
public void SetSSL(X509Certificate2 certificate)
{
this.tunnelAdapter = tunnelAdapter;
this.certificate = certificate;
}
@@ -181,7 +181,7 @@ namespace linker.tunnel.transport
}
public async Task OnBegin(TunnelTransportInfo tunnelTransportInfo)
{
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
if (tunnelTransportInfo.SSL && certificate == null)
{
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);
@@ -246,7 +246,7 @@ namespace linker.tunnel.transport
SslStream sslStream = null;
if (tunnelTransportInfo.SSL)
{
if (tunnelAdapter.Certificate == null)
if (certificate == null)
{
LoggerHelper.Instance.Error($"{Name}-> ssl Certificate not found");
socket.SafeClose();
@@ -254,7 +254,7 @@ namespace linker.tunnel.transport
}
sslStream = new SslStream(new NetworkStream(socket, false), false);
await sslStream.AuthenticateAsServerAsync(tunnelAdapter.Certificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false).ConfigureAwait(false);
}
TunnelConnectionTcp result = new TunnelConnectionTcp

View File

@@ -6,7 +6,7 @@ using System.Net;
using System.Net.Sockets;
using System.Text;
using linker.tunnel.wanport;
using linker.tunnel.adapter;
using System.Security.Cryptography.X509Certificates;
namespace linker.tunnel.transport
{
@@ -53,7 +53,7 @@ namespace linker.tunnel.transport
public TransportUdp()
{
}
public void SetAdapter(ITunnelAdapter tunnelAdapter)
public void SetSSL(X509Certificate2 certificate)
{
}

View File

@@ -6,7 +6,7 @@ using System.Text;
using linker.libs.extends;
using System.Collections.Concurrent;
using linker.libs;
using linker.tunnel.adapter;
using System.Security.Cryptography.X509Certificates;
namespace linker.tunnel.transport
{
@@ -46,14 +46,15 @@ namespace linker.tunnel.transport
private readonly ConcurrentDictionary<string, TaskCompletionSource<State>> distDic = new ConcurrentDictionary<string, TaskCompletionSource<State>>();
private readonly ConcurrentDictionary<IPEndPoint, ConnectionCacheInfo> connectionsDic = new ConcurrentDictionary<IPEndPoint, ConnectionCacheInfo>(new IPEndPointComparer());
private ITunnelAdapter tunnelAdapter;
public TransportUdpPortMap()
{
CleanTask();
}
public void SetAdapter(ITunnelAdapter tunnelAdapter)
private X509Certificate2 certificate;
public void SetSSL(X509Certificate2 certificate)
{
this.tunnelAdapter = tunnelAdapter;
this.certificate = certificate;
}
Socket socket;
@@ -197,7 +198,7 @@ namespace linker.tunnel.transport
}
public async Task OnBegin(TunnelTransportInfo tunnelTransportInfo)
{
if (tunnelTransportInfo.SSL && tunnelAdapter.Certificate == null)
if (tunnelTransportInfo.SSL && certificate == null)
{
LoggerHelper.Instance.Error($"{Name}->ssl Certificate not found");
await OnSendConnectFail(tunnelTransportInfo).ConfigureAwait(false);

View File

@@ -1,5 +1,4 @@
using linker.libs;
using linker.tunnel.adapter;
using System.Net;
namespace linker.tunnel.wanport
@@ -13,14 +12,10 @@ namespace linker.tunnel.wanport
public List<TunnelWanPortProtocolType> Protocols => tunnelWanPorts.Select(p => p.ProtocolType).ToList();
private readonly ITunnelAdapter tunnelAdapter;
public TunnelWanPortTransfer(ITunnelAdapter tunnelAdapter)
public TunnelWanPortTransfer()
{
this.tunnelAdapter = tunnelAdapter;
}
/// <summary>
/// 加载所有外网端口协议
/// </summary>
@@ -37,14 +32,13 @@ namespace linker.tunnel.wanport
/// </summary>
/// <param name="localIP">你的局域网IP</param>
/// <returns></returns>
public async Task<TunnelWanPortEndPoint> GetWanPortAsync(IPAddress localIP, TunnelWanPortProtocolType protocolType)
public async Task<TunnelWanPortEndPoint> GetWanPortAsync(IPEndPoint server,IPAddress localIP, TunnelWanPortProtocolType protocolType)
{
var tunnelWanPort = tunnelWanPorts.FirstOrDefault(c => c.ProtocolType == protocolType);
if (tunnelWanPort == null) return null;
try
{
if (tunnelAdapter.ServerHost == null) return null;
TunnelWanPortEndPoint wanPort = await tunnelWanPort.GetAsync(localIP, tunnelAdapter.ServerHost).ConfigureAwait(false);
TunnelWanPortEndPoint wanPort = await tunnelWanPort.GetAsync(localIP, server).ConfigureAwait(false);
if (wanPort != null)
{
wanPort.Local.Address = localIP;

View File

@@ -146,7 +146,6 @@ namespace linker.config
public IConfig PropertyMethod { get; set; }
}
public interface IConfig
{
public string Serialize(object obj);
@@ -217,7 +216,6 @@ namespace linker.config
}
}
[AttributeUsage(AttributeTargets.Class)]
public class JsonAotAttribute : Attribute { }
}

View File

@@ -12,7 +12,6 @@ namespace linker.plugins.relay.client
/// </summary>
public sealed class RelayTestTransfer
{
private readonly FileConfig fileConfig;
private readonly RelayTransfer relayTransfer;
private readonly ClientSignInState clientSignInState;
private readonly ClientConfigTransfer clientConfigTransfer;
@@ -20,9 +19,8 @@ namespace linker.plugins.relay.client
public List<RelayNodeReportInfo> Nodes { get; private set; } = new List<RelayNodeReportInfo>();
public RelayTestTransfer(FileConfig fileConfig, RelayTransfer relayTransfer, ClientSignInState clientSignInState, ClientConfigTransfer clientConfigTransfer, RelayClientConfigTransfer relayClientConfigTransfer)
public RelayTestTransfer( RelayTransfer relayTransfer, ClientSignInState clientSignInState, ClientConfigTransfer clientConfigTransfer, RelayClientConfigTransfer relayClientConfigTransfer)
{
this.fileConfig = fileConfig;
this.relayTransfer = relayTransfer;
this.clientSignInState = clientSignInState;
this.clientConfigTransfer = clientConfigTransfer;

View File

@@ -54,17 +54,6 @@ namespace linker.plugins.socks5
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Error(ex);
}
/*
bool online = await clientSignInTransfer.GetOnline(connection.RemoteMachineId);
if (online == false)
{
foreach (var item in ip2MachineDic.Where(c => c.Value == connection.RemoteMachineId).Select(c => c.Key).ToList())
{
ip2MachineDic.TryRemove(item, out string str);
}
RefreshConfig();
}
*/
await Task.CompletedTask;
}
/// <summary>

View File

@@ -1,46 +1,73 @@
using linker.client.config;
using linker.config;
using linker.plugins.tunnel.messenger;
using linker.tunnel.adapter;
using linker.plugins.tunnel.messenger;
using linker.tunnel.transport;
using linker.libs;
using MemoryPack;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using linker.plugins.client;
using linker.plugins.messenger;
using linker.plugins.tunnel.excludeip;
using linker.tunnel.wanport;
using linker.tunnel;
namespace linker.plugins.tunnel
{
public sealed class TunnelAdapter : ITunnelAdapter
public sealed class TunnelAdapter
{
public IPAddress LocalIP => clientSignInState.Connection?.LocalAddress.Address ?? IPAddress.Any;
public IPEndPoint ServerHost => clientSignInState.Connection?.Address ?? null;
public X509Certificate2 Certificate => tunnelConfigTransfer.Certificate;
private readonly ClientSignInState clientSignInState;
private readonly IMessengerSender messengerSender;
private readonly TunnelExcludeIPTransfer excludeIPTransfer;
private readonly ClientConfigTransfer clientConfigTransfer;
private readonly TunnelConfigTransfer tunnelConfigTransfer;
public TunnelAdapter(ClientSignInState clientSignInState, IMessengerSender messengerSender, TunnelExcludeIPTransfer excludeIPTransfer, ClientConfigTransfer clientConfigTransfer, TunnelConfigTransfer tunnelConfigTransfer)
private readonly TunnelWanPortTransfer tunnelWanPortTransfer;
private readonly TunnelUpnpTransfer tunnelUpnpTransfer;
private readonly TunnelTransfer tunnelTransfer;
public TunnelAdapter(ClientSignInState clientSignInState, IMessengerSender messengerSender,
TunnelExcludeIPTransfer excludeIPTransfer, ClientConfigTransfer clientConfigTransfer, TunnelConfigTransfer tunnelConfigTransfer,
TunnelWanPortTransfer tunnelWanPortTransfer, TunnelUpnpTransfer tunnelUpnpTransfer, TunnelTransfer tunnelTransfer)
{
this.clientSignInState = clientSignInState;
this.messengerSender = messengerSender;
this.excludeIPTransfer = excludeIPTransfer;
this.clientConfigTransfer = clientConfigTransfer;
this.tunnelConfigTransfer = tunnelConfigTransfer;
}
public List<TunnelTransportItemInfo> GetTunnelTransports()
{
return tunnelConfigTransfer.Transports;
}
public void SetTunnelTransports(List<TunnelTransportItemInfo> transports, bool updateVersion)
{
tunnelConfigTransfer.SetTransports(transports);
this.tunnelWanPortTransfer = tunnelWanPortTransfer;
this.tunnelUpnpTransfer = tunnelUpnpTransfer;
this.tunnelTransfer = tunnelTransfer;
tunnelWanPortTransfer.LoadTransports(new List<ITunnelWanPortProtocol>
{
new TunnelWanPortProtocolLinkerUdp(),
new TunnelWanPortProtocolLinkerTcp(),
});
tunnelTransfer.LocalIP = () => clientSignInState.Connection?.LocalAddress.Address ?? IPAddress.Any;
tunnelTransfer.ServerHost = () => clientSignInState.Connection?.Address ?? null;
tunnelTransfer.Certificate = () => tunnelConfigTransfer.Certificate;
tunnelTransfer.GetTunnelTransports = () => tunnelConfigTransfer.Transports;
tunnelTransfer.SetTunnelTransports = (transports,update) => tunnelConfigTransfer.SetTransports(transports);
tunnelTransfer.GetLocalConfig = GetLocalConfig;
tunnelTransfer.GetRemoteWanPort = GetRemoteWanPort;
tunnelTransfer.SendConnectBegin = SendConnectBegin;
tunnelTransfer.SendConnectFail = SendConnectFail;
tunnelTransfer.SendConnectSuccess = SendConnectSuccess;
tunnelTransfer.LoadTransports(tunnelWanPortTransfer, tunnelUpnpTransfer, new List<ITunnelTransport> {
new TunnelTransportTcpNutssb(),
new TransportMsQuic(),
new TransportTcpP2PNAT(),
new TransportTcpPortMap(),
new TransportUdpPortMap(),
new TransportUdp(),
});
clientSignInState.NetworkEnabledHandle += (times) =>
{
RefreshPortMap();
};
tunnelConfigTransfer.OnChanged += RefreshPortMap;
}
public NetworkInfo GetLocalConfig()
@@ -70,6 +97,7 @@ namespace linker.plugins.tunnel
MachineId = clientConfigTransfer.Id
};
}
public async Task<TunnelTransportWanPortInfo> GetRemoteWanPort(TunnelWanPortProtocolInfo info)
{
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
@@ -118,5 +146,17 @@ namespace linker.plugins.tunnel
return true;
}
private void RefreshPortMap()
{
if (tunnelConfigTransfer.PortMapLan > 0)
{
tunnelUpnpTransfer.SetMap(tunnelConfigTransfer.PortMapLan, tunnelConfigTransfer.PortMapWan);
}
else
{
tunnelUpnpTransfer.SetMap(clientSignInState.Connection.LocalAddress.Address, 18180);
}
}
}
}

View File

@@ -1,6 +1,5 @@
using linker.config;
using linker.plugins.tunnel.messenger;
using linker.tunnel.adapter;
using linker.tunnel.transport;
using linker.libs.api;
using linker.libs.extends;
@@ -20,27 +19,23 @@ namespace linker.plugins.tunnel
/// </summary>
public sealed class TunnelApiController : IApiClientController
{
private readonly FileConfig config;
private readonly TunnelWanPortTransfer compactTransfer;
private readonly ClientSignInState clientSignInState;
private readonly IMessengerSender messengerSender;
private readonly TunnelConfigTransfer tunnelConfigTransfer;
private readonly ITunnelAdapter tunnelMessengerAdapter;
private readonly TunnelExcludeIPTransfer excludeIPTransfer;
private readonly AccessTransfer accessTransfer;
private readonly ClientConfigTransfer clientConfigTransfer;
private readonly TunnelDecenter tunnelDecenter;
public TunnelApiController(FileConfig config, TunnelWanPortTransfer compactTransfer, ClientSignInState clientSignInState, IMessengerSender messengerSender, TunnelConfigTransfer tunnelConfigTransfer, ITunnelAdapter tunnelMessengerAdapter, TunnelExcludeIPTransfer excludeIPTransfer, AccessTransfer accessTransfer, ClientConfigTransfer clientConfigTransfer)
public TunnelApiController(ClientSignInState clientSignInState, IMessengerSender messengerSender, TunnelConfigTransfer tunnelConfigTransfer, TunnelExcludeIPTransfer excludeIPTransfer, AccessTransfer accessTransfer, ClientConfigTransfer clientConfigTransfer, TunnelDecenter tunnelDecenter)
{
this.config = config;
this.compactTransfer = compactTransfer;
this.clientSignInState = clientSignInState;
this.messengerSender = messengerSender;
this.tunnelConfigTransfer = tunnelConfigTransfer;
this.tunnelMessengerAdapter = tunnelMessengerAdapter;
this.excludeIPTransfer = excludeIPTransfer;
this.accessTransfer = accessTransfer;
this.clientConfigTransfer = clientConfigTransfer;
this.tunnelDecenter = tunnelDecenter;
}
/// <summary>
@@ -51,11 +46,11 @@ namespace linker.plugins.tunnel
public TunnelListInfo Get(ApiControllerParamsInfo param)
{
ulong hashCode = ulong.Parse(param.Content);
if (tunnelConfigTransfer.Version.Eq(hashCode, out ulong version) == false)
if (tunnelDecenter.Version.Eq(hashCode, out ulong version) == false)
{
return new TunnelListInfo
{
List = tunnelConfigTransfer.Config,
List = tunnelDecenter.Config,
HashCode = version
};
}
@@ -67,7 +62,7 @@ namespace linker.plugins.tunnel
/// <param name="param"></param>
public void Refresh(ApiControllerParamsInfo param)
{
tunnelConfigTransfer.RefreshConfig();
tunnelDecenter.Refresh();
}
/// <summary>
@@ -105,7 +100,7 @@ namespace linker.plugins.tunnel
/// <returns></returns>
public List<TunnelTransportItemInfo> GetTransports(ApiControllerParamsInfo param)
{
return tunnelMessengerAdapter.GetTunnelTransports();
return tunnelConfigTransfer.Transports;
}
/// <summary>
/// 设置打洞协议
@@ -116,7 +111,7 @@ namespace linker.plugins.tunnel
public bool SetTransports(ApiControllerParamsInfo param)
{
List<TunnelTransportItemInfo> info = param.Content.DeJson<List<TunnelTransportItemInfo>>();
tunnelMessengerAdapter.SetTunnelTransports(info, true);
tunnelConfigTransfer.SetTransports(info);
return true;
}

View File

@@ -1,5 +1,4 @@
using linker.config;
using linker.libs;
using linker.libs;
using linker.libs.extends;
using linker.plugins.client;
using linker.tunnel;
@@ -7,7 +6,6 @@ using linker.tunnel.connection;
using System.Collections.Concurrent;
using linker.plugins.relay.client;
using linker.plugins.pcp;
using linker.client.config;
namespace linker.plugins.tunnel
{

View File

@@ -2,26 +2,22 @@
using linker.config;
using linker.libs;
using linker.plugins.client;
using linker.plugins.decenter;
using linker.plugins.messenger;
using linker.tunnel;
using linker.tunnel.transport;
using MemoryPack;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Quic;
using System.Security.Cryptography.X509Certificates;
namespace linker.plugins.tunnel
{
public sealed class TunnelConfigTransfer : IDecenter
public sealed class TunnelConfigTransfer
{
public string Name => "tunnel";
public VersionManager DataVersion { get; } = new VersionManager();
public int RouteLevel => config.Data.Client.Tunnel.RouteLevel + running.Data.Tunnel.RouteLevelPlus;
public IPAddress[] LocalIPs => config.Data.Client.Tunnel.LocalIPs;
public IPAddress[] RouteIPs => config.Data.Client.Tunnel.RouteIPs;
public int PortMapLan => running.Data.Tunnel.PortMapLan;
public int PortMapWan => running.Data.Tunnel.PortMapWan;
public List<TunnelTransportItemInfo> Transports => config.Data.Client.Tunnel.Transports;
public X509Certificate2 Certificate { get; private set; }
@@ -32,8 +28,7 @@ namespace linker.plugins.tunnel
private readonly TunnelUpnpTransfer upnpTransfer;
private readonly ClientConfigTransfer clientConfigTransfer;
public VersionManager Version { get; } = new VersionManager();
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config { get; } = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
public Action OnChanged { get; set; } = () => { };
public TunnelConfigTransfer(FileConfig config, RunningConfig running, ClientSignInState clientSignInState, IMessengerSender messengerSender, TunnelUpnpTransfer upnpTransfer, ClientConfigTransfer clientConfigTransfer)
{
@@ -52,36 +47,10 @@ namespace linker.plugins.tunnel
clientSignInState.NetworkEnabledHandle += (times) =>
{
TimerHelper.Async(RefreshRouteLevel);
RefreshPortMap();
};
TestQuic();
}
public Memory<byte> GetData()
{
TunnelTransportRouteLevelInfo tunnelTransportRouteLevelInfo = GetLocalRouteLevel();
Config.AddOrUpdate(tunnelTransportRouteLevelInfo.MachineId, tunnelTransportRouteLevelInfo, (a, b) => tunnelTransportRouteLevelInfo);
Version.Add();
return MemoryPackSerializer.Serialize(tunnelTransportRouteLevelInfo);
}
public void SetData(Memory<byte> data)
{
TunnelTransportRouteLevelInfo tunnelTransportRouteLevelInfo = MemoryPackSerializer.Deserialize<TunnelTransportRouteLevelInfo>(data.Span);
Config.AddOrUpdate(tunnelTransportRouteLevelInfo.MachineId, tunnelTransportRouteLevelInfo, (a, b) => tunnelTransportRouteLevelInfo);
Version.Add();
}
public void SetData(List<ReadOnlyMemory<byte>> data)
{
List<TunnelTransportRouteLevelInfo> list = data.Select(c => MemoryPackSerializer.Deserialize<TunnelTransportRouteLevelInfo>(c.Span)).ToList();
foreach (var item in list)
{
Config.AddOrUpdate(item.MachineId, item, (a, b) => item);
}
TunnelTransportRouteLevelInfo config = GetLocalRouteLevel();
Config.AddOrUpdate(config.MachineId, config, (a, b) => config);
Version.Add();
}
public void SetTransports(List<TunnelTransportItemInfo> transports)
{
config.Data.Client.Tunnel.Transports = transports;
@@ -96,16 +65,9 @@ namespace linker.plugins.tunnel
config.Data.Client.Tunnel.RouteLevel = NetworkHelper.GetRouteLevel(clientConfigTransfer.Server.Host, out List<IPAddress> ips);
config.Data.Client.Tunnel.RouteIPs = ips.ToArray();
config.Data.Client.Tunnel.LocalIPs = NetworkHelper.GetIPV6().Concat(NetworkHelper.GetIPV4()).ToArray();
DataVersion.Add();
OnChanged();
}
/// <summary>
/// 刷新关于隧道的配置信息,也就是获取自己的和别的客户端的,方便查看
/// </summary>
public void RefreshConfig()
{
DataVersion.Add();
}
/// <summary>
/// 修改自己的网关层级信息
/// </summary>
@@ -116,10 +78,9 @@ namespace linker.plugins.tunnel
running.Data.Tunnel.PortMapWan = tunnelTransportFileConfigInfo.PortMapWan;
running.Data.Tunnel.PortMapLan = tunnelTransportFileConfigInfo.PortMapLan;
running.Data.Update();
GetData();
DataVersion.Add();
OnChanged();
}
private TunnelTransportRouteLevelInfo GetLocalRouteLevel()
public TunnelTransportRouteLevelInfo GetLocalRouteLevel()
{
return new TunnelTransportRouteLevelInfo
{
@@ -172,16 +133,6 @@ namespace linker.plugins.tunnel
}
}
}
private void RefreshPortMap()
{
if (running.Data.Tunnel.PortMapLan > 0)
{
upnpTransfer.SetMap(running.Data.Tunnel.PortMapLan, running.Data.Tunnel.PortMapWan);
}
else
{
upnpTransfer.SetMap(clientSignInState.Connection.LocalAddress.Address, 18180);
}
}
}
}

View File

@@ -0,0 +1,55 @@
using linker.config;
using linker.libs;
using linker.plugins.decenter;
using MemoryPack;
using System.Collections.Concurrent;
namespace linker.plugins.tunnel
{
public sealed class TunnelDecenter:IDecenter
{
public string Name => "tunnel";
public VersionManager DataVersion { get; } = new VersionManager();
public VersionManager Version { get; } = new VersionManager();
public ConcurrentDictionary<string, TunnelTransportRouteLevelInfo> Config { get; } = new ConcurrentDictionary<string, TunnelTransportRouteLevelInfo>();
private readonly TunnelConfigTransfer tunnelConfigTransfer;
public TunnelDecenter(TunnelConfigTransfer tunnelConfigTransfer)
{
this.tunnelConfigTransfer = tunnelConfigTransfer;
tunnelConfigTransfer.OnChanged += Refresh;
}
/// <summary>
/// 刷新关于隧道的配置信息,也就是获取自己的和别的客户端的,方便查看
/// </summary>
public void Refresh()
{
DataVersion.Add();
}
public Memory<byte> GetData()
{
TunnelTransportRouteLevelInfo tunnelTransportRouteLevelInfo = tunnelConfigTransfer.GetLocalRouteLevel();
Config.AddOrUpdate(tunnelTransportRouteLevelInfo.MachineId, tunnelTransportRouteLevelInfo, (a, b) => tunnelTransportRouteLevelInfo);
Version.Add();
return MemoryPackSerializer.Serialize(tunnelTransportRouteLevelInfo);
}
public void SetData(Memory<byte> data)
{
TunnelTransportRouteLevelInfo tunnelTransportRouteLevelInfo = MemoryPackSerializer.Deserialize<TunnelTransportRouteLevelInfo>(data.Span);
Config.AddOrUpdate(tunnelTransportRouteLevelInfo.MachineId, tunnelTransportRouteLevelInfo, (a, b) => tunnelTransportRouteLevelInfo);
Version.Add();
}
public void SetData(List<ReadOnlyMemory<byte>> data)
{
List<TunnelTransportRouteLevelInfo> list = data.Select(c => MemoryPackSerializer.Deserialize<TunnelTransportRouteLevelInfo>(c.Span)).ToList();
foreach (var item in list)
{
Config.AddOrUpdate(item.MachineId, item, (a, b) => item);
}
TunnelTransportRouteLevelInfo config = tunnelConfigTransfer.GetLocalRouteLevel();
Config.AddOrUpdate(config.MachineId, config, (a, b) => config);
Version.Add();
}
}
}

View File

@@ -2,12 +2,9 @@
using linker.plugins.tunnel.messenger;
using linker.startup;
using linker.tunnel;
using linker.tunnel.adapter;
using linker.tunnel.transport;
using linker.libs;
using MemoryPack;
using Microsoft.Extensions.DependencyInjection;
using System.Net;
using linker.tunnel.wanport;
using linker.plugins.tunnel.excludeip;
using linker.plugins.client;
@@ -36,7 +33,6 @@ namespace linker.plugins.tunnel
MemoryPackFormatterProvider.Register(new TunnelTransportInfoFormatter());
MemoryPackFormatterProvider.Register(new TunnelWanPortProtocolInfoFormatter());
//管理接口
serviceCollection.AddSingleton<TunnelApiController>();
//命令接口
@@ -44,30 +40,18 @@ namespace linker.plugins.tunnel
//外网端口协议
serviceCollection.AddSingleton<TunnelWanPortTransfer>();
serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerUdp>();
serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerTcp>();
//打洞协议
serviceCollection.AddSingleton<TunnelTransfer>();
serviceCollection.AddSingleton<TunnelTransportTcpNutssb>();
serviceCollection.AddSingleton<TransportMsQuic>();
serviceCollection.AddSingleton<TransportTcpP2PNAT>();
serviceCollection.AddSingleton<TransportTcpPortMap>();
serviceCollection.AddSingleton<TransportUdpPortMap>();
serviceCollection.AddSingleton<TransportUdp>();
serviceCollection.AddSingleton<TunnelUpnpTransfer>();
serviceCollection.AddSingleton<TunnelExcludeIPTransfer>();
serviceCollection.AddSingleton<TunnelExcludeIPTypesLoader>();
serviceCollection.AddSingleton<TunnelConfigTransfer>();
serviceCollection.AddSingleton<ITunnelAdapter, TunnelAdapter>();
serviceCollection.AddSingleton<TunnelUpnpTransfer>();
serviceCollection.AddSingleton<TunnelConfigSyncTransports>();
serviceCollection.AddSingleton<TunnelDecenter>();
serviceCollection.AddSingleton<TunnelConfigTransfer>();
serviceCollection.AddSingleton<TunnelAdapter>();
}
public void AddServer(ServiceCollection serviceCollection, FileConfig config)
@@ -83,36 +67,14 @@ namespace linker.plugins.tunnel
public void UseClient(ServiceProvider serviceProvider, FileConfig config)
{
ITunnelAdapter tunnelAdapter = serviceProvider.GetService<ITunnelAdapter>();
TunnelUpnpTransfer upnpTransfer = serviceProvider.GetService<TunnelUpnpTransfer>();
IEnumerable<Type> types = new List<Type> {
typeof(TunnelWanPortProtocolLinkerUdp),
typeof(TunnelWanPortProtocolLinkerTcp)
};
List<ITunnelWanPortProtocol> compacts = types.Select(c => (ITunnelWanPortProtocol)serviceProvider.GetService(c)).Where(c => c != null).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList();
TunnelWanPortTransfer compack = serviceProvider.GetService<TunnelWanPortTransfer>();
compack.LoadTransports(compacts);
types = new List<Type> {
typeof(TunnelTransportTcpNutssb),
typeof(TransportMsQuic),
typeof(TransportTcpP2PNAT),
typeof(TransportTcpPortMap),
typeof(TransportUdpPortMap),
typeof(TransportUdp),
};
List<ITunnelTransport> transports = types.Select(c => (ITunnelTransport)serviceProvider.GetService(c)).Where(c => c != null).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList();
TunnelTransfer tunnel = serviceProvider.GetService<TunnelTransfer>();
tunnel.LoadTransports(compack, tunnelAdapter, upnpTransfer, transports);
TunnelExcludeIPTransfer excludeIPTransfer = serviceProvider.GetService<TunnelExcludeIPTransfer>();
TunnelExcludeIPTypesLoader tunnelExcludeIPTypesLoader = serviceProvider.GetService<TunnelExcludeIPTypesLoader>();
ClientConfigTransfer clientConfigTransfer = serviceProvider.GetService<ClientConfigTransfer>();
TunnelConfigTransfer tunnelConfigTransfer = serviceProvider.GetService<TunnelConfigTransfer>();
TunnelAdapter tunnelAdapter = serviceProvider.GetService<TunnelAdapter>();
LoggerHelper.Instance.Info($"tunnel route level getting.");
tunnelConfigTransfer.RefreshRouteLevel();
LoggerHelper.Instance.Warning($"route ips:{string.Join(",", tunnelConfigTransfer.RouteIPs.Select(c => c.ToString()))}");

View File

@@ -5,7 +5,6 @@ using LiteDB;
using MemoryPack;
using System.Net;
using System.Text.Json.Serialization;
using linker.tunnel.adapter;
namespace linker.client.config

View File

@@ -1,8 +1,6 @@
using linker.client.config;
using linker.config;
using linker.libs;
using linker.plugins.client;
using MemoryPack;
namespace linker.plugins.tunnel.excludeip
{

View File

@@ -1,7 +1,6 @@
using linker.config;
using linker.plugins.signin.messenger;
using linker.tunnel;
using linker.tunnel.adapter;
using linker.tunnel.transport;
using linker.libs;
using MemoryPack;

View File

@@ -0,0 +1,237 @@
using linker.libs;
using linker.plugins.client;
using linker.plugins.tunnel;
using linker.plugins.tuntap.config;
using linker.tun;
using System.Net;
namespace linker.plugins.tuntap
{
public sealed class TuntapAdapter : ILinkerTunDeviceCallback
{
private List<LinkerTunDeviceForwardItem> forwardItems = new List<LinkerTunDeviceForwardItem>();
private LinkerTunDeviceRouteItem[] routeItems = new LinkerTunDeviceRouteItem[0];
private readonly TuntapTransfer tuntapTransfer;
private readonly TuntapConfigTransfer tuntapConfigTransfer;
private readonly TuntapDecenter tuntapDecenter;
private readonly TuntapProxy tuntapProxy;
private readonly ClientSignInState clientSignInState;
private readonly TunnelConfigTransfer tunnelConfigTransfer;
private readonly ClientConfigTransfer clientConfigTransfer;
public TuntapAdapter(TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer, TuntapDecenter tuntapDecenter, TuntapProxy tuntapProxy,
ClientSignInState clientSignInState, TunnelConfigTransfer tunnelConfigTransfer, ClientConfigTransfer clientConfigTransfer)
{
this.tuntapTransfer = tuntapTransfer;
this.tuntapConfigTransfer = tuntapConfigTransfer;
this.tuntapDecenter = tuntapDecenter;
this.tuntapProxy = tuntapProxy;
this.clientSignInState = clientSignInState;
this.tunnelConfigTransfer = tunnelConfigTransfer;
this.clientConfigTransfer = clientConfigTransfer;
//初始化网卡
tuntapTransfer.Init(tuntapConfigTransfer.DeviceName, this);
//与服务器连接刷新一下IP
clientSignInState.NetworkEnabledHandle += (times) => tuntapConfigTransfer.RefreshIP();
//配置又更新,去同步一下
tuntapConfigTransfer.OnUpdate += tuntapDecenter.Refresh;
//配置发生变化,重启网卡
tuntapConfigTransfer.OnChanged += RetstartDevice;
//收到新的信息,添加一下路由
tuntapDecenter.OnChangeBefore += DelRoute;
tuntapDecenter.OnChangeAfter += AddRoute;
tuntapDecenter.OnReset += tuntapProxy.ClearIPs;
tuntapDecenter.HandleCurrentInfo = GetCurrentInfo;
//网卡状态发生变化,同步一下信息
tuntapTransfer.OnSetupBefore += tuntapDecenter.Refresh;
tuntapTransfer.OnSetupAfter += tuntapDecenter.Refresh;
tuntapTransfer.OnSetupSuccess += () => { tuntapDecenter.Refresh(); AddForward(); tuntapConfigTransfer.SetRunning(true); };
tuntapTransfer.OnShutdownBefore += tuntapDecenter.Refresh;
tuntapTransfer.OnShutdownAfter += tuntapDecenter.Refresh;
tuntapTransfer.OnShutdownSuccess += () => { tuntapDecenter.Refresh(); DeleteForward(); tuntapConfigTransfer.SetRunning(false); };
//隧道关闭
tuntapProxy.OnTunnelClose += async (connection) => { tuntapDecenter.Refresh(); await Task.CompletedTask; };
//收到隧道数据包,写入网卡
tuntapProxy.OnReceivePacket += async (connection, buffer) => { tuntapTransfer.Write(buffer); await Task.CompletedTask; };
//IP没找到是否需要同步一下数据
tuntapProxy.OnIPNotFound += (ip) => tuntapDecenter.Refresh();
}
private TuntapInfo GetCurrentInfo()
{
return new TuntapInfo
{
IP = tuntapConfigTransfer.Info.IP,
Lans = tuntapConfigTransfer.Info.Lans.Where(c => c.IP != null && c.IP.Equals(IPAddress.Any) == false).Select(c => { c.Exists = false; return c; }).ToList(),
PrefixLength = tuntapConfigTransfer.Info.PrefixLength,
MachineId = clientConfigTransfer.Id,
Status = tuntapTransfer.Status,
SetupError = tuntapTransfer.SetupError,
NatError = tuntapTransfer.NatError,
SystemInfo = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} {(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_DOCKER")) == false ? "Docker" : "")}",
Forwards = tuntapConfigTransfer.Info.Forwards,
Switch = tuntapConfigTransfer.Info.Switch
};
}
public async Task Callback(LinkerTunDevicPacket packet)
{
if (packet.IPV4Broadcast || packet.IPV6Multicast)
{
if ((tuntapConfigTransfer.Switch & TuntapSwitch.Multicast) == TuntapSwitch.Multicast)
{
return;
}
}
await tuntapProxy.InputPacket(packet);
}
/// <summary>
/// 重启网卡
/// </summary>
/// <returns></returns>
public async Task RetstartDevice()
{
tuntapTransfer.Shutdown();
await tuntapConfigTransfer.RefreshIPASync();
tuntapTransfer.Setup(tuntapConfigTransfer.Info.IP, tuntapConfigTransfer.Info.PrefixLength);
}
/// <summary>
/// 关闭网卡
/// </summary>
public void StopDevice()
{
tuntapTransfer.Shutdown();
}
// <summary>
/// 添加端口转发
/// </summary>
private void AddForward()
{
var temp = ParseForwardItems();
var removes = forwardItems.Except(temp, new LinkerTunDeviceForwardItemComparer());
if (removes.Any())
{
tuntapTransfer.RemoveForward(removes.ToList());
}
forwardItems = temp;
tuntapTransfer.AddForward(forwardItems);
}
/// <summary>
/// 删除端口转发
/// </summary>
public void DeleteForward()
{
tuntapTransfer.RemoveForward(forwardItems);
}
private List<LinkerTunDeviceForwardItem> ParseForwardItems()
{
return tuntapConfigTransfer.Info.Forwards.Select(c => new LinkerTunDeviceForwardItem { ListenAddr = c.ListenAddr, ListenPort = c.ListenPort, ConnectAddr = c.ConnectAddr, ConnectPort = c.ConnectPort }).ToList();
}
/// <summary>
/// 删除路由
/// </summary>
private void DelRoute()
{
if (routeItems != null)
tuntapTransfer.DelRoute(routeItems);
}
/// <summary>
/// 添加路由
/// </summary>
private void AddRoute()
{
List<TuntapVeaLanIPAddressList> ipsList = ParseIPs(tuntapDecenter.Infos.Values.ToList());
TuntapVeaLanIPAddress[] ips = ipsList.SelectMany(c => c.IPS).ToArray();
routeItems = ipsList.SelectMany(c => c.IPS).Select(c => new LinkerTunDeviceRouteItem { Address = c.OriginIPAddress, PrefixLength = c.PrefixLength }).ToArray();
tuntapTransfer.AddRoute(routeItems, tuntapConfigTransfer.Info.IP);
tuntapProxy.SetIPs(ips);
foreach (var item in tuntapDecenter.Infos.Values)
{
tuntapProxy.SetIP(item.MachineId, NetworkHelper.IP2Value(item.IP));
}
foreach (var item in tuntapDecenter.Infos.Values.Where(c => c.IP.Equals(IPAddress.Any)))
{
tuntapProxy.RemoveIP(item.MachineId);
}
}
private List<TuntapVeaLanIPAddressList> ParseIPs(List<TuntapInfo> infos)
{
//排除的IP
uint[] excludeIps =//本机局域网IP
tunnelConfigTransfer.LocalIPs.Where(c => c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
//路由上的IP
.Concat(tunnelConfigTransfer.RouteIPs)
//网卡IP 服务器IP
.Concat(new IPAddress[] { tuntapConfigTransfer.Info.IP, clientSignInState.Connection.Address.Address })
//网卡配置的局域网IP
.Concat(tuntapConfigTransfer.Info.Lans.Select(c => c.IP))
.Select(NetworkHelper.IP2Value)
.ToArray();
HashSet<uint> hashSet = new HashSet<uint>();
return infos
.Where(c => c.MachineId != clientConfigTransfer.Id)
.OrderByDescending(c => c.Status)
.OrderByDescending(c => c.LastTicks.Value)
.Select(c =>
{
var lans = c.Lans.Where(c => c.Disabled == false && c.IP.Equals(IPAddress.Any) == false).Where(c =>
{
uint ipInt = NetworkHelper.IP2Value(c.IP);
uint maskValue = NetworkHelper.PrefixLength2Value(c.PrefixLength);
uint network = ipInt & maskValue;
c.Exists = excludeIps.Any(d => (d & maskValue) == network) || hashSet.Contains(network);
hashSet.Add(network);
return c.Exists == false;
});
return new TuntapVeaLanIPAddressList
{
MachineId = c.MachineId,
IPS = ParseIPs(lans.ToList(), c.MachineId)
.Where(c => excludeIps.Select(d => d & c.MaskValue).Contains(c.NetWork) == false).ToList(),
};
}).ToList();
}
private List<TuntapVeaLanIPAddress> ParseIPs(List<TuntapLanInfo> lans, string machineid)
{
return lans.Where(c => c.IP.Equals(IPAddress.Any) == false && c != null).Select((c, index) =>
{
return ParseIPAddress(c.IP, c.PrefixLength, machineid);
}).ToList();
}
private TuntapVeaLanIPAddress ParseIPAddress(IPAddress ip, byte prefixLength, string machineid)
{
uint ipInt = NetworkHelper.IP2Value(ip);
//掩码十进制
uint maskValue = NetworkHelper.PrefixLength2Value(prefixLength);
return new TuntapVeaLanIPAddress
{
IPAddress = ipInt,
PrefixLength = prefixLength,
MaskValue = maskValue,
NetWork = ipInt & maskValue,
Broadcast = ipInt | ~maskValue,
OriginIPAddress = ip,
MachineId = machineid
};
}
}
}

View File

@@ -22,28 +22,30 @@ namespace linker.plugins.tuntap
private readonly IMessengerSender messengerSender;
private readonly TuntapTransfer tuntapTransfer;
private readonly ClientSignInState clientSignInState;
private readonly FileConfig config;
private readonly TuntapProxy tuntapProxy;
private readonly RunningConfig runningConfig;
private readonly TuntapConfigTransfer tuntapConfigTransfer;
private readonly LeaseClientTreansfer leaseClientTreansfer;
private readonly TuntapPingTransfer pingTransfer;
private readonly AccessTransfer accessTransfer;
private readonly ClientConfigTransfer clientConfigTransfer;
private readonly TuntapDecenter tuntapDecenter;
private readonly TuntapAdapter tuntapAdapter;
public TuntapClientApiController(IMessengerSender messengerSender, TuntapTransfer tuntapTransfer, ClientSignInState clientSignInState, FileConfig config, TuntapProxy tuntapProxy, RunningConfig runningConfig, TuntapConfigTransfer tuntapConfigTransfer, LeaseClientTreansfer leaseClientTreansfer, TuntapPingTransfer pingTransfer, AccessTransfer accessTransfer, ClientConfigTransfer clientConfigTransfer)
public TuntapClientApiController(IMessengerSender messengerSender, TuntapTransfer tuntapTransfer, ClientSignInState clientSignInState,
TuntapProxy tuntapProxy,TuntapConfigTransfer tuntapConfigTransfer, LeaseClientTreansfer leaseClientTreansfer,
TuntapPingTransfer pingTransfer, AccessTransfer accessTransfer, ClientConfigTransfer clientConfigTransfer, TuntapDecenter tuntapDecenter, TuntapAdapter tuntapAdapter)
{
this.messengerSender = messengerSender;
this.tuntapTransfer = tuntapTransfer;
this.clientSignInState = clientSignInState;
this.config = config;
this.tuntapProxy = tuntapProxy;
this.runningConfig = runningConfig;
this.tuntapConfigTransfer = tuntapConfigTransfer;
this.leaseClientTreansfer = leaseClientTreansfer;
this.pingTransfer = pingTransfer;
this.accessTransfer = accessTransfer;
this.clientConfigTransfer = clientConfigTransfer;
this.tuntapDecenter = tuntapDecenter;
this.tuntapAdapter = tuntapAdapter;
}
public ConnectionListInfo Connections(ApiControllerParamsInfo param)
@@ -74,11 +76,11 @@ namespace linker.plugins.tuntap
public TuntabListInfo Get(ApiControllerParamsInfo param)
{
ulong hashCode = ulong.Parse(param.Content);
if (tuntapConfigTransfer.Version.Eq(hashCode, out ulong version) == false)
if (tuntapDecenter.Version.Eq(hashCode, out ulong version) == false)
{
return new TuntabListInfo
{
List = tuntapConfigTransfer.Infos,
List = tuntapDecenter.Infos,
HashCode = version
};
}
@@ -90,7 +92,7 @@ namespace linker.plugins.tuntap
/// <param name="param"></param>
public void Refresh(ApiControllerParamsInfo param)
{
tuntapConfigTransfer.RefreshConfig();
tuntapDecenter.Refresh();
}
/// <summary>
@@ -105,7 +107,7 @@ namespace linker.plugins.tuntap
{
if (accessTransfer.HasAccess(ClientApiAccess.TuntapStatusSelf) == false) return false;
await tuntapConfigTransfer.RetstartDevice();
await tuntapAdapter.RetstartDevice();
}
else
{
@@ -131,7 +133,7 @@ namespace linker.plugins.tuntap
if (param.Content == clientConfigTransfer.Id)
{
if (accessTransfer.HasAccess(ClientApiAccess.TuntapStatusSelf) == false) return false;
tuntapConfigTransfer.StopDevice();
tuntapAdapter.StopDevice();
}
else
{
@@ -160,7 +162,7 @@ namespace linker.plugins.tuntap
if (info.MachineId == clientConfigTransfer.Id)
{
if (accessTransfer.HasAccess(ClientApiAccess.TuntapChangeSelf) == false) return false;
tuntapConfigTransfer.UpdateConfig(info);
tuntapConfigTransfer.Update(info);
}
else
{

View File

@@ -1,413 +1,128 @@
using linker.client.config;
using linker.config;
using linker.libs;
using MemoryPack;
using System.Collections.Concurrent;
using System.Net;
using linker.plugins.client;
using linker.plugins.messenger;
using linker.plugins.tuntap.config;
using linker.tun;
using linker.plugins.tuntap.lease;
using linker.plugins.decenter;
using linker.plugins.tunnel;
namespace linker.plugins.tuntap
{
public sealed class TuntapConfigTransfer : IDecenter
public sealed class TuntapConfigTransfer
{
public string Name => "tuntap";
public VersionManager DataVersion { get; } = new VersionManager();
public TuntapConfigInfo Info => runningConfig.Data.Tuntap;
public IPAddress IP => Info.IP;
public bool Running => Info.Running;
public TuntapSwitch Switch => Info.Switch;
private TuntapConfigInfo configInfo => runningConfig.Data.Tuntap;
public IPAddress IP=> configInfo.IP;
public bool Running => configInfo.Running;
public TuntapSwitch Switch => configInfo.Switch;
public string DeviceName => "linker";
private readonly IMessengerSender messengerSender;
private readonly ClientSignInState clientSignInState;
private readonly RunningConfig runningConfig;
private readonly TuntapTransfer tuntapTransfer;
private readonly LeaseClientTreansfer leaseClientTreansfer;
private readonly ClientConfigTransfer clientConfigTransfer;
private readonly TunnelConfigTransfer tunnelConfigTransfer;
private LinkerTunDeviceRouteItem[] routeItems = new LinkerTunDeviceRouteItem[0];
private List<LinkerTunDeviceForwardItem> forwardItems = new List<LinkerTunDeviceForwardItem>();
public Action OnUpdate { get; set; } = () => { };
public Func<Task> OnChanged { get; set; } = async () => { await Task.CompletedTask; };
public VersionManager Version { get; } = new VersionManager();
private readonly ConcurrentDictionary<string, TuntapInfo> tuntapInfos = new ConcurrentDictionary<string, TuntapInfo>();
public ConcurrentDictionary<string, TuntapInfo> Infos => tuntapInfos;
public Action HandleReset { get; set; }
public Action<TuntapVeaLanIPAddress[]> HandleSetIPs { get; set; }
public Action<string,uint> HandleSetIP { get; set; }
public Action<string> HandleRemoveIP { get; set; }
private readonly SemaphoreSlim slim = new SemaphoreSlim(1);
public TuntapConfigTransfer(IMessengerSender messengerSender, ClientSignInState clientSignInState, RunningConfig runningConfig, TuntapTransfer tuntapTransfer, LeaseClientTreansfer leaseClientTreansfer, ClientConfigTransfer clientConfigTransfer, TunnelConfigTransfer tunnelConfigTransfer)
public TuntapConfigTransfer(RunningConfig runningConfig, LeaseClientTreansfer leaseClientTreansfer, ClientConfigTransfer clientConfigTransfer)
{
this.messengerSender = messengerSender;
this.clientSignInState = clientSignInState;
this.runningConfig = runningConfig;
this.tuntapTransfer = tuntapTransfer;
this.leaseClientTreansfer = leaseClientTreansfer;
this.clientConfigTransfer = clientConfigTransfer;
this.tunnelConfigTransfer = tunnelConfigTransfer;
clientSignInState.NetworkEnabledHandle += NetworkEnable;
tuntapTransfer.OnSetupBefore += () => { DataVersion.Add(); };
tuntapTransfer.OnSetupAfter += () => { DataVersion.Add(); };
tuntapTransfer.OnSetupSuccess += () => { DataVersion.Add(); configInfo.Running = true; runningConfig.Data.Update(); AddForward(); };
tuntapTransfer.OnShutdownBefore += () => { DataVersion.Add(); };
tuntapTransfer.OnShutdownAfter += () => { DataVersion.Add(); };
tuntapTransfer.OnShutdownSuccess += () => { DataVersion.Add(); DeleteForward(); DelRoute(); configInfo.Running = false; runningConfig.Data.Update(); DataVersion.Add(); };
}
string groupid = string.Empty;
private void NetworkEnable(int times)
{
if (groupid != clientConfigTransfer.Group.Id)
{
tuntapInfos.Clear(); HandleReset();
}
groupid = clientConfigTransfer.Group.Id;
RefreshIP();
}
/// <summary>
/// 更新本机网卡信息
/// 保存启动状态,方便下次启动时自动启动网卡
/// </summary>
/// <param name="running"></param>
public void SetRunning(bool running)
{
Info.Running = running;
runningConfig.Data.Update();
OnUpdate();
}
/// <summary>
/// 更新本机网卡信息,会触发事件
/// </summary>
/// <param name="info"></param>
public void UpdateConfig(TuntapInfo info)
public void Update(TuntapInfo info)
{
TimerHelper.Async(async () =>
{
IPAddress oldIP = configInfo.IP;
byte prefixLength = configInfo.PrefixLength;
IPAddress ip = Info.IP;
byte prefixLength = Info.PrefixLength;
configInfo.IP = info.IP ?? IPAddress.Any;
configInfo.Lans = info.Lans;
configInfo.PrefixLength = info.PrefixLength;
configInfo.Switch = info.Switch;
configInfo.Forwards = info.Forwards;
Info.IP = info.IP ?? IPAddress.Any;
Info.Lans = info.Lans;
Info.PrefixLength = info.PrefixLength;
Info.Switch = info.Switch;
Info.Forwards = info.Forwards;
runningConfig.Data.Update();
TuntapGroup2IPInfo tuntapGroup2IPInfo = new TuntapGroup2IPInfo { IP = configInfo.IP, PrefixLength = configInfo.PrefixLength };
configInfo.Group2IP.AddOrUpdate(clientConfigTransfer.Group.Id, tuntapGroup2IPInfo, (a, b) => tuntapGroup2IPInfo);
await LeaseIP();
SetGroupIP();
if ((oldIP.Equals(configInfo.IP) == false || prefixLength != configInfo.PrefixLength) && configInfo.Running)
if ((ip.Equals(Info.IP) == false || prefixLength != Info.PrefixLength) && Info.Running)
{
await RetstartDevice();
}
else
{
AddForward();
await OnChanged();
}
GetData();
DataVersion.Add();
OnUpdate();
});
}
public Memory<byte> GetData()
{
TuntapInfo info = new TuntapInfo
{
IP = configInfo.IP,
Lans = configInfo.Lans.Where(c => c.IP != null && c.IP.Equals(IPAddress.Any) == false).Select(c => { c.Exists = false; return c; }).ToList(),
PrefixLength = configInfo.PrefixLength,
MachineId = clientConfigTransfer.Id,
Status = tuntapTransfer.Status,
SetupError = tuntapTransfer.SetupError,
NatError = tuntapTransfer.NatError,
SystemInfo = $"{System.Runtime.InteropServices.RuntimeInformation.OSDescription} {(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SNLTTY_LINKER_IS_DOCKER")) == false ? "Docker" : "")}",
Forwards = configInfo.Forwards,
Switch = configInfo.Switch
};
tuntapInfos.AddOrUpdate(info.MachineId, info, (a, b) => info);
Version.Add();
return MemoryPackSerializer.Serialize(info);
}
public void SetData(Memory<byte> data)
{
TuntapInfo info = MemoryPackSerializer.Deserialize<TuntapInfo>(data.Span);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Debug($"tuntap got {info.IP}");
}
TimerHelper.Async(async () =>
{
await slim.WaitAsync();
try
{
DelRoute();
tuntapInfos.AddOrUpdate(info.MachineId, info, (a, b) => info);
Version.Add();
AddRoute();
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
slim.Release();
});
}
public void SetData(List<ReadOnlyMemory<byte>> data)
{
List<TuntapInfo> list = data.Select(c => MemoryPackSerializer.Deserialize<TuntapInfo>(c.Span)).ToList();
TimerHelper.Async(async () =>
{
await slim.WaitAsync();
try
{
DelRoute();
foreach (var item in list)
{
tuntapInfos.AddOrUpdate(item.MachineId, item, (a, b) => item);
item.LastTicks.Update();
}
var removes = tuntapInfos.Keys.Except(list.Select(c => c.MachineId)).Where(c => c != clientConfigTransfer.Id).ToList();
foreach (var item in removes)
{
if (tuntapInfos.TryGetValue(item, out TuntapInfo tuntapInfo))
{
tuntapInfo.Status = TuntapStatus.Normal;
tuntapInfo.LastTicks.Clear();
}
}
Version.Add();
AddRoute();
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
finally
{
slim.Release();
}
});
}
/// <summary>
/// 刷新信息,把自己的网卡配置发给别人,顺便把别人的网卡信息带回来
/// </summary>
public void RefreshConfig()
{
DataVersion.Add();
}
/// <summary>
/// 刷新IP
/// 刷新IP会触发OnChanged事件
/// </summary>
public void RefreshIP()
{
TimerHelper.Async(async () =>
{
IPAddress oldIP = configInfo.IP;
byte prefixLength = configInfo.PrefixLength;
IPAddress oldIP = Info.IP;
byte prefixLength = Info.PrefixLength;
await LeaseIP();
while (tuntapTransfer.Status == TuntapStatus.Operating)
await RefreshIPASync();
if ((oldIP.Equals(Info.IP) == false || prefixLength != Info.PrefixLength) && Info.Running)
{
await Task.Delay(1000);
await OnChanged();
}
bool run = (oldIP.Equals(configInfo.IP) == false || prefixLength != configInfo.PrefixLength) && configInfo.Running
|| configInfo.Running && tuntapTransfer.Status != TuntapStatus.Running;
if (run)
{
tuntapTransfer.Shutdown();
tuntapTransfer.Setup(configInfo.IP, configInfo.PrefixLength);
}
DataVersion.Add();
OnUpdate();
});
}
/// <summary>
/// 租赁IP
/// 刷新IP不会触发OnChanged
/// </summary>
/// <returns></returns>
public async Task RefreshIPASync()
{
LoadGroupIP();
await LeaseIP();
SetGroupIP();
OnUpdate();
}
private async Task LeaseIP()
{
if (configInfo.Group2IP.TryGetValue(clientConfigTransfer.Group.Id, out TuntapGroup2IPInfo tuntapGroup2IPInfo))
LeaseInfo leaseInfo = await leaseClientTreansfer.LeaseIp(Info.IP, Info.PrefixLength);
Info.IP = leaseInfo.IP;
Info.PrefixLength = leaseInfo.PrefixLength;
runningConfig.Data.Update();
}
private void LoadGroupIP()
{
if (Info.Group2IP.TryGetValue(clientConfigTransfer.Group.Id, out TuntapGroup2IPInfo tuntapGroup2IPInfo))
{
if (tuntapGroup2IPInfo.IP.Equals(configInfo.IP) == false || tuntapGroup2IPInfo.PrefixLength != configInfo.PrefixLength)
if (tuntapGroup2IPInfo.IP.Equals(Info.IP) == false || tuntapGroup2IPInfo.PrefixLength != Info.PrefixLength)
{
configInfo.IP = tuntapGroup2IPInfo.IP;
configInfo.PrefixLength = tuntapGroup2IPInfo.PrefixLength;
Info.IP = tuntapGroup2IPInfo.IP;
Info.PrefixLength = tuntapGroup2IPInfo.PrefixLength;
}
}
LeaseInfo leaseInfo = await leaseClientTreansfer.LeaseIp(configInfo.IP, configInfo.PrefixLength);
configInfo.IP = leaseInfo.IP;
configInfo.PrefixLength = leaseInfo.PrefixLength;
runningConfig.Data.Update();
tuntapGroup2IPInfo = new TuntapGroup2IPInfo { IP = configInfo.IP, PrefixLength = configInfo.PrefixLength };
configInfo.Group2IP.AddOrUpdate(clientConfigTransfer.Group.Id, tuntapGroup2IPInfo, (a, b) => tuntapGroup2IPInfo);
}
/// <summary>
/// 重启网卡
/// </summary>
/// <returns></returns>
public async Task RetstartDevice()
private void SetGroupIP()
{
tuntapTransfer.Shutdown();
await LeaseIP();
tuntapTransfer.Setup(configInfo.IP, configInfo.PrefixLength);
TuntapGroup2IPInfo tuntapGroup2IPInfo = new TuntapGroup2IPInfo { IP = Info.IP, PrefixLength = Info.PrefixLength };
Info.Group2IP.AddOrUpdate(clientConfigTransfer.Group.Id, tuntapGroup2IPInfo, (a, b) => tuntapGroup2IPInfo);
}
/// <summary>
/// 关闭网卡
/// </summary>
public void StopDevice()
{
tuntapTransfer.Shutdown();
}
// <summary>
/// 添加端口转发
/// </summary>
private void AddForward()
{
var temp = ParseForwardItems();
var removes = forwardItems.Except(temp, new LinkerTunDeviceForwardItemComparer());
if (removes.Any())
{
tuntapTransfer.RemoveForward(removes.ToList());
}
forwardItems = temp;
tuntapTransfer.AddForward(forwardItems);
}
/// <summary>
/// 删除端口转发
/// </summary>
private void DeleteForward()
{
tuntapTransfer.RemoveForward(forwardItems);
}
private List<LinkerTunDeviceForwardItem> ParseForwardItems()
{
return configInfo.Forwards.Select(c => new LinkerTunDeviceForwardItem { ListenAddr = c.ListenAddr, ListenPort = c.ListenPort, ConnectAddr = c.ConnectAddr, ConnectPort = c.ConnectPort }).ToList();
}
/// <summary>
/// 删除路由
/// </summary>
private void DelRoute()
{
if (routeItems != null)
tuntapTransfer.DelRoute(routeItems);
}
/// <summary>
/// 添加路由
/// </summary>
private void AddRoute()
{
List<TuntapVeaLanIPAddressList> ipsList = ParseIPs(tuntapInfos.Values.ToList());
TuntapVeaLanIPAddress[] ips = ipsList.SelectMany(c => c.IPS).ToArray();
routeItems = ipsList.SelectMany(c => c.IPS).Select(c => new LinkerTunDeviceRouteItem { Address = c.OriginIPAddress, PrefixLength = c.PrefixLength }).ToArray();
tuntapTransfer.AddRoute(routeItems, configInfo.IP);
HandleSetIPs(ips);
foreach (var item in tuntapInfos.Values)
{
HandleSetIP(item.MachineId, NetworkHelper.IP2Value(item.IP));
}
foreach (var item in tuntapInfos.Values.Where(c => c.IP.Equals(IPAddress.Any)))
{
HandleRemoveIP(item.MachineId);
}
Version.Add();
}
private List<TuntapVeaLanIPAddressList> ParseIPs(List<TuntapInfo> infos)
{
//排除的IP
uint[] excludeIps =//本机局域网IP
tunnelConfigTransfer.LocalIPs.Where(c => c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
//路由上的IP
.Concat(tunnelConfigTransfer.RouteIPs)
//网卡IP 服务器IP
.Concat(new IPAddress[] { configInfo.IP, clientSignInState.Connection.Address.Address })
//网卡配置的局域网IP
.Concat(configInfo.Lans.Select(c => c.IP))
.Select(NetworkHelper.IP2Value)
.ToArray();
HashSet<uint> hashSet = new HashSet<uint>();
return infos
.Where(c => c.MachineId != clientConfigTransfer.Id)
.OrderByDescending(c => c.Status)
.OrderByDescending(c => c.LastTicks.Value)
.Select(c =>
{
var lans = c.Lans.Where(c => c.Disabled == false && c.IP.Equals(IPAddress.Any) == false).Where(c =>
{
uint ipInt = NetworkHelper.IP2Value(c.IP);
uint maskValue = NetworkHelper.PrefixLength2Value(c.PrefixLength);
uint network = ipInt & maskValue;
c.Exists = excludeIps.Any(d => (d & maskValue) == network) || hashSet.Contains(network);
hashSet.Add(network);
return c.Exists == false;
});
return new TuntapVeaLanIPAddressList
{
MachineId = c.MachineId,
IPS = ParseIPs(lans.ToList(), c.MachineId)
.Where(c => excludeIps.Select(d => d & c.MaskValue).Contains(c.NetWork) == false).ToList(),
};
}).ToList();
}
private List<TuntapVeaLanIPAddress> ParseIPs(List<TuntapLanInfo> lans, string machineid)
{
return lans.Where(c => c.IP.Equals(IPAddress.Any) == false && c != null).Select((c, index) =>
{
return ParseIPAddress(c.IP, c.PrefixLength, machineid);
}).ToList();
}
private TuntapVeaLanIPAddress ParseIPAddress(IPAddress ip, byte prefixLength, string machineid)
{
uint ipInt = NetworkHelper.IP2Value(ip);
//掩码十进制
uint maskValue = NetworkHelper.PrefixLength2Value(prefixLength);
return new TuntapVeaLanIPAddress
{
IPAddress = ipInt,
PrefixLength = prefixLength,
MaskValue = maskValue,
NetWork = ipInt & maskValue,
Broadcast = ipInt | ~maskValue,
OriginIPAddress = ip,
MachineId = machineid
};
}
}
}

View File

@@ -0,0 +1,126 @@
using linker.libs;
using linker.plugins.client;
using linker.plugins.decenter;
using linker.plugins.tuntap.config;
using MemoryPack;
using System.Collections.Concurrent;
namespace linker.plugins.tuntap
{
public sealed class TuntapDecenter : IDecenter
{
public string Name => "tuntap";
public VersionManager DataVersion { get; } = new VersionManager();
public VersionManager Version { get; } = new VersionManager();
public ConcurrentDictionary<string, TuntapInfo> Infos => tuntapInfos;
private readonly SemaphoreSlim slim = new SemaphoreSlim(1);
private readonly ConcurrentDictionary<string, TuntapInfo> tuntapInfos = new ConcurrentDictionary<string, TuntapInfo>();
public Action OnChangeBefore { get; set; } = () => { };
public Action OnChangeAfter { get; set; } = () => { };
public Action OnReset { get; set; } = () => { };
public Func<TuntapInfo> HandleCurrentInfo { get; set; } = () => { return null; };
private readonly ClientConfigTransfer clientConfigTransfer;
public TuntapDecenter(ClientConfigTransfer clientConfigTransfer, ClientSignInState clientSignInState)
{
this.clientConfigTransfer = clientConfigTransfer;
clientSignInState.NetworkEnabledHandle += NetworkEnable;
}
string groupid = string.Empty;
private void NetworkEnable(int times)
{
if (groupid != clientConfigTransfer.Group.Id)
{
tuntapInfos.Clear();
OnReset();
}
groupid = clientConfigTransfer.Group.Id;
}
public void Refresh()
{
DataVersion.Add();
}
public Memory<byte> GetData()
{
TuntapInfo info = HandleCurrentInfo();
tuntapInfos.AddOrUpdate(info.MachineId, info, (a, b) => info);
Version.Add();
return MemoryPackSerializer.Serialize(info);
}
public void SetData(Memory<byte> data)
{
TuntapInfo info = MemoryPackSerializer.Deserialize<TuntapInfo>(data.Span);
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Debug($"tuntap got {info.IP}");
}
TimerHelper.Async(async () =>
{
await slim.WaitAsync();
try
{
OnChangeBefore();
tuntapInfos.AddOrUpdate(info.MachineId, info, (a, b) => info);
Version.Add();
OnChangeAfter();
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
slim.Release();
});
}
public void SetData(List<ReadOnlyMemory<byte>> data)
{
List<TuntapInfo> list = data.Select(c => MemoryPackSerializer.Deserialize<TuntapInfo>(c.Span)).ToList();
TimerHelper.Async(async () =>
{
await slim.WaitAsync();
try
{
OnChangeBefore();
foreach (var item in list)
{
tuntapInfos.AddOrUpdate(item.MachineId, item, (a, b) => item);
item.LastTicks.Update();
}
var removes = tuntapInfos.Keys.Except(list.Select(c => c.MachineId)).Where(c => c != clientConfigTransfer.Id).ToList();
foreach (var item in removes)
{
if (tuntapInfos.TryGetValue(item, out TuntapInfo tuntapInfo))
{
tuntapInfo.Status = TuntapStatus.Normal;
tuntapInfo.LastTicks.Clear();
}
}
Version.Add();
OnChangeAfter();
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
finally
{
slim.Release();
}
});
}
}
}

View File

@@ -1,28 +1,25 @@
using linker.client.config;
using linker.libs;
using linker.libs;
using linker.plugins.tuntap.config;
using linker.tun;
using System.Net.NetworkInformation;
namespace linker.plugins.tuntap
{
public sealed class TuntapDeviceStatusTransfer
{
private readonly RunningConfig runningConfig;
private readonly TuntapTransfer tuntapTransfer;
private readonly TuntapConfigTransfer tuntapConfigTransfer;
private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter;
private readonly TuntapAdapter tuntapAdapter;
private ulong setupTimes = 0;
public TuntapDeviceStatusTransfer(RunningConfig runningConfig, TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer, LinkerTunDeviceAdapter linkerTunDeviceAdapter)
public TuntapDeviceStatusTransfer(TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer, TuntapAdapter tuntapAdapter)
{
this.runningConfig = runningConfig;
this.tuntapTransfer = tuntapTransfer;
this.tuntapConfigTransfer = tuntapConfigTransfer;
this.linkerTunDeviceAdapter = linkerTunDeviceAdapter;
this.tuntapAdapter = tuntapAdapter;
tuntapTransfer.OnSetupSuccess += () => { setupTimes++; };
CheckTuntapStatusTask();
}
private void CheckTuntapStatusTask()
{
@@ -41,11 +38,10 @@ namespace linker.plugins.tuntap
if (await InterfaceAvailable() == false && tuntapTransfer.Status != TuntapStatus.Operating)
{
LoggerHelper.Instance.Error($"tuntap inerface {tuntapConfigTransfer.DeviceName} is down, restarting");
linkerTunDeviceAdapter.Shutdown();
await Task.Delay(5000).ConfigureAwait(false);
if (await InterfaceAvailable() == false && tuntapTransfer.Status != TuntapStatus.Operating)
{
await tuntapConfigTransfer.RetstartDevice();
await tuntapAdapter.RetstartDevice().ConfigureAwait(false);
}
}
}
@@ -53,18 +49,19 @@ namespace linker.plugins.tuntap
{
NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(c => c.Name == tuntapConfigTransfer.DeviceName);
return networkInterface != null && networkInterface.OperationalStatus == OperationalStatus.Up && await InterfacePing();
}
private async Task<bool> InterfacePing()
{
try
async Task<bool> InterfacePing()
{
using Ping ping = new Ping();
PingReply pingReply = await ping.SendPingAsync(tuntapConfigTransfer.IP, 500);
return pingReply.Status == IPStatus.Success;
}
catch (Exception)
{
return false;
try
{
using Ping ping = new Ping();
PingReply pingReply = await ping.SendPingAsync(tuntapConfigTransfer.IP, 500);
return pingReply.Status == IPStatus.Success;
}
catch (Exception)
{
return false;
}
}
}

View File

@@ -1,10 +1,8 @@
using linker.client.config;
using linker.libs;
using linker.libs;
using linker.plugins.tuntap.config;
using linker.tunnel.connection;
using System.Net.NetworkInformation;
using System.Net;
using linker.config;
using System.Net.Sockets;
using linker.libs.extends;
using linker.plugins.client;
@@ -17,19 +15,21 @@ namespace linker.plugins.tuntap
private readonly TuntapConfigTransfer tuntapConfigTransfer;
private readonly TuntapProxy tuntapProxy;
private readonly ClientConfigTransfer clientConfigTransfer;
private readonly TuntapDecenter tuntapDecenter;
public TuntapPingTransfer(TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer, TuntapProxy tuntapProxy, ClientConfigTransfer clientConfigTransfer)
public TuntapPingTransfer(TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer, TuntapProxy tuntapProxy, ClientConfigTransfer clientConfigTransfer, TuntapDecenter tuntapDecenter)
{
this.tuntapTransfer = tuntapTransfer;
this.tuntapConfigTransfer = tuntapConfigTransfer;
this.tuntapProxy = tuntapProxy;
this.clientConfigTransfer = clientConfigTransfer;
this.tuntapDecenter = tuntapDecenter;
PingTask();
}
private readonly LastTicksManager lastTicksManager = new LastTicksManager();
private readonly LastTicksManager lastTicksManager1 = new LastTicksManager();
public void SubscribePing()
{
lastTicksManager.Update();
@@ -49,7 +49,7 @@ namespace linker.plugins.tuntap
{
if (tuntapTransfer.Status == TuntapStatus.Running && (tuntapConfigTransfer.Switch & TuntapSwitch.ShowDelay) == TuntapSwitch.ShowDelay)
{
var items = tuntapConfigTransfer.Infos.Values.Where(c => c.IP != null && c.IP.Equals(IPAddress.Any) == false && (c.Status & TuntapStatus.Running) == TuntapStatus.Running);
var items = tuntapDecenter.Infos.Values.Where(c => c.IP != null && c.IP.Equals(IPAddress.Any) == false && (c.Status & TuntapStatus.Running) == TuntapStatus.Running);
if ((tuntapConfigTransfer.Switch & TuntapSwitch.AutoConnect) != TuntapSwitch.AutoConnect)
{
var connections = tuntapProxy.GetConnections();
@@ -61,7 +61,7 @@ namespace linker.plugins.tuntap
using Ping ping = new Ping();
PingReply pingReply = await ping.SendPingAsync(c.IP, 500);
c.Delay = pingReply.Status == IPStatus.Success ? (int)pingReply.RoundtripTime : -1;
tuntapConfigTransfer.Version.Add();
tuntapDecenter.Version.Add();
}));
}
}

View File

@@ -1,5 +1,4 @@
using linker.config;
using linker.tunnel;
using linker.tunnel;
using linker.tunnel.connection;
using linker.libs;
using System.Collections.Concurrent;
@@ -9,38 +8,32 @@ using System.Buffers.Binary;
using linker.plugins.client;
using linker.plugins.tunnel;
using System.Buffers;
using linker.client.config;
using linker.plugins.relay.client;
using linker.plugins.pcp;
namespace linker.plugins.tuntap
{
public sealed class TuntapProxy : TunnelBase, ILinkerTunDeviceCallback, ITunnelConnectionReceiveCallback
public sealed class TuntapProxy : TunnelBase, ITunnelConnectionReceiveCallback
{
public Func<ITunnelConnection, Task> OnTunnelClose { get; set; } = async (connection) => { await Task.CompletedTask; };
public Func<ITunnelConnection, ReadOnlyMemory<byte>, Task> OnReceivePacket { get; set; } = async (connection, packet) => { await Task.CompletedTask; };
public Action<uint> OnIPNotFound { get; set; } = (ip) =>{};
private uint[] maskValues = Array.Empty<uint>();
private readonly ConcurrentDictionary<uint, string> ip2MachineDic = new ConcurrentDictionary<uint, string>();
private readonly ConcurrentDictionary<uint, ITunnelConnection> ipConnections = new ConcurrentDictionary<uint, ITunnelConnection>();
private readonly OperatingMultipleManager operatingMultipleManager = new OperatingMultipleManager();
protected override string TransactionId => "tuntap";
private readonly LinkerTunDeviceAdapter linkerTunDeviceAdapter;
private HashSet<uint> ipRefreshCache = new HashSet<uint>();
protected override string TransactionId => "tuntap";
private readonly ClientSignInTransfer clientSignInTransfer;
private readonly TuntapConfigTransfer tuntapConfigTransfer;
public TuntapProxy(ClientConfigTransfer clientConfigTransfer, TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, PcpTransfer pcpTransfer, ClientSignInTransfer clientSignInTransfer, LinkerTunDeviceAdapter linkerTunDeviceAdapter, ClientSignInState clientSignInState,RelayClientConfigTransfer relayClientConfigTransfer, TuntapConfigTransfer tuntapConfigTransfer)
public TuntapProxy(ClientConfigTransfer clientConfigTransfer,
TunnelTransfer tunnelTransfer, RelayTransfer relayTransfer, PcpTransfer pcpTransfer,
ClientSignInTransfer clientSignInTransfer, TuntapTransfer tuntapTransfer, ClientSignInState clientSignInState,
RelayClientConfigTransfer relayClientConfigTransfer, TuntapConfigTransfer tuntapConfigTransfer)
: base(tunnelTransfer, relayTransfer, pcpTransfer, clientSignInTransfer, clientSignInState, clientConfigTransfer, relayClientConfigTransfer)
{
this.clientSignInTransfer = clientSignInTransfer;
this.linkerTunDeviceAdapter = linkerTunDeviceAdapter;
this.tuntapConfigTransfer = tuntapConfigTransfer;
tuntapConfigTransfer.HandleReset += ClearIPs;
tuntapConfigTransfer.HandleSetIPs += SetIPs;
tuntapConfigTransfer.HandleSetIP += SetIP;
tuntapConfigTransfer.HandleRemoveIP += RemoveIP;
}
protected override void Connected(ITunnelConnection connection)
@@ -64,8 +57,7 @@ namespace linker.plugins.tuntap
/// <returns></returns>
public async Task Receive(ITunnelConnection connection, ReadOnlyMemory<byte> buffer, object state)
{
linkerTunDeviceAdapter.Write(buffer);
await Task.CompletedTask;
await OnReceivePacket(connection, buffer).ConfigureAwait(false);
}
/// <summary>
/// 隧道关闭
@@ -75,9 +67,8 @@ namespace linker.plugins.tuntap
/// <returns></returns>
public async Task Closed(ITunnelConnection connection, object state)
{
tuntapConfigTransfer.RefreshConfig();
await OnTunnelClose(connection).ConfigureAwait(false);
Version.Add();
await Task.CompletedTask;
}
/// <summary>
@@ -85,12 +76,12 @@ namespace linker.plugins.tuntap
/// </summary>
/// <param name="packet"></param>
/// <returns></returns>
public async Task Callback(LinkerTunDevicPacket packet)
public async Task InputPacket(LinkerTunDevicPacket packet)
{
//IPV4广播组播、IPV6 多播
if (packet.IPV4Broadcast || packet.IPV6Multicast)
{
if (connections.IsEmpty == false && (tuntapConfigTransfer.Switch & TuntapSwitch.Multicast) == 0)
if (connections.IsEmpty == false)
{
await Task.WhenAll(connections.Values.Where(c => c != null && c.Connected).Select(c => c.SendAsync(packet.Packet)));
}
@@ -127,53 +118,6 @@ namespace linker.plugins.tuntap
await connection.SendAsync(packet.Packet);
}
/// <summary>
/// 设置IP等下有连接进来用IP匹配才能知道这个连接是要连谁
/// </summary>
/// <param name="ips"></param>
private void SetIPs(TuntapVeaLanIPAddress[] ips)
{
var dic = ips.GroupBy(c => c.NetWork).ToDictionary(c => c.Key, d => d.Select(e => e.MachineId).ToList());
foreach (var item in dic.Where(c => c.Value.Count > 0))
{
string machineId = item.Value[0];
ip2MachineDic.AddOrUpdate(item.Key, machineId, (a, b) => machineId);
if (ipConnections.TryGetValue(item.Key, out ITunnelConnection connection) && item.Value.Count > 0 && machineId != connection.RemoteMachineId)
{
ipConnections.TryRemove(item.Key, out _);
}
}
maskValues = ips.Select(c => c.MaskValue).Distinct().OrderBy(c => c).ToArray();
}
/// <summary>
/// 设置IP等下有连接进来用IP匹配才能知道这个连接是要连谁
/// </summary>
/// <param name="machineId"></param>
/// <param name="ip"></param>
private void SetIP(string machineId, uint ip)
{
ip2MachineDic.AddOrUpdate(ip, machineId, (a, b) => machineId);
if (ipConnections.TryGetValue(ip, out ITunnelConnection connection) && machineId != connection.RemoteMachineId)
{
ipConnections.TryRemove(ip, out _);
}
}
/// <summary>
/// 移除
/// </summary>
/// <param name="machineId"></param>
private void RemoveIP(string machineId)
{
foreach (var item in ip2MachineDic.Where(c => c.Value == machineId).ToList())
{
ipConnections.TryRemove(item.Key, out _);
ip2MachineDic.TryRemove(item.Key, out _);
}
}
/// <summary>
/// 打洞或者中继
/// </summary>
@@ -199,7 +143,7 @@ namespace linker.plugins.tuntap
if (ipRefreshCache.Contains(ip) == false)
{
ipRefreshCache.Add(ip);
tuntapConfigTransfer.RefreshConfig();
OnIPNotFound(ip);
}
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
@@ -210,7 +154,10 @@ namespace linker.plugins.tuntap
}
private void ClearIPs()
/// <summary>
/// 清除IP
/// </summary>
public void ClearIPs()
{
ip2MachineDic.Clear();
ipConnections.Clear();
@@ -220,5 +167,52 @@ namespace linker.plugins.tuntap
LoggerHelper.Instance.Debug($"tuntap cache clear");
}
}
/// <summary>
/// 设置IP等下有连接进来用IP匹配才能知道这个连接是要连谁
/// </summary>
/// <param name="ips"></param>
public void SetIPs(TuntapVeaLanIPAddress[] ips)
{
var dic = ips.GroupBy(c => c.NetWork).ToDictionary(c => c.Key, d => d.Select(e => e.MachineId).ToList());
foreach (var item in dic.Where(c => c.Value.Count > 0))
{
string machineId = item.Value[0];
ip2MachineDic.AddOrUpdate(item.Key, machineId, (a, b) => machineId);
if (ipConnections.TryGetValue(item.Key, out ITunnelConnection connection) && item.Value.Count > 0 && machineId != connection.RemoteMachineId)
{
ipConnections.TryRemove(item.Key, out _);
}
}
maskValues = ips.Select(c => c.MaskValue).Distinct().OrderBy(c => c).ToArray();
}
/// <summary>
/// 设置IP等下有连接进来用IP匹配才能知道这个连接是要连谁
/// </summary>
/// <param name="machineId"></param>
/// <param name="ip"></param>
public void SetIP(string machineId, uint ip)
{
ip2MachineDic.AddOrUpdate(ip, machineId, (a, b) => machineId);
if (ipConnections.TryGetValue(ip, out ITunnelConnection connection) && machineId != connection.RemoteMachineId)
{
ipConnections.TryRemove(ip, out _);
}
}
/// <summary>
/// 移除
/// </summary>
/// <param name="machineId"></param>
public void RemoveIP(string machineId)
{
foreach (var item in ip2MachineDic.Where(c => c.Value == machineId).ToList())
{
ipConnections.TryRemove(item.Key, out _);
ip2MachineDic.TryRemove(item.Key, out _);
}
}
}
}

View File

@@ -36,7 +36,9 @@ namespace linker.plugins.tuntap
serviceCollection.AddSingleton<TuntapPingTransfer>();
serviceCollection.AddSingleton<TuntapDeviceStatusTransfer>();
serviceCollection.AddSingleton<TuntapDecenter>();
serviceCollection.AddSingleton<TuntapAdapter>();
}
public void AddServer(ServiceCollection serviceCollection, FileConfig config)
@@ -57,7 +59,7 @@ namespace linker.plugins.tuntap
TuntapPingTransfer tuntapPingTransfer = serviceProvider.GetService<TuntapPingTransfer>();
TuntapDeviceStatusTransfer tuntapDeviceStatusTransfer = serviceProvider.GetService<TuntapDeviceStatusTransfer>();
tuntapTransfer.Init(tuntapConfigTransfer.DeviceName, tuntapProxy);
TuntapAdapter tuntapAdapter = serviceProvider.GetService<TuntapAdapter>();
}
public void UseServer(ServiceProvider serviceProvider, FileConfig config)

View File

@@ -1,7 +1,5 @@
using linker.client.config;
using linker.libs;
using linker.libs;
using System.Net;
using linker.plugins.client;
using linker.plugins.tuntap.config;
using linker.tun;
@@ -28,12 +26,20 @@ namespace linker.plugins.tuntap
this.linkerTunDeviceAdapter = linkerTunDeviceAdapter;
}
bool inited = false;
public void Init(string name,ILinkerTunDeviceCallback linkerTunDeviceCallback)
{
if (inited) return;
inited = true;
linkerTunDeviceAdapter.Initialize(name, linkerTunDeviceCallback);
AppDomain.CurrentDomain.ProcessExit += (s, e) => linkerTunDeviceAdapter.Shutdown();
Console.CancelKeyPress += (s, e) => linkerTunDeviceAdapter.Shutdown();
}
public bool Write(ReadOnlyMemory<byte> buffer)
{
return linkerTunDeviceAdapter.Write(buffer);
}
/// <summary>
/// 运行网卡

View File

@@ -4,7 +4,6 @@ using System.Net;
using linker.libs;
using MemoryPack;
using System.Collections.Concurrent;
using linker.libs.extends;
namespace linker.plugins.tuntap.lease
{

View File

@@ -17,8 +17,10 @@ namespace linker.plugins.tuntap.messenger
private readonly LeaseClientTreansfer leaseClientTreansfer;
private readonly TuntapPingTransfer pingTransfer;
private readonly IMessengerSender messengerSender;
private readonly TuntapAdapter tuntapAdapter;
public TuntapClientMessenger(TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer, TuntapProxy tuntapProxy, LeaseClientTreansfer leaseClientTreansfer, TuntapPingTransfer pingTransfer, IMessengerSender messengerSender)
public TuntapClientMessenger(TuntapTransfer tuntapTransfer, TuntapConfigTransfer tuntapConfigTransfer,
TuntapProxy tuntapProxy, LeaseClientTreansfer leaseClientTreansfer, TuntapPingTransfer pingTransfer, IMessengerSender messengerSender, TuntapAdapter tuntapAdapter)
{
this.tuntapTransfer = tuntapTransfer;
this.tuntapConfigTransfer = tuntapConfigTransfer;
@@ -26,6 +28,7 @@ namespace linker.plugins.tuntap.messenger
this.leaseClientTreansfer = leaseClientTreansfer;
this.pingTransfer = pingTransfer;
this.messengerSender = messengerSender;
this.tuntapAdapter = tuntapAdapter;
}
/// <summary>
@@ -35,7 +38,7 @@ namespace linker.plugins.tuntap.messenger
[MessengerId((ushort)TuntapMessengerIds.Run)]
public void Run(IConnection connection)
{
_ = tuntapConfigTransfer.RetstartDevice();
_ = tuntapAdapter.RetstartDevice();
}
/// <summary>
@@ -45,7 +48,7 @@ namespace linker.plugins.tuntap.messenger
[MessengerId((ushort)TuntapMessengerIds.Stop)]
public void Stop(IConnection connection)
{
tuntapConfigTransfer.StopDevice();
tuntapAdapter.StopDevice();
}
/// <summary>
@@ -56,7 +59,7 @@ namespace linker.plugins.tuntap.messenger
public void Update(IConnection connection)
{
TuntapInfo info = MemoryPackSerializer.Deserialize<TuntapInfo>(connection.ReceiveRequestWrap.Payload.Span);
tuntapConfigTransfer.UpdateConfig(info);
tuntapConfigTransfer.Update(info);
}
/// <summary>

View File

@@ -1,5 +1,5 @@
v1.6.3
2024-12-12 00:29:09
2024-12-12 17:37:53
1. 优化UI显示网络计算IP数
2. 修复内网穿透不停止直接删除导致的无法再次添加的问题
3. 优化网卡的端口转发