mirror of
https://github.com/snltty/linker.git
synced 2025-10-19 15:34:36 +08:00
sync
This commit is contained in:
@@ -14,7 +14,7 @@ namespace linker.tunnel
|
|||||||
{
|
{
|
||||||
private List<ITunnelTransport> transports;
|
private List<ITunnelTransport> transports;
|
||||||
private TunnelWanPortTransfer compactTransfer;
|
private TunnelWanPortTransfer compactTransfer;
|
||||||
private ITunnelAdapter tunnelAdapter ;
|
private ITunnelAdapter tunnelAdapter;
|
||||||
|
|
||||||
private ConcurrentDictionary<string, bool> connectingDic = new ConcurrentDictionary<string, bool>();
|
private ConcurrentDictionary<string, bool> connectingDic = new ConcurrentDictionary<string, bool>();
|
||||||
private Dictionary<string, List<Action<ITunnelConnection>>> OnConnected { get; } = new Dictionary<string, List<Action<ITunnelConnection>>>();
|
private Dictionary<string, List<Action<ITunnelConnection>>> OnConnected { get; } = new Dictionary<string, List<Action<ITunnelConnection>>>();
|
||||||
@@ -42,11 +42,38 @@ namespace linker.tunnel
|
|||||||
}
|
}
|
||||||
|
|
||||||
var transportItems = tunnelAdapter.GetTunnelTransports();
|
var transportItems = tunnelAdapter.GetTunnelTransports();
|
||||||
transportItems = transportItems.Concat(transports.Select(c => new TunnelTransportItemInfo { Label = c.Label, Name = c.Name, ProtocolType = c.ProtocolType.ToString() }))
|
transportItems = transportItems.Concat(transports.Select(c => new TunnelTransportItemInfo
|
||||||
|
{
|
||||||
|
Label = c.Label,
|
||||||
|
Name = c.Name,
|
||||||
|
ProtocolType = c.ProtocolType.ToString(),
|
||||||
|
Reverse = c.Reverse,
|
||||||
|
DisableReverse = c.DisableReverse,
|
||||||
|
SSL = c.SSL,
|
||||||
|
DisableSSL = c.DisableSSL
|
||||||
|
}))
|
||||||
.Distinct(new TunnelTransportItemInfoEqualityComparer())
|
.Distinct(new TunnelTransportItemInfoEqualityComparer())
|
||||||
.Where(c=> transports.Select(c=>c.Name).Contains(c.Name))
|
.Where(c => transports.Select(c => c.Name).Contains(c.Name))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var item in transportItems)
|
||||||
|
{
|
||||||
|
var transport = transports.FirstOrDefault(c => c.Name == item.Name);
|
||||||
|
if (transport != null)
|
||||||
|
{
|
||||||
|
item.DisableReverse = transport.DisableReverse;
|
||||||
|
item.DisableSSL = transport.DisableSSL;
|
||||||
|
if (transport.DisableReverse)
|
||||||
|
{
|
||||||
|
item.Reverse = transport.Reverse;
|
||||||
|
}
|
||||||
|
if (transport.DisableSSL)
|
||||||
|
{
|
||||||
|
item.SSL = transport.SSL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
tunnelAdapter.SetTunnelTransports(transportItems);
|
tunnelAdapter.SetTunnelTransports(transportItems);
|
||||||
|
|
||||||
@@ -98,66 +125,87 @@ namespace linker.tunnel
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (TunnelTransportItemInfo transportItem in tunnelAdapter.GetTunnelTransports().Where(c => c.Disabled == false))
|
foreach (var wanPortProtocol in tunnelAdapter.GetTunnelWanPortProtocols().Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false))
|
||||||
{
|
{
|
||||||
ITunnelTransport transport = transports.FirstOrDefault(c => c.Name == transportItem.Name);
|
foreach (TunnelTransportItemInfo transportItem in tunnelAdapter.GetTunnelTransports().Where(c => c.Disabled == false))
|
||||||
if (transport == null) continue;
|
|
||||||
|
|
||||||
TunnelTransportInfo tunnelTransportInfo = null;
|
|
||||||
//是否在失败后尝试反向连接
|
|
||||||
int times = transportItem.Reverse ? 1 : 0;
|
|
||||||
for (int i = 0; i <= times; i++)
|
|
||||||
{
|
{
|
||||||
try
|
ITunnelTransport transport = transports.FirstOrDefault(c => c.Name == transportItem.Name);
|
||||||
|
//找不到这个打洞协议
|
||||||
|
if (transport == null)
|
||||||
{
|
{
|
||||||
//获取自己的外网ip
|
continue;
|
||||||
TunnelTransportWanPortInfo localInfo = await GetLocalInfo();
|
}
|
||||||
if (localInfo == null)
|
//这个打洞协议不支持这个外网端口协议
|
||||||
{
|
if((transport.AllowWanPortProtocolType & wanPortProtocol.ProtocolType) != wanPortProtocol.ProtocolType)
|
||||||
LoggerHelper.Instance.Error($"tunnel {transport.Name} get local external ip fail ");
|
{
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
LoggerHelper.Instance.Info($"tunnel {transport.Name} got local external ip {localInfo.ToJson()}");
|
|
||||||
//获取对方的外网ip
|
|
||||||
TunnelTransportWanPortInfo remoteInfo = await tunnelAdapter.GetRemoteWanPort(remoteMachineId);
|
|
||||||
if (remoteInfo == null)
|
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Error($"tunnel {transport.Name} get remote {remoteMachineId} external ip fail ");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LoggerHelper.Instance.Info($"tunnel {transport.Name} got remote external ip {remoteInfo.ToJson()}");
|
|
||||||
|
|
||||||
tunnelTransportInfo = new TunnelTransportInfo
|
TunnelTransportInfo tunnelTransportInfo = null;
|
||||||
|
//是否在失败后尝试反向连接
|
||||||
|
int times = transportItem.Reverse ? 1 : 0;
|
||||||
|
for (int i = 0; i <= times; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Direction = (TunnelDirection)i,
|
//获取自己的外网ip
|
||||||
TransactionId = transactionId,
|
Task<TunnelTransportWanPortInfo> localInfo = GetLocalInfo(wanPortProtocol);
|
||||||
TransportName = transport.Name,
|
//获取对方的外网ip
|
||||||
TransportType = transport.ProtocolType,
|
Task<TunnelTransportWanPortInfo> remoteInfo = tunnelAdapter.GetRemoteWanPort(new TunnelWanPortProtocolInfo
|
||||||
Local = localInfo,
|
{
|
||||||
Remote = remoteInfo,
|
MachineId = remoteMachineId,
|
||||||
SSL = transportItem.SSL
|
ProtocolType = wanPortProtocol.ProtocolType,
|
||||||
};
|
Type = wanPortProtocol.Type,
|
||||||
OnConnecting(tunnelTransportInfo);
|
});
|
||||||
ParseRemoteEndPoint(tunnelTransportInfo);
|
await Task.WhenAll(localInfo, remoteInfo);
|
||||||
ITunnelConnection connection = await transport.ConnectAsync(tunnelTransportInfo);
|
|
||||||
if (connection != null)
|
if (localInfo.Result == null)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error($"tunnel {transport.Name} get local external ip fail ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remoteInfo.Result == null)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error($"tunnel {transport.Name} get remote {remoteMachineId} external ip fail ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LoggerHelper.Instance.Info($"tunnel {transport.Name} got local external ip {localInfo.ToJson()}");
|
||||||
|
LoggerHelper.Instance.Info($"tunnel {transport.Name} got remote external ip {remoteInfo.ToJson()}");
|
||||||
|
|
||||||
|
|
||||||
|
tunnelTransportInfo = new TunnelTransportInfo
|
||||||
|
{
|
||||||
|
Direction = (TunnelDirection)i,
|
||||||
|
TransactionId = transactionId,
|
||||||
|
TransportName = transport.Name,
|
||||||
|
TransportType = transport.ProtocolType,
|
||||||
|
Local = localInfo.Result,
|
||||||
|
Remote = remoteInfo.Result,
|
||||||
|
SSL = transportItem.SSL
|
||||||
|
};
|
||||||
|
OnConnecting(tunnelTransportInfo);
|
||||||
|
ParseRemoteEndPoint(tunnelTransportInfo);
|
||||||
|
ITunnelConnection connection = await transport.ConnectAsync(tunnelTransportInfo);
|
||||||
|
if (connection != null)
|
||||||
|
{
|
||||||
|
_OnConnected(connection);
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_OnConnected(connection);
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
return connection;
|
{
|
||||||
|
LoggerHelper.Instance.Error(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
if (tunnelTransportInfo != null)
|
||||||
{
|
{
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
OnConnectFail(tunnelTransportInfo);
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Error(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tunnelTransportInfo != null)
|
|
||||||
{
|
|
||||||
OnConnectFail(tunnelTransportInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -239,18 +287,19 @@ namespace linker.tunnel
|
|||||||
/// 获取自己的外网IP,给别人调用
|
/// 获取自己的外网IP,给别人调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<TunnelTransportWanPortInfo> GetWanPort()
|
public async Task<TunnelTransportWanPortInfo> GetWanPort(TunnelWanPortProtocolInfo _info)
|
||||||
{
|
{
|
||||||
return await GetLocalInfo();
|
TunnelWanPortInfo info = tunnelAdapter.GetTunnelWanPortProtocols().FirstOrDefault(c => c.Type == _info.Type && c.ProtocolType == _info.ProtocolType);
|
||||||
|
return await GetLocalInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取自己的外网IP
|
/// 获取自己的外网IP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<TunnelTransportWanPortInfo> GetLocalInfo()
|
private async Task<TunnelTransportWanPortInfo> GetLocalInfo(TunnelWanPortInfo info)
|
||||||
{
|
{
|
||||||
TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP);
|
TunnelWanPortEndPoint ip = await compactTransfer.GetWanPortAsync(tunnelAdapter.LocalIP, info);
|
||||||
if (ip != null)
|
if (ip != null)
|
||||||
{
|
{
|
||||||
var config = tunnelAdapter.GetLocalConfig();
|
var config = tunnelAdapter.GetLocalConfig();
|
||||||
|
@@ -21,12 +21,12 @@ namespace linker.tunnel.adapter
|
|||||||
/// 获取外网端口协议列表
|
/// 获取外网端口协议列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<TunnelWanPortInfo> GetTunnelWanPortCompacts();
|
public List<TunnelWanPortInfo> GetTunnelWanPortProtocols();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存外网端口协议列表
|
/// 保存外网端口协议列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="compacts"></param>
|
/// <param name="compacts"></param>
|
||||||
public void SetTunnelWanPortCompacts(List<TunnelWanPortInfo> compacts);
|
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> protocols);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取打洞协议列表
|
/// 获取打洞协议列表
|
||||||
@@ -49,7 +49,7 @@ namespace linker.tunnel.adapter
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="remoteMachineId"></param>
|
/// <param name="remoteMachineId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<TunnelTransportWanPortInfo> GetRemoteWanPort(string remoteMachineId);
|
public Task<TunnelTransportWanPortInfo> GetRemoteWanPort(TunnelWanPortProtocolInfo info);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送开始打洞
|
/// 发送开始打洞
|
||||||
@@ -86,4 +86,20 @@ namespace linker.tunnel.adapter
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string MachineId { get; set; }
|
public string MachineId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class TunnelWanPortProtocolInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 类别
|
||||||
|
/// </summary>
|
||||||
|
public TunnelWanPortType Type { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 协议
|
||||||
|
/// </summary>
|
||||||
|
public TunnelWanPortProtocolType ProtocolType { get; set; } = TunnelWanPortProtocolType.Udp;
|
||||||
|
/// <summary>
|
||||||
|
/// 本机名
|
||||||
|
/// </summary>
|
||||||
|
public string MachineId { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,43 @@
|
|||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
|
using linker.tunnel.wanport;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
namespace linker.tunnel.transport
|
namespace linker.tunnel.transport
|
||||||
{
|
{
|
||||||
public interface ITunnelTransport
|
public interface ITunnelTransport
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 打洞协议名
|
||||||
|
/// </summary>
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 打洞协议说明
|
||||||
|
/// </summary>
|
||||||
public string Label { get; }
|
public string Label { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 隧道协议
|
||||||
|
/// </summary>
|
||||||
public TunnelProtocolType ProtocolType { get; }
|
public TunnelProtocolType ProtocolType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 允许哪些端口协议
|
||||||
|
/// </summary>
|
||||||
|
public TunnelWanPortProtocolType AllowWanPortProtocolType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否反向打洞
|
||||||
|
/// </summary>
|
||||||
|
public bool Reverse { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否允许修改反向打洞配置
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableReverse { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否ssl
|
||||||
|
/// </summary>
|
||||||
|
public bool SSL { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 是否允许修改ssl配置
|
||||||
|
/// </summary>
|
||||||
|
public bool DisableSSL { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送连接开始信息
|
/// 发送连接开始信息
|
||||||
@@ -91,7 +121,9 @@ namespace linker.tunnel.transport
|
|||||||
|
|
||||||
public bool Disabled { get; set; } = false;
|
public bool Disabled { get; set; } = false;
|
||||||
public bool Reverse { get; set; } = true;
|
public bool Reverse { get; set; } = true;
|
||||||
|
public bool DisableReverse { get; set; } = false;
|
||||||
public bool SSL { get; set; } = true;
|
public bool SSL { get; set; } = true;
|
||||||
|
public bool DisableSSL { get; set; } = false;
|
||||||
|
|
||||||
public byte BufferSize { get; set; } = 4;
|
public byte BufferSize { get; set; } = 4;
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
using linker.tunnel.connection;
|
using linker.tunnel.connection;
|
||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Quic;
|
using System.Net.Quic;
|
||||||
@@ -10,6 +9,7 @@ using System.Net.Security;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using linker.tunnel.wanport;
|
||||||
|
|
||||||
namespace linker.tunnel.transport
|
namespace linker.tunnel.transport
|
||||||
{
|
{
|
||||||
@@ -20,12 +20,22 @@ namespace linker.tunnel.transport
|
|||||||
public string Label => "MsQuic,win10+、linux";
|
public string Label => "MsQuic,win10+、linux";
|
||||||
|
|
||||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Quic;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Quic;
|
||||||
|
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
|
||||||
|
public bool Reverse => true;
|
||||||
|
|
||||||
|
public bool DisableReverse => false;
|
||||||
|
|
||||||
|
public bool SSL => true;
|
||||||
|
|
||||||
|
public bool DisableSSL => true;
|
||||||
|
|
||||||
|
|
||||||
public Func<TunnelTransportInfo, Task<bool>> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult<bool>(false); };
|
public Func<TunnelTransportInfo, Task<bool>> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult<bool>(false); };
|
||||||
public Func<TunnelTransportInfo, Task> OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; };
|
public Func<TunnelTransportInfo, Task> OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; };
|
||||||
public Func<TunnelTransportInfo, Task> OnSendConnectSuccess { get; set; } = async (info) => { await Task.CompletedTask; };
|
public Func<TunnelTransportInfo, Task> OnSendConnectSuccess { get; set; } = async (info) => { await Task.CompletedTask; };
|
||||||
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
|
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private ConcurrentDictionary<int, ListenAsyncToken> stateDic = new ConcurrentDictionary<int, ListenAsyncToken>();
|
private ConcurrentDictionary<int, ListenAsyncToken> stateDic = new ConcurrentDictionary<int, ListenAsyncToken>();
|
||||||
private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl");
|
private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl");
|
||||||
|
@@ -8,6 +8,7 @@ using System.Net.Security;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using linker.tunnel.wanport;
|
||||||
|
|
||||||
namespace linker.tunnel.transport
|
namespace linker.tunnel.transport
|
||||||
{
|
{
|
||||||
@@ -16,6 +17,15 @@ namespace linker.tunnel.transport
|
|||||||
public string Name => "TcpNutssb";
|
public string Name => "TcpNutssb";
|
||||||
public string Label => "TCP、低TTL";
|
public string Label => "TCP、低TTL";
|
||||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
||||||
|
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
|
||||||
|
public bool Reverse => true;
|
||||||
|
|
||||||
|
public bool DisableReverse => false;
|
||||||
|
|
||||||
|
public bool SSL => true;
|
||||||
|
|
||||||
|
public bool DisableSSL => false;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送开始连接消息
|
/// 发送开始连接消息
|
||||||
|
@@ -8,6 +8,7 @@ using System.Net.Sockets;
|
|||||||
using System.Security.Authentication;
|
using System.Security.Authentication;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using linker.tunnel.wanport;
|
||||||
|
|
||||||
namespace linker.tunnel.transport
|
namespace linker.tunnel.transport
|
||||||
{
|
{
|
||||||
@@ -16,6 +17,14 @@ namespace linker.tunnel.transport
|
|||||||
public string Name => "TcpP2PNAT";
|
public string Name => "TcpP2PNAT";
|
||||||
public string Label => "TCP、同时打开";
|
public string Label => "TCP、同时打开";
|
||||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
||||||
|
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Tcp;
|
||||||
|
public bool Reverse => false;
|
||||||
|
|
||||||
|
public bool DisableReverse => true;
|
||||||
|
|
||||||
|
public bool SSL => true;
|
||||||
|
|
||||||
|
public bool DisableSSL => false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送开始连接消息
|
/// 发送开始连接消息
|
||||||
@@ -56,6 +65,7 @@ namespace linker.tunnel.transport
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
await Task.Delay(50);
|
||||||
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo, TunnelMode.Client);
|
ITunnelConnection connection = await ConnectForward(tunnelTransportInfo, TunnelMode.Client);
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
@@ -110,7 +120,7 @@ namespace linker.tunnel.transport
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
targetSocket.KeepAlive();
|
targetSocket.KeepAlive();
|
||||||
targetSocket.ReuseBind(new IPEndPoint(IPAddress.Any, tunnelTransportInfo.Local.Local.Port));
|
targetSocket.ReuseBind(new IPEndPoint(tunnelTransportInfo.Local.Local.Address, tunnelTransportInfo.Local.Local.Port));
|
||||||
|
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
{
|
{
|
||||||
@@ -137,6 +147,12 @@ namespace linker.tunnel.transport
|
|||||||
|
|
||||||
private async Task<ITunnelConnection> TcpClient(TunnelTransportInfo state, Socket socket)
|
private async Task<ITunnelConnection> TcpClient(TunnelTransportInfo state, Socket socket)
|
||||||
{
|
{
|
||||||
|
//随便发个消息看对方有没有收到
|
||||||
|
await socket.SendAsync(authBytes);
|
||||||
|
//如果对方收到,会回个消息,不管是啥,回了就行
|
||||||
|
int length = await socket.ReceiveAsync(new byte[1024]);
|
||||||
|
if (length == 0) return null;
|
||||||
|
|
||||||
//需要ssl
|
//需要ssl
|
||||||
SslStream sslStream = null;
|
SslStream sslStream = null;
|
||||||
if (state.SSL)
|
if (state.SSL)
|
||||||
@@ -167,6 +183,15 @@ namespace linker.tunnel.transport
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
//对方会随便发个消息,不管是啥
|
||||||
|
int length = await socket.ReceiveAsync(new byte[1024]);
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//回个消息给它就完了
|
||||||
|
await socket.SendAsync(endBytes);
|
||||||
|
|
||||||
socket.KeepAlive();
|
socket.KeepAlive();
|
||||||
SslStream sslStream = null;
|
SslStream sslStream = null;
|
||||||
if (state.SSL)
|
if (state.SSL)
|
||||||
|
@@ -5,6 +5,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using linker.tunnel.wanport;
|
||||||
|
|
||||||
namespace linker.tunnel.transport
|
namespace linker.tunnel.transport
|
||||||
{
|
{
|
||||||
@@ -15,12 +16,22 @@ namespace linker.tunnel.transport
|
|||||||
public string Label => "udp";
|
public string Label => "udp";
|
||||||
|
|
||||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Udp;
|
||||||
|
public TunnelWanPortProtocolType AllowWanPortProtocolType => TunnelWanPortProtocolType.Udp;
|
||||||
|
public bool Reverse => true;
|
||||||
|
|
||||||
|
public bool DisableReverse => false;
|
||||||
|
|
||||||
|
public bool SSL => true;
|
||||||
|
|
||||||
|
public bool DisableSSL => false;
|
||||||
|
|
||||||
|
|
||||||
public Func<TunnelTransportInfo, Task<bool>> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult<bool>(false); };
|
public Func<TunnelTransportInfo, Task<bool>> OnSendConnectBegin { get; set; } = async (info) => { return await Task.FromResult<bool>(false); };
|
||||||
public Func<TunnelTransportInfo, Task> OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; };
|
public Func<TunnelTransportInfo, Task> OnSendConnectFail { get; set; } = async (info) => { await Task.CompletedTask; };
|
||||||
public Func<TunnelTransportInfo, Task> OnSendConnectSuccess { get; set; } = async (info) => { await Task.CompletedTask; };
|
public Func<TunnelTransportInfo, Task> OnSendConnectSuccess { get; set; } = async (info) => { await Task.CompletedTask; };
|
||||||
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
|
public Action<ITunnelConnection> OnConnected { get; set; } = (state) => { };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl");
|
private byte[] authBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.ttl");
|
||||||
private byte[] endBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.end");
|
private byte[] endBytes = Encoding.UTF8.GetBytes($"{Helper.GlobalString}.end");
|
||||||
|
@@ -5,10 +5,11 @@ namespace linker.tunnel.wanport
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 外网端口协议
|
/// 外网端口协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITunnelWanPort
|
public interface ITunnelWanPortProtocol
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public TunnelWanPortType Type { get; }
|
public TunnelWanPortType Type { get; }
|
||||||
|
public TunnelWanPortProtocolType ProtocolType { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取外网端口
|
/// 获取外网端口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -39,6 +40,7 @@ namespace linker.tunnel.wanport
|
|||||||
/// 协议类别
|
/// 协议类别
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TunnelWanPortType Type { get; set; }
|
public TunnelWanPortType Type { get; set; }
|
||||||
|
public TunnelWanPortProtocolType ProtocolType { get; set; } = TunnelWanPortProtocolType.Udp;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 地址
|
/// 地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -55,6 +57,13 @@ namespace linker.tunnel.wanport
|
|||||||
Stun = 1
|
Stun = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum TunnelWanPortProtocolType : byte
|
||||||
|
{
|
||||||
|
Tcp = 1,
|
||||||
|
Udp = 2,
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class TunnelWanPortTypeInfo
|
public sealed class TunnelWanPortTypeInfo
|
||||||
{
|
{
|
||||||
public TunnelWanPortType Value { get; set; }
|
public TunnelWanPortType Value { get; set; }
|
@@ -1,54 +0,0 @@
|
|||||||
using linker.libs.extends;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
namespace linker.tunnel.wanport
|
|
||||||
{
|
|
||||||
public sealed class TunnelWanPortLinker : ITunnelWanPort
|
|
||||||
{
|
|
||||||
public string Name => "默认";
|
|
||||||
public TunnelWanPortType Type => TunnelWanPortType.Linker;
|
|
||||||
|
|
||||||
public TunnelWanPortLinker()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<TunnelWanPortEndPoint> GetAsync(IPEndPoint server)
|
|
||||||
{
|
|
||||||
UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork);
|
|
||||||
udpClient.Client.Reuse();
|
|
||||||
udpClient.Client.WindowsUdpBug();
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await udpClient.SendAsync(new byte[1] { 0 }, server);
|
|
||||||
UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(500));
|
|
||||||
if (result.Buffer.Length == 0)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < result.Buffer.Length; j++)
|
|
||||||
{
|
|
||||||
result.Buffer[j] = (byte)(result.Buffer[j] ^ byte.MaxValue);
|
|
||||||
}
|
|
||||||
AddressFamily addressFamily = (AddressFamily)result.Buffer[0];
|
|
||||||
int length = addressFamily == AddressFamily.InterNetwork ? 4 : 16;
|
|
||||||
IPAddress ip = new IPAddress(result.Buffer.AsSpan(1, length));
|
|
||||||
ushort port = result.Buffer.AsMemory(1 + length).ToUInt16();
|
|
||||||
|
|
||||||
IPEndPoint remoteEP = new IPEndPoint(ip, port);
|
|
||||||
|
|
||||||
return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP };
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
109
linker.tunnel/wanport/TunnelWanPortProtocolLinker.cs
Normal file
109
linker.tunnel/wanport/TunnelWanPortProtocolLinker.cs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
using linker.libs.extends;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace linker.tunnel.wanport
|
||||||
|
{
|
||||||
|
public sealed class TunnelWanPortProtocolLinkerUdp : ITunnelWanPortProtocol
|
||||||
|
{
|
||||||
|
public string Name => "Linker Udp";
|
||||||
|
public TunnelWanPortType Type => TunnelWanPortType.Linker;
|
||||||
|
|
||||||
|
public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Udp;
|
||||||
|
|
||||||
|
public TunnelWanPortProtocolLinkerUdp()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TunnelWanPortEndPoint> GetAsync(IPEndPoint server)
|
||||||
|
{
|
||||||
|
UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork);
|
||||||
|
udpClient.Client.Reuse();
|
||||||
|
udpClient.Client.WindowsUdpBug();
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await udpClient.SendAsync(new byte[1] { 0 }, server);
|
||||||
|
UdpReceiveResult result = await udpClient.ReceiveAsync().WaitAsync(TimeSpan.FromMilliseconds(500));
|
||||||
|
if (result.Buffer.Length == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < result.Buffer.Length; j++)
|
||||||
|
{
|
||||||
|
result.Buffer[j] = (byte)(result.Buffer[j] ^ byte.MaxValue);
|
||||||
|
}
|
||||||
|
AddressFamily addressFamily = (AddressFamily)result.Buffer[0];
|
||||||
|
int length = addressFamily == AddressFamily.InterNetwork ? 4 : 16;
|
||||||
|
IPAddress ip = new IPAddress(result.Buffer.AsSpan(1, length));
|
||||||
|
ushort port = result.Buffer.AsMemory(1 + length).ToUInt16();
|
||||||
|
|
||||||
|
IPEndPoint remoteEP = new IPEndPoint(ip, port);
|
||||||
|
|
||||||
|
return new TunnelWanPortEndPoint { Local = udpClient.Client.LocalEndPoint as IPEndPoint, Remote = remoteEP };
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public sealed class TunnelWanPortProtocolLinkerTcp : ITunnelWanPortProtocol
|
||||||
|
{
|
||||||
|
public string Name => "Linker Tcp";
|
||||||
|
public TunnelWanPortType Type => TunnelWanPortType.Linker;
|
||||||
|
|
||||||
|
public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Tcp;
|
||||||
|
|
||||||
|
public TunnelWanPortProtocolLinkerTcp()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TunnelWanPortEndPoint> GetAsync(IPEndPoint server)
|
||||||
|
{
|
||||||
|
byte[] buffer = ArrayPool<byte>.Shared.Rent(20);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Socket socket = new Socket(server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
|
||||||
|
await socket.ConnectAsync(server);
|
||||||
|
|
||||||
|
await socket.SendAsync(new byte[] { 0 });
|
||||||
|
int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None);
|
||||||
|
|
||||||
|
for (int j = 0; j < length; j++)
|
||||||
|
{
|
||||||
|
buffer[j] = (byte)(buffer[j] ^ byte.MaxValue);
|
||||||
|
}
|
||||||
|
AddressFamily addressFamily = (AddressFamily)buffer[0];
|
||||||
|
int iplength = addressFamily == AddressFamily.InterNetwork ? 4 : 16;
|
||||||
|
IPAddress ip = new IPAddress(buffer.AsSpan(1, iplength));
|
||||||
|
ushort port = buffer.AsMemory(1 + iplength).ToUInt16();
|
||||||
|
|
||||||
|
IPEndPoint remoteEP = new IPEndPoint(ip, port);
|
||||||
|
IPEndPoint localEP = socket.LocalEndPoint as IPEndPoint;
|
||||||
|
socket.Close();
|
||||||
|
|
||||||
|
return new TunnelWanPortEndPoint { Local = localEP, Remote = remoteEP };
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ArrayPool<byte>.Shared.Return(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -5,12 +5,14 @@ using System.Net.Sockets;
|
|||||||
|
|
||||||
namespace linker.tunnel.wanport
|
namespace linker.tunnel.wanport
|
||||||
{
|
{
|
||||||
public sealed class TunnelWanPortStun : ITunnelWanPort
|
public sealed class TunnelWanPortProtocolStun : ITunnelWanPortProtocol
|
||||||
{
|
{
|
||||||
public string Name => "Stun";
|
public string Name => "Stun Udp";
|
||||||
public TunnelWanPortType Type => TunnelWanPortType.Stun;
|
public TunnelWanPortType Type => TunnelWanPortType.Stun;
|
||||||
|
|
||||||
public TunnelWanPortStun()
|
public TunnelWanPortProtocolType ProtocolType => TunnelWanPortProtocolType.Udp;
|
||||||
|
|
||||||
|
public TunnelWanPortProtocolStun()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@@ -1,5 +1,4 @@
|
|||||||
using linker.tunnel.adapter;
|
using linker.libs;
|
||||||
using linker.libs;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
@@ -10,8 +9,7 @@ namespace linker.tunnel.wanport
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class TunnelWanPortTransfer
|
public sealed class TunnelWanPortTransfer
|
||||||
{
|
{
|
||||||
private List<ITunnelWanPort> tunnelWanPorts;
|
private List<ITunnelWanPortProtocol> tunnelWanPorts;
|
||||||
private ITunnelAdapter tunnelAdapter;
|
|
||||||
|
|
||||||
public TunnelWanPortTransfer()
|
public TunnelWanPortTransfer()
|
||||||
{
|
{
|
||||||
@@ -21,10 +19,8 @@ namespace linker.tunnel.wanport
|
|||||||
/// 加载所有外网端口协议
|
/// 加载所有外网端口协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assembs"></param>
|
/// <param name="assembs"></param>
|
||||||
public void Init(ITunnelAdapter tunnelAdapter, List<ITunnelWanPort> tunnelWanPorts)
|
public void Init(List<ITunnelWanPortProtocol> tunnelWanPorts)
|
||||||
{
|
{
|
||||||
|
|
||||||
this.tunnelAdapter = tunnelAdapter;
|
|
||||||
this.tunnelWanPorts = tunnelWanPorts;
|
this.tunnelWanPorts = tunnelWanPorts;
|
||||||
LoggerHelper.Instance.Warning($"load tunnel wanport compacts:{string.Join(",", tunnelWanPorts.Select(c => c.Name))}");
|
LoggerHelper.Instance.Warning($"load tunnel wanport compacts:{string.Join(",", tunnelWanPorts.Select(c => c.Name))}");
|
||||||
}
|
}
|
||||||
@@ -39,37 +35,31 @@ namespace linker.tunnel.wanport
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="localIP">你的局域网IP</param>
|
/// <param name="localIP">你的局域网IP</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<TunnelWanPortEndPoint> GetWanPortAsync(IPAddress localIP)
|
public async Task<TunnelWanPortEndPoint> GetWanPortAsync(IPAddress localIP, TunnelWanPortInfo info)
|
||||||
{
|
{
|
||||||
var tunnelWanPortItems = tunnelAdapter.GetTunnelWanPortCompacts();
|
if (info == null) return null;
|
||||||
foreach (TunnelWanPortInfo item in tunnelWanPortItems)
|
var tunnelWanPort = tunnelWanPorts.FirstOrDefault(c => c.Type == info.Type && c.ProtocolType == info.ProtocolType);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (item.Disabled || string.IsNullOrWhiteSpace(item.Host)) continue;
|
Stopwatch sw = new Stopwatch();
|
||||||
ITunnelWanPort tunnelWanPort = tunnelWanPorts.FirstOrDefault(c => c.Type == item.Type);
|
sw.Start();
|
||||||
if (tunnelWanPort == null) continue;
|
IPEndPoint server = NetworkHelper.GetEndPoint(info.Host, 3478);
|
||||||
|
sw.Stop();
|
||||||
try
|
if (sw.ElapsedMilliseconds > 1000)
|
||||||
{
|
{
|
||||||
Stopwatch sw = new Stopwatch();
|
LoggerHelper.Instance.Warning($"get domain ip time:{sw.ElapsedMilliseconds}ms");
|
||||||
sw.Start();
|
|
||||||
IPEndPoint server = NetworkHelper.GetEndPoint(item.Host, 3478);
|
|
||||||
sw.Stop();
|
|
||||||
if (sw.ElapsedMilliseconds > 1000)
|
|
||||||
{
|
|
||||||
LoggerHelper.Instance.Warning($"get domain ip time:{sw.ElapsedMilliseconds}ms");
|
|
||||||
}
|
|
||||||
TunnelWanPortEndPoint WanPort = await tunnelWanPort.GetAsync(server);
|
|
||||||
if (WanPort != null)
|
|
||||||
{
|
|
||||||
WanPort.Local.Address = localIP;
|
|
||||||
return WanPort;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
TunnelWanPortEndPoint WanPort = await tunnelWanPort.GetAsync(server);
|
||||||
|
if (WanPort != null)
|
||||||
{
|
{
|
||||||
LoggerHelper.Instance.Error(ex);
|
WanPort.Local.Address = localIP;
|
||||||
|
return WanPort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LoggerHelper.Instance.Error(ex);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column property="Name" label="名称">
|
<el-table-column property="Name" label="名称">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="scope.row.NameEditing">
|
<template v-if="scope.row.NameEditing && scope.row.Started==false">
|
||||||
<el-input autofocus size="small" v-model="scope.row.Name"
|
<el-input autofocus size="small" v-model="scope.row.Name"
|
||||||
@blur="handleEditBlur(scope.row, 'Name')"></el-input>
|
@blur="handleEditBlur(scope.row, 'Name')"></el-input>
|
||||||
</template>
|
</template>
|
||||||
@@ -26,14 +26,14 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="BindIPAddress" label="监听IP" width="140">
|
<el-table-column property="BindIPAddress" label="监听IP" width="140">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-select v-model="scope.row.BindIPAddress" size="small">
|
<el-select v-model="scope.row.BindIPAddress" size="small" :disabled="scope.row.Started">
|
||||||
<el-option v-for="item in state.ips" :key="item" :label="item" :value="item"/>
|
<el-option v-for="item in state.ips" :key="item" :label="item" :value="item"/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="Port" label="监听端口" width="80">
|
<el-table-column property="Port" label="监听端口" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="scope.row.PortEditing">
|
<template v-if="scope.row.PortEditing && scope.row.Started==false">
|
||||||
<el-input type="number" autofocus size="small" v-model="scope.row.Port"
|
<el-input type="number" autofocus size="small" v-model="scope.row.Port"
|
||||||
@blur="handleEditBlur(scope.row, 'Port')"></el-input>
|
@blur="handleEditBlur(scope.row, 'Port')"></el-input>
|
||||||
</template>
|
</template>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="TargetEP" label="目标服务" width="140">
|
<el-table-column property="TargetEP" label="目标服务" width="140">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="scope.row.TargetEPEditing">
|
<template v-if="scope.row.TargetEPEditing && scope.row.Started==false">
|
||||||
<el-input autofocus size="small" v-model="scope.row.TargetEP"
|
<el-input autofocus size="small" v-model="scope.row.TargetEP"
|
||||||
@blur="handleEditBlur(scope.row, 'TargetEP')"></el-input>
|
@blur="handleEditBlur(scope.row, 'TargetEP')"></el-input>
|
||||||
</template>
|
</template>
|
||||||
@@ -173,6 +173,10 @@ export default {
|
|||||||
saveRow({ ID: 0, Name: '', Port: 0, TargetEP: '127.0.0.1:80', machineId: state.machineId });
|
saveRow({ ID: 0, Name: '', Port: 0, TargetEP: '127.0.0.1:80', machineId: state.machineId });
|
||||||
}
|
}
|
||||||
const handleEdit = (row, p) => {
|
const handleEdit = (row, p) => {
|
||||||
|
if(row.Started){
|
||||||
|
ElMessage.error('请先停止');
|
||||||
|
return;
|
||||||
|
}
|
||||||
state.data.forEach(c => {
|
state.data.forEach(c => {
|
||||||
c[`NameEditing`] = false;
|
c[`NameEditing`] = false;
|
||||||
c[`PortEditing`] = false;
|
c[`PortEditing`] = false;
|
||||||
@@ -182,6 +186,10 @@ export default {
|
|||||||
row[`${p}Editing`] = true;
|
row[`${p}Editing`] = true;
|
||||||
}
|
}
|
||||||
const handleEditBlur = (row, p) => {
|
const handleEditBlur = (row, p) => {
|
||||||
|
if(row.Started){
|
||||||
|
ElMessage.error('请先停止');
|
||||||
|
return;
|
||||||
|
}
|
||||||
row[`${p}Editing`] = false;
|
row[`${p}Editing`] = false;
|
||||||
saveRow(row);
|
saveRow(row);
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
<el-table :data="state.data" size="small" border height="500" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column property="Name" label="名称">
|
<el-table-column property="Name" label="名称">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="scope.row.NameEditing">
|
<template v-if="scope.row.NameEditing && scope.row.Started==false ">
|
||||||
<el-input autofocus size="small" v-model="scope.row.Name"
|
<el-input autofocus size="small" v-model="scope.row.Name"
|
||||||
@blur="handleEditBlur(scope.row, 'Name')"></el-input>
|
@blur="handleEditBlur(scope.row, 'Name')"></el-input>
|
||||||
</template>
|
</template>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="Temp" label="远程端口/域名" width="160">
|
<el-table-column property="Temp" label="远程端口/域名" width="160">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="scope.row.TempEditing">
|
<template v-if="scope.row.TempEditing && scope.row.Started==false">
|
||||||
<el-input autofocus size="small" v-model="scope.row.Temp"
|
<el-input autofocus size="small" v-model="scope.row.Temp"
|
||||||
@blur="handleEditBlur(scope.row, 'Temp')"></el-input>
|
@blur="handleEditBlur(scope.row, 'Temp')"></el-input>
|
||||||
</template>
|
</template>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="LocalEP" label="本机服务" width="140">
|
<el-table-column property="LocalEP" label="本机服务" width="140">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="scope.row.LocalEPEditing">
|
<template v-if="scope.row.LocalEPEditing && scope.row.Started==false">
|
||||||
<el-input autofocus size="small" v-model="scope.row.LocalEP"
|
<el-input autofocus size="small" v-model="scope.row.LocalEP"
|
||||||
@blur="handleEditBlur(scope.row, 'LocalEP')"></el-input>
|
@blur="handleEditBlur(scope.row, 'LocalEP')"></el-input>
|
||||||
</template>
|
</template>
|
||||||
@@ -152,6 +152,10 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const handleEdit = (row, p) => {
|
const handleEdit = (row, p) => {
|
||||||
|
if(row.Started){
|
||||||
|
ElMessage.error('请先停止运行');
|
||||||
|
return;
|
||||||
|
}
|
||||||
state.data.forEach(c => {
|
state.data.forEach(c => {
|
||||||
c[`NameEditing`] = false;
|
c[`NameEditing`] = false;
|
||||||
c[`RemotePortEditing`] = false;
|
c[`RemotePortEditing`] = false;
|
||||||
@@ -162,6 +166,10 @@ export default {
|
|||||||
row[`${p}Editing`] = true;
|
row[`${p}Editing`] = true;
|
||||||
}
|
}
|
||||||
const handleEditBlur = (row, p) => {
|
const handleEditBlur = (row, p) => {
|
||||||
|
if(row.Started){
|
||||||
|
ElMessage.error('请先停止运行');
|
||||||
|
return;
|
||||||
|
}
|
||||||
row[`${p}Editing`] = false;
|
row[`${p}Editing`] = false;
|
||||||
saveRow(row);
|
saveRow(row);
|
||||||
}
|
}
|
||||||
|
@@ -17,9 +17,9 @@
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="Type" label="类别" width="80">
|
<el-table-column prop="RelayType" label="类别" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-select v-model="scope.row.Type" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'Type')">
|
<el-select v-model="scope.row.RelayType" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'RelayType')">
|
||||||
<el-option v-for="item in state.types" :key="item.Value" :label="item.Name" :value="item.Value"/>
|
<el-option v-for="item in state.types" :key="item.Value" :label="item.Name" :value="item.Value"/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
@@ -109,7 +109,7 @@ export default {
|
|||||||
const handleEdit = (row, p) => {
|
const handleEdit = (row, p) => {
|
||||||
state.list.forEach(c => {
|
state.list.forEach(c => {
|
||||||
c[`NameEditing`] = false;
|
c[`NameEditing`] = false;
|
||||||
c[`TypeEditing`] = false;
|
c[`RelayTypeEditing`] = false;
|
||||||
c[`HostEditing`] = false;
|
c[`HostEditing`] = false;
|
||||||
c[`SecretKeyEditing`] = false;
|
c[`SecretKeyEditing`] = false;
|
||||||
})
|
})
|
||||||
@@ -128,7 +128,7 @@ export default {
|
|||||||
if(state.list.filter(c=>c.Host == '' || c.Name == '').length > 0){
|
if(state.list.filter(c=>c.Host == '' || c.Name == '').length > 0){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.list.splice(index+1,0,{Name:'',Host:'',Type:0,SecretKey:'snltty',Disabled:false});
|
state.list.splice(index+1,0,{Name:'',Host:'',RelayType:0,SecretKey:'snltty',Disabled:false});
|
||||||
handleSave();
|
handleSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,12 +18,12 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="Reverse" label="反向" width="60">
|
<el-table-column property="Reverse" label="反向" width="60">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch v-model="scope.row.Reverse" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
|
<el-switch :disabled="scope.row.DisableReverse" v-model="scope.row.Reverse" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="SSL" label="SSL" width="60">
|
<el-table-column property="SSL" label="SSL" width="60">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch v-model="scope.row.SSL" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
|
<el-switch :disabled="scope.row.DisableSSL" v-model="scope.row.SSL" @change="handleSave" inline-prompt active-text="是" inactive-text="否" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column property="Disabled" label="禁用" width="60">
|
<el-table-column property="Disabled" label="禁用" width="60">
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
<div class="pdr-10 pdb-6 flex-1">
|
<div class="pdr-10 pdb-6 flex-1">
|
||||||
<el-checkbox v-model="state.sync" label="将更改同步到所有客户端" />
|
<el-checkbox v-model="state.sync" label="将更改同步到所有客户端" />
|
||||||
</div>
|
</div>
|
||||||
<div>将按顺序获取IP,直到其中一个成功获取,连接不同地域的服务器可能会走不同线路</div>
|
<div>将按顺序获取IP,进行尝试打洞</div>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
<el-table :data="state.list" border size="small" width="100%" :height="`${state.height}px`" @cell-dblclick="handleCellClick">
|
||||||
<el-table-column prop="Name" label="名称">
|
<el-table-column prop="Name" label="名称">
|
||||||
@@ -17,6 +17,16 @@
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="ProtocolType" label="协议" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<div>
|
||||||
|
<el-select v-model="scope.row.ProtocolType" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'ProtocolType')">
|
||||||
|
<el-option v-for="(item,index) in state.protocolTypes" :key="+index" :label="item" :value="+index"/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="Type" label="类别" width="100">
|
<el-table-column prop="Type" label="类别" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-select v-model="scope.row.Type" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'Type')">
|
<el-select v-model="scope.row.Type" placeholder="Select" size="small" @change="handleEditBlur(scope.row, 'Type')">
|
||||||
@@ -81,7 +91,8 @@ export default {
|
|||||||
list:((globalData.value.config.Running.Tunnel || {Servers:[]}).Servers || []).sort((a,b)=>a.Disabled - b.Disabled),
|
list:((globalData.value.config.Running.Tunnel || {Servers:[]}).Servers || []).sort((a,b)=>a.Disabled - b.Disabled),
|
||||||
types:[],
|
types:[],
|
||||||
height: computed(()=>globalData.value.height-130),
|
height: computed(()=>globalData.value.height-130),
|
||||||
sync:true
|
sync:true,
|
||||||
|
protocolTypes:{1:'tcp',2:'udp'},
|
||||||
});
|
});
|
||||||
|
|
||||||
const _getTunnelTypes = ()=>{
|
const _getTunnelTypes = ()=>{
|
||||||
@@ -98,6 +109,7 @@ export default {
|
|||||||
c[`NameEditing`] = false;
|
c[`NameEditing`] = false;
|
||||||
c[`TypeEditing`] = false;
|
c[`TypeEditing`] = false;
|
||||||
c[`HostEditing`] = false;
|
c[`HostEditing`] = false;
|
||||||
|
c[`ProtocolTypeEditing`] = false;
|
||||||
})
|
})
|
||||||
row[`${p}Editing`] = true;
|
row[`${p}Editing`] = true;
|
||||||
}
|
}
|
||||||
@@ -114,7 +126,7 @@ export default {
|
|||||||
if(state.list.filter(c=>c.Host == '' || c.Name == '').length > 0){
|
if(state.list.filter(c=>c.Host == '' || c.Name == '').length > 0){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.list.splice(index+1,0,{Name:'',Host:'',Type:0,Disabled:false});
|
state.list.splice(index+1,0,{Name:'',Host:'',Type:0,Disabled:false,ProtocolType:2});
|
||||||
handleSave();
|
handleSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,10 +10,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
<PublishProtocol>FileSystem</PublishProtocol>
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
<_TargetId>Folder</_TargetId>
|
<_TargetId>Folder</_TargetId>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<SelfContained>false</SelfContained>
|
||||||
<SelfContained>true</SelfContained>
|
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
|
||||||
<PublishTrimmed>true</PublishTrimmed>
|
|
||||||
<PublishReadyToRun>false</PublishReadyToRun>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
@@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||||||
-->
|
-->
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<History>True|2024-06-02T07:39:16.1880914Z;True|2024-06-02T15:38:26.4314913+08:00;True|2024-06-02T15:27:20.2651650+08:00;True|2024-06-02T15:26:34.3414728+08:00;True|2024-06-02T15:22:33.1407820+08:00;True|2024-06-02T15:22:01.4381533+08:00;True|2024-06-02T15:20:29.6692030+08:00;True|2024-06-02T15:19:55.9152032+08:00;True|2024-06-02T15:16:15.2278365+08:00;True|2024-04-23T09:09:03.5136215+08:00;True|2024-04-22T12:57:38.4988098+08:00;True|2023-12-23T09:50:45.7841097+08:00;True|2023-11-17T09:24:26.3650754+08:00;True|2023-11-17T09:11:28.0867966+08:00;True|2023-11-17T09:09:49.7366925+08:00;False|2023-11-17T09:08:56.6254247+08:00;False|2023-11-17T09:08:45.4560896+08:00;True|2023-11-16T11:49:56.3722044+08:00;True|2023-11-16T11:48:06.3192199+08:00;True|2023-11-16T11:47:35.3708397+08:00;True|2023-11-16T11:45:11.0208634+08:00;False|2023-11-16T11:44:01.7611210+08:00;True|2023-10-01T17:27:31.0065885+08:00;True|2023-09-04T18:19:54.7492652+08:00;True|2023-09-04T18:19:32.2969345+08:00;False|2023-09-04T18:18:51.7827366+08:00;True|2023-09-04T18:15:31.6783417+08:00;True|2023-09-04T18:14:40.9964104+08:00;</History>
|
<History>True|2024-07-01T09:25:46.1203574Z;True|2024-06-02T15:39:16.1880914+08:00;True|2024-06-02T15:38:26.4314913+08:00;True|2024-06-02T15:27:20.2651650+08:00;True|2024-06-02T15:26:34.3414728+08:00;True|2024-06-02T15:22:33.1407820+08:00;True|2024-06-02T15:22:01.4381533+08:00;True|2024-06-02T15:20:29.6692030+08:00;True|2024-06-02T15:19:55.9152032+08:00;True|2024-06-02T15:16:15.2278365+08:00;True|2024-04-23T09:09:03.5136215+08:00;True|2024-04-22T12:57:38.4988098+08:00;True|2023-12-23T09:50:45.7841097+08:00;True|2023-11-17T09:24:26.3650754+08:00;True|2023-11-17T09:11:28.0867966+08:00;True|2023-11-17T09:09:49.7366925+08:00;False|2023-11-17T09:08:56.6254247+08:00;False|2023-11-17T09:08:45.4560896+08:00;True|2023-11-16T11:49:56.3722044+08:00;True|2023-11-16T11:48:06.3192199+08:00;True|2023-11-16T11:47:35.3708397+08:00;True|2023-11-16T11:45:11.0208634+08:00;False|2023-11-16T11:44:01.7611210+08:00;True|2023-10-01T17:27:31.0065885+08:00;True|2023-09-04T18:19:54.7492652+08:00;True|2023-09-04T18:19:32.2969345+08:00;False|2023-09-04T18:18:51.7827366+08:00;True|2023-09-04T18:15:31.6783417+08:00;True|2023-09-04T18:14:40.9964104+08:00;</History>
|
||||||
<LastFailureDetails />
|
<LastFailureDetails />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_LastSelectedProfileId>C:\Users\snltty\Desktop\cmonitor\cmonitor\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
<_LastSelectedProfileId>C:\Users\snltty\Desktop\linker\linker\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
|
||||||
<ActiveDebugProfile>cmonitor</ActiveDebugProfile>
|
<ActiveDebugProfile>cmonitor</ActiveDebugProfile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
@@ -31,7 +31,7 @@ namespace linker.plugins.relay
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="param"></param>
|
/// <param name="param"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<RelayCompactTypeInfo> GetTypes(ApiControllerParamsInfo param)
|
public List<RelayTypeInfo> GetTypes(ApiControllerParamsInfo param)
|
||||||
{
|
{
|
||||||
return relayTransfer.GetTypes();
|
return relayTransfer.GetTypes();
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ namespace linker.plugins.relay
|
|||||||
public sealed class RelayCompactParamInfo
|
public sealed class RelayCompactParamInfo
|
||||||
{
|
{
|
||||||
public bool Sync { get; set; }
|
public bool Sync { get; set; }
|
||||||
public RelayCompactInfo[] List { get; set; } = Array.Empty<RelayCompactInfo>();
|
public RelayServerInfo[] List { get; set; } = Array.Empty<RelayServerInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -31,11 +31,11 @@ namespace linker.plugins.relay
|
|||||||
|
|
||||||
if (running.Data.Relay.Servers.Length == 0)
|
if (running.Data.Relay.Servers.Length == 0)
|
||||||
{
|
{
|
||||||
running.Data.Relay.Servers = new RelayCompactInfo[]
|
running.Data.Relay.Servers = new RelayServerInfo[]
|
||||||
{
|
{
|
||||||
new RelayCompactInfo{
|
new RelayServerInfo{
|
||||||
Name="默认",
|
Name="默认",
|
||||||
Type= RelayCompactType.linker,
|
RelayType= RelayType.Linker,
|
||||||
Disabled = false,
|
Disabled = false,
|
||||||
Host = running.Data.Client.Servers.FirstOrDefault().Host
|
Host = running.Data.Client.Servers.FirstOrDefault().Host
|
||||||
}
|
}
|
||||||
@@ -58,15 +58,15 @@ namespace linker.plugins.relay
|
|||||||
/// 获取所有中继协议
|
/// 获取所有中继协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<RelayCompactTypeInfo> GetTypes()
|
public List<RelayTypeInfo> GetTypes()
|
||||||
{
|
{
|
||||||
return transports.Select(c => new RelayCompactTypeInfo { Value = c.Type, Name = c.Type.ToString() }).Distinct(new RelayCompactTypeInfoEqualityComparer()).ToList();
|
return transports.Select(c => new RelayTypeInfo { Value = c.Type, Name = c.Type.ToString() }).Distinct(new RelayCompactTypeInfoEqualityComparer()).ToList();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 收到中继协议列表
|
/// 收到中继协议列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="servers"></param>
|
/// <param name="servers"></param>
|
||||||
public void OnServers(RelayCompactInfo[] servers)
|
public void OnServers(RelayServerInfo[] servers)
|
||||||
{
|
{
|
||||||
running.Data.Relay.Servers = servers;
|
running.Data.Relay.Servers = servers;
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
@@ -113,9 +113,9 @@ namespace linker.plugins.relay
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Type);
|
IEnumerable<ITransport> _transports = transports.OrderBy(c => c.Type);
|
||||||
foreach (RelayCompactInfo item in running.Data.Relay.Servers.Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false))
|
foreach (RelayServerInfo item in running.Data.Relay.Servers.Where(c => c.Disabled == false && string.IsNullOrWhiteSpace(c.Host) == false))
|
||||||
{
|
{
|
||||||
ITransport transport = _transports.FirstOrDefault(c => c.Type == item.Type);
|
ITransport transport = _transports.FirstOrDefault(c => c.Type == item.RelayType);
|
||||||
if (transport == null)
|
if (transport == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@@ -14,7 +14,7 @@ namespace linker.client.config
|
|||||||
public sealed class RelayRunningInfo
|
public sealed class RelayRunningInfo
|
||||||
{
|
{
|
||||||
public ObjectId Id { get; set; }
|
public ObjectId Id { get; set; }
|
||||||
public RelayCompactInfo[] Servers { get; set; } = Array.Empty<RelayCompactInfo>();
|
public RelayServerInfo[] Servers { get; set; } = Array.Empty<RelayServerInfo>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,35 +33,35 @@ namespace linker.config
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MemoryPackable]
|
[MemoryPackable]
|
||||||
public sealed partial class RelayCompactInfo
|
public sealed partial class RelayServerInfo
|
||||||
{
|
{
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
public RelayCompactType Type { get; set; } = RelayCompactType.linker;
|
public RelayType RelayType { get; set; } = RelayType.Linker;
|
||||||
public string SecretKey { get; set; } = "snltty";
|
public string SecretKey { get; set; } = "snltty";
|
||||||
public string Host { get; set; } = string.Empty;
|
public string Host { get; set; } = string.Empty;
|
||||||
public bool Disabled { get; set; }
|
public bool Disabled { get; set; }
|
||||||
public bool SSL { get; set; } = true;
|
public bool SSL { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RelayCompactType : byte
|
public enum RelayType : byte
|
||||||
{
|
{
|
||||||
linker = 0,
|
Linker = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class RelayCompactTypeInfo
|
public sealed class RelayTypeInfo
|
||||||
{
|
{
|
||||||
public RelayCompactType Value { get; set; }
|
public RelayType Value { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class RelayCompactTypeInfoEqualityComparer : IEqualityComparer<RelayCompactTypeInfo>
|
public sealed class RelayCompactTypeInfoEqualityComparer : IEqualityComparer<RelayTypeInfo>
|
||||||
{
|
{
|
||||||
public bool Equals(RelayCompactTypeInfo x, RelayCompactTypeInfo y)
|
public bool Equals(RelayTypeInfo x, RelayTypeInfo y)
|
||||||
{
|
{
|
||||||
return x.Value == y.Value;
|
return x.Value == y.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetHashCode([DisallowNull] RelayCompactTypeInfo obj)
|
public int GetHashCode([DisallowNull] RelayTypeInfo obj)
|
||||||
{
|
{
|
||||||
return obj.Value.GetHashCode();
|
return obj.Value.GetHashCode();
|
||||||
}
|
}
|
||||||
|
@@ -39,7 +39,7 @@ namespace linker.plugins.relay.messenger
|
|||||||
[MessengerId((ushort)RelayMessengerIds.Servers)]
|
[MessengerId((ushort)RelayMessengerIds.Servers)]
|
||||||
public void Servers(IConnection connection)
|
public void Servers(IConnection connection)
|
||||||
{
|
{
|
||||||
RelayCompactInfo[] servers = MemoryPackSerializer.Deserialize<RelayCompactInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
|
RelayServerInfo[] servers = MemoryPackSerializer.Deserialize<RelayServerInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
relayTransfer.OnServers(servers);
|
relayTransfer.OnServers(servers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ namespace linker.plugins.relay.messenger
|
|||||||
[MessengerId((ushort)RelayMessengerIds.ServersForward)]
|
[MessengerId((ushort)RelayMessengerIds.ServersForward)]
|
||||||
public async Task ServersForward(IConnection connection)
|
public async Task ServersForward(IConnection connection)
|
||||||
{
|
{
|
||||||
RelayCompactInfo[] servers = MemoryPackSerializer.Deserialize<RelayCompactInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
|
RelayServerInfo[] servers = MemoryPackSerializer.Deserialize<RelayServerInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
|
||||||
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
|
if (signCaching.TryGet(connection.Id, out SignCacheInfo cache))
|
||||||
{
|
{
|
||||||
|
@@ -17,7 +17,7 @@ namespace linker.plugins.relay.transport
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 中继类型
|
/// 中继类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RelayCompactType Type { get; }
|
public RelayType Type { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 协议
|
/// 协议
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -17,7 +17,7 @@ namespace linker.plugins.relay.transport
|
|||||||
public sealed class TransportSelfHost : ITransport
|
public sealed class TransportSelfHost : ITransport
|
||||||
{
|
{
|
||||||
public string Name => "默认";
|
public string Name => "默认";
|
||||||
public RelayCompactType Type => RelayCompactType.linker;
|
public RelayType Type => RelayType.Linker;
|
||||||
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
public TunnelProtocolType ProtocolType => TunnelProtocolType.Tcp;
|
||||||
|
|
||||||
private readonly TcpServer tcpServer;
|
private readonly TcpServer tcpServer;
|
||||||
|
@@ -10,8 +10,6 @@ using MemoryPack;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using linker.tunnel.wanport;
|
using linker.tunnel.wanport;
|
||||||
using System.Linq;
|
|
||||||
using linker.libs.extends;
|
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
|
|
||||||
namespace linker.plugins.tunnel
|
namespace linker.plugins.tunnel
|
||||||
@@ -42,11 +40,11 @@ namespace linker.plugins.tunnel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TunnelWanPortInfo> GetTunnelWanPortCompacts()
|
public List<TunnelWanPortInfo> GetTunnelWanPortProtocols()
|
||||||
{
|
{
|
||||||
return running.Data.Tunnel.Servers.ToList();
|
return running.Data.Tunnel.Servers.ToList();
|
||||||
}
|
}
|
||||||
public void SetTunnelWanPortCompacts(List<TunnelWanPortInfo> compacts)
|
public void SetTunnelWanPortProtocols(List<TunnelWanPortInfo> compacts)
|
||||||
{
|
{
|
||||||
running.Data.Tunnel.Servers = compacts.ToArray();
|
running.Data.Tunnel.Servers = compacts.ToArray();
|
||||||
running.Data.Update();
|
running.Data.Update();
|
||||||
@@ -68,16 +66,16 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
LocalIps = config.Data.Client.Tunnel.LocalIPs
|
LocalIps = config.Data.Client.Tunnel.LocalIPs
|
||||||
.Where(c => c.Equals(running.Data.Tuntap.IP) == false)
|
.Where(c => c.Equals(running.Data.Tuntap.IP) == false)
|
||||||
.Where(c=>
|
.Where(c =>
|
||||||
{
|
{
|
||||||
if(c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
|
if (c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
|
||||||
{
|
{
|
||||||
uint ip = BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes());
|
uint ip = BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes());
|
||||||
foreach (var item in running.Data.Tunnel.ExcludeIPs)
|
foreach (var item in running.Data.Tunnel.ExcludeIPs)
|
||||||
{
|
{
|
||||||
uint maskValue = NetworkHelper.MaskValue(item.Mask);
|
uint maskValue = NetworkHelper.MaskValue(item.Mask);
|
||||||
uint ip1 = BinaryPrimitives.ReadUInt32BigEndian(item.IPAddress.GetAddressBytes());
|
uint ip1 = BinaryPrimitives.ReadUInt32BigEndian(item.IPAddress.GetAddressBytes());
|
||||||
if((ip & maskValue) == (ip1 & maskValue))
|
if ((ip & maskValue) == (ip1 & maskValue))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -90,13 +88,13 @@ namespace linker.plugins.tunnel
|
|||||||
MachineId = config.Data.Client.Id
|
MachineId = config.Data.Client.Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public async Task<TunnelTransportWanPortInfo> GetRemoteWanPort(string remoteMachineId)
|
public async Task<TunnelTransportWanPortInfo> GetRemoteWanPort(TunnelWanPortProtocolInfo info)
|
||||||
{
|
{
|
||||||
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
|
||||||
{
|
{
|
||||||
Connection = clientSignInState.Connection,
|
Connection = clientSignInState.Connection,
|
||||||
MessengerId = (ushort)TunnelMessengerIds.InfoForward,
|
MessengerId = (ushort)TunnelMessengerIds.InfoForward,
|
||||||
Payload = MemoryPackSerializer.Serialize(remoteMachineId)
|
Payload = MemoryPackSerializer.Serialize(info)
|
||||||
});
|
});
|
||||||
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
|
if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0)
|
||||||
{
|
{
|
||||||
|
@@ -82,7 +82,7 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
SetServersParamInfo info = param.Content.DeJson<SetServersParamInfo>();
|
SetServersParamInfo info = param.Content.DeJson<SetServersParamInfo>();
|
||||||
|
|
||||||
tunnelMessengerAdapter.SetTunnelWanPortCompacts(info.List.ToList());
|
tunnelMessengerAdapter.SetTunnelWanPortProtocols(info.List.ToList());
|
||||||
if (info.Sync)
|
if (info.Sync)
|
||||||
{
|
{
|
||||||
await messengerSender.SendOnly(new MessageRequestWrap
|
await messengerSender.SendOnly(new MessageRequestWrap
|
||||||
|
@@ -38,10 +38,10 @@ namespace linker.plugins.tunnel
|
|||||||
running.Data.Tunnel.Servers = new TunnelWanPortInfo[]
|
running.Data.Tunnel.Servers = new TunnelWanPortInfo[]
|
||||||
{
|
{
|
||||||
new TunnelWanPortInfo{
|
new TunnelWanPortInfo{
|
||||||
Name="默认",
|
Name="Linker Udp",
|
||||||
Type= TunnelWanPortType.Linker,
|
Type= TunnelWanPortType.Linker,
|
||||||
Disabled = false,
|
Disabled = false,
|
||||||
Host = running.Data.Client.Servers.FirstOrDefault().Host
|
Host = running.Data.Client.Servers.FirstOrDefault().Host,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -42,14 +42,14 @@ namespace linker.plugins.tunnel
|
|||||||
|
|
||||||
//外网端口协议
|
//外网端口协议
|
||||||
serviceCollection.AddSingleton<TunnelWanPortTransfer>();
|
serviceCollection.AddSingleton<TunnelWanPortTransfer>();
|
||||||
serviceCollection.AddSingleton<TunnelWanPortLinker>();
|
serviceCollection.AddSingleton<TunnelWanPortProtocolLinkerUdp>();
|
||||||
serviceCollection.AddSingleton<TunnelWanPortStun>();
|
serviceCollection.AddSingleton<TunnelWanPortProtocolStun>();
|
||||||
|
|
||||||
//打洞协议
|
//打洞协议
|
||||||
serviceCollection.AddSingleton<TunnelTransfer>();
|
serviceCollection.AddSingleton<TunnelTransfer>();
|
||||||
serviceCollection.AddSingleton<TunnelTransportTcpNutssb>();
|
serviceCollection.AddSingleton<TunnelTransportTcpNutssb>();
|
||||||
serviceCollection.AddSingleton<TransportMsQuic>();
|
serviceCollection.AddSingleton<TransportMsQuic>();
|
||||||
serviceCollection.AddSingleton<TransportMsQuic>();
|
serviceCollection.AddSingleton<TransportTcpP2PNAT>();
|
||||||
|
|
||||||
serviceCollection.AddSingleton<TunnelConfigTransfer>();
|
serviceCollection.AddSingleton<TunnelConfigTransfer>();
|
||||||
serviceCollection.AddSingleton<ITunnelAdapter, TunnelAdapter>();
|
serviceCollection.AddSingleton<ITunnelAdapter, TunnelAdapter>();
|
||||||
@@ -77,10 +77,10 @@ namespace linker.plugins.tunnel
|
|||||||
{
|
{
|
||||||
ITunnelAdapter tunnelAdapter = serviceProvider.GetService<ITunnelAdapter>();
|
ITunnelAdapter tunnelAdapter = serviceProvider.GetService<ITunnelAdapter>();
|
||||||
|
|
||||||
IEnumerable<Type> types = ReflectionHelper.GetInterfaceSchieves(assemblies.Concat(new Assembly[] { typeof(TunnelWanPortTransfer).Assembly }).ToArray(), typeof(ITunnelWanPort));
|
IEnumerable<Type> types = ReflectionHelper.GetInterfaceSchieves(assemblies.Concat(new Assembly[] { typeof(TunnelWanPortTransfer).Assembly }).ToArray(), typeof(ITunnelWanPortProtocol));
|
||||||
List<ITunnelWanPort> compacts = types.Select(c => (ITunnelWanPort)serviceProvider.GetService(c)).Where(c => c != null).Where(c => string.IsNullOrWhiteSpace(c.Name) == false).ToList();
|
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>();
|
TunnelWanPortTransfer compack = serviceProvider.GetService<TunnelWanPortTransfer>();
|
||||||
compack.Init(tunnelAdapter,compacts);
|
compack.Init(compacts);
|
||||||
|
|
||||||
|
|
||||||
types = ReflectionHelper.GetInterfaceSchieves(assemblies.Concat(new Assembly[] { typeof(TunnelTransfer).Assembly }).ToArray(), typeof(ITunnelTransport));
|
types = ReflectionHelper.GetInterfaceSchieves(assemblies.Concat(new Assembly[] { typeof(TunnelTransfer).Assembly }).ToArray(), typeof(ITunnelTransport));
|
||||||
|
@@ -5,6 +5,8 @@ using LiteDB;
|
|||||||
using MemoryPack;
|
using MemoryPack;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using linker.tunnel.adapter;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
|
||||||
namespace linker.client.config
|
namespace linker.client.config
|
||||||
@@ -29,7 +31,7 @@ namespace linker.client.config
|
|||||||
public sealed partial class ExcludeIPItem
|
public sealed partial class ExcludeIPItem
|
||||||
{
|
{
|
||||||
[MemoryPackAllowSerialize]
|
[MemoryPackAllowSerialize]
|
||||||
public IPAddress IPAddress { get; set;}
|
public IPAddress IPAddress { get; set; }
|
||||||
public byte Mask { get; set; } = 32;
|
public byte Mask { get; set; } = 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,6 +62,60 @@ namespace linker.config
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MemoryPackable]
|
||||||
|
public readonly partial struct SerializableTunnelWanPortProtocolInfo
|
||||||
|
{
|
||||||
|
[MemoryPackIgnore]
|
||||||
|
public readonly TunnelWanPortProtocolInfo info;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
string MachineId => info.MachineId;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
TunnelWanPortType Type => info.Type;
|
||||||
|
|
||||||
|
[MemoryPackInclude]
|
||||||
|
TunnelWanPortProtocolType ProtocolType => info.ProtocolType;
|
||||||
|
|
||||||
|
[MemoryPackConstructor]
|
||||||
|
SerializableTunnelWanPortProtocolInfo(string machineId, TunnelWanPortType type, TunnelWanPortProtocolType protocolType)
|
||||||
|
{
|
||||||
|
var info = new TunnelWanPortProtocolInfo { MachineId = machineId, Type = type, ProtocolType = protocolType };
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializableTunnelWanPortProtocolInfo(TunnelWanPortProtocolInfo tunnelCompactInfo)
|
||||||
|
{
|
||||||
|
this.info = tunnelCompactInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class TunnelWanPortProtocolInfoFormatter : MemoryPackFormatter<TunnelWanPortProtocolInfo>
|
||||||
|
{
|
||||||
|
public override void Serialize<TBufferWriter>(ref MemoryPackWriter<TBufferWriter> writer, scoped ref TunnelWanPortProtocolInfo value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNullObjectHeader();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePackable(new SerializableTunnelWanPortProtocolInfo(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Deserialize(ref MemoryPackReader reader, scoped ref TunnelWanPortProtocolInfo value)
|
||||||
|
{
|
||||||
|
if (reader.PeekIsNull())
|
||||||
|
{
|
||||||
|
reader.Advance(1); // skip null block
|
||||||
|
value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrapped = reader.ReadPackable<SerializableTunnelWanPortProtocolInfo>();
|
||||||
|
value = wrapped.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MemoryPackable]
|
[MemoryPackable]
|
||||||
public readonly partial struct SerializableTunnelWanPortInfo
|
public readonly partial struct SerializableTunnelWanPortInfo
|
||||||
{
|
{
|
||||||
|
@@ -39,7 +39,8 @@ namespace linker.plugins.tunnel.messenger
|
|||||||
[MessengerId((ushort)TunnelMessengerIds.Info)]
|
[MessengerId((ushort)TunnelMessengerIds.Info)]
|
||||||
public async Task Info(IConnection connection)
|
public async Task Info(IConnection connection)
|
||||||
{
|
{
|
||||||
TunnelTransportWanPortInfo tunnelTransportPortInfo = await tunnel.GetWanPort();
|
TunnelWanPortProtocolInfo info = MemoryPackSerializer.Deserialize<TunnelWanPortProtocolInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
|
TunnelTransportWanPortInfo tunnelTransportPortInfo = await tunnel.GetWanPort(info);
|
||||||
if (tunnelTransportPortInfo != null)
|
if (tunnelTransportPortInfo != null)
|
||||||
{
|
{
|
||||||
connection.Write(MemoryPackSerializer.Serialize(tunnelTransportPortInfo));
|
connection.Write(MemoryPackSerializer.Serialize(tunnelTransportPortInfo));
|
||||||
@@ -95,7 +96,7 @@ namespace linker.plugins.tunnel.messenger
|
|||||||
public void Servers(IConnection connection)
|
public void Servers(IConnection connection)
|
||||||
{
|
{
|
||||||
TunnelWanPortInfo[] servers = MemoryPackSerializer.Deserialize<TunnelWanPortInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
|
TunnelWanPortInfo[] servers = MemoryPackSerializer.Deserialize<TunnelWanPortInfo[]>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
tunnelMessengerAdapter.SetTunnelWanPortCompacts(servers.ToList());
|
tunnelMessengerAdapter.SetTunnelWanPortProtocols(servers.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
[MessengerId((ushort)TunnelMessengerIds.ExcludeIPs)]
|
[MessengerId((ushort)TunnelMessengerIds.ExcludeIPs)]
|
||||||
@@ -119,8 +120,8 @@ namespace linker.plugins.tunnel.messenger
|
|||||||
[MessengerId((ushort)TunnelMessengerIds.InfoForward)]
|
[MessengerId((ushort)TunnelMessengerIds.InfoForward)]
|
||||||
public void InfoForward(IConnection connection)
|
public void InfoForward(IConnection connection)
|
||||||
{
|
{
|
||||||
string remoteMachineId = MemoryPackSerializer.Deserialize<string>(connection.ReceiveRequestWrap.Payload.Span);
|
TunnelWanPortProtocolInfo info = MemoryPackSerializer.Deserialize<TunnelWanPortProtocolInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||||
if (signCaching.TryGet(remoteMachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
|
if (signCaching.TryGet(info.MachineId, out SignCacheInfo cache) && signCaching.TryGet(connection.Id, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
|
||||||
{
|
{
|
||||||
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
uint requestid = connection.ReceiveRequestWrap.RequestId;
|
||||||
_ = messengerSender.SendReply(new MessageRequestWrap
|
_ = messengerSender.SendReply(new MessageRequestWrap
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using linker.libs;
|
using linker.libs;
|
||||||
using linker.libs.extends;
|
using linker.libs.extends;
|
||||||
|
using System.Buffers;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
@@ -64,6 +65,20 @@ namespace linker.server
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Memory<byte> BuildSendData(byte[] data, IPEndPoint ep)
|
||||||
|
{
|
||||||
|
//给客户端返回他的IP+端口
|
||||||
|
data[0] = (byte)ep.AddressFamily;
|
||||||
|
ep.Address.TryWriteBytes(data.AsSpan(1), out int length);
|
||||||
|
((ushort)ep.Port).ToBytes(data.AsMemory(1 + length));
|
||||||
|
|
||||||
|
//防止一些网关修改掉它的外网IP
|
||||||
|
for (int i = 0; i < 1 + length + 2; i++)
|
||||||
|
{
|
||||||
|
data[i] = (byte)(data[i] ^ byte.MaxValue);
|
||||||
|
}
|
||||||
|
return data.AsMemory(0, 1 + length + 2);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task BindUdp(int port)
|
private async Task BindUdp(int port)
|
||||||
{
|
{
|
||||||
@@ -81,18 +96,9 @@ namespace linker.server
|
|||||||
IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
|
IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//给客户端返回他的IP+端口
|
Memory<byte> memory = BuildSendData(sendData, ep);
|
||||||
sendData[0] = (byte)ep.AddressFamily;
|
|
||||||
ep.Address.TryWriteBytes(sendData.AsSpan(1), out int length);
|
|
||||||
((ushort)ep.Port).ToBytes(sendData.AsMemory(1 + length));
|
|
||||||
|
|
||||||
//防止一些网关修改掉它的外网IP
|
await socketUdp.SendToAsync(memory, ep);
|
||||||
for (int i = 0; i < 1 + length + 2; i++)
|
|
||||||
{
|
|
||||||
sendData[i] = (byte)(sendData[i] ^ byte.MaxValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
await socketUdp.SendToAsync(sendData.AsMemory(0, 1 + length + 2), ep);
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
@@ -140,15 +146,45 @@ namespace linker.server
|
|||||||
StartAccept(e);
|
StartAccept(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async Task<IConnection> BeginReceiveServer(Socket socket)
|
|
||||||
|
private async Task<byte> ReceiveType(Socket socket)
|
||||||
|
{
|
||||||
|
byte[] sendData = ArrayPool<byte>.Shared.Rent(20);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await socket.ReceiveAsync(sendData.AsMemory(0, 1), SocketFlags.None);
|
||||||
|
byte type = sendData[0];
|
||||||
|
if (type == 0)
|
||||||
|
{
|
||||||
|
Memory<byte> memory = BuildSendData(sendData, socket.RemoteEndPoint as IPEndPoint);
|
||||||
|
await socket.SendAsync(memory, SocketFlags.None);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ArrayPool<byte>.Shared.Return(sendData);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
private async Task BeginReceiveServer(Socket socket)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (socket == null || socket.RemoteEndPoint == null)
|
if (socket == null || socket.RemoteEndPoint == null)
|
||||||
{
|
{
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
socket.KeepAlive();
|
socket.KeepAlive();
|
||||||
|
|
||||||
|
if (await ReceiveType(socket) == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkStream networkStream = new NetworkStream(socket, false);
|
NetworkStream networkStream = new NetworkStream(socket, false);
|
||||||
SslStream sslStream = new SslStream(networkStream, true);
|
SslStream sslStream = new SslStream(networkStream, true);
|
||||||
await sslStream.AuthenticateAsServerAsync(serverCertificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false);
|
await sslStream.AuthenticateAsServerAsync(serverCertificate, false, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13, false);
|
||||||
@@ -156,14 +192,12 @@ namespace linker.server
|
|||||||
|
|
||||||
|
|
||||||
connection.BeginReceive(connectionReceiveCallback, null, true);
|
connection.BeginReceive(connectionReceiveCallback, null, true);
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||||
LoggerHelper.Instance.Error(ex);
|
LoggerHelper.Instance.Error(ex);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||||
@@ -179,6 +213,7 @@ namespace linker.server
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
socket.KeepAlive();
|
socket.KeepAlive();
|
||||||
|
await socket.SendAsync(new byte[] { 1 });
|
||||||
NetworkStream networkStream = new NetworkStream(socket, false);
|
NetworkStream networkStream = new NetworkStream(socket, false);
|
||||||
SslStream sslStream = new SslStream(networkStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
|
SslStream sslStream = new SslStream(networkStream, true, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
|
||||||
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
|
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
|
||||||
|
@@ -17,6 +17,7 @@ for %%r in (win-x64,win-arm64) do (
|
|||||||
echo F|xcopy "linker\\msquic.dll" "public\\extends\\%%r\\linker-%%r\\msquic.dll" /s /f /h /y
|
echo F|xcopy "linker\\msquic.dll" "public\\extends\\%%r\\linker-%%r\\msquic.dll" /s /f /h /y
|
||||||
echo F|xcopy "linker\\msquic-openssl.dll" "public\\extends\\%%r\\linker-%%r\\msquic-openssl.dll" /s /f /h /y
|
echo F|xcopy "linker\\msquic-openssl.dll" "public\\extends\\%%r\\linker-%%r\\msquic-openssl.dll" /s /f /h /y
|
||||||
)
|
)
|
||||||
|
|
||||||
for %%r in (linux-x64,linux-arm64,osx-x64,osx-arm64) do (
|
for %%r in (linux-x64,linux-arm64,osx-x64,osx-arm64) do (
|
||||||
echo F|xcopy "linker\\plugins\\tuntap\\tun2socks-%%r" "public\\extends\\%%r\\linker-%%r\\plugins\\tuntap\\tun2socks" /s /f /h /y
|
echo F|xcopy "linker\\plugins\\tuntap\\tun2socks-%%r" "public\\extends\\%%r\\linker-%%r\\plugins\\tuntap\\tun2socks" /s /f /h /y
|
||||||
)
|
)
|
||||||
@@ -24,7 +25,6 @@ for %%r in (win-x64,win-arm64) do (
|
|||||||
echo F|xcopy "linker\\plugins\\tuntap\\tun2socks-%%r" "public\\extends\\%%r\\linker-%%r\\plugins\\tuntap\\tun2socks.exe" /s /f /h /y
|
echo F|xcopy "linker\\plugins\\tuntap\\tun2socks-%%r" "public\\extends\\%%r\\linker-%%r\\plugins\\tuntap\\tun2socks.exe" /s /f /h /y
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
for %%r in (win-x64,win-arm64,linux-x64,linux-arm64,osx-x64,osx-arm64) do (
|
for %%r in (win-x64,win-arm64,linux-x64,linux-arm64,osx-x64,osx-arm64) do (
|
||||||
|
|
||||||
dotnet publish ./linker -c release -f net8.0 -o ./public/publish/%%r/linker-%%r -r %%r -p:PublishTrimmed=true -p:TrimMode=partial --self-contained true -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:PublishSingleFile=true -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true
|
dotnet publish ./linker -c release -f net8.0 -o ./public/publish/%%r/linker-%%r -r %%r -p:PublishTrimmed=true -p:TrimMode=partial --self-contained true -p:TieredPGO=true -p:DebugType=none -p:DebugSymbols=false -p:PublishSingleFile=true -p:EnableCompressionInSingleFile=true -p:DebuggerSupport=false -p:EnableUnsafeBinaryFormatterSerialization=false -p:EnableUnsafeUTF7Encoding=false -p:HttpActivityPropagationSupport=false -p:InvariantGlobalization=true -p:MetadataUpdaterSupport=false -p:UseSystemResourceKeys=true
|
||||||
@@ -33,4 +33,4 @@ for %%r in (win-x64,win-arm64,linux-x64,linux-arm64,osx-x64,osx-arm64) do (
|
|||||||
echo F|xcopy "public\\extends\\any\\*" "public\\publish\\%%r\\linker-%%r\\*" /s /f /h /y
|
echo F|xcopy "public\\extends\\any\\*" "public\\publish\\%%r\\linker-%%r\\*" /s /f /h /y
|
||||||
|
|
||||||
7z a -tzip ./public/publish-zip/linker-%%r.zip ./public/publish/%%r/*
|
7z a -tzip ./public/publish-zip/linker-%%r.zip ./public/publish/%%r/*
|
||||||
)
|
)
|
Reference in New Issue
Block a user