diff --git a/src/linker.doc.web/docs/2、安装运行/2.7、初始化配置2(服务端).md b/src/linker.doc.web/docs/2、安装运行/2.7、初始化配置2(服务端).md index 6c0eb1c3..f1264db5 100644 --- a/src/linker.doc.web/docs/2、安装运行/2.7、初始化配置2(服务端).md +++ b/src/linker.doc.web/docs/2、安装运行/2.7、初始化配置2(服务端).md @@ -22,30 +22,21 @@ server.json //cdkey 加密密钥 "SecretKey": "snltty" }, - //中继 - "Relay": { - //中继密钥,客户端密钥不准确时无法使用本中继 - "SecretKey": "", - - }, //信标服务器端口 "ServicePort": 1802, //内网穿透配置 "SForward": { - //内网穿透密钥 - "SecretKey": "", "BufferSize": 3, //web端口,用于按域名穿透 "WebPort": 0, //隧道端口范围,用于按端口穿透 - "TunnelPortRange": [ - 10000, - 60000 - ] + "TunnelPortRange": [ 10000,60000] }, //登入信标密钥,默认为空,即为所有客户端均可登入本信标服务器 "SignIn": { - "SecretKey": "", + "Anonymous": true, //允许匿名登录 + "SuperKey": "snltty", //超级密钥 + "SuperPassword": "snltty",//超级密码 "CleanDays": 7 //当一组内的所有设备都超过7天未上线则清理 }, //虚拟网卡 @@ -56,11 +47,10 @@ server.json "NetworkDays": 30 //网络租期 } }, - - //更新密钥,客户端密钥不正确时,只能更新自己本身 "Updater": { - "SecretKey": "" + "Sync2Server": false //客户端自动同步到服务器版本 } + } ``` action.json,这个可以不管,等用得上自定义验证的时候就知道了 @@ -68,6 +58,7 @@ action.json,这个可以不管,等用得上自定义验证的时候就知道 { "SignInActionUrl": "", //登入信标的验证接口 "RelayActionUrl": "", //中继验证接口 + "RelayNodeUrl": "", //中继节点验证接口 "SForwardActionUrl": ""//服务器穿透的验证接口 } ``` diff --git a/src/linker.doc.web/docs/2、安装运行/2.8、初始化配置3(客户端).md b/src/linker.doc.web/docs/2、安装运行/2.8、初始化配置3(客户端).md index 033c2a1f..e228bd6a 100644 --- a/src/linker.doc.web/docs/2、安装运行/2.8、初始化配置3(客户端).md +++ b/src/linker.doc.web/docs/2、安装运行/2.8、初始化配置3(客户端).md @@ -20,6 +20,10 @@ sidebar_position: 8 对应配置文件 client.json ``` { + //自定义验证 + "Action": { + "Args": {} //自定义验证的参数 + }, "Name": "A", //客户端名 //顶级满权限 "FullAccess": true, @@ -31,17 +35,16 @@ sidebar_position: 8 "WebPort": 1804, //web端口 "WebRoot": "./web/" //web根目录 }, - //cdkey - "Cdkey": { - "SecretKey": "snltty" - }, //服务器 "Servers": [ { "Name": "Linker", //信标服务器名称 "Host": "127.0.0.1:1802", //信标服务器地址 - "SecretKey": null, //信标密钥 - "UserId": "8225e9d4-0ac7-4d76-9946-c4fe04ad4696" //用户标识,多个客户端可相同 + "Host1": "127.0.0.1:1802", //信标服务器地址1 + "UserId": "8225e9d4-0ac7-4d76-9946-c4fe04ad4696", //用户标识,多个客户端可相同 + "SuperKey": "", //服务器密钥 + "SuperPassword": "" //服务器密码 + } ], //分组 @@ -56,23 +59,17 @@ sidebar_position: 8 "Relay": { "Servers": [ { - "SecretKey": "snltty", //中继密钥 "Disabled": false, //是否禁用 - "SSL": true //启用ssl + "SSL": true, //启用ssl + "RelayType": 0, //默认0 + "UseCdkey": true //使用cdkey + } ] }, - //内网穿透 - "SForward": { - "SecretKey": "snltty" //服务器穿透密钥 - }, //更新 "Updater": { - "SecretKey": "snltty" //更新密钥 - }, - //自定义验证 - "Action": { - "Args": {} //自定义验证的参数 + "Sync2Server": true //自动同步到服务器版本 } } ``` diff --git a/src/linker.doc.web/docs/3、打洞和中继/3.2、中继.md b/src/linker.doc.web/docs/3、打洞和中继/3.2、中继.md index cec90a27..bb893762 100644 --- a/src/linker.doc.web/docs/3、打洞和中继/3.2、中继.md +++ b/src/linker.doc.web/docs/3、打洞和中继/3.2、中继.md @@ -8,11 +8,9 @@ sidebar_position: 2 :::tip[说明] -1. 如果你自建信标服务器,在服务端 `configs/server.json` 复制中继密钥(`Relay->SecretKey`),在客户端中填写,如果密钥正确,则可以管理服务器的中继cdkey,发布cdkey给别人使用 +1. 如果你自建信标服务器,填写你服务器的管理密钥和管理密码,则可以管理服务器的中继cdkey,发布cdkey给别人使用 2. 如果你使用别人的服务器,你没有密钥可以不填写,则需要使用别人服务器的公开中继节点,或使用他提供的cdkey 3. `按喜好调整好即可,往后的所有通信都是自动的,无需其它操作` - -![Docusaurus Plushie](./img/relay.jpg) ::: diff --git a/src/linker.doc.web/docs/3、打洞和中继/img/relay.jpg b/src/linker.doc.web/docs/3、打洞和中继/img/relay.jpg deleted file mode 100644 index 401eee3b..00000000 Binary files a/src/linker.doc.web/docs/3、打洞和中继/img/relay.jpg and /dev/null differ diff --git a/src/linker.doc.web/docs/4、通信功能/4.4、服务器穿透.md b/src/linker.doc.web/docs/4、通信功能/4.4、服务器穿透.md index 6ced00d4..68ff49e6 100644 --- a/src/linker.doc.web/docs/4、通信功能/4.4、服务器穿透.md +++ b/src/linker.doc.web/docs/4、通信功能/4.4、服务器穿透.md @@ -11,14 +11,12 @@ sidebar_position: 4 3. 只在被访问端运行linker客户端,访问端不需要运行客户端 ::: -## 1、配置穿透密钥和端口 +## 1、配置穿透 :::tip[说明] 1. 在服务端`configs/server.json`中 2. `WebPort` 用于单一端口承载多个HTTP服务,因为HTTP Headers 中有Host字段,可以用于区分不同的HTTP服务 3. `TunnelPortRange` 用于开放一个端口范围,提供给客户端动态添加端口监听,每个端口对应不同的TCP+UDP服务 -4. `SecretKey` 为密钥,客户端填写此密钥,才能使用穿透 -![Docusaurus Plushie](./img/sforward1.jpg) ::: ## 2、配置端口转发 diff --git a/src/linker.doc.web/docs/6、自定义验证.md b/src/linker.doc.web/docs/6、自定义验证.md index cd292082..ebcbbe12 100644 --- a/src/linker.doc.web/docs/6、自定义验证.md +++ b/src/linker.doc.web/docs/6、自定义验证.md @@ -71,6 +71,10 @@ public sealed class JsonArgSignInInfo /// 分组id /// public string GroupId { get; set; } = string.Empty; + /// + /// 是否超级管理员 + /// + public bool Super { get; set; } } public sealed class JsonArgRelayInfo { diff --git a/src/linker.messenger.action/IActionServerStore.cs b/src/linker.messenger.action/IActionServerStore.cs index aa07316f..e26c8170 100644 --- a/src/linker.messenger.action/IActionServerStore.cs +++ b/src/linker.messenger.action/IActionServerStore.cs @@ -11,6 +11,10 @@ /// public string RelayActionUrl { get; } /// + /// 中继节点验证地址 + /// + public string RelayNodeUrl { get; } + /// /// 内网穿透验证地址 /// public string SForwardActionUrl { get; } @@ -27,6 +31,7 @@ /// /// public bool SetRelayActionUrl(string url); + public bool SetRelayNodeUrl(string url); /// /// 登录验证地址 /// diff --git a/src/linker.messenger.action/SignInArgsAction.cs b/src/linker.messenger.action/SignInArgsAction.cs index 4df5fc32..27e4ff52 100644 --- a/src/linker.messenger.action/SignInArgsAction.cs +++ b/src/linker.messenger.action/SignInArgsAction.cs @@ -1,4 +1,6 @@ using linker.libs.extends; +using linker.messenger.relay.client.transport; +using linker.messenger.relay.server; using linker.messenger.relay.server.validator; using linker.messenger.sforward; using linker.messenger.sforward.server.validator; @@ -20,6 +22,10 @@ namespace linker.messenger.action /// public JsonArgRelayInfo Relay { get; set; } /// + /// 中继节点验证, + /// + public JsonArgRelayNodeInfo RelayNode { get; set; } + /// /// 穿透信息,非穿透验证时为null /// public JsonArgSForwardInfo SForward { get; set; } @@ -82,6 +88,24 @@ namespace linker.messenger.action /// public ulong FlowingId { get; set; } } + public sealed class JsonArgRelayNodeInfo + { + /// + /// 来源设备id + /// + public string FromMachineId { get; set; } + /// + /// 来源设备名 + /// + public string FromMachineName { get; set; } + public List Nodes { get; set; } = []; + } + public sealed class JsonArgRelayNodeItemInfo + { + public string Id { get; set; } + public string Name { get; set; } + public bool Public { get; set; } + } public sealed class JsonArgSForwardInfo { /// @@ -204,6 +228,44 @@ namespace linker.messenger.action } return string.Empty; } + public async Task> Validate(string userid, SignCacheInfo fromMachine, List nodes) + { + if (string.IsNullOrWhiteSpace(actionServerStore.RelayNodeUrl) == false) + { + if (actionServerStore.TryGetActionArg(fromMachine.Args, out string str, out string machineKey) == false) + { + return []; + } + JsonArgInfo replace = new JsonArgInfo + { + RelayNode = new JsonArgRelayNodeInfo + { + FromMachineId = fromMachine.Id, + FromMachineName = fromMachine.MachineName, + Nodes = nodes.Select(c => new JsonArgRelayNodeItemInfo + { + Id = c.Id, + Name = c.Name, + Public = c.Public + }).ToList() ?? [] + }, + Signin = new JsonArgSignInInfo + { + GroupId = fromMachine.GroupId, + MachineId = fromMachine.MachineId, + MachineName = fromMachine.MachineName, + MachineKey = machineKey, + IPAddress = fromMachine.Connection.Address.Address, + Super = fromMachine.Super + } + }; + string ids = await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.RelayNodeUrl).ConfigureAwait(false); + if (string.IsNullOrWhiteSpace(ids)) return []; + + return nodes.Where(c => ids.Split(',').Contains(c.Id)).ToList(); + } + return nodes; + } } public sealed class SForwardValidatorAction : JsonArgReplace, ISForwardValidator diff --git a/src/linker.messenger.cdkey/CdkeyMessenger.cs b/src/linker.messenger.cdkey/CdkeyMessenger.cs index f4e8dd89..d896beea 100644 --- a/src/linker.messenger.cdkey/CdkeyMessenger.cs +++ b/src/linker.messenger.cdkey/CdkeyMessenger.cs @@ -52,7 +52,7 @@ namespace linker.messenger.cdkey connection.Write(Helper.FalseArray); return; } - if (cache.Super == false) + if (cache.Super) { await cdkeyStore.Del(info.Id).ConfigureAwait(false); } diff --git a/src/linker.messenger.flow/messenger/FlowMessenger.cs b/src/linker.messenger.flow/messenger/FlowMessenger.cs index 278bc024..71545711 100644 --- a/src/linker.messenger.flow/messenger/FlowMessenger.cs +++ b/src/linker.messenger.flow/messenger/FlowMessenger.cs @@ -103,7 +103,7 @@ namespace linker.messenger.flow.messenger return; } - if (cache.Super == false) + if (cache.Super) { info.GroupId = string.Empty; } diff --git a/src/linker.messenger.relay/messenger/RelayMessenger.cs b/src/linker.messenger.relay/messenger/RelayMessenger.cs index 5404f40c..5fa4ee66 100644 --- a/src/linker.messenger.relay/messenger/RelayMessenger.cs +++ b/src/linker.messenger.relay/messenger/RelayMessenger.cs @@ -79,7 +79,7 @@ namespace linker.messenger.relay.messenger connection.Write(serializer.Serialize(new List { })); return; } - (List nodes, bool validated) = await GetNodes(cache.Super, info.UserId); + List nodes = await GetNodes(info.UserId, cache); connection.Write(serializer.Serialize(nodes)); } @@ -103,18 +103,18 @@ namespace linker.messenger.relay.messenger } RelayAskResultInfo170 result = new RelayAskResultInfo170(); - (result.Nodes, bool validated) = await GetNodes(from.Super, info.UserId).ConfigureAwait(false); + result.Nodes = await GetNodes(info.UserId, from).ConfigureAwait(false); if (result.Nodes.Count > 0) { - result.FlowingId = relayServerTransfer.AddRelay(from.MachineId, from.MachineName, to.MachineId, to.MachineName, from.GroupId, info.UserId, validated, info.UseCdkey); + result.FlowingId = relayServerTransfer.AddRelay(from.MachineId, from.MachineName, to.MachineId, to.MachineName, from.GroupId, info.UserId, from.Super, info.UseCdkey); } connection.Write(serializer.Serialize(result)); } - private async Task<(List, bool)> GetNodes(bool super, string userid) + private async Task> GetNodes(string userid, SignCacheInfo from) { - return (await relayServerTransfer.GetNodes(super, userid), super); + return await relayServerTransfer.GetNodes(from.Super, userid); } @@ -248,7 +248,7 @@ namespace linker.messenger.relay.messenger public async Task UpdateNodeForward(IConnection connection) { RelayServerNodeUpdateWrapInfo info = serializer.Deserialize(connection.ReceiveRequestWrap.Payload.Span); - if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) && cache.Super) + if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) && cache.Super) { await relayServerTransfer.UpdateNodeReport(info.Info).ConfigureAwait(false); connection.Write(Helper.TrueArray); diff --git a/src/linker.messenger.relay/server/validator/IRelayServerValidator.cs b/src/linker.messenger.relay/server/validator/IRelayServerValidator.cs index 522006d7..52be0715 100644 --- a/src/linker.messenger.relay/server/validator/IRelayServerValidator.cs +++ b/src/linker.messenger.relay/server/validator/IRelayServerValidator.cs @@ -17,5 +17,13 @@ namespace linker.messenger.relay.server.validator /// 目标客户端,可能为null /// public Task Validate(RelayInfo170 relayInfo, SignCacheInfo fromMachine, SignCacheInfo toMachine); + /// + /// 验证节点 + /// + /// + /// + /// + /// + public Task> Validate(string userid, SignCacheInfo fromMachine, List nodes); } } diff --git a/src/linker.messenger.relay/server/validator/RelayServerValidatorTransfer.cs b/src/linker.messenger.relay/server/validator/RelayServerValidatorTransfer.cs index c0120d70..4536041d 100644 --- a/src/linker.messenger.relay/server/validator/RelayServerValidatorTransfer.cs +++ b/src/linker.messenger.relay/server/validator/RelayServerValidatorTransfer.cs @@ -60,6 +60,18 @@ namespace linker.messenger.relay.server.validator } return string.Empty; } + public async Task> Validate(string userid, SignCacheInfo fromMachine, List nodes) + { + foreach (var item in validators) + { + nodes = await item.Validate(userid, fromMachine, nodes).ConfigureAwait(false); + if (nodes == null || nodes.Count == 0) + { + return []; + } + } + return nodes; + } public sealed class RelayServerValidatorEqualityComparer : IEqualityComparer { diff --git a/src/linker.messenger.sforward/server/validator/SForwardValidator.cs b/src/linker.messenger.sforward/server/validator/SForwardValidator.cs index 1593cfc8..7eda9c4f 100644 --- a/src/linker.messenger.sforward/server/validator/SForwardValidator.cs +++ b/src/linker.messenger.sforward/server/validator/SForwardValidator.cs @@ -17,7 +17,7 @@ namespace linker.messenger.sforward.server.validator public async Task Validate(SignCacheInfo signCacheInfo, SForwardAddInfo sForwardAddInfo) { - if (signCacheInfo.Super) + if (signCacheInfo.Super == false) { return $"need super key and password"; } diff --git a/src/linker.messenger.store.file/action/ActionServerStore.cs b/src/linker.messenger.store.file/action/ActionServerStore.cs index 244de2bd..f7290c52 100644 --- a/src/linker.messenger.store.file/action/ActionServerStore.cs +++ b/src/linker.messenger.store.file/action/ActionServerStore.cs @@ -7,7 +7,9 @@ namespace linker.messenger.store.file.action public string SignInActionUrl => config.Data.Action.SignInActionUrl; public string RelayActionUrl => config.Data.Action.RelayActionUrl; + public string RelayNodeUrl => config.Data.Action.RelayNodeUrl; public string SForwardActionUrl => config.Data.Action.SForwardActionUrl; + private readonly FileConfig config; public ActionServerStore(FileConfig config) @@ -26,6 +28,11 @@ namespace linker.messenger.store.file.action config.Data.Action.RelayActionUrl = url; return true; } + public bool SetRelayNodeUrl(string url) + { + config.Data.Action.RelayNodeUrl = url; + return true; + } public bool SetSForwardActionUrl(string url) { @@ -47,7 +54,7 @@ namespace linker.messenger.store.file.action return true; } - + } } \ No newline at end of file diff --git a/src/linker.messenger.store.file/action/Config.cs b/src/linker.messenger.store.file/action/Config.cs index 5e3929a9..0c8978b0 100644 --- a/src/linker.messenger.store.file/action/Config.cs +++ b/src/linker.messenger.store.file/action/Config.cs @@ -12,7 +12,9 @@ namespace linker.messenger.store.file public ConfigActionInfo() { } public string SignInActionUrl { get; set; } = string.Empty; public string RelayActionUrl { get; set; } = string.Empty; + public string RelayNodeUrl { get; set; } = string.Empty; public string SForwardActionUrl { get; set; } = string.Empty; + public object Deserialize(string text) { diff --git a/src/linker.messenger.store.file/relay/Config.cs b/src/linker.messenger.store.file/relay/Config.cs index 982f42f2..98e9147b 100644 --- a/src/linker.messenger.store.file/relay/Config.cs +++ b/src/linker.messenger.store.file/relay/Config.cs @@ -58,7 +58,6 @@ namespace linker.messenger.store.file public string SecretKey { get; set; } = Helper.GlobalString; #else public string SecretKey { get; set; } = Guid.NewGuid().ToString().ToUpper(); - public string SuperPassword { get; set; } = Guid.NewGuid().ToString().ToUpper(); #endif } } diff --git a/src/linker.messenger.updater/UpdaterMessenger.cs b/src/linker.messenger.updater/UpdaterMessenger.cs index 67087d73..cd0916fb 100644 --- a/src/linker.messenger.updater/UpdaterMessenger.cs +++ b/src/linker.messenger.updater/UpdaterMessenger.cs @@ -229,7 +229,7 @@ namespace linker.messenger.updater } //需要密钥 - if (confirm.All && cache.Super) + if (confirm.All && cache.Super == false) { connection.Write(Helper.FalseArray); return; diff --git a/src/linker.web/src/views/full/server/Updater.vue b/src/linker.web/src/views/full/server/Updater.vue index 4ff17d2b..0cd34707 100644 --- a/src/linker.web/src/views/full/server/Updater.vue +++ b/src/linker.web/src/views/full/server/Updater.vue @@ -19,7 +19,7 @@ export default { const {t} = useI18n(); const globalData = injectGlobalData(); const state = reactive({ - sync2Server:false + sync2Server:globalData.value.config.Client.Updater.Sync2Server, }); const handleSync2ServerChange = ()=>{ setSync2Server(state.sync2Server).then(()=>{ diff --git a/version.txt b/version.txt index 0f20e1e3..f693546d 100644 --- a/version.txt +++ b/version.txt @@ -1,5 +1,5 @@ v1.8.6 -2025-07-05 13:23:49 +2025-07-05 15:47:10 1. 一些累计更新 2. 白名单 3. 优化防火墙