This commit is contained in:
snltty
2024-10-31 17:45:21 +08:00
parent b66efa010f
commit 921c34af9e
43 changed files with 581 additions and 185 deletions

View File

@@ -13,9 +13,9 @@ namespace linker.gen
{ {
private List<GeneratorInfo> generators = new List<GeneratorInfo> { private List<GeneratorInfo> generators = new List<GeneratorInfo> {
new GeneratorInfo{ ClassName="FlowTypesLoader", ClassNameSpace="linker.plugins.flow", InterfaceName="linker.plugins.flow.IFlow" }, new GeneratorInfo{ ClassName="FlowTypesLoader", ClassNameSpace="linker.plugins.flow", InterfaceName="linker.plugins.flow.IFlow" },
new GeneratorInfo{ ClassName="RelayValidatorTypeLoader", ClassNameSpace="linker.plugins.relay.validator", InterfaceName="linker.plugins.relay.validator.IRelayValidator" }, new GeneratorInfo{ ClassName="RelayTypesLoader", ClassNameSpace="linker.plugins.relay.client", InterfaceName="linker.plugins.relay.client.transport.ITransport" },
new GeneratorInfo{ ClassName="RelayValidatorTypeLoader", ClassNameSpace="linker.plugins.relay.server.validator", InterfaceName="linker.plugins.relay.server.validator.IRelayValidator" },
new GeneratorInfo{ ClassName="SignInArgsTypesLoader", ClassNameSpace="linker.plugins.signIn.args", InterfaceName="linker.plugins.signIn.args.ISignInArgs" }, new GeneratorInfo{ ClassName="SignInArgsTypesLoader", ClassNameSpace="linker.plugins.signIn.args", InterfaceName="linker.plugins.signIn.args.ISignInArgs" },
new GeneratorInfo{ ClassName="RelayTypesLoader", ClassNameSpace="linker.plugins.relay", InterfaceName="linker.plugins.relay.transport.ITransport" },
new GeneratorInfo{ ClassName="ResolverTypesLoader", ClassNameSpace="linker.plugins.resolver", InterfaceName="linker.plugins.resolver.IResolver" }, new GeneratorInfo{ ClassName="ResolverTypesLoader", ClassNameSpace="linker.plugins.resolver", InterfaceName="linker.plugins.resolver.IResolver" },
new GeneratorInfo{ ClassName="TunnelExcludeIPTypesLoader", ClassNameSpace="linker.plugins.tunnel.excludeip", InterfaceName="linker.plugins.tunnel.excludeip.ITunnelExcludeIP" }, new GeneratorInfo{ ClassName="TunnelExcludeIPTypesLoader", ClassNameSpace="linker.plugins.tunnel.excludeip", InterfaceName="linker.plugins.tunnel.excludeip.ITunnelExcludeIP" },
new GeneratorInfo{ ClassName="StartupTransfer", ClassNameSpace="linker.startup", InterfaceName="linker.startup.IStartup", Instance=true }, new GeneratorInfo{ ClassName="StartupTransfer", ClassNameSpace="linker.startup", InterfaceName="linker.startup.IStartup", Instance=true },

View File

@@ -8,6 +8,7 @@ using System.Net.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace linker.libs namespace linker.libs
{ {
@@ -38,6 +39,25 @@ namespace linker.libs
} }
return null; return null;
} }
public static async Task<IPAddress> GetDomainIpAsync(string domain)
{
try
{
if (string.IsNullOrWhiteSpace(domain))
{
return null;
}
if (IPAddress.TryParse(domain, out IPAddress ip))
{
return ip;
}
return (await Dns.GetHostEntryAsync(domain, AddressFamily.InterNetwork)).AddressList.FirstOrDefault();
}
catch (Exception)
{
}
return null;
}
public static IPEndPoint GetEndPoint(string host, int defaultPort) public static IPEndPoint GetEndPoint(string host, int defaultPort)
{ {
try try
@@ -56,6 +76,24 @@ namespace linker.libs
} }
return null; return null;
} }
public static async Task<IPEndPoint> GetEndPointAsync(string host, int defaultPort)
{
try
{
string[] hostArr = host.Split(':');
int port = defaultPort;
if (hostArr.Length == 2)
{
port = int.Parse(hostArr[1]);
}
IPAddress ip = await GetDomainIpAsync(hostArr[0]);
return new IPEndPoint(ip, port);
}
catch (Exception)
{
}
return null;
}

View File

@@ -81,6 +81,7 @@ export default {
} }
const id2text = { const id2text = {
'External':{text:'外网端口',detail:false}, 'External':{text:'外网端口',detail:false},
'RelayReport':{text:'中继节点',detail:false},
'Relay':{text:'中继',detail:hasRelayFlow.value}, 'Relay':{text:'中继',detail:hasRelayFlow.value},
'Messenger':{text:'信标',detail:hasSigninFlow.value}, 'Messenger':{text:'信标',detail:hasSigninFlow.value},
'SForward':{text:'内网穿透',detail:hasSForwardFlow.value}, 'SForward':{text:'内网穿透',detail:hasSForwardFlow.value},

View File

@@ -1,6 +1,6 @@
using linker.config; using linker.config;
using linker.libs.extends; using linker.libs.extends;
using linker.plugins.relay.validator; using linker.plugins.relay.server.validator;
using linker.plugins.sforward.config; using linker.plugins.sforward.config;
using linker.plugins.sforward.validator; using linker.plugins.sforward.validator;
using linker.plugins.signin.messenger; using linker.plugins.signin.messenger;
@@ -158,7 +158,7 @@ namespace linker.plugins.action
this.fileConfig = fileConfig; this.fileConfig = fileConfig;
} }
public async Task<string> Validate(linker.plugins.relay.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine) public async Task<string> Validate(linker.plugins.relay.client.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine)
{ {
if (string.IsNullOrWhiteSpace(fileConfig.Data.Action.RelayActionUrl) == false) if (string.IsNullOrWhiteSpace(fileConfig.Data.Action.RelayActionUrl) == false)
{ {

View File

@@ -77,7 +77,7 @@ namespace linker.plugins.client
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
LoggerHelper.Instance.Info($"connect to signin server:{config.Data.Client.ServerInfo.Host}"); LoggerHelper.Instance.Info($"connect to signin server:{config.Data.Client.ServerInfo.Host}");
IPEndPoint ip = NetworkHelper.GetEndPoint(config.Data.Client.ServerInfo.Host, 1802); IPEndPoint ip = await NetworkHelper.GetEndPointAsync(config.Data.Client.ServerInfo.Host, 1802);
if (ip == null) if (ip == null)
{ {
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)

View File

@@ -48,8 +48,8 @@ namespace linker.plugins.flow
servers.TryAdd(ep.Address, onlineFlowInfo); servers.TryAdd(ep.Address, onlineFlowInfo);
} }
onlineFlowInfo.Time = time; onlineFlowInfo.Time = time;
onlineFlowInfo.Online = memory.Slice(1, 4).ToInt32(); onlineFlowInfo.Online = memory.Slice(0, 4).ToInt32();
onlineFlowInfo.Total = memory.Slice(5, 4).ToInt32(); onlineFlowInfo.Total = memory.Slice(4, 4).ToInt32();
} }
catch (Exception) catch (Exception)
{ {

View File

@@ -2,6 +2,7 @@
using linker.plugins.flow.messenger; using linker.plugins.flow.messenger;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.relay; using linker.plugins.relay;
using linker.plugins.relay.server;
using linker.plugins.sforward.proxy; using linker.plugins.sforward.proxy;
using linker.plugins.tunnel; using linker.plugins.tunnel;
using linker.startup; using linker.startup;
@@ -24,11 +25,15 @@ namespace linker.plugins.flow
serviceCollection.AddSingleton<FlowTypesLoader>(); serviceCollection.AddSingleton<FlowTypesLoader>();
serviceCollection.AddSingleton<MessengerFlow>(); serviceCollection.AddSingleton<MessengerFlow>();
serviceCollection.AddSingleton<IMessengerResolver,MessengerResolverFlow>(); serviceCollection.AddSingleton<IMessengerResolver, MessengerResolverFlow>();
serviceCollection.AddSingleton<IMessengerSender,MessengerSenderFlow>(); serviceCollection.AddSingleton<IMessengerSender, MessengerSenderFlow>();
serviceCollection.AddSingleton<RelayFlow>(); serviceCollection.AddSingleton<RelayFlow>();
serviceCollection.AddSingleton<RelayResolver, RelayResolverFlow>(); serviceCollection.AddSingleton<RelayResolver, RelayResolverFlow>();
serviceCollection.AddSingleton<RelayReportFlow>();
serviceCollection.AddSingleton<RelayServerTransfer, RelayServerTransferFlow>();
} }
public void AddServer(ServiceCollection serviceCollection, FileConfig config) public void AddServer(ServiceCollection serviceCollection, FileConfig config)

View File

@@ -1,14 +1,48 @@
using linker.libs; using linker.config;
using linker.plugins.relay; using linker.libs;
using linker.plugins.relay.server;
using linker.plugins.relay.server.caching;
using MemoryPack; using MemoryPack;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace linker.plugins.flow namespace linker.plugins.flow
{ {
public sealed class RelayReportFlow : IFlow
{
public ulong ReceiveBytes { get; private set; }
public ulong SendtBytes { get; private set; }
public string FlowName => "RelayReport";
public RelayReportFlow()
{
}
public void AddReceive(ulong bytes) { ReceiveBytes += bytes; }
public void AddSendt(ulong bytes) { SendtBytes += bytes; }
}
public sealed class RelayServerTransferFlow : RelayServerTransfer
{
private readonly RelayReportFlow relayReportFlow;
public RelayServerTransferFlow(RelayReportFlow relayReportFlow,IRelayCaching relayCaching,FileConfig fileConfig):base(relayCaching, fileConfig)
{
this.relayReportFlow = relayReportFlow;
}
public override void AddReceive(ulong bytes) { relayReportFlow.AddReceive(bytes); }
public override void AddSendt(ulong bytes) { relayReportFlow.AddSendt(bytes); }
}
public sealed class RelayResolverFlow : RelayResolver public sealed class RelayResolverFlow : RelayResolver
{ {
private readonly RelayFlow relayFlow; private readonly RelayFlow relayFlow;
public RelayResolverFlow(RelayFlow relayFlow) public RelayResolverFlow(RelayFlow relayFlow, RelayServerTransfer relayServerTransfer) : base(relayServerTransfer)
{ {
this.relayFlow = relayFlow; this.relayFlow = relayFlow;
} }

View File

@@ -1,5 +1,4 @@
using linker.config; using linker.config;
using linker.plugins.relay;
using linker.tunnel; using linker.tunnel;
using linker.tunnel.connection; using linker.tunnel.connection;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@@ -7,6 +6,7 @@ using System.Net;
using linker.plugins.client; using linker.plugins.client;
using linker.plugins.tunnel; using linker.plugins.tunnel;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.relay.client;
namespace linker.plugins.forward.proxy namespace linker.plugins.forward.proxy
{ {

View File

@@ -1,8 +1,10 @@
using linker.config; using linker.config;
using linker.plugins.relay.caching; using linker.plugins.relay.client;
using linker.plugins.relay.client.transport;
using linker.plugins.relay.messenger; using linker.plugins.relay.messenger;
using linker.plugins.relay.transport; using linker.plugins.relay.server;
using linker.plugins.relay.validator; using linker.plugins.relay.server.caching;
using linker.plugins.relay.server.validator;
using linker.startup; using linker.startup;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -42,17 +44,19 @@ namespace linker.plugins.relay
serviceCollection.AddSingleton<RelayServerMessenger>(); serviceCollection.AddSingleton<RelayServerMessenger>();
serviceCollection.AddSingleton<RelayResolver>(); serviceCollection.AddSingleton<RelayResolver>();
serviceCollection.AddSingleton<RelayReportResolver>();
serviceCollection.AddSingleton<RelayServerTransfer>();
serviceCollection.AddSingleton<RelayValidatorTransfer>(); serviceCollection.AddSingleton<RelayValidatorTransfer>();
serviceCollection.AddSingleton<RelayValidatorTypeLoader>(); serviceCollection.AddSingleton<RelayValidatorTypeLoader>();
serviceCollection.AddSingleton<RelayValidatorSecretKey>(); serviceCollection.AddSingleton<RelayValidatorSecretKey>();
if (config.Data.Server.Relay.Caching.Name == "memory") if (config.Data.Server.Relay.Distributed.Caching.Type == "memory")
{ {
serviceCollection.AddSingleton<IRelayCaching, RelayCachingMemory>(); serviceCollection.AddSingleton<IRelayCaching, RelayCachingMemory>();
} }
else if (config.Data.Server.Relay.Caching.Name == "redis") else if (config.Data.Server.Relay.Distributed.Caching.Type == "redis")
{ {
serviceCollection.AddSingleton<IRelayCaching, RelayCachingRedis>(); serviceCollection.AddSingleton<IRelayCaching, RelayCachingRedis>();
} }
@@ -68,6 +72,8 @@ namespace linker.plugins.relay
{ {
RelayValidatorTypeLoader relayValidatorTypeLoader = serviceProvider.GetService<RelayValidatorTypeLoader>(); RelayValidatorTypeLoader relayValidatorTypeLoader = serviceProvider.GetService<RelayValidatorTypeLoader>();
IRelayCaching relayCaching = serviceProvider.GetService<IRelayCaching>(); IRelayCaching relayCaching = serviceProvider.GetService<IRelayCaching>();
RelayReportResolver relayReportResolver = serviceProvider.GetService<RelayReportResolver>();
} }
} }
} }

View File

@@ -2,7 +2,7 @@
using linker.plugins.config; using linker.plugins.config;
using MemoryPack; using MemoryPack;
namespace linker.plugins.relay namespace linker.plugins.relay.client
{ {
public sealed class ConfigSyncRelaySecretKey : IConfigSync public sealed class ConfigSyncRelaySecretKey : IConfigSync
{ {

View File

@@ -3,7 +3,7 @@ using linker.libs.api;
using linker.libs.extends; using linker.libs.extends;
using linker.plugins.capi; using linker.plugins.capi;
namespace linker.plugins.relay namespace linker.plugins.relay.client
{ {
/// <summary> /// <summary>
/// 中继管理接口 /// 中继管理接口
@@ -24,7 +24,7 @@ namespace linker.plugins.relay
/// </summary> /// </summary>
/// <param name="param"></param> /// <param name="param"></param>
/// <returns></returns> /// <returns></returns>
[ClientApiAccessAttribute(ClientApiAccess.Config)] [ClientApiAccess(ClientApiAccess.Config)]
public bool SetServers(ApiControllerParamsInfo param) public bool SetServers(ApiControllerParamsInfo param)
{ {
RelayServerInfo info = param.Content.DeJson<RelayServerInfo>(); RelayServerInfo info = param.Content.DeJson<RelayServerInfo>();

View File

@@ -1,8 +1,8 @@
using linker.config; using linker.config;
using linker.plugins.relay.transport;
using linker.libs; using linker.libs;
using linker.plugins.relay.client.transport;
namespace linker.plugins.relay namespace linker.plugins.relay.client
{ {
/// <summary> /// <summary>
/// 中继 /// 中继
@@ -56,6 +56,6 @@ namespace linker.plugins.relay
return true; return true;
}, () => lastTicksManager.DiffLessEqual(3000) ? 3000 : 30000); }, () => lastTicksManager.DiffLessEqual(3000) ? 3000 : 30000);
} }
} }
} }

View File

@@ -1,11 +1,11 @@
using linker.config; using linker.config;
using linker.plugins.relay.transport; using linker.plugins.relay.client.transport;
using linker.tunnel.connection; using linker.tunnel.connection;
using linker.libs; using linker.libs;
using linker.libs.extends; using linker.libs.extends;
using System.Collections.Concurrent; using System.Collections.Concurrent;
namespace linker.plugins.relay namespace linker.plugins.relay.client
{ {
/// <summary> /// <summary>
/// 中继 /// 中继
@@ -136,7 +136,7 @@ namespace linker.plugins.relay
ITransport _transports = Transports.FirstOrDefault(c => c.Name == relayInfo.TransportName); ITransport _transports = Transports.FirstOrDefault(c => c.Name == relayInfo.TransportName);
if (_transports == null) return false; if (_transports == null) return false;
await _transports.OnBeginAsync(relayInfo, (ITunnelConnection connection) => await _transports.OnBeginAsync(relayInfo, (connection) =>
{ {
if (connection != null) if (connection != null)
{ {

View File

@@ -1,7 +1,7 @@
using linker.libs; using linker.libs;
using linker.plugins.relay.transport; using linker.plugins.relay.client.transport;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace linker.plugins.relay namespace linker.plugins.relay.client
{ {
public sealed partial class RelayTypesLoader public sealed partial class RelayTypesLoader
{ {

View File

@@ -2,7 +2,7 @@
using MemoryPack; using MemoryPack;
using System.Net; using System.Net;
namespace linker.plugins.relay.transport namespace linker.plugins.relay.client.transport
{ {
public enum RelayType : byte public enum RelayType : byte
{ {
@@ -98,6 +98,11 @@ namespace linker.plugins.relay.transport
/// </summary> /// </summary>
public ulong FlowingId { get; set; } public ulong FlowingId { get; set; }
/// <summary>
/// 中继节点id
/// </summary>
public string NodeId { get; set; }
/// <summary> /// <summary>
/// 服务器a端选择用什么服务器就带给bb直接用不需要再做复杂的选择 /// 服务器a端选择用什么服务器就带给bb直接用不需要再做复杂的选择
/// </summary> /// </summary>

View File

@@ -12,8 +12,10 @@ using System.Security.Cryptography.X509Certificates;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.client; using linker.plugins.client;
using System.Diagnostics; using System.Diagnostics;
using System.Buffers;
using linker.plugins.relay.server;
namespace linker.plugins.relay.transport namespace linker.plugins.relay.client.transport
{ {
public sealed class TransportSelfHost : ITransport public sealed class TransportSelfHost : ITransport
{ {
@@ -41,53 +43,31 @@ namespace linker.plugins.relay.transport
public async Task<ITunnelConnection> RelayAsync(RelayInfo relayInfo) public async Task<ITunnelConnection> RelayAsync(RelayInfo relayInfo)
{ {
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try try
{ {
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap //问一下能不能中继
{ RelayAskResultInfo relayAskResultInfo = await RelayAsk(relayInfo);
Connection = clientSignInState.Connection, relayInfo.FlowingId = relayAskResultInfo.FlowingId;
MessengerId = (ushort)RelayMessengerIds.RelayAsk, if (relayInfo.FlowingId == 0 || relayAskResultInfo.Nodes.Count == 0)
Payload = MemoryPackSerializer.Serialize(relayInfo),
Timeout = 2000
}).ConfigureAwait(false);
if (resp.Code != MessageResponeCodes.OK)
{ {
return null; return null;
} }
relayInfo.FlowingId = resp.Data.Span.ToUInt64();
//RelayAskResultInfo relayAskResultInfo = MemoryPackSerializer.Deserialize<RelayAskResultInfo>(resp.Data.Span); //连接中继节点服务器
// relayInfo.FlowingId = relayAskResultInfo.FlowingId; Socket socket = await ConnectNodeServer(relayInfo, relayAskResultInfo.Nodes);
// relayInfo.Server = relayAskResultInfo.Server; if (socket == null)
if (relayInfo.FlowingId == 0)
{ {
return null; return null;
} }
// if (relayInfo.Server == null)
{
relayInfo.Server = clientSignInState.Connection.Address;
}
//连接中继服务器 //让对方确认中继
Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); if (await RelayConfirm(relayInfo) == false)
socket.KeepAlive();
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
RelayMessage relayMessage = new RelayMessage { FlowId = relayInfo.FlowingId, Type = RelayMessengerType.Ask, FromId = relayInfo.FromMachineId, ToId = relayInfo.RemoteMachineId };
await socket.SendAsync(relayMessage.ToBytes());
//通知对方,确认中继
resp = await messengerSender.SendReply(new MessageRequestWrap
{ {
Connection = clientSignInState.Connection,
MessengerId = (ushort)RelayMessengerIds.RelayForward,
Payload = MemoryPackSerializer.Serialize(relayInfo),
});
if (resp.Code != MessageResponeCodes.OK || resp.Data.Span.SequenceEqual(Helper.TrueArray) == false)
{
socket.SafeClose();
return null; return null;
} }
//成功建立连接,
SslStream sslStream = null; SslStream sslStream = null;
if (relayInfo.SSL) if (relayInfo.SSL)
{ {
@@ -122,8 +102,86 @@ namespace linker.plugins.relay.transport
LoggerHelper.Instance.Error(ex); LoggerHelper.Instance.Error(ex);
} }
} }
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
return null; return null;
} }
private async Task<RelayAskResultInfo> RelayAsk(RelayInfo relayInfo)
{
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)RelayMessengerIds.RelayAsk,
Payload = MemoryPackSerializer.Serialize(relayInfo),
Timeout = 2000
}).ConfigureAwait(false);
if (resp.Code != MessageResponeCodes.OK)
{
return new RelayAskResultInfo();
}
return MemoryPackSerializer.Deserialize<RelayAskResultInfo>(resp.Data.Span);
}
private async Task<bool> RelayConfirm(RelayInfo relayInfo)
{
//通知对方去确认中继
var resp = await messengerSender.SendReply(new MessageRequestWrap
{
Connection = clientSignInState.Connection,
MessengerId = (ushort)RelayMessengerIds.RelayForward,
Payload = MemoryPackSerializer.Serialize(relayInfo),
});
return resp.Code == MessageResponeCodes.OK && resp.Data.Span.SequenceEqual(Helper.TrueArray);
}
private async Task<Socket> ConnectNodeServer(RelayInfo relayInfo, List<RelayNodeReportInfo> nodes)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
foreach (var node in nodes)
{
//连接中继服务器
Socket socket = new Socket(node.EndPoint.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
socket.KeepAlive();
await socket.ConnectAsync(node.EndPoint).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
//是否允许连接
int length = await socket.ReceiveAsync(buffer);
if (buffer[0] != 0)
{
socket.SafeClose();
return null;
}
//建立关联
RelayMessage relayMessage = new RelayMessage { FlowId = relayInfo.FlowingId, Type = RelayMessengerType.Ask, FromId = relayInfo.FromMachineId, ToId = relayInfo.RemoteMachineId };
await socket.SendAsync(relayMessage.ToBytes());
relayInfo.Server = node.EndPoint;
relayInfo.NodeId = node.Id;
return socket;
}
}
catch (Exception ex)
{
if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
LoggerHelper.Instance.Error(ex);
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
return null;
}
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ {
return true; return true;
@@ -132,8 +190,8 @@ namespace linker.plugins.relay.transport
{ {
try try
{ {
//if (relayInfo.Server == null) if (relayInfo.Server == null)
relayInfo.Server = clientSignInState.Connection.Address; relayInfo.Server = clientSignInState.Connection.Address;
Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
socket.KeepAlive(); socket.KeepAlive();
await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false); await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);

View File

@@ -1,6 +1,7 @@
using linker.libs; using linker.libs;
using linker.plugins.relay.transport; using linker.plugins.relay.client.transport;
using MemoryPack; using MemoryPack;
using System.Net;
namespace linker.config namespace linker.config
{ {
@@ -35,14 +36,61 @@ namespace linker.config
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper(); public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
#endif #endif
public RelayCacheInfo Caching { get; set; } = new RelayCacheInfo { }; public DistributedInfo Distributed { get; set; } = new DistributedInfo { };
} }
public sealed class RelayCacheInfo
public sealed class DistributedInfo
{ {
public string Name { get; set; } = "memory"; public string Type { get; set; } = "master";
public RelayCachingInfo Caching { get; set; } = new RelayCachingInfo { };
public RelayNodeInfo Node { get; set; } = new RelayNodeInfo { };
public RelayMasterInfo Master { get; set; } = new RelayMasterInfo { };
}
public sealed class RelayMasterInfo
{
#if DEBUG
public string SecretKey { get; set; } = Helper.GlobalString;
#else
public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper();
#endif
}
public sealed class RelayNodeInfo
{
public string Id { get; set; } = Guid.NewGuid().ToString().ToUpper();
public string Name { get; set; } = "default node";
public string Host { get; set; } = string.Empty;
public string MasterHost { get; set; } = string.Empty;
public string MasterSecretKey { get; set; } = Helper.GlobalString;
public int MaxConnection { get; set; } = 100;
public int MaxBandwidth { get; set; } = 500;
public bool Public { get; set; }
}
public sealed class RelayCachingInfo
{
public string Type { get; set; } = "memory";
public string ConnectString { get; set; } = string.Empty; public string ConnectString { get; set; } = string.Empty;
} }
[MemoryPackable]
public sealed partial class RelayNodeReportInfo
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public double ConnectionRatio { get; set; }
public double BandwidthRatio { get; set; }
public bool Public { get; set; }
[MemoryPackAllowSerialize]
public IPEndPoint EndPoint { get; set; }
}
/// <summary> /// <summary>
/// 中继服务器 /// 中继服务器
/// </summary> /// </summary>

View File

@@ -1,11 +1,13 @@
using linker.config; using linker.config;
using linker.plugins.relay.transport; using linker.plugins.relay.client.transport;
using linker.plugins.signin.messenger; using linker.plugins.signin.messenger;
using linker.libs; using linker.libs;
using MemoryPack; using MemoryPack;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.relay.validator;
using System.Net; using System.Net;
using linker.plugins.relay.client;
using linker.plugins.relay.server.validator;
using linker.plugins.relay.server;
namespace linker.plugins.relay.messenger namespace linker.plugins.relay.messenger
{ {
@@ -28,7 +30,7 @@ namespace linker.plugins.relay.messenger
[MessengerId((ushort)RelayMessengerIds.Relay)] [MessengerId((ushort)RelayMessengerIds.Relay)]
public async Task Relay(IConnection connection) public async Task Relay(IConnection connection)
{ {
transport.RelayInfo info = MemoryPackSerializer.Deserialize<transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span); client.transport.RelayInfo info = MemoryPackSerializer.Deserialize<client.transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
bool res = await relayTransfer.OnBeginAsync(info).ConfigureAwait(false); bool res = await relayTransfer.OnBeginAsync(info).ConfigureAwait(false);
connection.Write(res ? Helper.TrueArray : Helper.FalseArray); connection.Write(res ? Helper.TrueArray : Helper.FalseArray);
} }
@@ -43,16 +45,16 @@ namespace linker.plugins.relay.messenger
private readonly FileConfig config; private readonly FileConfig config;
private readonly IMessengerSender messengerSender; private readonly IMessengerSender messengerSender;
private readonly SignCaching signCaching; private readonly SignCaching signCaching;
private readonly RelayResolver relayResolver; private readonly RelayServerTransfer relayServerTransfer;
private readonly RelayValidatorTransfer relayValidatorTransfer; private readonly RelayValidatorTransfer relayValidatorTransfer;
public RelayServerMessenger(FileConfig config, IMessengerSender messengerSender, SignCaching signCaching, RelayResolver relayResolver, RelayValidatorTransfer relayValidatorTransfer) public RelayServerMessenger(FileConfig config, IMessengerSender messengerSender, SignCaching signCaching, RelayServerTransfer relayServerTransfer, RelayValidatorTransfer relayValidatorTransfer)
{ {
this.config = config; this.config = config;
this.messengerSender = messengerSender; this.messengerSender = messengerSender;
this.signCaching = signCaching; this.signCaching = signCaching;
this.relayResolver = relayResolver; this.relayServerTransfer = relayServerTransfer;
this.relayValidatorTransfer = relayValidatorTransfer; this.relayValidatorTransfer = relayValidatorTransfer;
} }
@@ -69,7 +71,7 @@ namespace linker.plugins.relay.messenger
connection.Write(Helper.FalseArray); connection.Write(Helper.FalseArray);
return; return;
} }
string result = await relayValidatorTransfer.Validate(new transport.RelayInfo string result = await relayValidatorTransfer.Validate(new client.transport.RelayInfo
{ {
SecretKey = info.SecretKey, SecretKey = info.SecretKey,
FromMachineId = info.MachineId, FromMachineId = info.MachineId,
@@ -79,7 +81,7 @@ namespace linker.plugins.relay.messenger
}, cache, null); }, cache, null);
if (string.IsNullOrWhiteSpace(result) == false) if (string.IsNullOrWhiteSpace(result) == false)
{ {
connection.Write(ulong.MinValue); connection.Write(Helper.FalseArray);
return; return;
} }
@@ -94,11 +96,10 @@ namespace linker.plugins.relay.messenger
[MessengerId((ushort)RelayMessengerIds.RelayAsk)] [MessengerId((ushort)RelayMessengerIds.RelayAsk)]
public async Task RelayAsk(IConnection connection) public async Task RelayAsk(IConnection connection)
{ {
transport.RelayInfo info = MemoryPackSerializer.Deserialize<transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span); client.transport.RelayInfo info = MemoryPackSerializer.Deserialize<client.transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) == false || signCaching.TryGet(info.RemoteMachineId, out SignCacheInfo cacheTo) == false || cacheFrom.GroupId != cacheTo.GroupId) if (signCaching.TryGet(connection.Id, out SignCacheInfo cacheFrom) == false || signCaching.TryGet(info.RemoteMachineId, out SignCacheInfo cacheTo) == false || cacheFrom.GroupId != cacheTo.GroupId)
{ {
connection.Write(ulong.MinValue); connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { }));
//connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = ulong.MinValue, Server = null }));
return; return;
} }
@@ -107,17 +108,16 @@ namespace linker.plugins.relay.messenger
info.RemoteMachineName = cacheTo.MachineName; info.RemoteMachineName = cacheTo.MachineName;
info.FromMachineName = cacheFrom.MachineName; info.FromMachineName = cacheFrom.MachineName;
string result = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo); RelayAskResultInfo result = new RelayAskResultInfo();
if (string.IsNullOrWhiteSpace(result) == false) string error = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo);
result.Nodes = relayServerTransfer.GetNodes(string.IsNullOrWhiteSpace(error));
if (result.Nodes.Count > 0)
{ {
connection.Write(ulong.MinValue); result.FlowingId = await relayServerTransfer.AddRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName);
//connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = ulong.MinValue, Server = null }));
return;
} }
ulong flowingId = await relayResolver.NewRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName); connection.Write(MemoryPackSerializer.Serialize(result));
connection.Write(flowingId);
// connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = flowingId, Server = null }));
} }
/// <summary> /// <summary>
@@ -128,31 +128,37 @@ namespace linker.plugins.relay.messenger
[MessengerId((ushort)RelayMessengerIds.RelayForward)] [MessengerId((ushort)RelayMessengerIds.RelayForward)]
public async Task RelayForward(IConnection connection) public async Task RelayForward(IConnection connection)
{ {
transport.RelayInfo info = MemoryPackSerializer.Deserialize<transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span); client.transport.RelayInfo info = MemoryPackSerializer.Deserialize<client.transport.RelayInfo>(connection.ReceiveRequestWrap.Payload.Span);
if (signCaching.TryGet(info.FromMachineId, out SignCacheInfo cacheFrom) == false || signCaching.TryGet(info.RemoteMachineId, out SignCacheInfo cacheTo) == false || cacheFrom.GroupId != cacheTo.GroupId) if (signCaching.TryGet(info.FromMachineId, out SignCacheInfo cacheFrom) == false || signCaching.TryGet(info.RemoteMachineId, out SignCacheInfo cacheTo) == false || cacheFrom.GroupId != cacheTo.GroupId)
{ {
connection.Write(Helper.FalseArray); connection.Write(Helper.FalseArray);
return; return;
} }
info.RemoteMachineId = cacheTo.MachineId; //需要验证
info.FromMachineId = cacheFrom.MachineId; if (relayServerTransfer.NodeValidate(info.NodeId))
info.RemoteMachineName = cacheTo.MachineName;
info.FromMachineName = cacheFrom.MachineName;
string result = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo);
if (string.IsNullOrWhiteSpace(result) == false)
{ {
connection.Write(Helper.FalseArray); info.RemoteMachineId = cacheTo.MachineId;
return; info.FromMachineId = cacheFrom.MachineId;
info.RemoteMachineName = cacheTo.MachineName;
info.FromMachineName = cacheFrom.MachineName;
string result = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo);
if (string.IsNullOrWhiteSpace(result) == false)
{
connection.Write(Helper.FalseArray);
return;
}
}
//本服务器,让对方按信标服务器地址连
if (string.IsNullOrWhiteSpace(info.NodeId))
{
info.Server = null;
} }
info.RemoteMachineId = cacheFrom.MachineId; info.RemoteMachineId = cacheFrom.MachineId;
info.FromMachineId = cacheTo.MachineId; info.FromMachineId = cacheTo.MachineId;
info.RemoteMachineName = cacheFrom.MachineName; info.RemoteMachineName = cacheFrom.MachineName;
info.FromMachineName = cacheTo.MachineName; info.FromMachineName = cacheTo.MachineName;
info.Server = null;
try try
{ {
MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap
@@ -182,7 +188,7 @@ namespace linker.plugins.relay.messenger
public ulong FlowingId { get; set; } public ulong FlowingId { get; set; }
[MemoryPackAllowSerialize] [MemoryPackAllowSerialize]
public IPEndPoint Server { get; set; } public List<RelayNodeReportInfo> Nodes { get; set; } = new List<RelayNodeReportInfo>();
} }
} }

View File

@@ -0,0 +1,34 @@
using linker.libs;
using linker.libs.extends;
using linker.plugins.resolver;
using System.Net;
using System.Net.Sockets;
namespace linker.plugins.relay.server
{
public class RelayReportResolver : IResolver
{
public ResolverType Type => ResolverType.RelayReport;
private readonly ICrypto cryptoMaster;
private readonly ICrypto cryptoNode;
private readonly RelayServerTransfer relayServerTransfer;
public RelayReportResolver(RelayServerTransfer relayServerTransfer)
{
this.relayServerTransfer = relayServerTransfer;
}
public async Task Resolve(Socket socket, Memory<byte> memory)
{
socket.SafeClose();
await Task.CompletedTask;
}
public async Task Resolve(Socket socket, IPEndPoint ep, Memory<byte> memory)
{
relayServerTransfer.SetNodeReport(ep, memory);
await Task.CompletedTask;
}
}
}

View File

@@ -4,10 +4,10 @@ using linker.libs.extends;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using linker.plugins.resolver; using linker.plugins.resolver;
using System.Net; using System.Net;
using linker.plugins.relay.caching;
using MemoryPack; using MemoryPack;
using linker.plugins.relay.server.caching;
namespace linker.plugins.relay namespace linker.plugins.relay.server
{ {
/// <summary> /// <summary>
/// 中继连接处理 /// 中继连接处理
@@ -16,31 +16,13 @@ namespace linker.plugins.relay
{ {
public ResolverType Type => ResolverType.Relay; public ResolverType Type => ResolverType.Relay;
private readonly IRelayCaching relayCaching; private readonly RelayServerTransfer relayServerTransfer;
public RelayResolver(IRelayCaching relayCaching) public RelayResolver(RelayServerTransfer relayServerTransfer)
{ {
this.relayCaching = relayCaching; this.relayServerTransfer = relayServerTransfer;
} }
private readonly ConcurrentDictionary<ulong, RelayWrap> relayDic = new ConcurrentDictionary<ulong, RelayWrap>(); private readonly ConcurrentDictionary<ulong, RelayWrap> relayDic = new ConcurrentDictionary<ulong, RelayWrap>();
private ulong relayFlowingId = 0;
public async Task<ulong> NewRelay(string fromid, string fromName, string toid, string toName)
{
ulong flowingId = Interlocked.Increment(ref relayFlowingId);
RelayCache cache = new RelayCache
{
FlowId = flowingId,
FromId = fromid,
FromName = fromName,
ToId = toid,
ToName = toName
};
bool added = await relayCaching.TryAdd($"{fromid}->{toid}", cache, 5000);
if (added == false) return 0;
return flowingId;
}
public virtual void AddReceive(string key, string from, string to, ulong bytes) public virtual void AddReceive(string key, string from, string to, ulong bytes)
@@ -66,13 +48,22 @@ namespace linker.plugins.relay
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024); byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try try
{ {
if (relayServerTransfer.ValidateConnection() == false)
{
await socket.SendAsync(new byte[] { 1 });
socket.SafeClose();
return;
}
await socket.SendAsync(new byte[] { 0 });
int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false); int length = await socket.ReceiveAsync(buffer.AsMemory(), SocketFlags.None).ConfigureAwait(false);
RelayMessage relayMessage = RelayMessage.FromBytes(buffer.AsMemory(0, length)); RelayMessage relayMessage = RelayMessage.FromBytes(buffer.AsMemory(0, length));
//ask 是发起端来的那key就是 发起端->目标端, answer的目标和来源会交换所以转换一下 //ask 是发起端来的那key就是 发起端->目标端, answer的目标和来源会交换所以转换一下
string key = relayMessage.Type == RelayMessengerType.Ask ? $"{relayMessage.FromId}->{relayMessage.ToId}" : $"{relayMessage.ToId}->{relayMessage.FromId}"; string key = relayMessage.Type == RelayMessengerType.Ask ? $"{relayMessage.FromId}->{relayMessage.ToId}" : $"{relayMessage.ToId}->{relayMessage.FromId}";
RelayCachingValue<RelayCache> relayCacheWrap = new RelayCachingValue<RelayCache>(); RelayCachingValue<RelayCache> relayCacheWrap = new RelayCachingValue<RelayCache>();
if (await relayCaching.TryGetValue(key, relayCacheWrap) == false) if (await relayServerTransfer.TryGetRelay(key, relayCacheWrap) == false)
{ {
socket.SafeClose(); socket.SafeClose();
return; return;
@@ -84,35 +75,35 @@ namespace linker.plugins.relay
switch (relayMessage.Type) switch (relayMessage.Type)
{ {
case RelayMessengerType.Ask: case RelayMessengerType.Ask:
{
//添加本地缓存
RelayWrap relayWrap = new RelayWrap { Socket = socket, Tcs = new TaskCompletionSource<Socket>() };
relayDic.TryAdd(relayCacheWrap.Value.FlowId, relayWrap);
//等待对方连接
Socket targetSocket = await relayWrap.Tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(3000));
_ = CopyToAsync(relayCacheWrap.Value.FromId, relayCacheWrap.Value.FromName, relayCacheWrap.Value.ToName, 3, socket, targetSocket);
}
break; break;
case RelayMessengerType.Answer: case RelayMessengerType.Answer:
{
//看发起端缓存
if (relayDic.TryRemove(relayCacheWrap.Value.FlowId, out RelayWrap relayWrap) == false || relayWrap.Socket == null)
{
socket.SafeClose();
return;
}
//告诉发起端我的socket
relayWrap.Tcs.SetResult(socket);
_ = CopyToAsync(relayCacheWrap.Value.FromId, relayCacheWrap.Value.FromName, relayCacheWrap.Value.ToName, 3, socket, relayWrap.Socket);
}
break; break;
default: default:
{
socket.SafeClose();
}
break; break;
} }
//发起端
if (relayMessage.Type == RelayMessengerType.Ask)
{
//添加本地缓存
RelayWrap relayWrap = new RelayWrap { Socket = socket, Tcs = new TaskCompletionSource<Socket>() };
relayDic.TryAdd(relayCacheWrap.Value.FlowId, relayWrap);
//等待对方连接
Socket targetSocket = await relayWrap.Tcs.Task.WaitAsync(TimeSpan.FromMilliseconds(3000));
_ = CopyToAsync(relayCacheWrap.Value.FromId, relayCacheWrap.Value.FromName, relayCacheWrap.Value.ToName, 3, socket, targetSocket);
}
else if (relayMessage.Type == RelayMessengerType.Answer)
{
//看发起端缓存
if (relayDic.TryRemove(relayCacheWrap.Value.FlowId, out RelayWrap relayWrap) == false || relayWrap.Socket == null)
{
socket.SafeClose();
return;
}
//告诉发起端我的socket
relayWrap.Tcs.SetResult(socket);
_ = CopyToAsync(relayCacheWrap.Value.FromId, relayCacheWrap.Value.FromName, relayCacheWrap.Value.ToName, 3, socket, relayWrap.Socket);
}
} }
catch (Exception) catch (Exception)
{ {
@@ -136,6 +127,7 @@ namespace linker.plugins.relay
byte[] buffer = new byte[(1 << bufferSize) * 1024]; byte[] buffer = new byte[(1 << bufferSize) * 1024];
try try
{ {
relayServerTransfer.IncrementConnectionNum();
int bytesRead; int bytesRead;
while ((bytesRead = await source.ReceiveAsync(buffer.AsMemory()).ConfigureAwait(false)) != 0) while ((bytesRead = await source.ReceiveAsync(buffer.AsMemory()).ConfigureAwait(false)) != 0)
{ {
@@ -147,7 +139,12 @@ namespace linker.plugins.relay
catch (Exception) catch (Exception)
{ {
} }
finally
{
relayServerTransfer.DecrementConnectionNum();
}
} }
} }
@@ -171,7 +168,6 @@ namespace linker.plugins.relay
public TaskCompletionSource<Socket> Tcs { get; set; } public TaskCompletionSource<Socket> Tcs { get; set; }
public Socket Socket { get; set; } public Socket Socket { get; set; }
} }
public sealed class RelayMessage public sealed class RelayMessage
{ {
public RelayMessengerType Type { get; set; } public RelayMessengerType Type { get; set; }

View File

@@ -0,0 +1,167 @@
using linker.config;
using linker.libs;
using linker.libs.extends;
using linker.plugins.relay.server.caching;
using linker.plugins.resolver;
using MemoryPack;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
namespace linker.plugins.relay.server
{
public class RelayServerTransfer
{
private uint connectionNum = 0;
private ulong relayFlowingId = 0;
private readonly IRelayCaching relayCaching;
private readonly FileConfig fileConfig;
private readonly ICrypto cryptoMaster;
private readonly ICrypto cryptoNode;
private readonly ConcurrentDictionary<string, RelayNodeReportInfo> reports = new ConcurrentDictionary<string, RelayNodeReportInfo>();
public RelayServerTransfer(IRelayCaching relayCaching, FileConfig fileConfig)
{
this.relayCaching = relayCaching;
this.fileConfig = fileConfig;
if (fileConfig.Data.Server.Relay.Distributed.Type == "master" && string.IsNullOrWhiteSpace(fileConfig.Data.Server.Relay.Distributed.Master.SecretKey) == false)
{
cryptoMaster = CryptoFactory.CreateSymmetric(fileConfig.Data.Server.Relay.Distributed.Master.SecretKey);
}
if (fileConfig.Data.Server.Relay.Distributed.Type == "node" && string.IsNullOrWhiteSpace(fileConfig.Data.Server.Relay.Distributed.Node.MasterSecretKey) == false)
{
cryptoNode = CryptoFactory.CreateSymmetric(fileConfig.Data.Server.Relay.Distributed.Node.MasterSecretKey);
}
if (cryptoNode != null)
{
ReportTask();
}
}
public void IncrementConnectionNum()
{
Interlocked.Increment(ref connectionNum);
}
public void DecrementConnectionNum()
{
Interlocked.Decrement(ref connectionNum);
}
public bool ValidateConnection()
{
return fileConfig.Data.Server.Relay.Distributed.Type == "master"
|| (fileConfig.Data.Server.Relay.Distributed.Type == "node" && fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection * 2 > connectionNum);
}
public async Task<ulong> AddRelay(string fromid, string fromName, string toid, string toName)
{
ulong flowingId = Interlocked.Increment(ref relayFlowingId);
RelayCache cache = new RelayCache
{
FlowId = flowingId,
FromId = fromid,
FromName = fromName,
ToId = toid,
ToName = toName
};
bool added = await relayCaching.TryAdd($"{fromid}->{toid}", cache, 5000);
if (added == false) return 0;
return flowingId;
}
public async ValueTask<bool> TryGetRelay(string key, RelayCachingValue<RelayCache> wrap)
{
return await relayCaching.TryGetValue(key, wrap);
}
public virtual void AddReceive(ulong bytes)
{
}
public virtual void AddSendt(ulong bytes)
{
}
public void SetNodeReport(IPEndPoint ep, Memory<byte> data)
{
AddReceive((ulong)data.Length);
if (cryptoMaster == null) return;
data = cryptoMaster.Decode(data.ToArray());
RelayNodeReportInfo relayNodeReportInfo = MemoryPackSerializer.Deserialize<RelayNodeReportInfo>(data.Span);
if (relayNodeReportInfo.EndPoint.Address.Equals(IPAddress.Any))
{
relayNodeReportInfo.EndPoint.Address = ep.Address;
}
reports.AddOrUpdate(relayNodeReportInfo.Id, relayNodeReportInfo, (a, b) => relayNodeReportInfo);
}
public List<RelayNodeReportInfo> GetNodes(bool validated)
{
List<RelayNodeReportInfo> result = reports.Values.Where(c => c.Public || (c.Public == false && validated)).ToList();
if (validated)
{
result.Add(new RelayNodeReportInfo { Id = string.Empty, Name = "server", BandwidthRatio = 1, ConnectionRatio = 1, Public = false });
}
return result.OrderBy(c => c.ConnectionRatio).ToList();
}
public bool NodeValidate(string nodeId)
{
if (string.IsNullOrWhiteSpace(nodeId)) return true;
return reports.TryGetValue(nodeId, out RelayNodeReportInfo relayNodeReportInfo) && relayNodeReportInfo.Public == false;
}
private void ReportTask()
{
TimerHelper.SetInterval(async () =>
{
try
{
IPEndPoint endPoint = await NetworkHelper.GetEndPointAsync(fileConfig.Data.Server.Relay.Distributed.Node.Host, fileConfig.Data.Server.ServicePort) ?? new IPEndPoint(IPAddress.Any, fileConfig.Data.Server.ServicePort);
double connectionRatio = fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection == 0 ? 0 : connectionNum / fileConfig.Data.Server.Relay.Distributed.Node.MaxConnection;
RelayNodeReportInfo relayNodeReportInfo = new RelayNodeReportInfo
{
Id = fileConfig.Data.Server.Relay.Distributed.Node.Id,
Name = fileConfig.Data.Server.Relay.Distributed.Node.Name,
Public = fileConfig.Data.Server.Relay.Distributed.Node.Public,
BandwidthRatio = 0,
ConnectionRatio = Math.Round(connectionRatio, 2),
EndPoint = endPoint,
};
IPEndPoint ep = await NetworkHelper.GetEndPointAsync(fileConfig.Data.Server.Relay.Distributed.Node.MasterHost, 1802);
byte[] content = cryptoMaster.Encode(MemoryPackSerializer.Serialize(relayNodeReportInfo));
byte[] data = new byte[content.Length + 1];
data[0] = (byte)ResolverType.RelayReport;
content.AsMemory().CopyTo(data.AsMemory(1));
using UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork);
udpClient.Client.WindowsUdpBug();
AddSendt((ulong)data.Length);
await udpClient.SendAsync(data, ep);
}
catch (Exception)
{
}
return true;
}, () => 5000);
}
}
}

View File

@@ -1,4 +1,4 @@
namespace linker.plugins.relay.caching namespace linker.plugins.relay.server.caching
{ {
public interface IRelayCaching public interface IRelayCaching
{ {

View File

@@ -1,6 +1,6 @@
using MemoryPack; using MemoryPack;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
namespace linker.plugins.relay.caching namespace linker.plugins.relay.server.caching
{ {
public sealed class RelayCachingMemory : IRelayCaching public sealed class RelayCachingMemory : IRelayCaching
{ {

View File

@@ -2,7 +2,7 @@
using MemoryPack; using MemoryPack;
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.StackExchangeRedis; using Microsoft.Extensions.Caching.StackExchangeRedis;
namespace linker.plugins.relay.caching namespace linker.plugins.relay.server.caching
{ {
public sealed class RelayCachingRedis : IRelayCaching public sealed class RelayCachingRedis : IRelayCaching
{ {
@@ -13,7 +13,7 @@ namespace linker.plugins.relay.caching
{ {
cache = new RedisCache(new RedisCacheOptions cache = new RedisCache(new RedisCacheOptions
{ {
Configuration = fileConfig.Data.Server.Relay.Caching.ConnectString, Configuration = fileConfig.Data.Server.Relay.Distributed.Caching.ConnectString,
InstanceName = "Linker" InstanceName = "Linker"
}); });
} }

View File

@@ -1,8 +1,8 @@
using linker.config; using linker.config;
using linker.plugins.signin.messenger; using linker.plugins.signin.messenger;
using RelayInfo = linker.plugins.relay.transport.RelayInfo; using RelayInfo = linker.plugins.relay.client.transport.RelayInfo;
namespace linker.plugins.relay.validator namespace linker.plugins.relay.server.validator
{ {
public interface IRelayValidator public interface IRelayValidator
{ {
@@ -25,7 +25,7 @@ namespace linker.plugins.relay.validator
this.fileConfig = fileConfig; this.fileConfig = fileConfig;
} }
public async Task<string> Validate(linker.plugins.relay.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine) public async Task<string> Validate(RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine)
{ {
if (relayInfo.SecretKey != fileConfig.Data.Server.Relay.SecretKey) if (relayInfo.SecretKey != fileConfig.Data.Server.Relay.SecretKey)
{ {

View File

@@ -1,7 +1,7 @@
using linker.plugins.relay.transport; using linker.plugins.relay.client.transport;
using linker.plugins.signin.messenger; using linker.plugins.signin.messenger;
namespace linker.plugins.relay.validator namespace linker.plugins.relay.server.validator
{ {
public sealed partial class RelayValidatorTransfer public sealed partial class RelayValidatorTransfer
{ {

View File

@@ -1,7 +1,7 @@
using linker.libs; using linker.libs;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace linker.plugins.relay.validator namespace linker.plugins.relay.server.validator
{ {
public sealed partial class RelayValidatorTypeLoader public sealed partial class RelayValidatorTypeLoader
{ {

View File

@@ -10,7 +10,8 @@ namespace linker.plugins.resolver
Relay = 2, Relay = 2,
Socks4 = 4, Socks4 = 4,
Socks5 = 5, Socks5 = 5,
Flow = 6 Flow = 6,
RelayReport = 7,
} }
public interface IResolver public interface IResolver
{ {

View File

@@ -40,7 +40,7 @@ namespace linker.plugins.resolver
if (resolvers.TryGetValue(type, out IResolver resolver)) if (resolvers.TryGetValue(type, out IResolver resolver))
{ {
await resolver.Resolve(socket, buffer.AsMemory(0, length)); await resolver.Resolve(socket, buffer.AsMemory(1, length));
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -57,7 +57,7 @@ namespace linker.plugins.resolver
{ {
if (resolvers.TryGetValue((ResolverType)memory.Span[0], out IResolver resolver)) if (resolvers.TryGetValue((ResolverType)memory.Span[0], out IResolver resolver))
{ {
await resolver.Resolve(socket, ep, memory); await resolver.Resolve(socket, ep, memory.Slice(1));
} }
} }
} }

View File

@@ -8,7 +8,6 @@ using linker.plugins.capi;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.config; using linker.config;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using linker.plugins.tuntap.client;
namespace linker.plugins.sforward namespace linker.plugins.sforward
{ {

View File

@@ -1,5 +1,4 @@
using linker.config; using linker.config;
using linker.plugins.relay;
using linker.tunnel; using linker.tunnel;
using linker.tunnel.connection; using linker.tunnel.connection;
using linker.libs; using linker.libs;
@@ -13,6 +12,7 @@ using linker.plugins.client;
using linker.plugins.socks5.config; using linker.plugins.socks5.config;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using linker.plugins.relay.client;
namespace linker.plugins.socks5 namespace linker.plugins.socks5
{ {

View File

@@ -2,7 +2,6 @@
using linker.libs; using linker.libs;
using linker.libs.extends; using linker.libs.extends;
using linker.plugins.client; using linker.plugins.client;
using linker.plugins.relay;
using linker.plugins.resolver; using linker.plugins.resolver;
using linker.tunnel; using linker.tunnel;
using linker.tunnel.connection; using linker.tunnel.connection;
@@ -14,6 +13,7 @@ using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.tuntap.messenger; using linker.plugins.tuntap.messenger;
using linker.plugins.relay.client;
namespace linker.plugins.tunnel namespace linker.plugins.tunnel
{ {

View File

@@ -1,7 +1,7 @@
using linker.client.config; using linker.client.config;
using linker.plugins.tunnel.excludeip; using linker.plugins.tunnel.excludeip;
namespace linker.plugins.tuntap.client namespace linker.plugins.tuntap
{ {
public sealed class ExcludeIP : ITunnelExcludeIP public sealed class ExcludeIP : ITunnelExcludeIP
{ {

View File

@@ -12,7 +12,7 @@ using linker.plugins.tuntap.config;
using linker.client.config; using linker.client.config;
using linker.plugins.tuntap.lease; using linker.plugins.tuntap.lease;
namespace linker.plugins.tuntap.client namespace linker.plugins.tuntap
{ {
public sealed class TuntapClientApiController : IApiClientController public sealed class TuntapClientApiController : IApiClientController
{ {

View File

@@ -12,7 +12,7 @@ using linker.tun;
using linker.plugins.tuntap.lease; using linker.plugins.tuntap.lease;
using linker.plugins.decenter; using linker.plugins.decenter;
namespace linker.plugins.tuntap.client namespace linker.plugins.tuntap
{ {
public sealed class TuntapConfigTransfer : IDecenter public sealed class TuntapConfigTransfer : IDecenter
{ {
@@ -92,8 +92,8 @@ namespace linker.plugins.tuntap.client
await LeaseIP(); await LeaseIP();
bool needReboot = ((oldIP.Equals(runningConfig.Data.Tuntap.IP) == false || prefixLength != runningConfig.Data.Tuntap.PrefixLength) && runningConfig.Data.Tuntap.Running) bool needReboot = (oldIP.Equals(runningConfig.Data.Tuntap.IP) == false || prefixLength != runningConfig.Data.Tuntap.PrefixLength) && runningConfig.Data.Tuntap.Running
|| (runningConfig.Data.Tuntap.Running && tuntapTransfer.Status != TuntapStatus.Running); || runningConfig.Data.Tuntap.Running && tuntapTransfer.Status != TuntapStatus.Running;
if (needReboot) if (needReboot)
{ {
@@ -216,8 +216,8 @@ namespace linker.plugins.tuntap.client
await Task.Delay(1000); await Task.Delay(1000);
} }
bool run = ((oldIP.Equals(runningConfig.Data.Tuntap.IP) == false || prefixLength != runningConfig.Data.Tuntap.PrefixLength) && runningConfig.Data.Tuntap.Running) bool run = (oldIP.Equals(runningConfig.Data.Tuntap.IP) == false || prefixLength != runningConfig.Data.Tuntap.PrefixLength) && runningConfig.Data.Tuntap.Running
|| (runningConfig.Data.Tuntap.Running && tuntapTransfer.Status != TuntapStatus.Running); || runningConfig.Data.Tuntap.Running && tuntapTransfer.Status != TuntapStatus.Running;
if (run) if (run)
{ {

View File

@@ -4,7 +4,7 @@ using linker.plugins.tuntap.config;
using linker.tun; using linker.tun;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
namespace linker.plugins.tuntap.client namespace linker.plugins.tuntap
{ {
public sealed class TuntapDeviceStatusTransfer public sealed class TuntapDeviceStatusTransfer
{ {

View File

@@ -6,7 +6,7 @@ using System.Net.NetworkInformation;
using System.Net; using System.Net;
using linker.config; using linker.config;
namespace linker.plugins.tuntap.client namespace linker.plugins.tuntap
{ {
public sealed class TuntapPingTransfer public sealed class TuntapPingTransfer
{ {

View File

@@ -1,5 +1,4 @@
using linker.config; using linker.config;
using linker.plugins.relay;
using linker.tunnel; using linker.tunnel;
using linker.tunnel.connection; using linker.tunnel.connection;
using linker.libs; using linker.libs;
@@ -11,8 +10,9 @@ using linker.plugins.client;
using linker.plugins.tunnel; using linker.plugins.tunnel;
using System.Buffers; using System.Buffers;
using linker.client.config; using linker.client.config;
using linker.plugins.relay.client;
namespace linker.plugins.tuntap.client namespace linker.plugins.tuntap
{ {
public sealed class TuntapProxy : TunnelBase, ILinkerTunDeviceCallback, ITunnelConnectionReceiveCallback public sealed class TuntapProxy : TunnelBase, ILinkerTunDeviceCallback, ITunnelConnectionReceiveCallback
{ {

View File

@@ -1,5 +1,4 @@
using linker.config; using linker.config;
using linker.plugins.tuntap.client;
using linker.plugins.tuntap.lease; using linker.plugins.tuntap.lease;
using linker.plugins.tuntap.messenger; using linker.plugins.tuntap.messenger;
using linker.startup; using linker.startup;

View File

@@ -5,7 +5,7 @@ using linker.plugins.client;
using linker.plugins.tuntap.config; using linker.plugins.tuntap.config;
using linker.tun; using linker.tun;
namespace linker.plugins.tuntap.client namespace linker.plugins.tuntap
{ {
public sealed class TuntapTransfer public sealed class TuntapTransfer
{ {
@@ -33,11 +33,11 @@ namespace linker.plugins.tuntap.client
AppDomain.CurrentDomain.ProcessExit += (s, e) => linkerTunDeviceAdapter.Shutdown(); AppDomain.CurrentDomain.ProcessExit += (s, e) => linkerTunDeviceAdapter.Shutdown();
Console.CancelKeyPress += (s, e) => linkerTunDeviceAdapter.Shutdown(); Console.CancelKeyPress += (s, e) => linkerTunDeviceAdapter.Shutdown();
} }
/// <summary> /// <summary>
/// 运行网卡 /// 运行网卡
/// </summary> /// </summary>
public void Setup(IPAddress ip,byte prefixLength) public void Setup(IPAddress ip, byte prefixLength)
{ {
if (operatingManager.StartOperation() == false) if (operatingManager.StartOperation() == false)
{ {

View File

@@ -2,7 +2,6 @@
using linker.libs; using linker.libs;
using linker.plugins.messenger; using linker.plugins.messenger;
using linker.plugins.signin.messenger; using linker.plugins.signin.messenger;
using linker.plugins.tuntap.client;
using linker.plugins.tuntap.config; using linker.plugins.tuntap.config;
using linker.plugins.tuntap.lease; using linker.plugins.tuntap.lease;
using MemoryPack; using MemoryPack;

View File

@@ -1,5 +1,5 @@
v1.5.1 v1.5.1
2024-10-30 18:01:05 2024-10-31 17:45:20
1. 优化点对网和网对网的局域网IP包括禁用IP和冲突检测 1. 优化点对网和网对网的局域网IP包括禁用IP和冲突检测
2. 一些UI优化 2. 一些UI优化
3. 新增socks5代理 3. 新增socks5代理