From b90a30c8d173067b1d56206e9e62ecdc04719f12 Mon Sep 17 00:00:00 2001 From: snltty <1069410172@qq.com> Date: Mon, 25 Aug 2025 16:21:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=E7=A9=BF=E9=80=8Fcd?= =?UTF-8?q?key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dotnet.yml | 2 +- .../docs/3、打洞和中继/3.2、中继.md | 5 +++- src/linker.libs/FireWallHelper.cs | 30 +++++++++++++++---- src/linker.messenger.cdkey/Entry.cs | 2 ++ .../ICdkeyServerStore.cs | 6 ++++ .../SForwardCdkeyStore.cs | 6 +++- .../client/RelayClientTestTransfer.cs | 2 +- .../CdkeySerializer.cs | 16 ++++++---- .../client/SForwardClientTestTransfer.cs | 26 +++++++++------- .../messenger/SForwardMessenger.cs | 2 +- .../server/IRelayServerCdkeyStore.cs | 5 ++++ .../server/SForwardServerMasterTransfer.cs | 6 ++-- .../{cekey => cdkey}/CdkeyServerStore.cs | 9 ++++-- .../{cekey => cdkey}/Config.cs | 0 src/linker.messenger.tuntap/TuntapAdapter.cs | 1 + src/linker.tunnel/transport/TransportUdp.cs | 22 ++++++++++---- src/linker.web/src/App.vue | 6 ++-- src/linker.web/src/assets/style.css | 5 ++-- src/linker.web/src/lang/en-us.js | 2 ++ src/linker.web/src/lang/zh-cn.js | 2 ++ .../src/views/components/cdkey/Add.vue | 9 +++++- .../src/views/components/cdkey/Index.vue | 9 +++--- .../src/views/components/cdkey/Manager.vue | 14 ++++++--- .../src/views/components/forward/Config.vue | 5 ++-- .../src/views/components/forward/Nodes.vue | 11 +++---- .../src/views/components/relay/Nodes.vue | 11 +++---- .../src/views/layout/full/Index.vue | 2 ++ .../src/views/layout/full/head/Index.vue | 1 - src/linker/Program.cs | 2 +- src/linker/linker.csproj | 7 +++-- version.txt | 9 +++--- 31 files changed, 166 insertions(+), 69 deletions(-) rename src/linker.messenger.store.file/{cekey => cdkey}/CdkeyServerStore.cs (94%) rename src/linker.messenger.store.file/{cekey => cdkey}/Config.cs (100%) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index a5f51696..a36e85e2 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -37,7 +37,7 @@ jobs: release_name: v1.9.0.${{ steps.date.outputs.today }} draft: false prerelease: false - body: "1. 一些累计更新\r\n2. 修复一些APP问题\r\n3. 增加一些数据统计\r\n4. 可选关闭信标服务" + body: "1. 一些累计更新\r\n2. 服务器转发多节点\r\n3. 一些代码优化\r\n4. 修复一些错误\r\n5. 其它一些小改变" - name: publish projects run: ./publish.bat "C:\\Android\\android-sdk" - name: upload-win-x86-oss diff --git a/src/linker.doc.web/docs/3、打洞和中继/3.2、中继.md b/src/linker.doc.web/docs/3、打洞和中继/3.2、中继.md index 1c5b1684..f2096215 100644 --- a/src/linker.doc.web/docs/3、打洞和中继/3.2、中继.md +++ b/src/linker.doc.web/docs/3、打洞和中继/3.2、中继.md @@ -44,7 +44,10 @@ slug: /p2p/relay "MaxGbTotalLastBytes": 0, //流量统计月度,0即可 "MaxGbTotalMonth": 0, - //是否公开本节点,公开则主服务器上的所有客户端可用本节点,不公开则中继认证通过时可用 + //是否公开本节点 + // 1、公开时,则所有客户端可用本节点,受MaxConnection、MaxBandwidth、MaxBandwidthTotal、MaxGbTotal 限制 + // 2、未公开时,仅超级管理、白名单内、cdkey 可使用 + // 3、超级管理、白名单内 无任何限制 "Public": false, //主服务器地址 diff --git a/src/linker.libs/FireWallHelper.cs b/src/linker.libs/FireWallHelper.cs index ece56dde..003d3e27 100644 --- a/src/linker.libs/FireWallHelper.cs +++ b/src/linker.libs/FireWallHelper.cs @@ -1,11 +1,12 @@ using System; using System.IO; +using System.Net; namespace linker.libs { public static class FireWallHelper { - public static void Write(string fileName) + public static void WriteAny(string fileName) { if (OperatingSystem.IsWindows()) { @@ -16,6 +17,13 @@ namespace linker.libs Linux(fileName); } } + public static void WriteIcmp(string fileName, IPAddress ip, byte prefixLength) + { + if (OperatingSystem.IsWindows()) + { + Windows(fileName, ip, prefixLength); + } + } private static void Linux(string fileName) { @@ -40,10 +48,22 @@ namespace linker.libs { string name = Path.GetFileNameWithoutExtension(fileName); CommandHelper.Windows(string.Empty, new string[] { - $"netsh advfirewall firewall delete rule name=\"{name}\"", - $"netsh advfirewall firewall add rule name=\"{name}\" dir=in action=allow program=\"{fileName}\" protocol=tcp enable=yes", - $"netsh advfirewall firewall add rule name=\"{name}\" dir=in action=allow program=\"{fileName}\" protocol=udp enable=yes", - $"netsh advfirewall firewall add rule name=\"{name}\" dir=in action=allow program=\"{fileName}\" protocol=icmpv4 enable=yes", + $"netsh advfirewall firewall delete rule name=\"{name}-any\"", + $"netsh advfirewall firewall add rule name=\"{name}-any\" dir=in action=allow program=\"{fileName}\" enable=yes" + }); + } + catch (Exception) + { + } + } + private static void Windows(string fileName, IPAddress ip, byte prefixLength) + { + try + { + string name = Path.GetFileNameWithoutExtension(fileName); + CommandHelper.Windows(string.Empty, new string[] { + $"netsh advfirewall firewall delete rule name=\"{name}-icmp\"", + $"netsh advfirewall firewall add rule name=\"{name}-icmp\" dir=in action=allow protocol=icmpv4 remoteip={ip}/{prefixLength} enable=yes", }); } catch (Exception) diff --git a/src/linker.messenger.cdkey/Entry.cs b/src/linker.messenger.cdkey/Entry.cs index 9c2ee53e..42217bf8 100644 --- a/src/linker.messenger.cdkey/Entry.cs +++ b/src/linker.messenger.cdkey/Entry.cs @@ -1,5 +1,6 @@ using linker.libs.web; using linker.messenger.relay.server; +using linker.messenger.sforward.server; using Microsoft.Extensions.DependencyInjection; namespace linker.messenger.cdkey { @@ -25,6 +26,7 @@ namespace linker.messenger.cdkey serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); return serviceCollection; } diff --git a/src/linker.messenger.cdkey/ICdkeyServerStore.cs b/src/linker.messenger.cdkey/ICdkeyServerStore.cs index 82ef0bbd..a170bcf9 100644 --- a/src/linker.messenger.cdkey/ICdkeyServerStore.cs +++ b/src/linker.messenger.cdkey/ICdkeyServerStore.cs @@ -43,6 +43,7 @@ namespace linker.messenger.cdkey /// /// public Task> GetAvailable(string userid, string type); + public Task> GetAvailable(string userid, string type,string value); /// /// 获取CDKEY列表 /// @@ -202,6 +203,7 @@ namespace linker.messenger.cdkey /// 支付金额 /// public double PayPrice { get; set; } + /// /// 备注 /// @@ -219,6 +221,8 @@ namespace linker.messenger.cdkey /// 已删除 /// public bool Deleted { get; set; } + + public string[] Values { get; set; } = []; } /// @@ -290,5 +294,7 @@ namespace linker.messenger.cdkey public int Count { get; set; } public string Type { get; set; } + + public string[] Values { get; set; } = []; } } diff --git a/src/linker.messenger.cdkey/SForwardCdkeyStore.cs b/src/linker.messenger.cdkey/SForwardCdkeyStore.cs index 79035661..3afa46b7 100644 --- a/src/linker.messenger.cdkey/SForwardCdkeyStore.cs +++ b/src/linker.messenger.cdkey/SForwardCdkeyStore.cs @@ -9,10 +9,14 @@ namespace linker.messenger.cdkey { this.cdkeyServerStore = cdkeyServerStore; } - public async Task> GetAvailable(string userid,string target) + public async Task> GetAvailable(string userid) { return (await cdkeyServerStore.GetAvailable(userid, "SForward")).Select(c => new SForwardCdkeyInfo { Bandwidth = c.Bandwidth, Id = c.Id, LastBytes = c.LastBytes }).ToList(); } + public async Task> GetAvailable(string userid, string target) + { + return (await cdkeyServerStore.GetAvailable(userid, "SForward", target)).Select(c => new SForwardCdkeyInfo { Bandwidth = c.Bandwidth, Id = c.Id, LastBytes = c.LastBytes }).ToList(); + } public async Task> GetLastBytes(List ids) { diff --git a/src/linker.messenger.relay/client/RelayClientTestTransfer.cs b/src/linker.messenger.relay/client/RelayClientTestTransfer.cs index 11a96c70..63a4d1df 100644 --- a/src/linker.messenger.relay/client/RelayClientTestTransfer.cs +++ b/src/linker.messenger.relay/client/RelayClientTestTransfer.cs @@ -67,7 +67,7 @@ namespace linker.messenger.relay.client { TimerHelper.SetIntervalLong(async () => { - if (lastTicksManager.DiffLessEqual(3000) || Nodes.Count <= 0) + if ((lastTicksManager.DiffLessEqual(3000) || Nodes.Count <= 0) && signInClientState.Connected) { await TaskRelay().ConfigureAwait(false); } diff --git a/src/linker.messenger.serializer.memorypack/CdkeySerializer.cs b/src/linker.messenger.serializer.memorypack/CdkeySerializer.cs index b9c84096..6a9d6cad 100644 --- a/src/linker.messenger.serializer.memorypack/CdkeySerializer.cs +++ b/src/linker.messenger.serializer.memorypack/CdkeySerializer.cs @@ -111,8 +111,11 @@ namespace linker.messenger.serializer.memorypack [MemoryPackInclude] string Type => info.Type; + [MemoryPackInclude] + string[] Values => info.Values; + [MemoryPackConstructor] - SerializableCdkeyStoreInfo(double bandwidth, long lastBytes, int id, string userid, DateTime addTime, DateTime startTime, DateTime endTime, DateTime useTime, long maxBytes, double costPrice, double price, double userPrice, double payPrice, string remark, string orderId, string contact, bool deleted, string type) + SerializableCdkeyStoreInfo(double bandwidth, long lastBytes, int id, string userid, DateTime addTime, DateTime startTime, DateTime endTime, DateTime useTime, long maxBytes, double costPrice, double price, double userPrice, double payPrice, string remark, string orderId, string contact, bool deleted, string type, string[] values) { var info = new CdkeyStoreInfo { @@ -133,7 +136,8 @@ namespace linker.messenger.serializer.memorypack OrderId = orderId, Contact = contact, Deleted = deleted, - Type = type + Type = type, + Values = values }; this.info = info; } @@ -574,10 +578,11 @@ namespace linker.messenger.serializer.memorypack int Count => info.Count; [MemoryPackInclude] string Type => info.Type; - + [MemoryPackInclude] + string[] Values => info.Values; [MemoryPackConstructor] - SerializableCdkeyOrderInfo(int gb, int speed, string time, string widgetUserId, string orderId, string contact, double costPrice, double price, double userPrice, double payPrice, int count, string type) + SerializableCdkeyOrderInfo(int gb, int speed, string time, string widgetUserId, string orderId, string contact, double costPrice, double price, double userPrice, double payPrice, int count, string type, string[] values) { var info = new CdkeyOrderInfo { @@ -592,7 +597,8 @@ namespace linker.messenger.serializer.memorypack UserPrice = userPrice, PayPrice = payPrice, Count = count, - Type = type + Type = type, + Values= values }; this.info = info; } diff --git a/src/linker.messenger.sforward/client/SForwardClientTestTransfer.cs b/src/linker.messenger.sforward/client/SForwardClientTestTransfer.cs index e07d582b..da125fe9 100644 --- a/src/linker.messenger.sforward/client/SForwardClientTestTransfer.cs +++ b/src/linker.messenger.sforward/client/SForwardClientTestTransfer.cs @@ -2,6 +2,7 @@ using linker.libs.timer; using linker.messenger.sforward.server; using linker.messenger.signin; +using linker.plugins.sforward.messenger; using System.Net; using System.Net.NetworkInformation; @@ -45,18 +46,19 @@ namespace linker.messenger.sforward.client { try { - var tasks = Nodes.Select(async (c) => + var resp = await messengerSender.SendReply(new MessageRequestWrap { - c.Address = c.Address == null || c.Address.Equals(IPAddress.Any) ? signInClientState.Connection.Address.Address : c.Address; - - using Ping ping = new Ping(); - var resp = await ping.SendPingAsync(c.Address, 1000); - c.Delay = resp.Status == IPStatus.Success ? (int)resp.RoundtripTime : -1; + Connection = signInClientState.Connection, + MessengerId = (ushort)SForwardMessengerIds.Nodes }); - await Task.WhenAll(tasks).ConfigureAwait(false); + Nodes = serializer.Deserialize>(resp.Data.Span); } - catch (Exception) + catch (Exception ex) { + if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) + { + LoggerHelper.Instance.Error(ex); + } } } private async Task PingNodes() @@ -73,8 +75,12 @@ namespace linker.messenger.sforward.client }); await Task.WhenAll(tasks).ConfigureAwait(false); } - catch (Exception) + catch (Exception ex) { + if (LoggerHelper.Instance.LoggerLevel <= LoggerTypes.DEBUG) + { + LoggerHelper.Instance.Error(ex); + } } } @@ -83,7 +89,7 @@ namespace linker.messenger.sforward.client { TimerHelper.SetIntervalLong(async () => { - if (lastTicksManager.DiffLessEqual(3000) || Nodes.Count <= 0) + if ((lastTicksManager.DiffLessEqual(3000) || Nodes.Count <= 0) && signInClientState.Connected) { await TaskNodes().ConfigureAwait(false); await PingNodes().ConfigureAwait(false); diff --git a/src/linker.messenger.sforward/messenger/SForwardMessenger.cs b/src/linker.messenger.sforward/messenger/SForwardMessenger.cs index 4c891ac1..57163081 100644 --- a/src/linker.messenger.sforward/messenger/SForwardMessenger.cs +++ b/src/linker.messenger.sforward/messenger/SForwardMessenger.cs @@ -428,7 +428,7 @@ namespace linker.plugins.sforward.messenger { Add((SForwardAddInfo)sForwardAddInfo, sForwardAddInfo.MachineId, sForwardAddInfo.GroupId, result, sForwardAddInfo.Validated, sForwardAddInfo.Cdkey); } - private bool PortRange(string str, out int min, out int max) + private static bool PortRange(string str, out int min, out int max) { min = 0; max = 0; string[] arr = str.Split('/'); diff --git a/src/linker.messenger.sforward/server/IRelayServerCdkeyStore.cs b/src/linker.messenger.sforward/server/IRelayServerCdkeyStore.cs index 4f4a5441..dc531421 100644 --- a/src/linker.messenger.sforward/server/IRelayServerCdkeyStore.cs +++ b/src/linker.messenger.sforward/server/IRelayServerCdkeyStore.cs @@ -2,6 +2,7 @@ { public interface ISForwardServerCdkeyStore { + public Task> GetAvailable(string userid); public Task> GetAvailable(string userid,string target); /// @@ -20,6 +21,10 @@ public sealed class SForwardServerCdkeyStore : ISForwardServerCdkeyStore { + public async Task> GetAvailable(string userid) + { + return await Task.FromResult(new List()); + } public async Task> GetAvailable(string userid, string target) { return await Task.FromResult(new List()); diff --git a/src/linker.messenger.sforward/server/SForwardServerMasterTransfer.cs b/src/linker.messenger.sforward/server/SForwardServerMasterTransfer.cs index a43c06ff..b74a49b0 100644 --- a/src/linker.messenger.sforward/server/SForwardServerMasterTransfer.cs +++ b/src/linker.messenger.sforward/server/SForwardServerMasterTransfer.cs @@ -111,11 +111,13 @@ namespace linker.messenger.sforward.server List sforward = await sForwardServerWhiteListStore.Get(from.UserId); string target = string.IsNullOrWhiteSpace(info.Domain) ? info.RemotePort.ToString() : info.Domain; - info.Validated = from.Super && (sforward.Contains($"sfp->{target}") || sforward.Contains($"sfp->*")) && (sforward.Contains(info.NodeId) || sforward.Contains($"*")); + info.Validated = from.Super || (sforward.Contains($"sfp->{target}") || sforward.Contains($"sfp->*")) && (sforward.Contains(info.NodeId) || sforward.Contains($"*")); if (info.Validated == false) { - info.Cdkey = (await sForwardServerCdkeyStore.GetAvailable(from.UserId, target).ConfigureAwait(false)).Select(c => new SForwardCdkeyInfo { Bandwidth = c.Bandwidth, Id = c.Id, LastBytes = c.LastBytes }).ToList(); + var cdkeys = await sForwardServerCdkeyStore.GetAvailable(from.UserId, $"sfp->{target}").ConfigureAwait(false); + var anyCdkeys = await sForwardServerCdkeyStore.GetAvailable(from.UserId, $"sfp->*").ConfigureAwait(false); + info.Cdkey = cdkeys.Concat(anyCdkeys).Select(c => new SForwardCdkeyInfo { Bandwidth = c.Bandwidth, Id = c.Id, LastBytes = c.LastBytes }).ToList(); if (info.Cdkey.Count <= 0 && node.Public == false) { diff --git a/src/linker.messenger.store.file/cekey/CdkeyServerStore.cs b/src/linker.messenger.store.file/cdkey/CdkeyServerStore.cs similarity index 94% rename from src/linker.messenger.store.file/cekey/CdkeyServerStore.cs rename to src/linker.messenger.store.file/cdkey/CdkeyServerStore.cs index 810e2801..ed70b4a0 100644 --- a/src/linker.messenger.store.file/cekey/CdkeyServerStore.cs +++ b/src/linker.messenger.store.file/cdkey/CdkeyServerStore.cs @@ -152,7 +152,8 @@ namespace linker.messenger.store.file.cdkey Contact = order.Contact, OrderId = order.OrderId, PayPrice = order.PayPrice, - UserPrice = order.UserPrice + UserPrice = order.UserPrice, + Values = order.Values ?? [], }; liteCollection.Insert(store); return await Task.FromResult(string.Empty).ConfigureAwait(false); @@ -179,9 +180,13 @@ namespace linker.messenger.store.file.cdkey public async Task> GetAvailable(string userid, string type) { if (string.IsNullOrWhiteSpace(userid) || string.IsNullOrWhiteSpace(type)) return []; - return await Task.FromResult(liteCollection.Find(x => x.UserId == userid && x.Type == type && x.LastBytes > 0 && x.StartTime <= DateTime.Now && x.EndTime >= DateTime.Now && x.Deleted == false).ToList()).ConfigureAwait(false); } + public async Task> GetAvailable(string userid, string type, string value) + { + if (string.IsNullOrWhiteSpace(userid) || string.IsNullOrWhiteSpace(type)) return []; + return await Task.FromResult(liteCollection.Find(x => x.UserId == userid && x.Type == type && x.Values.Contains(value) && x.LastBytes > 0 && x.StartTime <= DateTime.Now && x.EndTime >= DateTime.Now && x.Deleted == false).ToList()).ConfigureAwait(false); + } public async Task> Get(List ids) { return await Task.FromResult(liteCollection.Find(x => ids.Contains(x.Id)).ToList()).ConfigureAwait(false); diff --git a/src/linker.messenger.store.file/cekey/Config.cs b/src/linker.messenger.store.file/cdkey/Config.cs similarity index 100% rename from src/linker.messenger.store.file/cekey/Config.cs rename to src/linker.messenger.store.file/cdkey/Config.cs diff --git a/src/linker.messenger.tuntap/TuntapAdapter.cs b/src/linker.messenger.tuntap/TuntapAdapter.cs index 90e4490b..0972de1b 100644 --- a/src/linker.messenger.tuntap/TuntapAdapter.cs +++ b/src/linker.messenger.tuntap/TuntapAdapter.cs @@ -56,6 +56,7 @@ namespace linker.messenger.tuntap private void SignInSuccess(int times) { _ = CheckDevice(); + FireWallHelper.WriteIcmp(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName, tuntapConfigTransfer.Info.IP, tuntapConfigTransfer.Info.PrefixLength); } private void Update() { diff --git a/src/linker.tunnel/transport/TransportUdp.cs b/src/linker.tunnel/transport/TransportUdp.cs index da9faf0a..674c10b6 100644 --- a/src/linker.tunnel/transport/TransportUdp.cs +++ b/src/linker.tunnel/transport/TransportUdp.cs @@ -149,7 +149,7 @@ namespace linker.tunnel.transport TaskCompletionSource taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); //监听连接 - Socket remoteUdp = BindListen(tunnelTransportInfo.Local.Local, taskCompletionSource); + Socket remoteUdp = BindListen(tunnelTransportInfo.Local.Local, taskCompletionSource, tunnelTransportInfo.RemoteEndPoints.Select(c=>c.Address).ToList()); //给对方发送简单消息 foreach (IPEndPoint ep in tunnelTransportInfo.RemoteEndPoints) @@ -214,7 +214,7 @@ namespace linker.tunnel.transport /// /// /// - private Socket BindListen(IPEndPoint local, TaskCompletionSource tcs) + private Socket BindListen(IPEndPoint local, TaskCompletionSource tcs,List ips) { local = new IPEndPoint(IPAddress.IPv6Any, local.Port); Socket socket = new Socket(local.AddressFamily, SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); @@ -224,9 +224,21 @@ namespace linker.tunnel.transport TimerHelper.Async(async () => { - SocketReceiveFromResult result = await socket.ReceiveFromAsync(new byte[1024], new IPEndPoint(IPAddress.IPv6Any, 0)).ConfigureAwait(false); - await socket.SendToAsync(endBytes, result.RemoteEndPoint).ConfigureAwait(false); - tcs.TrySetResult(result.RemoteEndPoint as IPEndPoint); + byte[] buffer = new byte[1024]; + while (true) + { + SocketReceiveFromResult result = await socket.ReceiveFromAsync(buffer, new IPEndPoint(IPAddress.IPv6Any, 0)).ConfigureAwait(false); + if (ips.Contains((result.RemoteEndPoint as IPEndPoint).Address)) + { + await socket.SendToAsync(endBytes, result.RemoteEndPoint).ConfigureAwait(false); + tcs.TrySetResult(result.RemoteEndPoint as IPEndPoint); + break; + } + else + { + LoggerHelper.Instance.Warning($"{Name} connect recv from {result.RemoteEndPoint} {buffer.AsMemory(0, result.ReceivedBytes).GetString()}"); + } + } }); return socket; } diff --git a/src/linker.web/src/App.vue b/src/linker.web/src/App.vue index 8dc86f74..96a318bd 100644 --- a/src/linker.web/src/App.vue +++ b/src/linker.web/src/App.vue @@ -1,5 +1,5 @@