diff --git a/v2rayN/ServiceLib/Enums/EInboundProtocol.cs b/v2rayN/ServiceLib/Enums/EInboundProtocol.cs index 768a428b..8c75c65f 100644 --- a/v2rayN/ServiceLib/Enums/EInboundProtocol.cs +++ b/v2rayN/ServiceLib/Enums/EInboundProtocol.cs @@ -9,5 +9,6 @@ public enum EInboundProtocol api, api2, mixed, + split, speedtest = 21 } diff --git a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs index 80b89654..14a531d4 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs @@ -513,6 +513,92 @@ public class CoreConfigSingboxService } } + public async Task GeneratePureEndpointConfig(ProfileItem node) + { + var ret = new RetResult(); + try + { + if (node == null + || node.Port <= 0) + { + ret.Msg = ResUI.CheckServerSettings; + return ret; + } + if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp)) + { + ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}"; + return ret; + } + + ret.Msg = ResUI.InitialConfiguration; + + var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); + if (result.IsNullOrEmpty()) + { + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; + } + + var singboxConfig = JsonUtils.Deserialize(result); + if (singboxConfig == null) + { + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; + } + + await GenLog(singboxConfig); + + var inbound = new Inbound4Sbox() + { + type = EInboundProtocol.mixed.ToString(), + tag = EInboundProtocol.socks.ToString(), + listen = Global.Loopback, + listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.split) + }; + singboxConfig.inbounds = new() { inbound }; + + if (node.ConfigType == EConfigType.WireGuard) + { + singboxConfig.outbounds.RemoveAt(0); + var endpoints = new Endpoints4Sbox(); + await GenEndpoint(node, endpoints); + endpoints.tag = Global.ProxyTag; + singboxConfig.endpoints = new() { endpoints }; + } + else + { + await GenOutbound(node, singboxConfig.outbounds.First()); + } + + if (singboxConfig.endpoints == null) + { + singboxConfig.outbounds = new() { JsonUtils.DeepCopy(singboxConfig.outbounds.First()) }; + } + else + { + singboxConfig.outbounds.Clear(); + } + + await GenMoreOutbounds(node, singboxConfig); + + ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Success = true; + var config = JsonNode.Parse(JsonUtils.Serialize(singboxConfig)).AsObject(); + + config.Remove("route"); + + ret.Data = config.ToJsonString(new() { WriteIndented = true }); + + return ret; + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; + } + } + #endregion public gen function #region private gen function diff --git a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs index 60b4df3e..c15c05ff 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigV2rayService.cs @@ -416,6 +416,71 @@ public class CoreConfigV2rayService } } + public async Task GeneratePureEndpointConfig(ProfileItem node) + { + var ret = new RetResult(); + try + { + if (node == null + || node.Port <= 0) + { + ret.Msg = ResUI.CheckServerSettings; + return ret; + } + + if (node.GetNetwork() is nameof(ETransport.quic)) + { + ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}"; + return ret; + } + + ret.Msg = ResUI.InitialConfiguration; + + var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); + if (result.IsNullOrEmpty()) + { + ret.Msg = ResUI.FailedGetDefaultConfiguration; + return ret; + } + + var v2rayConfig = JsonUtils.Deserialize(result); + if (v2rayConfig == null) + { + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; + } + + await GenLog(v2rayConfig); + + var inbound = GetInbound(_config.Inbound.First(), EInboundProtocol.split, true); + + v2rayConfig.inbounds = new() { inbound }; + + await GenOutbound(node, v2rayConfig.outbounds.First()); + + v2rayConfig.outbounds = new() { JsonUtils.DeepCopy(v2rayConfig.outbounds.First()) }; + + await GenMoreOutbounds(node, v2rayConfig); + + ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); + ret.Success = true; + + var config = JsonNode.Parse(JsonUtils.Serialize(v2rayConfig)).AsObject(); + + config.Remove("routing"); + + ret.Data = config.ToJsonString(new() { WriteIndented = true }); + + return ret; + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return ret; + } + } + #endregion public gen function #region private gen function diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigBrookService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigBrookService.cs new file mode 100644 index 00000000..39e2bc5c --- /dev/null +++ b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigBrookService.cs @@ -0,0 +1,50 @@ +namespace ServiceLib.Services.CoreConfig.Minimal; +public class CoreConfigBrookService +{ + private Config _config; + private static readonly string _tag = "CoreConfigBrookService"; + + public CoreConfigBrookService(Config config) + { + _config = config; + } + + public async Task GeneratePureEndpointConfig(ProfileItem node) + { + var ret = new RetResult(); + try + { + if (node == null + || node.Port <= 0) + { + ret.Msg = ResUI.CheckServerSettings; + return ret; + } + + //if (node.ConfigType != EConfigType.Brook) + //{ + // ret.Msg = ResUI.Incorrectconfiguration + $" - {node.ConfigType}"; + // return ret; + //} + + var processArgs = "client"; + + // inbound + processArgs += " --socks5 " + Global.Loopback + ":" + AppHandler.Instance.GetLocalPort(EInboundProtocol.split).ToString(); + + // outbound + processArgs += " --server " + node.Address + ":" + node.Port; + processArgs += " --password " + node.Id; + + ret.Data = processArgs; + + return await Task.FromResult(ret); + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return await Task.FromResult(ret); + } + } +} diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigHy2Service.cs b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigHy2Service.cs new file mode 100644 index 00000000..25026dba --- /dev/null +++ b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigHy2Service.cs @@ -0,0 +1,88 @@ +using System.Text.Json.Nodes; + +namespace ServiceLib.Services.CoreConfig.Minimal; +public class CoreConfigHy2Service +{ + private Config _config; + private static readonly string _tag = "CoreConfigHy2Service"; + + public CoreConfigHy2Service(Config config) + { + _config = config; + } + + public async Task GeneratePureEndpointConfig(ProfileItem node) + { + var ret = new RetResult(); + try + { + if (node == null + || node.Port <= 0) + { + ret.Msg = ResUI.CheckServerSettings; + return ret; + } + + if (node.ConfigType != EConfigType.Hysteria2) + { + ret.Msg = ResUI.Incorrectconfiguration + $" - {node.ConfigType}"; + return ret; + } + + var configJsonNode = new JsonObject(); + + // inbound + configJsonNode["socks5"] = new JsonObject + { + ["listen"] = Global.Loopback + ":" + AppHandler.Instance.GetLocalPort(EInboundProtocol.split).ToString() + }; + + // outbound + var port = string.Empty; + if (node.Ports.IsNotEmpty()) + { + port = node.Ports.Replace(':', '-'); + if (_config.HysteriaItem.HopInterval > 0) + { + configJsonNode["transport"] = new JsonObject + { + ["udp"] = new JsonObject + { + ["hopInterval"] = $"{_config.HysteriaItem.HopInterval}s" + } + }; + } + } + else + { + port = node.Port.ToString(); + } + configJsonNode["server"] = node.Address + ":" + port; + configJsonNode["auth"] = node.Id; + + var bandwidthObject = new JsonObject(); + if (_config.HysteriaItem.UpMbps > 0) + { + bandwidthObject["up"] = $"{_config.HysteriaItem.UpMbps} mbps"; + } + if (_config.HysteriaItem.DownMbps > 0) + { + bandwidthObject["down"] = $"{_config.HysteriaItem.DownMbps} mbps"; + } + if (bandwidthObject.Count > 0) + { + configJsonNode["bandwidth"] = bandwidthObject; + } + + ret.Data = configJsonNode.ToJsonString(new() { WriteIndented = true }); + + return await Task.FromResult(ret); + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return await Task.FromResult(ret); + } + } +} diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigJuicityService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigJuicityService.cs new file mode 100644 index 00000000..14b6083f --- /dev/null +++ b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigJuicityService.cs @@ -0,0 +1,72 @@ +using System.Text.Json.Nodes; + +namespace ServiceLib.Services.CoreConfig.Minimal; +public class CoreConfigJuicityService +{ + private Config _config; + private static readonly string _tag = "CoreConfigJuicityService"; + + public CoreConfigJuicityService(Config config) + { + _config = config; + } + + public async Task GeneratePureEndpointConfig(ProfileItem node) + { + var ret = new RetResult(); + try + { + if (node == null + || node.Port <= 0) + { + ret.Msg = ResUI.CheckServerSettings; + return ret; + } + + //if (node.ConfigType != EConfigType.Juicity) + //{ + // ret.Msg = ResUI.Incorrectconfiguration + $" - {node.ConfigType}"; + // return ret; + //} + + var configJsonNode = new JsonObject(); + + // log + var logLevel = string.Empty; + switch (_config.CoreBasicItem.Loglevel) + { + case "warning": + logLevel = "warn"; + break; + default: + logLevel = _config.CoreBasicItem.Loglevel; + break; + } + configJsonNode["log_level"] = logLevel; + + // inbound + configJsonNode["listen"] = ":" + AppHandler.Instance.GetLocalPort(EInboundProtocol.split).ToString(); + + // outbound + configJsonNode["server"] = node.Address + ":" + node.Port; + configJsonNode["uuid"] = node.Id; + configJsonNode["password"] = node.Security; + if (node.Sni.IsNotEmpty()) + { + configJsonNode["sni"] = node.Sni; + } + configJsonNode["allow_insecure"] = node.AllowInsecure == "true"; + configJsonNode["congestion_control"] = "bbr"; + + ret.Data = configJsonNode.ToJsonString(new() { WriteIndented = true }); + + return await Task.FromResult(ret); + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return await Task.FromResult(ret); + } + } +} diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigNaiveService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigNaiveService.cs new file mode 100644 index 00000000..8307d5b0 --- /dev/null +++ b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigNaiveService.cs @@ -0,0 +1,53 @@ +using System.Text.Json.Nodes; + +namespace ServiceLib.Services.CoreConfig.Minimal; +public class CoreConfigNaiveService +{ + private Config _config; + private static readonly string _tag = "CoreConfigNaiveService"; + + public CoreConfigNaiveService(Config config) + { + _config = config; + } + + public async Task GeneratePureEndpointConfig(ProfileItem node) + { + var ret = new RetResult(); + try + { + if (node == null + || node.Port <= 0) + { + ret.Msg = ResUI.CheckServerSettings; + return ret; + } + + // TODO: EConfigType.Naive + + //if (node.ConfigType != EConfigType.Naive) + //{ + // ret.Msg = ResUI.Incorrectconfiguration + $" - {node.ConfigType}"; + // return ret; + //} + + var configJsonNode = new JsonObject(); + + // inbound + configJsonNode["listen"] = Global.SocksProtocol + Global.Loopback + ":" + AppHandler.Instance.GetLocalPort(EInboundProtocol.split).ToString(); + + // outbound + configJsonNode["proxy"] = (node.Network == "quic" ? "quic://" : Global.HttpsProtocol) + node.Id + "@" + node.Address + ":" + node.Port; + + ret.Data = configJsonNode.ToJsonString(new() { WriteIndented = true }); + + return await Task.FromResult(ret); + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return await Task.FromResult(ret); + } + } +} diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigShadowquicService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigShadowquicService.cs new file mode 100644 index 00000000..3ca89444 --- /dev/null +++ b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigShadowquicService.cs @@ -0,0 +1,81 @@ +namespace ServiceLib.Services.CoreConfig.Minimal; +public class CoreConfigShadowquicService +{ + private Config _config; + private static readonly string _tag = "CoreConfigShadowquicService"; + + public CoreConfigShadowquicService(Config config) + { + _config = config; + } + + public async Task GeneratePureEndpointConfig(ProfileItem node) + { + var ret = new RetResult(); + try + { + if (node == null + || node.Port <= 0) + { + ret.Msg = ResUI.CheckServerSettings; + return ret; + } + + //if (node.ConfigType != EConfigType.Shadowquic) + //{ + // ret.Msg = ResUI.Incorrectconfiguration + $" - {node.ConfigType}"; + // return ret; + //} + + var configYamlNode = new Dictionary(); + + // log + var logLevel = string.Empty; + switch (_config.CoreBasicItem.Loglevel) + { + case "warning": + logLevel = "warn"; + break; + default: + logLevel = _config.CoreBasicItem.Loglevel; + break; + } + configYamlNode["log-level"] = logLevel; + + // inbound + var inboundNode = new Dictionary + { + ["type"] = "socks5", + ["listen"] = Global.Loopback + ":" + AppHandler.Instance.GetLocalPort(EInboundProtocol.split).ToString() + }; + configYamlNode["inbound"] = inboundNode; + + // outbound + var outboundNode = new Dictionary + { + ["type"] = "shadowquic", + ["addr"] = node.Address + ":" + node.Port, + ["password"] = node.Id, + ["username"] = node.Security, + ["alpn"] = new List { "h3" }, + ["congestion-control"] = "bbr", + ["zero-rtt"] = true + }; + if (node.Sni.IsNotEmpty()) + { + outboundNode["server-name"] = node.Sni; + } + configYamlNode["outbound"] = outboundNode; + + ret.Data = YamlUtils.ToYaml(configYamlNode); + + return await Task.FromResult(ret); + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return await Task.FromResult(ret); + } + } +} diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigTuicService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigTuicService.cs new file mode 100644 index 00000000..3f95bebd --- /dev/null +++ b/v2rayN/ServiceLib/Services/CoreConfig/Minimal/CoreConfigTuicService.cs @@ -0,0 +1,75 @@ +using System.Text.Json.Nodes; + +namespace ServiceLib.Services.CoreConfig.Minimal; +public class CoreConfigTuicService +{ + private Config _config; + private static readonly string _tag = "CoreConfigTuicService"; + + public CoreConfigTuicService(Config config) + { + _config = config; + } + + public async Task GeneratePureEndpointConfig(ProfileItem node) + { + var ret = new RetResult(); + try + { + if (node == null + || node.Port <= 0) + { + ret.Msg = ResUI.CheckServerSettings; + return ret; + } + + if (node.ConfigType != EConfigType.TUIC) + { + ret.Msg = ResUI.Incorrectconfiguration + $" - {node.ConfigType}"; + return ret; + } + + var configJsonNode = new JsonObject(); + + // log + var logLevel = string.Empty; + switch (_config.CoreBasicItem.Loglevel) + { + case "warning": + logLevel = "warn"; + break; + default: + logLevel = _config.CoreBasicItem.Loglevel; + break; + } + configJsonNode["log_level"] = logLevel; + + // inbound + configJsonNode["local"] = new JsonObject + { + ["server"] = Global.Loopback + ":" + AppHandler.Instance.GetLocalPort(EInboundProtocol.split).ToString() + }; + + // outbound + configJsonNode["relay"] = new JsonObject + { + ["server"] = node.Address + ":" + node.Port, + ["uuid"] = node.Id, + ["password"] = node.Security, + ["udp_relay_mode"] = "quic", + ["congestion_control"] = "bbr", + ["alpn"] = new JsonArray { "h3", "spdy/3.1" } + }; + + ret.Data = configJsonNode.ToJsonString(new() { WriteIndented = true }); + + return await Task.FromResult(ret); + } + catch (Exception ex) + { + Logging.SaveLog(_tag, ex); + ret.Msg = ResUI.FailedGenDefaultConfiguration; + return await Task.FromResult(ret); + } + } +}