diff --git a/linker.gen/InterfaceSourceGenerator.cs b/linker.gen/InterfaceSourceGenerator.cs index 80e74e6b..3c134606 100644 --- a/linker.gen/InterfaceSourceGenerator.cs +++ b/linker.gen/InterfaceSourceGenerator.cs @@ -13,9 +13,9 @@ namespace linker.gen { private List generators = new List { 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="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="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 }, diff --git a/linker.libs/NetworkHelper.cs b/linker.libs/NetworkHelper.cs index c3174f73..c1d70494 100644 --- a/linker.libs/NetworkHelper.cs +++ b/linker.libs/NetworkHelper.cs @@ -8,6 +8,7 @@ using System.Net.NetworkInformation; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; +using System.Threading.Tasks; namespace linker.libs { @@ -38,6 +39,25 @@ namespace linker.libs } return null; } + public static async Task 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) { try @@ -56,6 +76,24 @@ namespace linker.libs } return null; } + public static async Task 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; + } diff --git a/linker.web/src/views/full/status/server/ServerFlow.vue b/linker.web/src/views/full/status/server/ServerFlow.vue index c5ada169..2584c95b 100644 --- a/linker.web/src/views/full/status/server/ServerFlow.vue +++ b/linker.web/src/views/full/status/server/ServerFlow.vue @@ -81,6 +81,7 @@ export default { } const id2text = { 'External':{text:'外网端口',detail:false}, + 'RelayReport':{text:'中继节点',detail:false}, 'Relay':{text:'中继',detail:hasRelayFlow.value}, 'Messenger':{text:'信标',detail:hasSigninFlow.value}, 'SForward':{text:'内网穿透',detail:hasSForwardFlow.value}, diff --git a/linker/plugins/action/SignInArgsAction.cs b/linker/plugins/action/SignInArgsAction.cs index b04c3e9a..b03ef1a7 100644 --- a/linker/plugins/action/SignInArgsAction.cs +++ b/linker/plugins/action/SignInArgsAction.cs @@ -1,6 +1,6 @@ using linker.config; using linker.libs.extends; -using linker.plugins.relay.validator; +using linker.plugins.relay.server.validator; using linker.plugins.sforward.config; using linker.plugins.sforward.validator; using linker.plugins.signin.messenger; @@ -158,7 +158,7 @@ namespace linker.plugins.action this.fileConfig = fileConfig; } - public async Task Validate(linker.plugins.relay.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine) + public async Task Validate(linker.plugins.relay.client.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine) { if (string.IsNullOrWhiteSpace(fileConfig.Data.Action.RelayActionUrl) == false) { diff --git a/linker/plugins/client/ClientSignInTransfer.cs b/linker/plugins/client/ClientSignInTransfer.cs index 29e4b53c..cfdcfc51 100644 --- a/linker/plugins/client/ClientSignInTransfer.cs +++ b/linker/plugins/client/ClientSignInTransfer.cs @@ -77,7 +77,7 @@ namespace linker.plugins.client if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) 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 (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) diff --git a/linker/plugins/flow/FlowResolver.cs b/linker/plugins/flow/FlowResolver.cs index 0e4eb80a..591afb58 100644 --- a/linker/plugins/flow/FlowResolver.cs +++ b/linker/plugins/flow/FlowResolver.cs @@ -48,8 +48,8 @@ namespace linker.plugins.flow servers.TryAdd(ep.Address, onlineFlowInfo); } onlineFlowInfo.Time = time; - onlineFlowInfo.Online = memory.Slice(1, 4).ToInt32(); - onlineFlowInfo.Total = memory.Slice(5, 4).ToInt32(); + onlineFlowInfo.Online = memory.Slice(0, 4).ToInt32(); + onlineFlowInfo.Total = memory.Slice(4, 4).ToInt32(); } catch (Exception) { diff --git a/linker/plugins/flow/FlowStartup.cs b/linker/plugins/flow/FlowStartup.cs index 15bc741f..8cbb2028 100644 --- a/linker/plugins/flow/FlowStartup.cs +++ b/linker/plugins/flow/FlowStartup.cs @@ -2,6 +2,7 @@ using linker.plugins.flow.messenger; using linker.plugins.messenger; using linker.plugins.relay; +using linker.plugins.relay.server; using linker.plugins.sforward.proxy; using linker.plugins.tunnel; using linker.startup; @@ -24,11 +25,15 @@ namespace linker.plugins.flow serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + } public void AddServer(ServiceCollection serviceCollection, FileConfig config) diff --git a/linker/plugins/flow/RelayFlow.cs b/linker/plugins/flow/RelayFlow.cs index 133d6307..33e42808 100644 --- a/linker/plugins/flow/RelayFlow.cs +++ b/linker/plugins/flow/RelayFlow.cs @@ -1,14 +1,48 @@ -using linker.libs; -using linker.plugins.relay; +using linker.config; +using linker.libs; +using linker.plugins.relay.server; +using linker.plugins.relay.server.caching; using MemoryPack; using System.Text.Json.Serialization; 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 { private readonly RelayFlow relayFlow; - public RelayResolverFlow(RelayFlow relayFlow) + public RelayResolverFlow(RelayFlow relayFlow, RelayServerTransfer relayServerTransfer) : base(relayServerTransfer) { this.relayFlow = relayFlow; } diff --git a/linker/plugins/forward/proxy/ForwardProxyTunnel.cs b/linker/plugins/forward/proxy/ForwardProxyTunnel.cs index da4b48b8..4b38ea69 100644 --- a/linker/plugins/forward/proxy/ForwardProxyTunnel.cs +++ b/linker/plugins/forward/proxy/ForwardProxyTunnel.cs @@ -1,5 +1,4 @@ using linker.config; -using linker.plugins.relay; using linker.tunnel; using linker.tunnel.connection; using System.Collections.Concurrent; @@ -7,6 +6,7 @@ using System.Net; using linker.plugins.client; using linker.plugins.tunnel; using linker.plugins.messenger; +using linker.plugins.relay.client; namespace linker.plugins.forward.proxy { diff --git a/linker/plugins/relay/RelayStartup.cs b/linker/plugins/relay/RelayStartup.cs index 4cdc5484..595faad7 100644 --- a/linker/plugins/relay/RelayStartup.cs +++ b/linker/plugins/relay/RelayStartup.cs @@ -1,8 +1,10 @@ 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.transport; -using linker.plugins.relay.validator; +using linker.plugins.relay.server; +using linker.plugins.relay.server.caching; +using linker.plugins.relay.server.validator; using linker.startup; using Microsoft.Extensions.DependencyInjection; @@ -42,17 +44,19 @@ namespace linker.plugins.relay serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - if (config.Data.Server.Relay.Caching.Name == "memory") + if (config.Data.Server.Relay.Distributed.Caching.Type == "memory") { serviceCollection.AddSingleton(); } - else if (config.Data.Server.Relay.Caching.Name == "redis") + else if (config.Data.Server.Relay.Distributed.Caching.Type == "redis") { serviceCollection.AddSingleton(); } @@ -68,6 +72,8 @@ namespace linker.plugins.relay { RelayValidatorTypeLoader relayValidatorTypeLoader = serviceProvider.GetService(); IRelayCaching relayCaching = serviceProvider.GetService(); + + RelayReportResolver relayReportResolver = serviceProvider.GetService(); } } } diff --git a/linker/plugins/relay/ConfigSyncRelaySecretKey.cs b/linker/plugins/relay/client/ConfigSyncRelaySecretKey.cs similarity index 95% rename from linker/plugins/relay/ConfigSyncRelaySecretKey.cs rename to linker/plugins/relay/client/ConfigSyncRelaySecretKey.cs index 59d967c6..67b4f8c6 100644 --- a/linker/plugins/relay/ConfigSyncRelaySecretKey.cs +++ b/linker/plugins/relay/client/ConfigSyncRelaySecretKey.cs @@ -2,7 +2,7 @@ using linker.plugins.config; using MemoryPack; -namespace linker.plugins.relay +namespace linker.plugins.relay.client { public sealed class ConfigSyncRelaySecretKey : IConfigSync { diff --git a/linker/plugins/relay/RelayApiController.cs b/linker/plugins/relay/client/RelayApiController.cs similarity index 92% rename from linker/plugins/relay/RelayApiController.cs rename to linker/plugins/relay/client/RelayApiController.cs index fefc9d68..acf5556d 100644 --- a/linker/plugins/relay/RelayApiController.cs +++ b/linker/plugins/relay/client/RelayApiController.cs @@ -3,7 +3,7 @@ using linker.libs.api; using linker.libs.extends; using linker.plugins.capi; -namespace linker.plugins.relay +namespace linker.plugins.relay.client { /// /// 中继管理接口 @@ -24,7 +24,7 @@ namespace linker.plugins.relay /// /// /// - [ClientApiAccessAttribute(ClientApiAccess.Config)] + [ClientApiAccess(ClientApiAccess.Config)] public bool SetServers(ApiControllerParamsInfo param) { RelayServerInfo info = param.Content.DeJson(); diff --git a/linker/plugins/relay/RelayTestTransfer.cs b/linker/plugins/relay/client/RelayTestTransfer.cs similarity index 95% rename from linker/plugins/relay/RelayTestTransfer.cs rename to linker/plugins/relay/client/RelayTestTransfer.cs index f8b5f8f9..66b866f5 100644 --- a/linker/plugins/relay/RelayTestTransfer.cs +++ b/linker/plugins/relay/client/RelayTestTransfer.cs @@ -1,8 +1,8 @@ using linker.config; -using linker.plugins.relay.transport; using linker.libs; +using linker.plugins.relay.client.transport; -namespace linker.plugins.relay +namespace linker.plugins.relay.client { /// /// 中继 @@ -56,6 +56,6 @@ namespace linker.plugins.relay return true; }, () => lastTicksManager.DiffLessEqual(3000) ? 3000 : 30000); } - + } } \ No newline at end of file diff --git a/linker/plugins/relay/RelayTransfer.cs b/linker/plugins/relay/client/RelayTransfer.cs similarity index 97% rename from linker/plugins/relay/RelayTransfer.cs rename to linker/plugins/relay/client/RelayTransfer.cs index 05356a5a..328cd116 100644 --- a/linker/plugins/relay/RelayTransfer.cs +++ b/linker/plugins/relay/client/RelayTransfer.cs @@ -1,11 +1,11 @@ using linker.config; -using linker.plugins.relay.transport; +using linker.plugins.relay.client.transport; using linker.tunnel.connection; using linker.libs; using linker.libs.extends; using System.Collections.Concurrent; -namespace linker.plugins.relay +namespace linker.plugins.relay.client { /// /// 中继 @@ -136,7 +136,7 @@ namespace linker.plugins.relay ITransport _transports = Transports.FirstOrDefault(c => c.Name == relayInfo.TransportName); if (_transports == null) return false; - await _transports.OnBeginAsync(relayInfo, (ITunnelConnection connection) => + await _transports.OnBeginAsync(relayInfo, (connection) => { if (connection != null) { diff --git a/linker/plugins/relay/RelayTypesLoader.cs b/linker/plugins/relay/client/RelayTypesLoader.cs similarity index 87% rename from linker/plugins/relay/RelayTypesLoader.cs rename to linker/plugins/relay/client/RelayTypesLoader.cs index 12b601b3..894e3a58 100644 --- a/linker/plugins/relay/RelayTypesLoader.cs +++ b/linker/plugins/relay/client/RelayTypesLoader.cs @@ -1,7 +1,7 @@ using linker.libs; -using linker.plugins.relay.transport; +using linker.plugins.relay.client.transport; using Microsoft.Extensions.DependencyInjection; -namespace linker.plugins.relay +namespace linker.plugins.relay.client { public sealed partial class RelayTypesLoader { diff --git a/linker/plugins/relay/transport/ITransport.cs b/linker/plugins/relay/client/transport/ITransport.cs similarity index 94% rename from linker/plugins/relay/transport/ITransport.cs rename to linker/plugins/relay/client/transport/ITransport.cs index 261c513d..4d985e7a 100644 --- a/linker/plugins/relay/transport/ITransport.cs +++ b/linker/plugins/relay/client/transport/ITransport.cs @@ -2,7 +2,7 @@ using MemoryPack; using System.Net; -namespace linker.plugins.relay.transport +namespace linker.plugins.relay.client.transport { public enum RelayType : byte { @@ -98,6 +98,11 @@ namespace linker.plugins.relay.transport /// public ulong FlowingId { get; set; } + /// + /// 中继节点id + /// + public string NodeId { get; set; } + /// /// 服务器,a端选择用什么服务器,就带给b,b直接用,不需要再做复杂的选择 /// diff --git a/linker/plugins/relay/transport/TransportSelfHost.cs b/linker/plugins/relay/client/transport/TransportSelfHost.cs similarity index 66% rename from linker/plugins/relay/transport/TransportSelfHost.cs rename to linker/plugins/relay/client/transport/TransportSelfHost.cs index f77a0107..f8a0000a 100644 --- a/linker/plugins/relay/transport/TransportSelfHost.cs +++ b/linker/plugins/relay/client/transport/TransportSelfHost.cs @@ -12,8 +12,10 @@ using System.Security.Cryptography.X509Certificates; using linker.plugins.messenger; using linker.plugins.client; 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 { @@ -41,53 +43,31 @@ namespace linker.plugins.relay.transport public async Task RelayAsync(RelayInfo relayInfo) { + byte[] buffer = ArrayPool.Shared.Rent(1024); try { - 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) + //问一下能不能中继 + RelayAskResultInfo relayAskResultInfo = await RelayAsk(relayInfo); + relayInfo.FlowingId = relayAskResultInfo.FlowingId; + if (relayInfo.FlowingId == 0 || relayAskResultInfo.Nodes.Count == 0) { return null; } - relayInfo.FlowingId = resp.Data.Span.ToUInt64(); - //RelayAskResultInfo relayAskResultInfo = MemoryPackSerializer.Deserialize(resp.Data.Span); - // relayInfo.FlowingId = relayAskResultInfo.FlowingId; - // relayInfo.Server = relayAskResultInfo.Server; - if (relayInfo.FlowingId == 0) + + //连接中继节点服务器 + Socket socket = await ConnectNodeServer(relayInfo, relayAskResultInfo.Nodes); + if (socket == 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); - 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 + //让对方确认中继 + if (await RelayConfirm(relayInfo) == false) { - 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; } + //成功建立连接, SslStream sslStream = null; if (relayInfo.SSL) { @@ -122,8 +102,86 @@ namespace linker.plugins.relay.transport LoggerHelper.Instance.Error(ex); } } + finally + { + ArrayPool.Shared.Return(buffer); + } return null; } + + private async Task 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(resp.Data.Span); + } + private async Task 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 ConnectNodeServer(RelayInfo relayInfo, List nodes) + { + byte[] buffer = ArrayPool.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.Shared.Return(buffer); + } + return null; + } + + private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; @@ -132,8 +190,8 @@ namespace linker.plugins.relay.transport { try { - //if (relayInfo.Server == null) - relayInfo.Server = clientSignInState.Connection.Address; + if (relayInfo.Server == null) + relayInfo.Server = clientSignInState.Connection.Address; Socket socket = new Socket(relayInfo.Server.AddressFamily, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); socket.KeepAlive(); await socket.ConnectAsync(relayInfo.Server).WaitAsync(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false); diff --git a/linker/plugins/relay/config/Config.cs b/linker/plugins/relay/config/Config.cs index 34582497..c0fc0141 100644 --- a/linker/plugins/relay/config/Config.cs +++ b/linker/plugins/relay/config/Config.cs @@ -1,6 +1,7 @@ using linker.libs; -using linker.plugins.relay.transport; +using linker.plugins.relay.client.transport; using MemoryPack; +using System.Net; namespace linker.config { @@ -35,14 +36,61 @@ namespace linker.config public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper(); #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; } + + [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; } + } + + /// /// 中继服务器 /// diff --git a/linker/plugins/relay/messenger/RelayMessenger.cs b/linker/plugins/relay/messenger/RelayMessenger.cs index 47872d02..2a1b60db 100644 --- a/linker/plugins/relay/messenger/RelayMessenger.cs +++ b/linker/plugins/relay/messenger/RelayMessenger.cs @@ -1,11 +1,13 @@ using linker.config; -using linker.plugins.relay.transport; +using linker.plugins.relay.client.transport; using linker.plugins.signin.messenger; using linker.libs; using MemoryPack; using linker.plugins.messenger; -using linker.plugins.relay.validator; using System.Net; +using linker.plugins.relay.client; +using linker.plugins.relay.server.validator; +using linker.plugins.relay.server; namespace linker.plugins.relay.messenger { @@ -28,7 +30,7 @@ namespace linker.plugins.relay.messenger [MessengerId((ushort)RelayMessengerIds.Relay)] public async Task Relay(IConnection connection) { - transport.RelayInfo info = MemoryPackSerializer.Deserialize(connection.ReceiveRequestWrap.Payload.Span); + client.transport.RelayInfo info = MemoryPackSerializer.Deserialize(connection.ReceiveRequestWrap.Payload.Span); bool res = await relayTransfer.OnBeginAsync(info).ConfigureAwait(false); connection.Write(res ? Helper.TrueArray : Helper.FalseArray); } @@ -43,16 +45,16 @@ namespace linker.plugins.relay.messenger private readonly FileConfig config; private readonly IMessengerSender messengerSender; private readonly SignCaching signCaching; - private readonly RelayResolver relayResolver; + private readonly RelayServerTransfer relayServerTransfer; 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.messengerSender = messengerSender; this.signCaching = signCaching; - this.relayResolver = relayResolver; + this.relayServerTransfer = relayServerTransfer; this.relayValidatorTransfer = relayValidatorTransfer; } @@ -69,7 +71,7 @@ namespace linker.plugins.relay.messenger connection.Write(Helper.FalseArray); return; } - string result = await relayValidatorTransfer.Validate(new transport.RelayInfo + string result = await relayValidatorTransfer.Validate(new client.transport.RelayInfo { SecretKey = info.SecretKey, FromMachineId = info.MachineId, @@ -79,7 +81,7 @@ namespace linker.plugins.relay.messenger }, cache, null); if (string.IsNullOrWhiteSpace(result) == false) { - connection.Write(ulong.MinValue); + connection.Write(Helper.FalseArray); return; } @@ -94,11 +96,10 @@ namespace linker.plugins.relay.messenger [MessengerId((ushort)RelayMessengerIds.RelayAsk)] public async Task RelayAsk(IConnection connection) { - transport.RelayInfo info = MemoryPackSerializer.Deserialize(connection.ReceiveRequestWrap.Payload.Span); + client.transport.RelayInfo info = MemoryPackSerializer.Deserialize(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) { - connection.Write(ulong.MinValue); - //connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = ulong.MinValue, Server = null })); + connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { })); return; } @@ -107,17 +108,16 @@ namespace linker.plugins.relay.messenger info.RemoteMachineName = cacheTo.MachineName; info.FromMachineName = cacheFrom.MachineName; - string result = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo); - if (string.IsNullOrWhiteSpace(result) == false) + RelayAskResultInfo result = new RelayAskResultInfo(); + string error = await relayValidatorTransfer.Validate(info, cacheFrom, cacheTo); + result.Nodes = relayServerTransfer.GetNodes(string.IsNullOrWhiteSpace(error)); + + if (result.Nodes.Count > 0) { - connection.Write(ulong.MinValue); - //connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = ulong.MinValue, Server = null })); - return; + result.FlowingId = await relayServerTransfer.AddRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName); } - ulong flowingId = await relayResolver.NewRelay(cacheFrom.MachineId, cacheFrom.MachineName, cacheTo.MachineId, cacheTo.MachineName); - connection.Write(flowingId); - // connection.Write(MemoryPackSerializer.Serialize(new RelayAskResultInfo { FlowingId = flowingId, Server = null })); + connection.Write(MemoryPackSerializer.Serialize(result)); } /// @@ -128,31 +128,37 @@ namespace linker.plugins.relay.messenger [MessengerId((ushort)RelayMessengerIds.RelayForward)] public async Task RelayForward(IConnection connection) { - transport.RelayInfo info = MemoryPackSerializer.Deserialize(connection.ReceiveRequestWrap.Payload.Span); + client.transport.RelayInfo info = MemoryPackSerializer.Deserialize(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) { connection.Write(Helper.FalseArray); return; - } + } - info.RemoteMachineId = cacheTo.MachineId; - 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) + //需要验证 + if (relayServerTransfer.NodeValidate(info.NodeId)) { - connection.Write(Helper.FalseArray); - return; + info.RemoteMachineId = cacheTo.MachineId; + 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.FromMachineId = cacheTo.MachineId; info.RemoteMachineName = cacheFrom.MachineName; info.FromMachineName = cacheTo.MachineName; - - info.Server = null; try { MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap @@ -182,7 +188,7 @@ namespace linker.plugins.relay.messenger public ulong FlowingId { get; set; } [MemoryPackAllowSerialize] - public IPEndPoint Server { get; set; } + public List Nodes { get; set; } = new List(); } } diff --git a/linker/plugins/relay/server/RelayReportResolver.cs b/linker/plugins/relay/server/RelayReportResolver.cs new file mode 100644 index 00000000..9b4220c7 --- /dev/null +++ b/linker/plugins/relay/server/RelayReportResolver.cs @@ -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 memory) + { + socket.SafeClose(); + await Task.CompletedTask; + } + + public async Task Resolve(Socket socket, IPEndPoint ep, Memory memory) + { + relayServerTransfer.SetNodeReport(ep, memory); + await Task.CompletedTask; + } + } +} diff --git a/linker/plugins/relay/RelayResolver.cs b/linker/plugins/relay/server/RelayResolver.cs similarity index 72% rename from linker/plugins/relay/RelayResolver.cs rename to linker/plugins/relay/server/RelayResolver.cs index cb4c2ad4..8a2d01a9 100644 --- a/linker/plugins/relay/RelayResolver.cs +++ b/linker/plugins/relay/server/RelayResolver.cs @@ -4,10 +4,10 @@ using linker.libs.extends; using System.Collections.Concurrent; using linker.plugins.resolver; using System.Net; -using linker.plugins.relay.caching; using MemoryPack; +using linker.plugins.relay.server.caching; -namespace linker.plugins.relay +namespace linker.plugins.relay.server { /// /// 中继连接处理 @@ -16,31 +16,13 @@ namespace linker.plugins.relay { public ResolverType Type => ResolverType.Relay; - private readonly IRelayCaching relayCaching; - public RelayResolver(IRelayCaching relayCaching) + private readonly RelayServerTransfer relayServerTransfer; + public RelayResolver(RelayServerTransfer relayServerTransfer) { - this.relayCaching = relayCaching; + this.relayServerTransfer = relayServerTransfer; } private readonly ConcurrentDictionary relayDic = new ConcurrentDictionary(); - private ulong relayFlowingId = 0; - public async Task 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) @@ -66,13 +48,22 @@ namespace linker.plugins.relay byte[] buffer = ArrayPool.Shared.Rent(1024); 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); RelayMessage relayMessage = RelayMessage.FromBytes(buffer.AsMemory(0, length)); //ask 是发起端来的,那key就是 发起端->目标端, answer的,目标和来源会交换,所以转换一下 string key = relayMessage.Type == RelayMessengerType.Ask ? $"{relayMessage.FromId}->{relayMessage.ToId}" : $"{relayMessage.ToId}->{relayMessage.FromId}"; RelayCachingValue relayCacheWrap = new RelayCachingValue(); - if (await relayCaching.TryGetValue(key, relayCacheWrap) == false) + if (await relayServerTransfer.TryGetRelay(key, relayCacheWrap) == false) { socket.SafeClose(); return; @@ -84,35 +75,35 @@ namespace linker.plugins.relay switch (relayMessage.Type) { case RelayMessengerType.Ask: + { + //添加本地缓存 + RelayWrap relayWrap = new RelayWrap { Socket = socket, Tcs = new TaskCompletionSource() }; + 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; 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; default: + { + socket.SafeClose(); + } break; } - //发起端 - if (relayMessage.Type == RelayMessengerType.Ask) - { - //添加本地缓存 - RelayWrap relayWrap = new RelayWrap { Socket = socket, Tcs = new TaskCompletionSource() }; - 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) { @@ -136,6 +127,7 @@ namespace linker.plugins.relay byte[] buffer = new byte[(1 << bufferSize) * 1024]; try { + relayServerTransfer.IncrementConnectionNum(); int bytesRead; while ((bytesRead = await source.ReceiveAsync(buffer.AsMemory()).ConfigureAwait(false)) != 0) { @@ -147,7 +139,12 @@ namespace linker.plugins.relay catch (Exception) { } + finally + { + relayServerTransfer.DecrementConnectionNum(); + } } + } @@ -171,7 +168,6 @@ namespace linker.plugins.relay public TaskCompletionSource Tcs { get; set; } public Socket Socket { get; set; } } - public sealed class RelayMessage { public RelayMessengerType Type { get; set; } diff --git a/linker/plugins/relay/server/RelayServerTransfer.cs b/linker/plugins/relay/server/RelayServerTransfer.cs new file mode 100644 index 00000000..5677692f --- /dev/null +++ b/linker/plugins/relay/server/RelayServerTransfer.cs @@ -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 reports = new ConcurrentDictionary(); + + 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 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 TryGetRelay(string key, RelayCachingValue 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 data) + { + AddReceive((ulong)data.Length); + + if (cryptoMaster == null) return; + + data = cryptoMaster.Decode(data.ToArray()); + RelayNodeReportInfo relayNodeReportInfo = MemoryPackSerializer.Deserialize(data.Span); + + if (relayNodeReportInfo.EndPoint.Address.Equals(IPAddress.Any)) + { + relayNodeReportInfo.EndPoint.Address = ep.Address; + } + reports.AddOrUpdate(relayNodeReportInfo.Id, relayNodeReportInfo, (a, b) => relayNodeReportInfo); + } + + public List GetNodes(bool validated) + { + List 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); + } + } + + +} diff --git a/linker/plugins/relay/caching/IRelayCaching.cs b/linker/plugins/relay/server/caching/IRelayCaching.cs similarity index 87% rename from linker/plugins/relay/caching/IRelayCaching.cs rename to linker/plugins/relay/server/caching/IRelayCaching.cs index 9545f4bb..0cb54234 100644 --- a/linker/plugins/relay/caching/IRelayCaching.cs +++ b/linker/plugins/relay/server/caching/IRelayCaching.cs @@ -1,4 +1,4 @@ -namespace linker.plugins.relay.caching +namespace linker.plugins.relay.server.caching { public interface IRelayCaching { diff --git a/linker/plugins/relay/caching/RelayCachingMemory.cs b/linker/plugins/relay/server/caching/RelayCachingMemory.cs similarity index 95% rename from linker/plugins/relay/caching/RelayCachingMemory.cs rename to linker/plugins/relay/server/caching/RelayCachingMemory.cs index 5d213612..5d5cf997 100644 --- a/linker/plugins/relay/caching/RelayCachingMemory.cs +++ b/linker/plugins/relay/server/caching/RelayCachingMemory.cs @@ -1,6 +1,6 @@ using MemoryPack; using Microsoft.Extensions.Caching.Memory; -namespace linker.plugins.relay.caching +namespace linker.plugins.relay.server.caching { public sealed class RelayCachingMemory : IRelayCaching { diff --git a/linker/plugins/relay/caching/RelayCachingRedis.cs b/linker/plugins/relay/server/caching/RelayCachingRedis.cs similarity index 89% rename from linker/plugins/relay/caching/RelayCachingRedis.cs rename to linker/plugins/relay/server/caching/RelayCachingRedis.cs index 1ab5ff5c..55ee0666 100644 --- a/linker/plugins/relay/caching/RelayCachingRedis.cs +++ b/linker/plugins/relay/server/caching/RelayCachingRedis.cs @@ -2,7 +2,7 @@ using MemoryPack; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.StackExchangeRedis; -namespace linker.plugins.relay.caching +namespace linker.plugins.relay.server.caching { public sealed class RelayCachingRedis : IRelayCaching { @@ -13,7 +13,7 @@ namespace linker.plugins.relay.caching { cache = new RedisCache(new RedisCacheOptions { - Configuration = fileConfig.Data.Server.Relay.Caching.ConnectString, + Configuration = fileConfig.Data.Server.Relay.Distributed.Caching.ConnectString, InstanceName = "Linker" }); } diff --git a/linker/plugins/relay/validator/IRelayValidator.cs b/linker/plugins/relay/server/validator/IRelayValidator.cs similarity index 80% rename from linker/plugins/relay/validator/IRelayValidator.cs rename to linker/plugins/relay/server/validator/IRelayValidator.cs index da3dd42e..dd8d9c55 100644 --- a/linker/plugins/relay/validator/IRelayValidator.cs +++ b/linker/plugins/relay/server/validator/IRelayValidator.cs @@ -1,8 +1,8 @@ using linker.config; 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 { @@ -25,7 +25,7 @@ namespace linker.plugins.relay.validator this.fileConfig = fileConfig; } - public async Task Validate(linker.plugins.relay.transport.RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine) + public async Task Validate(RelayInfo relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine) { if (relayInfo.SecretKey != fileConfig.Data.Server.Relay.SecretKey) { diff --git a/linker/plugins/relay/validator/RelayValidatorTransfer.cs b/linker/plugins/relay/server/validator/RelayValidatorTransfer.cs similarity index 89% rename from linker/plugins/relay/validator/RelayValidatorTransfer.cs rename to linker/plugins/relay/server/validator/RelayValidatorTransfer.cs index ef412457..78277d38 100644 --- a/linker/plugins/relay/validator/RelayValidatorTransfer.cs +++ b/linker/plugins/relay/server/validator/RelayValidatorTransfer.cs @@ -1,7 +1,7 @@ -using linker.plugins.relay.transport; +using linker.plugins.relay.client.transport; using linker.plugins.signin.messenger; -namespace linker.plugins.relay.validator +namespace linker.plugins.relay.server.validator { public sealed partial class RelayValidatorTransfer { diff --git a/linker/plugins/relay/validator/RelayValidatorTypeLoader.cs b/linker/plugins/relay/server/validator/RelayValidatorTypeLoader.cs similarity index 93% rename from linker/plugins/relay/validator/RelayValidatorTypeLoader.cs rename to linker/plugins/relay/server/validator/RelayValidatorTypeLoader.cs index 8ac30f17..f4f2b6aa 100644 --- a/linker/plugins/relay/validator/RelayValidatorTypeLoader.cs +++ b/linker/plugins/relay/server/validator/RelayValidatorTypeLoader.cs @@ -1,7 +1,7 @@ using linker.libs; using Microsoft.Extensions.DependencyInjection; -namespace linker.plugins.relay.validator +namespace linker.plugins.relay.server.validator { public sealed partial class RelayValidatorTypeLoader { diff --git a/linker/plugins/resolver/IResolver.cs b/linker/plugins/resolver/IResolver.cs index 753e2360..404e9b86 100644 --- a/linker/plugins/resolver/IResolver.cs +++ b/linker/plugins/resolver/IResolver.cs @@ -10,7 +10,8 @@ namespace linker.plugins.resolver Relay = 2, Socks4 = 4, Socks5 = 5, - Flow = 6 + Flow = 6, + RelayReport = 7, } public interface IResolver { diff --git a/linker/plugins/resolver/ResolverTransfer.cs b/linker/plugins/resolver/ResolverTransfer.cs index c29af4cc..f76ed2d5 100644 --- a/linker/plugins/resolver/ResolverTransfer.cs +++ b/linker/plugins/resolver/ResolverTransfer.cs @@ -40,7 +40,7 @@ namespace linker.plugins.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) @@ -57,7 +57,7 @@ namespace linker.plugins.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)); } } } diff --git a/linker/plugins/sforward/SForwardApiController.cs b/linker/plugins/sforward/SForwardApiController.cs index 24891cde..040921b6 100644 --- a/linker/plugins/sforward/SForwardApiController.cs +++ b/linker/plugins/sforward/SForwardApiController.cs @@ -8,7 +8,6 @@ using linker.plugins.capi; using linker.plugins.messenger; using linker.config; using System.Collections.Concurrent; -using linker.plugins.tuntap.client; namespace linker.plugins.sforward { diff --git a/linker/plugins/socks5/Socks5Proxy.cs b/linker/plugins/socks5/Socks5Proxy.cs index 9182557d..5034bff4 100644 --- a/linker/plugins/socks5/Socks5Proxy.cs +++ b/linker/plugins/socks5/Socks5Proxy.cs @@ -1,5 +1,4 @@ using linker.config; -using linker.plugins.relay; using linker.tunnel; using linker.tunnel.connection; using linker.libs; @@ -13,6 +12,7 @@ using linker.plugins.client; using linker.plugins.socks5.config; using System.Text; using System.Collections.Generic; +using linker.plugins.relay.client; namespace linker.plugins.socks5 { diff --git a/linker/plugins/tunnel/TunnelBase.cs b/linker/plugins/tunnel/TunnelBase.cs index c9257183..1ca45b31 100644 --- a/linker/plugins/tunnel/TunnelBase.cs +++ b/linker/plugins/tunnel/TunnelBase.cs @@ -2,7 +2,6 @@ using linker.libs; using linker.libs.extends; using linker.plugins.client; -using linker.plugins.relay; using linker.plugins.resolver; using linker.tunnel; using linker.tunnel.connection; @@ -14,6 +13,7 @@ using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using linker.plugins.messenger; using linker.plugins.tuntap.messenger; +using linker.plugins.relay.client; namespace linker.plugins.tunnel { diff --git a/linker/plugins/tuntap/client/ExcludeIP.cs b/linker/plugins/tuntap/ExcludeIP.cs similarity index 93% rename from linker/plugins/tuntap/client/ExcludeIP.cs rename to linker/plugins/tuntap/ExcludeIP.cs index 3cf55fb7..7ef6aadc 100644 --- a/linker/plugins/tuntap/client/ExcludeIP.cs +++ b/linker/plugins/tuntap/ExcludeIP.cs @@ -1,7 +1,7 @@ using linker.client.config; using linker.plugins.tunnel.excludeip; -namespace linker.plugins.tuntap.client +namespace linker.plugins.tuntap { public sealed class ExcludeIP : ITunnelExcludeIP { diff --git a/linker/plugins/tuntap/client/TuntapApiController.cs b/linker/plugins/tuntap/TuntapApiController.cs similarity index 99% rename from linker/plugins/tuntap/client/TuntapApiController.cs rename to linker/plugins/tuntap/TuntapApiController.cs index 7be32a16..cbe4359c 100644 --- a/linker/plugins/tuntap/client/TuntapApiController.cs +++ b/linker/plugins/tuntap/TuntapApiController.cs @@ -12,7 +12,7 @@ using linker.plugins.tuntap.config; using linker.client.config; using linker.plugins.tuntap.lease; -namespace linker.plugins.tuntap.client +namespace linker.plugins.tuntap { public sealed class TuntapClientApiController : IApiClientController { diff --git a/linker/plugins/tuntap/client/TuntapConfigTransfer.cs b/linker/plugins/tuntap/TuntapConfigTransfer.cs similarity index 96% rename from linker/plugins/tuntap/client/TuntapConfigTransfer.cs rename to linker/plugins/tuntap/TuntapConfigTransfer.cs index 0876197a..b382a4a0 100644 --- a/linker/plugins/tuntap/client/TuntapConfigTransfer.cs +++ b/linker/plugins/tuntap/TuntapConfigTransfer.cs @@ -12,7 +12,7 @@ using linker.tun; using linker.plugins.tuntap.lease; using linker.plugins.decenter; -namespace linker.plugins.tuntap.client +namespace linker.plugins.tuntap { public sealed class TuntapConfigTransfer : IDecenter { @@ -92,8 +92,8 @@ namespace linker.plugins.tuntap.client await LeaseIP(); - 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); + 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; if (needReboot) { @@ -216,8 +216,8 @@ namespace linker.plugins.tuntap.client await Task.Delay(1000); } - 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); + 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; if (run) { diff --git a/linker/plugins/tuntap/client/TuntapDeviceStatusTransfer.cs b/linker/plugins/tuntap/TuntapDeviceStatusTransfer.cs similarity index 98% rename from linker/plugins/tuntap/client/TuntapDeviceStatusTransfer.cs rename to linker/plugins/tuntap/TuntapDeviceStatusTransfer.cs index 2e42c800..600aed0d 100644 --- a/linker/plugins/tuntap/client/TuntapDeviceStatusTransfer.cs +++ b/linker/plugins/tuntap/TuntapDeviceStatusTransfer.cs @@ -4,7 +4,7 @@ using linker.plugins.tuntap.config; using linker.tun; using System.Net.NetworkInformation; -namespace linker.plugins.tuntap.client +namespace linker.plugins.tuntap { public sealed class TuntapDeviceStatusTransfer { diff --git a/linker/plugins/tuntap/client/TuntapPingTransfer.cs b/linker/plugins/tuntap/TuntapPingTransfer.cs similarity index 98% rename from linker/plugins/tuntap/client/TuntapPingTransfer.cs rename to linker/plugins/tuntap/TuntapPingTransfer.cs index 7a6cfe09..a9f013fa 100644 --- a/linker/plugins/tuntap/client/TuntapPingTransfer.cs +++ b/linker/plugins/tuntap/TuntapPingTransfer.cs @@ -6,7 +6,7 @@ using System.Net.NetworkInformation; using System.Net; using linker.config; -namespace linker.plugins.tuntap.client +namespace linker.plugins.tuntap { public sealed class TuntapPingTransfer { diff --git a/linker/plugins/tuntap/client/TuntapProxy.cs b/linker/plugins/tuntap/TuntapProxy.cs similarity index 99% rename from linker/plugins/tuntap/client/TuntapProxy.cs rename to linker/plugins/tuntap/TuntapProxy.cs index 7fee4066..70e72b02 100644 --- a/linker/plugins/tuntap/client/TuntapProxy.cs +++ b/linker/plugins/tuntap/TuntapProxy.cs @@ -1,5 +1,4 @@ using linker.config; -using linker.plugins.relay; using linker.tunnel; using linker.tunnel.connection; using linker.libs; @@ -11,8 +10,9 @@ using linker.plugins.client; using linker.plugins.tunnel; using System.Buffers; 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 { diff --git a/linker/plugins/tuntap/TuntapStartup.cs b/linker/plugins/tuntap/TuntapStartup.cs index 72bc4848..8596b984 100644 --- a/linker/plugins/tuntap/TuntapStartup.cs +++ b/linker/plugins/tuntap/TuntapStartup.cs @@ -1,5 +1,4 @@ using linker.config; -using linker.plugins.tuntap.client; using linker.plugins.tuntap.lease; using linker.plugins.tuntap.messenger; using linker.startup; diff --git a/linker/plugins/tuntap/client/TuntapTransfer.cs b/linker/plugins/tuntap/TuntapTransfer.cs similarity index 97% rename from linker/plugins/tuntap/client/TuntapTransfer.cs rename to linker/plugins/tuntap/TuntapTransfer.cs index 6efb365b..42a5cb1f 100644 --- a/linker/plugins/tuntap/client/TuntapTransfer.cs +++ b/linker/plugins/tuntap/TuntapTransfer.cs @@ -5,7 +5,7 @@ using linker.plugins.client; using linker.plugins.tuntap.config; using linker.tun; -namespace linker.plugins.tuntap.client +namespace linker.plugins.tuntap { public sealed class TuntapTransfer { @@ -33,11 +33,11 @@ namespace linker.plugins.tuntap.client AppDomain.CurrentDomain.ProcessExit += (s, e) => linkerTunDeviceAdapter.Shutdown(); Console.CancelKeyPress += (s, e) => linkerTunDeviceAdapter.Shutdown(); } - + /// /// 运行网卡 /// - public void Setup(IPAddress ip,byte prefixLength) + public void Setup(IPAddress ip, byte prefixLength) { if (operatingManager.StartOperation() == false) { diff --git a/linker/plugins/tuntap/messenger/TuntapMessenger.cs b/linker/plugins/tuntap/messenger/TuntapMessenger.cs index a2e0465a..d1c2324c 100644 --- a/linker/plugins/tuntap/messenger/TuntapMessenger.cs +++ b/linker/plugins/tuntap/messenger/TuntapMessenger.cs @@ -2,7 +2,6 @@ using linker.libs; using linker.plugins.messenger; using linker.plugins.signin.messenger; -using linker.plugins.tuntap.client; using linker.plugins.tuntap.config; using linker.plugins.tuntap.lease; using MemoryPack; diff --git a/version.txt b/version.txt index eb74a210..7531754b 100644 --- a/version.txt +++ b/version.txt @@ -1,5 +1,5 @@ v1.5.1 -2024-10-30 18:01:05 +2024-10-31 17:45:20 1. 优化点对网和网对网的局域网IP,包括禁用IP,和冲突检测 2. 一些UI优化 3. 新增socks5代理