From 4e9dfe5478b5417890beb17d789f51c7b262a04d Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Sun, 14 Jul 2024 17:16:07 +0800 Subject: [PATCH] Improve --- v2rayN/v2rayN/Handler/ConfigHandler.cs | 2 +- .../Handler/CoreConfig/CoreConfigClash.cs | 2 +- .../Handler/CoreConfig/CoreConfigHandler.cs | 7 +- .../Handler/CoreConfig/CoreConfigSingbox.cs | 1212 +++++++++-------- .../Handler/CoreConfig/CoreConfigV2ray.cs | 296 ++-- v2rayN/v2rayN/Resx/ResUI.Designer.cs | 2 +- v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx | 2 +- v2rayN/v2rayN/Resx/ResUI.resx | 2 +- v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx | 2 +- v2rayN/v2rayN/Views/ClashProxiesView.xaml | 31 +- v2rayN/v2rayN/Views/ClashProxiesView.xaml.cs | 1 - 11 files changed, 817 insertions(+), 742 deletions(-) diff --git a/v2rayN/v2rayN/Handler/ConfigHandler.cs b/v2rayN/v2rayN/Handler/ConfigHandler.cs index b87981ab4f..5b6268858f 100644 --- a/v2rayN/v2rayN/Handler/ConfigHandler.cs +++ b/v2rayN/v2rayN/Handler/ConfigHandler.cs @@ -1081,7 +1081,7 @@ public static int AddCustomServer4Multiple(Config config, List sele return -1; } - var profileItem = LazyConfig.Instance.GetProfileItem(config.indexId) ?? new(); + var profileItem = LazyConfig.Instance.GetProfileItem(indexId) ?? new(); profileItem.indexId = indexId; profileItem.remarks = "Multi-server Config"; profileItem.address = Global.CoreMultipleLoadConfigFileName; diff --git a/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigClash.cs b/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigClash.cs index 80e48adb24..b29a571a6e 100644 --- a/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigClash.cs +++ b/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigClash.cs @@ -25,7 +25,7 @@ public CoreConfigClash(Config config) /// /// /// - public int GenerateClientConfig(ProfileItem node, string? fileName, out string msg) + public int GenerateClientCustomConfig(ProfileItem node, string? fileName, out string msg) { if (node == null || fileName is null) { diff --git a/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigHandler.cs b/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigHandler.cs index 12d5b45840..e42f15af31 100644 --- a/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigHandler.cs +++ b/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigHandler.cs @@ -28,7 +28,12 @@ public static int GenerateClientConfig(ProfileItem node, string? fileName, out s if (node.coreType is ECoreType.clash or ECoreType.clash_meta or ECoreType.mihomo) { var configGenClash = new CoreConfigClash(config); - return configGenClash.GenerateClientConfig(node, fileName, out msg); + return configGenClash.GenerateClientCustomConfig(node, fileName, out msg); + } + if (node.coreType is ECoreType.sing_box) + { + var configGenSingbox = new CoreConfigSingbox(config); + return configGenSingbox.GenerateClientCustomConfig(node, fileName, out msg); } else { diff --git a/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigSingbox.cs b/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigSingbox.cs index a391d87893..0184f34a11 100644 --- a/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigSingbox.cs +++ b/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigSingbox.cs @@ -17,6 +17,8 @@ public CoreConfigSingbox(Config config) _config = config; } + #region public gen function + public int GenerateClientConfigContent(ProfileItem node, out SingboxConfig? singboxConfig, out string msg) { singboxConfig = null; @@ -77,285 +79,376 @@ public int GenerateClientConfigContent(ProfileItem node, out SingboxConfig? sing return 0; } - #region private gen function - - private int GenLog(SingboxConfig singboxConfig) + public int GenerateClientSpeedtestConfig(List selecteds, out SingboxConfig? singboxConfig, out string msg) { + singboxConfig = null; try { - switch (_config.coreBasicItem.loglevel) + if (_config == null) { - case "debug": - case "info": - case "error": - singboxConfig.log.level = _config.coreBasicItem.loglevel; - break; + msg = ResUI.CheckServerSettings; + return -1; + } - case "warning": - singboxConfig.log.level = "warn"; - break; + msg = ResUI.InitialConfiguration; - default: - break; + string result = Utils.GetEmbedText(Global.SingboxSampleClient); + string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); + if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) + { + msg = ResUI.FailedGetDefaultConfiguration; + return -1; } - if (_config.coreBasicItem.loglevel == Global.None) + + singboxConfig = JsonUtils.Deserialize(result); + if (singboxConfig == null) { - singboxConfig.log.disabled = true; + msg = ResUI.FailedGenDefaultConfiguration; + return -1; } - if (_config.coreBasicItem.logEnabled) + List lstIpEndPoints = new(); + List lstTcpConns = new(); + try { - var dtNow = DateTime.Now; - singboxConfig.log.output = Utils.GetLogPath($"sbox_{dtNow:yyyy-MM-dd}.txt"); + lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()); + lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners()); + lstTcpConns.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections()); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return 0; - } - private int GenInbounds(SingboxConfig singboxConfig) - { - try - { - var listen = "::"; - singboxConfig.inbounds = []; + GenLog(singboxConfig); + //GenDns(new(), singboxConfig); + singboxConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts. + singboxConfig.outbounds.RemoveAt(0); - if (!_config.tunModeItem.enableTun - || (_config.tunModeItem.enableTun && _config.tunModeItem.enableExInbound && _config.runningCoreType == ECoreType.sing_box)) + int httpPort = LazyConfig.Instance.GetLocalPort(EInboundProtocol.speedtest); + + foreach (var it in selecteds) { - var inbound = new Inbound4Sbox() + if (it.configType == EConfigType.Custom) { - type = EInboundProtocol.socks.ToString(), - tag = EInboundProtocol.socks.ToString(), - listen = Global.Loopback, - }; - singboxConfig.inbounds.Add(inbound); - - inbound.listen_port = LazyConfig.Instance.GetLocalPort(EInboundProtocol.socks); - inbound.sniff = _config.inbound[0].sniffingEnabled; - inbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled; - inbound.domain_strategy = Utils.IsNullOrEmpty(_config.routingBasicItem.domainStrategy4Singbox) ? null : _config.routingBasicItem.domainStrategy4Singbox; - - if (_config.routingBasicItem.enableRoutingAdvanced) + continue; + } + if (it.port <= 0) { - var routing = ConfigHandler.GetDefaultRouting(_config); - if (!Utils.IsNullOrEmpty(routing.domainStrategy4Singbox)) + continue; + } + if (it.configType is EConfigType.VMess or EConfigType.VLESS) + { + var item2 = LazyConfig.Instance.GetProfileItem(it.indexId); + if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id)) { - inbound.domain_strategy = routing.domainStrategy4Singbox; + continue; } } - //http - var inbound2 = GetInbound(inbound, EInboundProtocol.http, false); - singboxConfig.inbounds.Add(inbound2); - - if (_config.inbound[0].allowLANConn) + //find unused port + var port = httpPort; + for (int k = httpPort; k < Global.MaxPort; k++) { - if (_config.inbound[0].newPort4LAN) + if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0) { - var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true); - inbound3.listen = listen; - singboxConfig.inbounds.Add(inbound3); - - var inbound4 = GetInbound(inbound, EInboundProtocol.http2, false); - inbound4.listen = listen; - singboxConfig.inbounds.Add(inbound4); - - //auth - if (!Utils.IsNullOrEmpty(_config.inbound[0].user) && !Utils.IsNullOrEmpty(_config.inbound[0].pass)) - { - inbound3.users = new() { new() { username = _config.inbound[0].user, password = _config.inbound[0].pass } }; - inbound4.users = new() { new() { username = _config.inbound[0].user, password = _config.inbound[0].pass } }; - } + continue; } - else + if (lstTcpConns?.FindIndex(_it => _it.LocalEndPoint.Port == k) >= 0) { - inbound.listen = listen; - inbound2.listen = listen; + continue; } + //found + port = k; + httpPort = port + 1; + break; } - } - if (_config.tunModeItem.enableTun) - { - if (_config.tunModeItem.mtu <= 0) + //Port In Used + if (lstIpEndPoints?.FindIndex(_it => _it.Port == port) >= 0) { - _config.tunModeItem.mtu = Utils.ToInt(Global.TunMtus[0]); + continue; } - if (Utils.IsNullOrEmpty(_config.tunModeItem.stack)) + it.port = port; + it.allowTest = true; + + //inbound + Inbound4Sbox inbound = new() { - _config.tunModeItem.stack = Global.TunStacks[0]; - } + listen = Global.Loopback, + listen_port = port, + type = EInboundProtocol.http.ToString(), + }; + inbound.tag = inbound.type + inbound.listen_port.ToString(); + singboxConfig.inbounds.Add(inbound); - var tunInbound = JsonUtils.Deserialize(Utils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { }; - tunInbound.mtu = _config.tunModeItem.mtu; - tunInbound.strict_route = _config.tunModeItem.strictRoute; - tunInbound.stack = _config.tunModeItem.stack; - tunInbound.sniff = _config.inbound[0].sniffingEnabled; - //tunInbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled; - if (_config.tunModeItem.enableIPv6Address == false) + //outbound + var item = LazyConfig.Instance.GetProfileItem(it.indexId); + if (item is null) { - tunInbound.inet6_address = null; + continue; + } + if (item.configType == EConfigType.Shadowsocks + && !Global.SsSecuritiesInSingbox.Contains(item.security)) + { + continue; + } + if (item.configType == EConfigType.VLESS + && !Global.Flows.Contains(item.flow)) + { + continue; } - singboxConfig.inbounds.Add(tunInbound); + var outbound = JsonUtils.Deserialize(txtOutbound); + GenOutbound(item, outbound); + outbound.tag = Global.ProxyTag + inbound.listen_port.ToString(); + singboxConfig.outbounds.Add(outbound); + + //rule + Rule4Sbox rule = new() + { + inbound = new List { inbound.tag }, + outbound = outbound.tag + }; + singboxConfig.route.rules.Add(rule); } + + GenDnsDomains(null, singboxConfig, null); + //var dnsServer = singboxConfig.dns?.servers.FirstOrDefault(); + //if (dnsServer != null) + //{ + // dnsServer.detour = singboxConfig.route.rules.LastOrDefault()?.outbound; + //} + //var dnsRule = singboxConfig.dns?.rules.Where(t => t.outbound != null).FirstOrDefault(); + //if (dnsRule != null) + //{ + // singboxConfig.dns.rules = []; + // singboxConfig.dns.rules.Add(dnsRule); + //} + + //msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); + return 0; } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); + msg = ResUI.FailedGenDefaultConfiguration; + return -1; } - return 0; - } - - private Inbound4Sbox GetInbound(Inbound4Sbox inItem, EInboundProtocol protocol, bool bSocks) - { - var inbound = JsonUtils.DeepCopy(inItem); - inbound.tag = protocol.ToString(); - inbound.listen_port = inItem.listen_port + (int)protocol; - inbound.type = bSocks ? EInboundProtocol.socks.ToString() : EInboundProtocol.http.ToString(); - return inbound; } - private int GenOutbound(ProfileItem node, Outbound4Sbox outbound) + public int GenerateClientMultipleLoadConfig(List selecteds, out SingboxConfig? singboxConfig, out string msg) { + singboxConfig = null; try { - outbound.server = node.address; - outbound.server_port = node.port; - outbound.type = Global.ProtocolTypes[node.configType]; - - switch (node.configType) + if (_config == null) { - case EConfigType.VMess: - { - outbound.uuid = node.id; - outbound.alter_id = node.alterId; - if (Global.VmessSecurities.Contains(node.security)) - { - outbound.security = node.security; - } - else - { - outbound.security = Global.DefaultSecurity; - } + msg = ResUI.CheckServerSettings; + return -1; + } - GenOutboundMux(node, outbound); - break; - } - case EConfigType.Shadowsocks: - { - outbound.method = LazyConfig.Instance.GetShadowsocksSecurities(node).Contains(node.security) ? node.security : Global.None; - outbound.password = node.id; + msg = ResUI.InitialConfiguration; - GenOutboundMux(node, outbound); - break; - } - case EConfigType.Socks: - { - outbound.version = "5"; - if (!Utils.IsNullOrEmpty(node.security) - && !Utils.IsNullOrEmpty(node.id)) - { - outbound.username = node.security; - outbound.password = node.id; - } - break; - } - case EConfigType.Http: + string result = Utils.GetEmbedText(Global.SingboxSampleClient); + string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); + if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) + { + msg = ResUI.FailedGetDefaultConfiguration; + return -1; + } + + singboxConfig = JsonUtils.Deserialize(result); + if (singboxConfig == null) + { + msg = ResUI.FailedGenDefaultConfiguration; + return -1; + } + + GenLog(singboxConfig); + GenInbounds(singboxConfig); + GenRouting(singboxConfig); + GenExperimental(singboxConfig); + singboxConfig.outbounds.RemoveAt(0); + + var tagProxy = new List(); + foreach (var it in selecteds) + { + if (it.configType == EConfigType.Custom) + { + continue; + } + if (it.port <= 0) + { + continue; + } + var item = LazyConfig.Instance.GetProfileItem(it.indexId); + if (item is null) + { + continue; + } + if (it.configType is EConfigType.VMess or EConfigType.VLESS) + { + if (Utils.IsNullOrEmpty(item.id) || !Utils.IsGuidByParse(item.id)) { - if (!Utils.IsNullOrEmpty(node.security) - && !Utils.IsNullOrEmpty(node.id)) - { - outbound.username = node.security; - outbound.password = node.id; - } - break; + continue; } - case EConfigType.VLESS: - { - outbound.uuid = node.id; + } + if (item.configType == EConfigType.Shadowsocks + && !Global.SsSecuritiesInSingbox.Contains(item.security)) + { + continue; + } + if (item.configType == EConfigType.VLESS && !Global.Flows.Contains(item.flow)) + { + continue; + } - outbound.packet_encoding = "xudp"; + //outbound + var outbound = JsonUtils.Deserialize(txtOutbound); + GenOutbound(item, outbound); + outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}"; + singboxConfig.outbounds.Add(outbound); + tagProxy.Add(outbound.tag); + } + if (tagProxy.Count <= 0) + { + msg = ResUI.FailedGenDefaultConfiguration; + return -1; + } - if (Utils.IsNullOrEmpty(node.flow)) - { - GenOutboundMux(node, outbound); - } - else - { - outbound.flow = node.flow; - } - break; - } - case EConfigType.Trojan: - { - outbound.password = node.id; + GenDns(null, singboxConfig); + ConvertGeo2Ruleset(singboxConfig); - GenOutboundMux(node, outbound); - break; - } - case EConfigType.Hysteria2: - { - outbound.password = node.id; + //add urltest outbound + var outUrltest = new Outbound4Sbox + { + type = "urltest", + tag = $"{Global.ProxyTag}-auto", + outbounds = tagProxy, + interrupt_exist_connections = false, + }; + singboxConfig.outbounds.Add(outUrltest); - if (!Utils.IsNullOrEmpty(node.path)) - { - outbound.obfs = new() - { - type = "salamander", - password = node.path.TrimEx(), - }; - } + //add selector outbound + var outSelector = new Outbound4Sbox + { + type = "selector", + tag = Global.ProxyTag, + outbounds = JsonUtils.DeepCopy(tagProxy), + interrupt_exist_connections = false, + }; + outSelector.outbounds.Insert(0, outUrltest.tag); + singboxConfig.outbounds.Add(outSelector); - outbound.up_mbps = _config.hysteriaItem.up_mbps > 0 ? _config.hysteriaItem.up_mbps : null; - outbound.down_mbps = _config.hysteriaItem.down_mbps > 0 ? _config.hysteriaItem.down_mbps : null; - break; - } - case EConfigType.Tuic: - { - outbound.uuid = node.id; - outbound.password = node.security; - outbound.congestion_control = node.headerType; - break; - } - case EConfigType.Wireguard: - { - outbound.private_key = node.id; - outbound.peer_public_key = node.publicKey; - outbound.reserved = Utils.String2List(node.path).Select(int.Parse).ToArray(); - outbound.local_address = [.. Utils.String2List(node.requestHost)]; - outbound.mtu = Utils.ToInt(node.shortId.IsNullOrEmpty() ? Global.TunMtus.FirstOrDefault() : node.shortId); - break; - } + return 0; + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + msg = ResUI.FailedGenDefaultConfiguration; + return -1; + } + } + + public int GenerateClientCustomConfig(ProfileItem node, string? fileName, out string msg) + { + if (node == null || fileName is null) + { + msg = ResUI.CheckServerSettings; + return -1; + } + + msg = ResUI.InitialConfiguration; + + try + { + if (node == null) + { + msg = ResUI.CheckServerSettings; + return -1; } - GenOutboundTls(node, outbound); + if (File.Exists(fileName)) + { + File.Delete(fileName); + } - GenOutboundTransport(node, outbound); + string addressFileName = node.address; + if (string.IsNullOrEmpty(addressFileName)) + { + msg = ResUI.FailedGetDefaultConfiguration; + return -1; + } + if (!File.Exists(addressFileName)) + { + addressFileName = Path.Combine(Utils.GetConfigPath(), addressFileName); + } + if (!File.Exists(addressFileName)) + { + msg = ResUI.FailedReadConfiguration + "1"; + return -1; + } + + var txtFile = File.ReadAllText(addressFileName); + var singboxConfig = JsonUtils.Deserialize(txtFile); + if (singboxConfig == null) + { + msg = ResUI.FailedConversionConfiguration; + return -1; + } + + GenExperimental(singboxConfig); + JsonUtils.ToFile(singboxConfig, fileName, false); + + //check again + if (!File.Exists(fileName)) + { + msg = ResUI.FailedReadConfiguration + "2"; + return -1; + } + + msg = string.Format(ResUI.SuccessfulConfiguration, $"{node.GetSummary()}"); } catch (Exception ex) { Logging.SaveLog(ex.Message, ex); + msg = ResUI.FailedGenDefaultConfiguration; + return -1; } return 0; } - private int GenOutboundMux(ProfileItem node, Outbound4Sbox outbound) + #endregion public gen function + + #region private gen function + + private int GenLog(SingboxConfig singboxConfig) { try { - if (_config.coreBasicItem.muxEnabled && !Utils.IsNullOrEmpty(_config.mux4SboxItem.protocol)) + switch (_config.coreBasicItem.loglevel) { - var mux = new Multiplex4Sbox() - { - enabled = true, - protocol = _config.mux4SboxItem.protocol, - max_connections = _config.mux4SboxItem.max_connections, - }; - outbound.multiplex = mux; + case "debug": + case "info": + case "error": + singboxConfig.log.level = _config.coreBasicItem.loglevel; + break; + + case "warning": + singboxConfig.log.level = "warn"; + break; + + default: + break; + } + if (_config.coreBasicItem.loglevel == Global.None) + { + singboxConfig.log.disabled = true; + } + if (_config.coreBasicItem.logEnabled) + { + var dtNow = DateTime.Now; + singboxConfig.log.output = Utils.GetLogPath($"sbox_{dtNow:yyyy-MM-dd}.txt"); } } catch (Exception ex) @@ -365,47 +458,92 @@ private int GenOutboundMux(ProfileItem node, Outbound4Sbox outbound) return 0; } - private int GenOutboundTls(ProfileItem node, Outbound4Sbox outbound) + private int GenInbounds(SingboxConfig singboxConfig) { try { - if (node.streamSecurity == Global.StreamSecurityReality || node.streamSecurity == Global.StreamSecurity) + var listen = "::"; + singboxConfig.inbounds = []; + + if (!_config.tunModeItem.enableTun + || (_config.tunModeItem.enableTun && _config.tunModeItem.enableExInbound && _config.runningCoreType == ECoreType.sing_box)) { - var server_name = string.Empty; - if (!Utils.IsNullOrEmpty(node.sni)) - { - server_name = node.sni; - } - else if (!Utils.IsNullOrEmpty(node.requestHost)) - { - server_name = Utils.String2List(node.requestHost)[0]; - } - var tls = new Tls4Sbox() + var inbound = new Inbound4Sbox() { - enabled = true, - server_name = server_name, - insecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? _config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure), - alpn = node.GetAlpn(), - }; - if (!Utils.IsNullOrEmpty(node.fingerprint)) + type = EInboundProtocol.socks.ToString(), + tag = EInboundProtocol.socks.ToString(), + listen = Global.Loopback, + }; + singboxConfig.inbounds.Add(inbound); + + inbound.listen_port = LazyConfig.Instance.GetLocalPort(EInboundProtocol.socks); + inbound.sniff = _config.inbound[0].sniffingEnabled; + inbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled; + inbound.domain_strategy = Utils.IsNullOrEmpty(_config.routingBasicItem.domainStrategy4Singbox) ? null : _config.routingBasicItem.domainStrategy4Singbox; + + if (_config.routingBasicItem.enableRoutingAdvanced) { - tls.utls = new Utls4Sbox() + var routing = ConfigHandler.GetDefaultRouting(_config); + if (!Utils.IsNullOrEmpty(routing.domainStrategy4Singbox)) { - enabled = true, - fingerprint = node.fingerprint.IsNullOrEmpty() ? _config.coreBasicItem.defFingerprint : node.fingerprint - }; + inbound.domain_strategy = routing.domainStrategy4Singbox; + } } - if (node.streamSecurity == Global.StreamSecurityReality) + + //http + var inbound2 = GetInbound(inbound, EInboundProtocol.http, false); + singboxConfig.inbounds.Add(inbound2); + + if (_config.inbound[0].allowLANConn) { - tls.reality = new Reality4Sbox() + if (_config.inbound[0].newPort4LAN) { - enabled = true, - public_key = node.publicKey, - short_id = node.shortId - }; - tls.insecure = false; + var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true); + inbound3.listen = listen; + singboxConfig.inbounds.Add(inbound3); + + var inbound4 = GetInbound(inbound, EInboundProtocol.http2, false); + inbound4.listen = listen; + singboxConfig.inbounds.Add(inbound4); + + //auth + if (!Utils.IsNullOrEmpty(_config.inbound[0].user) && !Utils.IsNullOrEmpty(_config.inbound[0].pass)) + { + inbound3.users = new() { new() { username = _config.inbound[0].user, password = _config.inbound[0].pass } }; + inbound4.users = new() { new() { username = _config.inbound[0].user, password = _config.inbound[0].pass } }; + } + } + else + { + inbound.listen = listen; + inbound2.listen = listen; + } } - outbound.tls = tls; + } + + if (_config.tunModeItem.enableTun) + { + if (_config.tunModeItem.mtu <= 0) + { + _config.tunModeItem.mtu = Utils.ToInt(Global.TunMtus[0]); + } + if (Utils.IsNullOrEmpty(_config.tunModeItem.stack)) + { + _config.tunModeItem.stack = Global.TunStacks[0]; + } + + var tunInbound = JsonUtils.Deserialize(Utils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { }; + tunInbound.mtu = _config.tunModeItem.mtu; + tunInbound.strict_route = _config.tunModeItem.strictRoute; + tunInbound.stack = _config.tunModeItem.stack; + tunInbound.sniff = _config.inbound[0].sniffingEnabled; + //tunInbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled; + if (_config.tunModeItem.enableIPv6Address == false) + { + tunInbound.inet6_address = null; + } + + singboxConfig.inbounds.Add(tunInbound); } } catch (Exception ex) @@ -415,75 +553,131 @@ private int GenOutboundTls(ProfileItem node, Outbound4Sbox outbound) return 0; } - private int GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound) + private Inbound4Sbox GetInbound(Inbound4Sbox inItem, EInboundProtocol protocol, bool bSocks) + { + var inbound = JsonUtils.DeepCopy(inItem); + inbound.tag = protocol.ToString(); + inbound.listen_port = inItem.listen_port + (int)protocol; + inbound.type = bSocks ? EInboundProtocol.socks.ToString() : EInboundProtocol.http.ToString(); + return inbound; + } + + private int GenOutbound(ProfileItem node, Outbound4Sbox outbound) { try { - var transport = new Transport4Sbox(); + outbound.server = node.address; + outbound.server_port = node.port; + outbound.type = Global.ProtocolTypes[node.configType]; - switch (node.GetNetwork()) + switch (node.configType) { - case nameof(ETransport.h2): - transport.type = nameof(ETransport.http); - transport.host = Utils.IsNullOrEmpty(node.requestHost) ? null : Utils.String2List(node.requestHost); - transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path; - break; - - case nameof(ETransport.tcp): //http - if (node.headerType == Global.TcpHeaderHttp) + case EConfigType.VMess: { - if (node.configType == EConfigType.Shadowsocks) + outbound.uuid = node.id; + outbound.alter_id = node.alterId; + if (Global.VmessSecurities.Contains(node.security)) { - outbound.plugin = "obfs-local"; - outbound.plugin_opts = $"obfs=http;obfs-host={node.requestHost};"; + outbound.security = node.security; } else { - transport.type = nameof(ETransport.http); - transport.host = Utils.IsNullOrEmpty(node.requestHost) ? null : Utils.String2List(node.requestHost); - transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path; + outbound.security = Global.DefaultSecurity; } + + GenOutboundMux(node, outbound); + break; } - break; + case EConfigType.Shadowsocks: + { + outbound.method = LazyConfig.Instance.GetShadowsocksSecurities(node).Contains(node.security) ? node.security : Global.None; + outbound.password = node.id; - case nameof(ETransport.ws): - transport.type = nameof(ETransport.ws); - transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path; - if (!Utils.IsNullOrEmpty(node.requestHost)) + GenOutboundMux(node, outbound); + break; + } + case EConfigType.Socks: { - transport.headers = new() + outbound.version = "5"; + if (!Utils.IsNullOrEmpty(node.security) + && !Utils.IsNullOrEmpty(node.id)) { - Host = node.requestHost - }; + outbound.username = node.security; + outbound.password = node.id; + } + break; } - break; + case EConfigType.Http: + { + if (!Utils.IsNullOrEmpty(node.security) + && !Utils.IsNullOrEmpty(node.id)) + { + outbound.username = node.security; + outbound.password = node.id; + } + break; + } + case EConfigType.VLESS: + { + outbound.uuid = node.id; - case nameof(ETransport.httpupgrade): - transport.type = nameof(ETransport.httpupgrade); - transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path; - transport.host = Utils.IsNullOrEmpty(node.requestHost) ? null : node.requestHost; + outbound.packet_encoding = "xudp"; - break; + if (Utils.IsNullOrEmpty(node.flow)) + { + GenOutboundMux(node, outbound); + } + else + { + outbound.flow = node.flow; + } + break; + } + case EConfigType.Trojan: + { + outbound.password = node.id; - case nameof(ETransport.quic): - transport.type = nameof(ETransport.quic); - break; + GenOutboundMux(node, outbound); + break; + } + case EConfigType.Hysteria2: + { + outbound.password = node.id; - case nameof(ETransport.grpc): - transport.type = nameof(ETransport.grpc); - transport.service_name = node.path; - transport.idle_timeout = _config.grpcItem.idle_timeout.ToString("##s"); - transport.ping_timeout = _config.grpcItem.health_check_timeout.ToString("##s"); - transport.permit_without_stream = _config.grpcItem.permit_without_stream; - break; + if (!Utils.IsNullOrEmpty(node.path)) + { + outbound.obfs = new() + { + type = "salamander", + password = node.path.TrimEx(), + }; + } - default: - break; - } - if (transport.type != null) - { - outbound.transport = transport; + outbound.up_mbps = _config.hysteriaItem.up_mbps > 0 ? _config.hysteriaItem.up_mbps : null; + outbound.down_mbps = _config.hysteriaItem.down_mbps > 0 ? _config.hysteriaItem.down_mbps : null; + break; + } + case EConfigType.Tuic: + { + outbound.uuid = node.id; + outbound.password = node.security; + outbound.congestion_control = node.headerType; + break; + } + case EConfigType.Wireguard: + { + outbound.private_key = node.id; + outbound.peer_public_key = node.publicKey; + outbound.reserved = Utils.String2List(node.path).Select(int.Parse).ToArray(); + outbound.local_address = [.. Utils.String2List(node.requestHost)]; + outbound.mtu = Utils.ToInt(node.shortId.IsNullOrEmpty() ? Global.TunMtus.FirstOrDefault() : node.shortId); + break; + } } + + GenOutboundTls(node, outbound); + + GenOutboundTransport(node, outbound); } catch (Exception ex) { @@ -492,21 +686,170 @@ private int GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound) return 0; } - private int GenMoreOutbounds(ProfileItem node, SingboxConfig singboxConfig) + private int GenOutboundMux(ProfileItem node, Outbound4Sbox outbound) { - if (node.subid.IsNullOrEmpty()) - { - return 0; - } try { - var subItem = LazyConfig.Instance.GetSubItem(node.subid); - if (subItem is null) + if (_config.coreBasicItem.muxEnabled && !Utils.IsNullOrEmpty(_config.mux4SboxItem.protocol)) { - return 0; + var mux = new Multiplex4Sbox() + { + enabled = true, + protocol = _config.mux4SboxItem.protocol, + max_connections = _config.mux4SboxItem.max_connections, + }; + outbound.multiplex = mux; } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return 0; + } - //current proxy + private int GenOutboundTls(ProfileItem node, Outbound4Sbox outbound) + { + try + { + if (node.streamSecurity == Global.StreamSecurityReality || node.streamSecurity == Global.StreamSecurity) + { + var server_name = string.Empty; + if (!Utils.IsNullOrEmpty(node.sni)) + { + server_name = node.sni; + } + else if (!Utils.IsNullOrEmpty(node.requestHost)) + { + server_name = Utils.String2List(node.requestHost)[0]; + } + var tls = new Tls4Sbox() + { + enabled = true, + server_name = server_name, + insecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? _config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure), + alpn = node.GetAlpn(), + }; + if (!Utils.IsNullOrEmpty(node.fingerprint)) + { + tls.utls = new Utls4Sbox() + { + enabled = true, + fingerprint = node.fingerprint.IsNullOrEmpty() ? _config.coreBasicItem.defFingerprint : node.fingerprint + }; + } + if (node.streamSecurity == Global.StreamSecurityReality) + { + tls.reality = new Reality4Sbox() + { + enabled = true, + public_key = node.publicKey, + short_id = node.shortId + }; + tls.insecure = false; + } + outbound.tls = tls; + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return 0; + } + + private int GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound) + { + try + { + var transport = new Transport4Sbox(); + + switch (node.GetNetwork()) + { + case nameof(ETransport.h2): + transport.type = nameof(ETransport.http); + transport.host = Utils.IsNullOrEmpty(node.requestHost) ? null : Utils.String2List(node.requestHost); + transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path; + break; + + case nameof(ETransport.tcp): //http + if (node.headerType == Global.TcpHeaderHttp) + { + if (node.configType == EConfigType.Shadowsocks) + { + outbound.plugin = "obfs-local"; + outbound.plugin_opts = $"obfs=http;obfs-host={node.requestHost};"; + } + else + { + transport.type = nameof(ETransport.http); + transport.host = Utils.IsNullOrEmpty(node.requestHost) ? null : Utils.String2List(node.requestHost); + transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path; + } + } + break; + + case nameof(ETransport.ws): + transport.type = nameof(ETransport.ws); + transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path; + if (!Utils.IsNullOrEmpty(node.requestHost)) + { + transport.headers = new() + { + Host = node.requestHost + }; + } + break; + + case nameof(ETransport.httpupgrade): + transport.type = nameof(ETransport.httpupgrade); + transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path; + transport.host = Utils.IsNullOrEmpty(node.requestHost) ? null : node.requestHost; + + break; + + case nameof(ETransport.quic): + transport.type = nameof(ETransport.quic); + break; + + case nameof(ETransport.grpc): + transport.type = nameof(ETransport.grpc); + transport.service_name = node.path; + transport.idle_timeout = _config.grpcItem.idle_timeout.ToString("##s"); + transport.ping_timeout = _config.grpcItem.health_check_timeout.ToString("##s"); + transport.permit_without_stream = _config.grpcItem.permit_without_stream; + break; + + default: + break; + } + if (transport.type != null) + { + outbound.transport = transport; + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return 0; + } + + private int GenMoreOutbounds(ProfileItem node, SingboxConfig singboxConfig) + { + if (node.subid.IsNullOrEmpty()) + { + return 0; + } + try + { + var subItem = LazyConfig.Instance.GetSubItem(node.subid); + if (subItem is null) + { + return 0; + } + + //current proxy var outbound = singboxConfig.outbounds[0]; var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); @@ -1009,284 +1352,5 @@ static void AddRuleSets(List ruleSets, List? rule_set) } #endregion private gen function - - #region Gen speedtest config - - public int GenerateClientSpeedtestConfig(List selecteds, out SingboxConfig? singboxConfig, out string msg) - { - singboxConfig = null; - try - { - if (_config == null) - { - msg = ResUI.CheckServerSettings; - return -1; - } - - msg = ResUI.InitialConfiguration; - - string result = Utils.GetEmbedText(Global.SingboxSampleClient); - string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); - if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) - { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; - } - - singboxConfig = JsonUtils.Deserialize(result); - if (singboxConfig == null) - { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; - } - List lstIpEndPoints = new(); - List lstTcpConns = new(); - try - { - lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()); - lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners()); - lstTcpConns.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections()); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - - GenLog(singboxConfig); - //GenDns(new(), singboxConfig); - singboxConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts. - singboxConfig.outbounds.RemoveAt(0); - - int httpPort = LazyConfig.Instance.GetLocalPort(EInboundProtocol.speedtest); - - foreach (var it in selecteds) - { - if (it.configType == EConfigType.Custom) - { - continue; - } - if (it.port <= 0) - { - continue; - } - if (it.configType is EConfigType.VMess or EConfigType.VLESS) - { - var item2 = LazyConfig.Instance.GetProfileItem(it.indexId); - if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id)) - { - continue; - } - } - - //find unused port - var port = httpPort; - for (int k = httpPort; k < Global.MaxPort; k++) - { - if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0) - { - continue; - } - if (lstTcpConns?.FindIndex(_it => _it.LocalEndPoint.Port == k) >= 0) - { - continue; - } - //found - port = k; - httpPort = port + 1; - break; - } - - //Port In Used - if (lstIpEndPoints?.FindIndex(_it => _it.Port == port) >= 0) - { - continue; - } - it.port = port; - it.allowTest = true; - - //inbound - Inbound4Sbox inbound = new() - { - listen = Global.Loopback, - listen_port = port, - type = EInboundProtocol.http.ToString(), - }; - inbound.tag = inbound.type + inbound.listen_port.ToString(); - singboxConfig.inbounds.Add(inbound); - - //outbound - var item = LazyConfig.Instance.GetProfileItem(it.indexId); - if (item is null) - { - continue; - } - if (item.configType == EConfigType.Shadowsocks - && !Global.SsSecuritiesInSingbox.Contains(item.security)) - { - continue; - } - if (item.configType == EConfigType.VLESS - && !Global.Flows.Contains(item.flow)) - { - continue; - } - - var outbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(item, outbound); - outbound.tag = Global.ProxyTag + inbound.listen_port.ToString(); - singboxConfig.outbounds.Add(outbound); - - //rule - Rule4Sbox rule = new() - { - inbound = new List { inbound.tag }, - outbound = outbound.tag - }; - singboxConfig.route.rules.Add(rule); - } - - GenDnsDomains(null, singboxConfig, null); - //var dnsServer = singboxConfig.dns?.servers.FirstOrDefault(); - //if (dnsServer != null) - //{ - // dnsServer.detour = singboxConfig.route.rules.LastOrDefault()?.outbound; - //} - //var dnsRule = singboxConfig.dns?.rules.Where(t => t.outbound != null).FirstOrDefault(); - //if (dnsRule != null) - //{ - // singboxConfig.dns.rules = []; - // singboxConfig.dns.rules.Add(dnsRule); - //} - - //msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); - return 0; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; - } - } - - #endregion Gen speedtest config - - #region Gen Multiple Load config - - public int GenerateClientMultipleLoadConfig(List selecteds, out SingboxConfig? singboxConfig, out string msg) - { - singboxConfig = null; - try - { - if (_config == null) - { - msg = ResUI.CheckServerSettings; - return -1; - } - - msg = ResUI.InitialConfiguration; - - string result = Utils.GetEmbedText(Global.SingboxSampleClient); - string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound); - if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) - { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; - } - - singboxConfig = JsonUtils.Deserialize(result); - if (singboxConfig == null) - { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; - } - - GenLog(singboxConfig); - GenInbounds(singboxConfig); - GenRouting(singboxConfig); - GenExperimental(singboxConfig); - singboxConfig.outbounds.RemoveAt(0); - - var tagProxy = new List(); - foreach (var it in selecteds) - { - if (it.configType == EConfigType.Custom) - { - continue; - } - if (it.port <= 0) - { - continue; - } - var item = LazyConfig.Instance.GetProfileItem(it.indexId); - if (item is null) - { - continue; - } - if (it.configType is EConfigType.VMess or EConfigType.VLESS) - { - if (Utils.IsNullOrEmpty(item.id) || !Utils.IsGuidByParse(item.id)) - { - continue; - } - } - if (item.configType == EConfigType.Shadowsocks - && !Global.SsSecuritiesInSingbox.Contains(item.security)) - { - continue; - } - if (item.configType == EConfigType.VLESS && !Global.Flows.Contains(item.flow)) - { - continue; - } - - //outbound - var outbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(item, outbound); - outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}"; - singboxConfig.outbounds.Add(outbound); - tagProxy.Add(outbound.tag); - } - if (tagProxy.Count <= 0) - { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; - } - - GenDns(null, singboxConfig); - ConvertGeo2Ruleset(singboxConfig); - - //add urltest outbound - var outUrltest = new Outbound4Sbox - { - type = "urltest", - tag = $"{Global.ProxyTag}-auto", - outbounds = tagProxy, - interrupt_exist_connections = false, - }; - singboxConfig.outbounds.Add(outUrltest); - - //add selector outbound - var outSelector = new Outbound4Sbox - { - type = "selector", - tag = Global.ProxyTag, - outbounds = JsonUtils.DeepCopy(tagProxy), - interrupt_exist_connections = false, - }; - outSelector.outbounds.Insert(0, outUrltest.tag); - singboxConfig.outbounds.Add(outSelector); - - return 0; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; - } - } - - #endregion Gen Multiple config } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigV2ray.cs b/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigV2ray.cs index d720898c62..3323e445db 100644 --- a/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigV2ray.cs +++ b/v2rayN/v2rayN/Handler/CoreConfig/CoreConfigV2ray.cs @@ -16,6 +16,8 @@ public CoreConfigV2ray(Config config) _config = config; } + #region public gen function + public int GenerateClientConfigContent(ProfileItem node, out V2rayConfig? v2rayConfig, out string msg) { v2rayConfig = null; @@ -69,6 +71,152 @@ public int GenerateClientConfigContent(ProfileItem node, out V2rayConfig? v2rayC return 0; } + public int GenerateClientSpeedtestConfig(List selecteds, out V2rayConfig? v2rayConfig, out string msg) + { + v2rayConfig = null; + try + { + if (_config == null) + { + msg = ResUI.CheckServerSettings; + return -1; + } + + msg = ResUI.InitialConfiguration; + + string result = Utils.GetEmbedText(Global.V2raySampleClient); + string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound); + if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) + { + msg = ResUI.FailedGetDefaultConfiguration; + return -1; + } + + v2rayConfig = JsonUtils.Deserialize(result); + if (v2rayConfig == null) + { + msg = ResUI.FailedGenDefaultConfiguration; + return -1; + } + List lstIpEndPoints = new(); + List lstTcpConns = new(); + try + { + lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()); + lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners()); + lstTcpConns.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections()); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + + GenLog(v2rayConfig); + v2rayConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts. + v2rayConfig.outbounds.RemoveAt(0); + + int httpPort = LazyConfig.Instance.GetLocalPort(EInboundProtocol.speedtest); + + foreach (var it in selecteds) + { + if (it.configType == EConfigType.Custom) + { + continue; + } + if (it.port <= 0) + { + continue; + } + if (it.configType is EConfigType.VMess or EConfigType.VLESS) + { + var item2 = LazyConfig.Instance.GetProfileItem(it.indexId); + if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id)) + { + continue; + } + } + + //find unused port + var port = httpPort; + for (int k = httpPort; k < Global.MaxPort; k++) + { + if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0) + { + continue; + } + if (lstTcpConns?.FindIndex(_it => _it.LocalEndPoint.Port == k) >= 0) + { + continue; + } + //found + port = k; + httpPort = port + 1; + break; + } + + //Port In Used + if (lstIpEndPoints?.FindIndex(_it => _it.Port == port) >= 0) + { + continue; + } + it.port = port; + it.allowTest = true; + + //inbound + Inbounds4Ray inbound = new() + { + listen = Global.Loopback, + port = port, + protocol = EInboundProtocol.http.ToString(), + }; + inbound.tag = inbound.protocol + inbound.port.ToString(); + v2rayConfig.inbounds.Add(inbound); + + //outbound + var item = LazyConfig.Instance.GetProfileItem(it.indexId); + if (item is null) + { + continue; + } + if (item.configType == EConfigType.Shadowsocks + && !Global.SsSecuritiesInXray.Contains(item.security)) + { + continue; + } + if (item.configType == EConfigType.VLESS + && !Global.Flows.Contains(item.flow)) + { + continue; + } + + var outbound = JsonUtils.Deserialize(txtOutbound); + GenOutbound(item, outbound); + outbound.tag = Global.ProxyTag + inbound.port.ToString(); + v2rayConfig.outbounds.Add(outbound); + + //rule + RulesItem4Ray rule = new() + { + inboundTag = new List { inbound.tag }, + outboundTag = outbound.tag, + type = "field" + }; + v2rayConfig.routing.rules.Add(rule); + } + + //msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); + return 0; + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + msg = ResUI.FailedGenDefaultConfiguration; + return -1; + } + } + + #endregion public gen function + #region private gen function private int GenLog(V2rayConfig v2rayConfig) @@ -973,153 +1121,5 @@ private int GenMoreOutbounds(ProfileItem node, V2rayConfig v2rayConfig) } #endregion private gen function - - #region Gen speedtest config - - public int GenerateClientSpeedtestConfig(List selecteds, out V2rayConfig? v2rayConfig, out string msg) - { - v2rayConfig = null; - try - { - if (_config == null) - { - msg = ResUI.CheckServerSettings; - return -1; - } - - msg = ResUI.InitialConfiguration; - - string result = Utils.GetEmbedText(Global.V2raySampleClient); - string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound); - if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty()) - { - msg = ResUI.FailedGetDefaultConfiguration; - return -1; - } - - v2rayConfig = JsonUtils.Deserialize(result); - if (v2rayConfig == null) - { - msg = ResUI.FailedGenDefaultConfiguration; - return -1; - } - List lstIpEndPoints = new(); - List lstTcpConns = new(); - try - { - lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()); - lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners()); - lstTcpConns.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections()); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - - GenLog(v2rayConfig); - v2rayConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts. - v2rayConfig.outbounds.RemoveAt(0); - - int httpPort = LazyConfig.Instance.GetLocalPort(EInboundProtocol.speedtest); - - foreach (var it in selecteds) - { - if (it.configType == EConfigType.Custom) - { - continue; - } - if (it.port <= 0) - { - continue; - } - if (it.configType is EConfigType.VMess or EConfigType.VLESS) - { - var item2 = LazyConfig.Instance.GetProfileItem(it.indexId); - if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id)) - { - continue; - } - } - - //find unused port - var port = httpPort; - for (int k = httpPort; k < Global.MaxPort; k++) - { - if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0) - { - continue; - } - if (lstTcpConns?.FindIndex(_it => _it.LocalEndPoint.Port == k) >= 0) - { - continue; - } - //found - port = k; - httpPort = port + 1; - break; - } - - //Port In Used - if (lstIpEndPoints?.FindIndex(_it => _it.Port == port) >= 0) - { - continue; - } - it.port = port; - it.allowTest = true; - - //inbound - Inbounds4Ray inbound = new() - { - listen = Global.Loopback, - port = port, - protocol = EInboundProtocol.http.ToString(), - }; - inbound.tag = inbound.protocol + inbound.port.ToString(); - v2rayConfig.inbounds.Add(inbound); - - //outbound - var item = LazyConfig.Instance.GetProfileItem(it.indexId); - if (item is null) - { - continue; - } - if (item.configType == EConfigType.Shadowsocks - && !Global.SsSecuritiesInXray.Contains(item.security)) - { - continue; - } - if (item.configType == EConfigType.VLESS - && !Global.Flows.Contains(item.flow)) - { - continue; - } - - var outbound = JsonUtils.Deserialize(txtOutbound); - GenOutbound(item, outbound); - outbound.tag = Global.ProxyTag + inbound.port.ToString(); - v2rayConfig.outbounds.Add(outbound); - - //rule - RulesItem4Ray rule = new() - { - inboundTag = new List { inbound.tag }, - outboundTag = outbound.tag, - type = "field" - }; - v2rayConfig.routing.rules.Add(rule); - } - - //msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); - return 0; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - msg = ResUI.FailedGenDefaultConfiguration; - return -1; - } - } - - #endregion Gen speedtest config } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Resx/ResUI.Designer.cs b/v2rayN/v2rayN/Resx/ResUI.Designer.cs index 6fd8ee18c1..ace2d10e40 100644 --- a/v2rayN/v2rayN/Resx/ResUI.Designer.cs +++ b/v2rayN/v2rayN/Resx/ResUI.Designer.cs @@ -1060,7 +1060,7 @@ public static string menuPromotion { } /// - /// 查找类似 All Node Latency Test 的本地化字符串。 + /// 查找类似 Latency Test 的本地化字符串。 /// public static string menuProxiesDelaytest { get { diff --git a/v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx b/v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx index 83fd500e3a..83793e39e3 100644 --- a/v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx @@ -1061,7 +1061,7 @@ قانون - All Node Latency Test + Latency Test Part Node Latency Test diff --git a/v2rayN/v2rayN/Resx/ResUI.resx b/v2rayN/v2rayN/Resx/ResUI.resx index b83b6a7f9c..43e8237968 100644 --- a/v2rayN/v2rayN/Resx/ResUI.resx +++ b/v2rayN/v2rayN/Resx/ResUI.resx @@ -1286,7 +1286,7 @@ Rule - All Node Latency Test + Latency Test Part Node Latency Test diff --git a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx index e041b2cae0..dbed5c62fc 100644 --- a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx @@ -1283,7 +1283,7 @@ 规则 - 全部节点延迟测试 + 延迟测试 当前部分节点延迟测试 diff --git a/v2rayN/v2rayN/Views/ClashProxiesView.xaml b/v2rayN/v2rayN/Views/ClashProxiesView.xaml index a541d3f384..05d99e6fae 100644 --- a/v2rayN/v2rayN/Views/ClashProxiesView.xaml +++ b/v2rayN/v2rayN/Views/ClashProxiesView.xaml @@ -26,7 +26,7 @@ VerticalAlignment="Center" ClipToBounds="True" Style="{StaticResource MaterialDesignToolBar}"> - + + - - - - - - @@ -98,20 +102,23 @@ - + - - + - + + vm.ProxyDetails, v => v.lstProxyDetails.ItemsSource).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedDetail, v => v.lstProxyDetails.SelectedItem).DisposeWith(disposables); - this.BindCommand(ViewModel, vm => vm.ProxiesReloadCmd, v => v.menuReload).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ProxiesReloadCmd, v => v.menuProxiesReload).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ProxiesDelaytestCmd, v => v.menuProxiesDelaytest).DisposeWith(disposables);