diff --git a/README.md b/README.md index a7d7ad5c..754b6035 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ - 仰望 * 2 - 李氏の天下 - 小猪 +- 菜菜(木子) diff --git a/src/linker.doc.web/docs/2、安装运行/2.10、导出配置.md b/src/linker.doc.web/docs/2、安装运行/2.10、导出配置.md index 75ed23d7..eff1f724 100644 --- a/src/linker.doc.web/docs/2、安装运行/2.10、导出配置.md +++ b/src/linker.doc.web/docs/2、安装运行/2.10、导出配置.md @@ -6,7 +6,7 @@ sidebar_position: 10 :::tip[说明] 1. 首次运行手动初始化的客户端拥有完全管理权限,可导出配置,用以作为组网其它设备运行 -2. 可以指定导出的设备名,管理端口,管理密码,和本客户端的其它配置信息,比如设定好的中继密钥什么的 +2. 可以指定导出的设备名,管理端口,管理密码,和本客户端的其它配置信息 3. 可以指定导出的配置拥有什么权限 4. `下载`则导出压缩包,可以复制到其它电脑上直接运行 5. `复制`导出的配置复制到剪贴板,对应初始化配置时的`粘贴配置` diff --git a/src/linker.doc.web/docs/2、安装运行/img/client2.jpg b/src/linker.doc.web/docs/2、安装运行/img/client2.jpg index cd4b196a..3101febb 100644 Binary files a/src/linker.doc.web/docs/2、安装运行/img/client2.jpg and b/src/linker.doc.web/docs/2、安装运行/img/client2.jpg differ diff --git a/src/linker.doc.web/docs/2、安装运行/img/export.jpg b/src/linker.doc.web/docs/2、安装运行/img/export.jpg index 74c68b42..f6123369 100644 Binary files a/src/linker.doc.web/docs/2、安装运行/img/export.jpg and b/src/linker.doc.web/docs/2、安装运行/img/export.jpg differ diff --git a/src/linker.doc.web/docs/96、为爱发电.md b/src/linker.doc.web/docs/96、为爱发电.md index c7b64fb5..db300af9 100644 --- a/src/linker.doc.web/docs/96、为爱发电.md +++ b/src/linker.doc.web/docs/96、为爱发电.md @@ -18,6 +18,7 @@ sidebar_position: 96 - 仰望 * 2 - 李氏の天下 - 小猪 +- 菜菜(木子) \ No newline at end of file diff --git a/src/linker.messenger.action/SignInArgsAction.cs b/src/linker.messenger.action/SignInArgsAction.cs index 27e4ff52..f7604515 100644 --- a/src/linker.messenger.action/SignInArgsAction.cs +++ b/src/linker.messenger.action/SignInArgsAction.cs @@ -1,5 +1,4 @@ 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; @@ -53,6 +52,10 @@ namespace linker.messenger.action /// public string GroupId { get; set; } = string.Empty; /// + /// 用户id + /// + public string UserId { get; set; } = string.Empty; + /// /// 超级管理 /// public bool Super { get; set; } @@ -169,7 +172,8 @@ namespace linker.messenger.action MachineName = signInfo.MachineName, MachineKey = machineKey, IPAddress = signInfo.Connection.Address.Address, - Super = signInfo.Super + Super = signInfo.Super, + UserId = signInfo.UserId } }; return await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.SignInActionUrl).ConfigureAwait(false); @@ -221,7 +225,8 @@ namespace linker.messenger.action MachineName = fromMachine.MachineName, MachineKey = machineKey, IPAddress = fromMachine.Connection.Address.Address, - Super = fromMachine.Super + Super = fromMachine.Super, + UserId = fromMachine.UserId } }; return await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.RelayActionUrl).ConfigureAwait(false); @@ -256,7 +261,8 @@ namespace linker.messenger.action MachineName = fromMachine.MachineName, MachineKey = machineKey, IPAddress = fromMachine.Connection.Address.Address, - Super = fromMachine.Super + Super = fromMachine.Super, + UserId = fromMachine.UserId } }; string ids = await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.RelayNodeUrl).ConfigureAwait(false); @@ -302,7 +308,8 @@ namespace linker.messenger.action MachineName = cache.MachineName, MachineKey = machineKey, IPAddress = cache.Connection.Address.Address, - Super = cache.Super + Super = cache.Super, + UserId = cache.UserId } }; return await actionTransfer.ExcuteActions(Replace(replace, str), actionServerStore.SForwardActionUrl).ConfigureAwait(false); diff --git a/src/linker.messenger.flow/FlowApiController.cs b/src/linker.messenger.flow/FlowApiController.cs index 19fd9095..daf27705 100644 --- a/src/linker.messenger.flow/FlowApiController.cs +++ b/src/linker.messenger.flow/FlowApiController.cs @@ -54,6 +54,7 @@ namespace linker.messenger.flow { Connection = signInClientState.Connection, MessengerId = messengerId, + Payload = serializer.Serialize(param.Content) }).ConfigureAwait(false); if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0) { @@ -87,6 +88,7 @@ namespace linker.messenger.flow { Connection = signInClientState.Connection, MessengerId = messengerId, + Payload = serializer.Serialize(param.Content) }).ConfigureAwait(false); if (resp.Code == MessageResponeCodes.OK && resp.Data.Length > 0) { diff --git a/src/linker.messenger.serializer.memorypack/Entry.cs b/src/linker.messenger.serializer.memorypack/Entry.cs index 255ce68f..0213cb5f 100644 --- a/src/linker.messenger.serializer.memorypack/Entry.cs +++ b/src/linker.messenger.serializer.memorypack/Entry.cs @@ -24,6 +24,8 @@ namespace linker.messenger.serializer.memorypack MemoryPackFormatterProvider.Register(new SignInResponseInfoFormatter()); MemoryPackFormatterProvider.Register(new SignInConfigSetNameInfoFormatter()); MemoryPackFormatterProvider.Register(new SignInNamesResponseItemInfoFormatter()); + MemoryPackFormatterProvider.Register(new SignInUserIdsResponseItemInfoFormatter()); + MemoryPackFormatterProvider.Register(new SignInPushArgInfoFormatter()); diff --git a/src/linker.messenger.serializer.memorypack/SignInSerializer.cs b/src/linker.messenger.serializer.memorypack/SignInSerializer.cs index 15983555..2526be70 100644 --- a/src/linker.messenger.serializer.memorypack/SignInSerializer.cs +++ b/src/linker.messenger.serializer.memorypack/SignInSerializer.cs @@ -493,7 +493,59 @@ namespace linker.messenger.serializer.memorypack value = wrapped.info; } } + [MemoryPackable] + public readonly partial struct SerializableSignInUserIdsResponseItemInfo + { + [MemoryPackIgnore] + public readonly SignInUserIdsResponseItemInfo info; + [MemoryPackInclude] + string UserId => info.UserId; + + [MemoryPackInclude] + string MachineName => info.MachineName; + + [MemoryPackInclude] + bool Online => info.Online; + + [MemoryPackConstructor] + SerializableSignInUserIdsResponseItemInfo(string userId, string machineName, bool online) + { + var info = new SignInUserIdsResponseItemInfo { UserId = userId, MachineName = machineName, Online = online }; + this.info = info; + } + + public SerializableSignInUserIdsResponseItemInfo(SignInUserIdsResponseItemInfo signInfo) + { + this.info = signInfo; + } + } + public class SignInUserIdsResponseItemInfoFormatter : MemoryPackFormatter + { + public override void Serialize(ref MemoryPackWriter writer, scoped ref SignInUserIdsResponseItemInfo value) + { + if (value == null) + { + writer.WriteNullObjectHeader(); + return; + } + + writer.WritePackable(new SerializableSignInUserIdsResponseItemInfo(value)); + } + + public override void Deserialize(ref MemoryPackReader reader, scoped ref SignInUserIdsResponseItemInfo value) + { + if (reader.PeekIsNull()) + { + reader.Advance(1); // skip null block + value = null; + return; + } + + var wrapped = reader.ReadPackable(); + value = wrapped.info; + } + } [MemoryPackable] diff --git a/src/linker.messenger.sforward/linker.messenger.sforward.csproj b/src/linker.messenger.sforward/linker.messenger.sforward.csproj index 61ffd154..6c4f3927 100644 --- a/src/linker.messenger.sforward/linker.messenger.sforward.csproj +++ b/src/linker.messenger.sforward/linker.messenger.sforward.csproj @@ -42,6 +42,7 @@ + diff --git a/src/linker.messenger.sforward/server/validator/SForwardValidator.cs b/src/linker.messenger.sforward/server/validator/SForwardValidator.cs index 7eda9c4f..4f851a1b 100644 --- a/src/linker.messenger.sforward/server/validator/SForwardValidator.cs +++ b/src/linker.messenger.sforward/server/validator/SForwardValidator.cs @@ -1,4 +1,5 @@ using linker.messenger.signin; +using linker.messenger.wlist; namespace linker.messenger.sforward.server.validator { @@ -10,14 +11,19 @@ namespace linker.messenger.sforward.server.validator public string Name => "default"; private readonly ISForwardServerStore sForwardServerStore; - public SForwardValidator(ISForwardServerStore sForwardServerStore) + private readonly IWhiteListServerStore whiteListServerStore; + public SForwardValidator(ISForwardServerStore sForwardServerStore, IWhiteListServerStore whiteListServerStore) { this.sForwardServerStore = sForwardServerStore; + this.whiteListServerStore = whiteListServerStore; } public async Task Validate(SignCacheInfo signCacheInfo, SForwardAddInfo sForwardAddInfo) { - if (signCacheInfo.Super == false) + List sforward = await whiteListServerStore.Get("SForward", signCacheInfo.UserId); + string target = string.IsNullOrWhiteSpace(sForwardAddInfo.Domain) ? sForwardAddInfo.RemotePort.ToString() : sForwardAddInfo.Domain; + + if (signCacheInfo.Super == false && sforward.Contains(target) == false) { return $"need super key and password"; } diff --git a/src/linker.messenger.signin/Entry.cs b/src/linker.messenger.signin/Entry.cs index 78785e46..543bc539 100644 --- a/src/linker.messenger.signin/Entry.cs +++ b/src/linker.messenger.signin/Entry.cs @@ -14,6 +14,7 @@ namespace linker.messenger.signin serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -34,6 +35,7 @@ namespace linker.messenger.signin serviceProvider.GetService(), serviceProvider.GetService(), serviceProvider.GetService(), + serviceProvider.GetService(), }); linker.messenger.api.IWebServer apiServer = serviceProvider.GetService(); @@ -63,6 +65,7 @@ namespace linker.messenger.signin serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -81,6 +84,7 @@ namespace linker.messenger.signin serviceProvider.GetService(), serviceProvider.GetService(), serviceProvider.GetService(), + serviceProvider.GetService(), }); return serviceProvider; diff --git a/src/linker.messenger.signin/SignInApiController.cs b/src/linker.messenger.signin/SignInApiController.cs index 6b701791..52c867eb 100644 --- a/src/linker.messenger.signin/SignInApiController.cs +++ b/src/linker.messenger.signin/SignInApiController.cs @@ -137,6 +137,20 @@ namespace linker.messenger.signin return new List(); } + public async Task> UserIds(ApiControllerParamsInfo param) + { + MessageResponeInfo resp = await messengerSender.SendReply(new MessageRequestWrap + { + Connection = signInClientState.Connection, + MessengerId = (ushort)SignInMessengerIds.UserIds, + Payload = serializer.Serialize(param.Content) + }).ConfigureAwait(false); + if (resp.Code == MessageResponeCodes.OK) + { + return serializer.Deserialize>(resp.Data.Span); + } + return new List(); + } public async Task CheckSuper(ApiControllerParamsInfo param) { diff --git a/src/linker.messenger.signin/SignInMessenger.cs b/src/linker.messenger.signin/SignInMessenger.cs index 1d95de47..2bb61e51 100644 --- a/src/linker.messenger.signin/SignInMessenger.cs +++ b/src/linker.messenger.signin/SignInMessenger.cs @@ -212,6 +212,19 @@ namespace linker.messenger.signin connection.Write(serializer.Serialize(list)); } } + [MessengerId((ushort)SignInMessengerIds.UserIds)] + public void UserIds(IConnection connection) + { + string name = serializer.Deserialize(connection.ReceiveRequestWrap.Payload.Span); + if (signCaching.TryGet(connection.Id, out SignCacheInfo cache) == false || cache.Super == false) + { + connection.Write(serializer.Serialize(new List())); + return; + } + + List list = signCaching.Get(name, 10).Select(c => new SignInUserIdsResponseItemInfo { UserId = c.UserId, MachineName = c.MachineName, Online = c.Connected }).ToList(); + connection.Write(serializer.Serialize(list)); + } [MessengerId((ushort)SignInMessengerIds.Exists)] @@ -374,7 +387,6 @@ namespace linker.messenger.signin public int Count { get; set; } public List List { get; set; } = new List(); } - public sealed class SignInIdsResponseItemInfo { public string MachineId { get; set; } @@ -387,6 +399,12 @@ namespace linker.messenger.signin public string MachineName { get; set; } public bool Online { get; set; } } + public sealed class SignInUserIdsResponseItemInfo + { + public string UserId { get; set; } + public string MachineName { get; set; } + public bool Online { get; set; } + } /// /// 登录返回 diff --git a/src/linker.messenger.signin/SignInMessengerIds.cs b/src/linker.messenger.signin/SignInMessengerIds.cs index a4ebafa8..1625ee7e 100644 --- a/src/linker.messenger.signin/SignInMessengerIds.cs +++ b/src/linker.messenger.signin/SignInMessengerIds.cs @@ -32,6 +32,8 @@ CheckSuper = 19, + UserIds = 20, + None = 99 } } diff --git a/src/linker.messenger.signin/SignInServerCaching.cs b/src/linker.messenger.signin/SignInServerCaching.cs index da94fc03..2d5ae45b 100644 --- a/src/linker.messenger.signin/SignInServerCaching.cs +++ b/src/linker.messenger.signin/SignInServerCaching.cs @@ -72,6 +72,8 @@ namespace linker.messenger.signin cache.Args = signInfo.Args; cache.GroupId = signInfo.GroupId; cache.Super = signInfo.Super; + cache.UserId = signInfo.UserId; + signInStore.Update(cache); signInStore.Confirm(); return string.Empty; @@ -101,6 +103,10 @@ namespace linker.messenger.signin { return Clients.Values.ToList(); } + public List Get(string name,int count) + { + return Clients.Values.Where(c=>c.MachineName.Contains(name) || c.UserId.Contains(name)).Take(count).ToList(); + } public List Get(SignCacheInfo other) { return Clients.Values.Where(c => c.GroupId == other.GroupId).ToList(); @@ -176,7 +182,7 @@ namespace linker.messenger.signin /// /// 登录缓存对象 /// - public sealed class SignCacheInfo + public partial class SignCacheInfo { public string Id { get; set; } /// @@ -240,6 +246,7 @@ namespace linker.messenger.signin public bool Super { get; set; } + public string UserId { get; set; } = string.Empty; /// @@ -258,15 +265,13 @@ namespace linker.messenger.signin /// /// 登录参数 /// - public sealed class SignInfo + public partial class SignInfo { public string MachineId { get; set; } = string.Empty; public string MachineName { get; set; } = string.Empty; public string GroupId { get; set; } = string.Empty; public string Version { get; set; } = string.Empty; - public bool Super { get; set; } = false; - public Dictionary Args { get; set; } = new Dictionary(); public IConnection Connection { get; set; } diff --git a/src/linker.messenger.signin/args/SignInArgsSuper.cs b/src/linker.messenger.signin/args/SignInArgsSuper.cs index 462125b4..dda6cfce 100644 --- a/src/linker.messenger.signin/args/SignInArgsSuper.cs +++ b/src/linker.messenger.signin/args/SignInArgsSuper.cs @@ -56,3 +56,13 @@ } } + + +namespace linker.messenger.signin +{ + public partial class SignInfo + { + public bool Super { get; set; } = false; + } + +} \ No newline at end of file diff --git a/src/linker.messenger.signin/args/SignInArgsUserId.cs b/src/linker.messenger.signin/args/SignInArgsUserId.cs new file mode 100644 index 00000000..2024823f --- /dev/null +++ b/src/linker.messenger.signin/args/SignInArgsUserId.cs @@ -0,0 +1,54 @@ +using linker.libs; +using linker.messenger; + +namespace linker.messenger.signin.args +{ + /// + /// 版本限制 + /// + public sealed class SignInArgsUserIdClient : ISignInArgsClient + { + public string Name => "userid"; + public SignInArgsLevel Level => SignInArgsLevel.Default; + + private readonly ISignInClientStore signInClientStore; + public SignInArgsUserIdClient(ISignInClientStore signInClientStore) + { + this.signInClientStore = signInClientStore; + } + public async Task Invoke(string host, Dictionary args) + { + args.TryAdd("userid", signInClientStore.Server.UserId); + return await Task.FromResult(string.Empty); + } + } + public sealed class SignInArgsUserIdServer : ISignInArgsServer + { + public string Name => "userid"; + public SignInArgsLevel Level => SignInArgsLevel.Default; + + /// + /// 服务端调用 + /// + /// 新登录参数 + /// 之前的登录信息 + /// + public async Task Validate(SignInfo signInfo, SignCacheInfo cache) + { + if (signInfo.Args.TryGetValue("userid", out string userid)) + { + signInfo.UserId = userid; + } + return await Task.FromResult(string.Empty); + } + } +} + +namespace linker.messenger.signin +{ + public partial class SignInfo + { + public string UserId { get; set; } = string.Empty; + } + +} diff --git a/src/linker.messenger.store.file/cekey/CdkeyServerStore.cs b/src/linker.messenger.store.file/cekey/CdkeyServerStore.cs index 3d9123f5..810e2801 100644 --- a/src/linker.messenger.store.file/cekey/CdkeyServerStore.cs +++ b/src/linker.messenger.store.file/cekey/CdkeyServerStore.cs @@ -9,7 +9,7 @@ namespace linker.messenger.store.file.cdkey { public sealed class CdkeyServerStore : ICdkeyServerStore { - private string regex = @"([0-9]+|\?)-([0-9]+|\?)-([0-9]+|\?)\s+([0-9]+|\?):([0-9]+|\?):([0-9]+|\?)"; + private readonly string regex = @"([0-9]+|\?)-([0-9]+|\?)-([0-9]+|\?)\s+([0-9]+|\?):([0-9]+|\?):([0-9]+|\?)"; private int index = 0; private readonly Storefactory dBfactory; diff --git a/src/linker.messenger.tuntap/cidr/TuntapCidrMapfileManager.cs b/src/linker.messenger.tuntap/cidr/TuntapCidrMapfileManager.cs index d2c3bcdf..56a1441b 100644 --- a/src/linker.messenger.tuntap/cidr/TuntapCidrMapfileManager.cs +++ b/src/linker.messenger.tuntap/cidr/TuntapCidrMapfileManager.cs @@ -78,7 +78,7 @@ namespace linker.messenger.tuntap.cidr { try { - Dictionary ip2machine = tuntapDecenter.Infos.Values.ToDictionary(c => c.IP, c => c.MachineId); + Dictionary ip2machine = tuntapDecenter.Infos.Values.Where(c=>c.Available).DistinctBy(c=>c.IP).ToDictionary(c => c.IP, c => c.MachineId); CidrAddInfo[] cidrs = maps.Select(c => { ip2machine.TryGetValue(c.Dst, out string machineId); diff --git a/src/linker.web/src/apis/flow.js b/src/linker.web/src/apis/flow.js index 2b7869cc..f262da0e 100644 --- a/src/linker.web/src/apis/flow.js +++ b/src/linker.web/src/apis/flow.js @@ -1,9 +1,9 @@ import { sendWebsocketMsg } from './request' -export const getFlows = (machineId) => { +export const getFlows = (machineId = '') => { return sendWebsocketMsg('flow/GetFlows',machineId); } -export const getMessengerFlows = (machineId) => { +export const getMessengerFlows = (machineId = '') => { return sendWebsocketMsg('flow/GetMessengerFlows',machineId); } export const getSForwardFlows = (data) => { @@ -15,7 +15,7 @@ export const getRelayFlows = (data) => { export const getCitys = () => { return sendWebsocketMsg('flow/GetCitys'); } -export const getStopwatch = (machineId) => { +export const getStopwatch = (machineId = '') => { return sendWebsocketMsg('flow/GetStopwatch',machineId); } export const getForwardFlows = (data) => { diff --git a/src/linker.web/src/apis/signin.js b/src/linker.web/src/apis/signin.js index 94b73b72..f45bce8e 100644 --- a/src/linker.web/src/apis/signin.js +++ b/src/linker.web/src/apis/signin.js @@ -37,4 +37,7 @@ export const getSignInNames = () => { } export const checkSignInKey = () => { return sendWebsocketMsg('signIn/CheckSuper'); +} +export const getSignInUserIds = (name) => { + return sendWebsocketMsg('signIn/UserIds',name); } \ No newline at end of file diff --git a/src/linker.web/src/lang/en-us.js b/src/linker.web/src/lang/en-us.js index 9d1f987d..c231687e 100644 --- a/src/linker.web/src/lang/en-us.js +++ b/src/linker.web/src/lang/en-us.js @@ -246,6 +246,7 @@ export default { 'server.wlistAddTime': 'Add time', 'server.wlistNodes': 'Value', 'server.wlistNodesRelay': 'Nodes', + 'server.wlistNodesSForward': 'Port/Domain', 'server.wlistOper': 'Oper', 'server.wlistDelConfirm': 'Are you sure to delete?', 'server.wlistAdd': 'Add', @@ -253,7 +254,7 @@ export default { 'server.wlistSelected': 'Selected', - 'server.sforwardSecretKey': 'Server forward secretKey', + 'server.sforward': 'Server forward', 'server.sforwardText': 'The server forward can be used when the key is correct', 'server.updater':'Updater', diff --git a/src/linker.web/src/lang/zh-cn.js b/src/linker.web/src/lang/zh-cn.js index 1aef99fd..e3c9590e 100644 --- a/src/linker.web/src/lang/zh-cn.js +++ b/src/linker.web/src/lang/zh-cn.js @@ -337,13 +337,14 @@ export default { 'server.wlistAddTime': '添加时间', 'server.wlistNodes': '内容', 'server.wlistNodesRelay': '节点', + 'server.wlistNodesSForward': '端口/域名', 'server.wlistOper': '操作', 'server.wlistDelConfirm': '确认删除吗?', 'server.wlistAdd': '添加白名单', 'server.wlistUnselect': '未选择', 'server.wlistSelected': '已选择', - 'server.sforwardSecretKey': '服务器穿透密钥', + 'server.sforward': '服务器穿透', 'server.sforwardText': '密钥正确时可使用服务器穿透', 'server.updater': '更新', diff --git a/src/linker.web/src/views/full/server/RelayServers.vue b/src/linker.web/src/views/full/server/RelayServers.vue index 29e3fee9..de560d8a 100644 --- a/src/linker.web/src/views/full/server/RelayServers.vue +++ b/src/linker.web/src/views/full/server/RelayServers.vue @@ -1,21 +1,23 @@