mirror of
https://github.com/2dust/v2rayN.git
synced 2025-04-18 21:22:23 +00:00
Merge e3831d1695
into 456ffb200a
This commit is contained in:
commit
84e43f46e2
31 changed files with 641 additions and 132 deletions
|
@ -427,11 +427,11 @@ public class Utils
|
|||
return false;
|
||||
}
|
||||
|
||||
public static int GetFreePort(int defaultPort = 9090)
|
||||
public static int GetFreePort(int defaultPort = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Utils.PortInUse(defaultPort))
|
||||
if (!(defaultPort == 0 || Utils.PortInUse(defaultPort)))
|
||||
{
|
||||
return defaultPort;
|
||||
}
|
||||
|
|
|
@ -11,5 +11,6 @@ public enum EConfigType
|
|||
Hysteria2 = 7,
|
||||
TUIC = 8,
|
||||
WireGuard = 9,
|
||||
HTTP = 10
|
||||
HTTP = 10,
|
||||
Anytls = 11
|
||||
}
|
||||
|
|
|
@ -169,7 +169,8 @@ public class Global
|
|||
{ EConfigType.Trojan, "trojan://" },
|
||||
{ EConfigType.Hysteria2, "hysteria2://" },
|
||||
{ EConfigType.TUIC, "tuic://" },
|
||||
{ EConfigType.WireGuard, "wireguard://" }
|
||||
{ EConfigType.WireGuard, "wireguard://" },
|
||||
{ EConfigType.Anytls, "anytls://" }
|
||||
};
|
||||
|
||||
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
|
||||
|
@ -182,7 +183,8 @@ public class Global
|
|||
{ EConfigType.Trojan, "trojan" },
|
||||
{ EConfigType.Hysteria2, "hysteria2" },
|
||||
{ EConfigType.TUIC, "tuic" },
|
||||
{ EConfigType.WireGuard, "wireguard" }
|
||||
{ EConfigType.WireGuard, "wireguard" },
|
||||
{ EConfigType.Anytls, "anytls" }
|
||||
};
|
||||
|
||||
public static readonly List<string> VmessSecurities =
|
||||
|
|
|
@ -259,6 +259,7 @@ public class ConfigHandler
|
|||
EConfigType.Hysteria2 => await AddHysteria2Server(config, item),
|
||||
EConfigType.TUIC => await AddTuicServer(config, item),
|
||||
EConfigType.WireGuard => await AddWireguardServer(config, item),
|
||||
EConfigType.Anytls => await AddAnytlsServer(config, item),
|
||||
_ => -1,
|
||||
};
|
||||
return ret;
|
||||
|
@ -783,6 +784,35 @@ public class ConfigHandler
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add or edit a Anytls server
|
||||
/// Validates and processes Anytls-specific settings
|
||||
/// </summary>
|
||||
/// <param name="config">Current configuration</param>
|
||||
/// <param name="profileItem">Anytls profile to add</param>
|
||||
/// <param name="toFile">Whether to save to file</param>
|
||||
/// <returns>0 if successful, -1 if failed</returns>
|
||||
public static async Task<int> AddAnytlsServer(Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.ConfigType = EConfigType.Anytls;
|
||||
profileItem.CoreType = ECoreType.sing_box;
|
||||
|
||||
profileItem.Address = profileItem.Address.TrimEx();
|
||||
profileItem.Id = profileItem.Id.TrimEx();
|
||||
profileItem.Security = profileItem.Security.TrimEx();
|
||||
profileItem.Network = string.Empty;
|
||||
if (profileItem.StreamSecurity.IsNullOrEmpty())
|
||||
{
|
||||
profileItem.StreamSecurity = Global.StreamSecurity;
|
||||
}
|
||||
if (profileItem.Id.IsNullOrEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
await AddServerCommon(config, profileItem, toFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort the server list by the specified column
|
||||
/// Updates the sort order in the profile extension data
|
||||
|
@ -1277,6 +1307,7 @@ public class ConfigHandler
|
|||
EConfigType.Hysteria2 => await AddHysteria2Server(config, profileItem, false),
|
||||
EConfigType.TUIC => await AddTuicServer(config, profileItem, false),
|
||||
EConfigType.WireGuard => await AddWireguardServer(config, profileItem, false),
|
||||
EConfigType.Anytls => await AddAnytlsServer(config, profileItem, false),
|
||||
_ => -1,
|
||||
};
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ public class CoreHandler
|
|||
|
||||
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
||||
{
|
||||
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC) ? ECoreType.sing_box : ECoreType.Xray;
|
||||
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls) ? ECoreType.sing_box : ECoreType.Xray;
|
||||
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
|
||||
var configPath = Utils.GetBinConfigPath(fileName);
|
||||
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
||||
|
|
54
v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs
Normal file
54
v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using static QRCoder.PayloadGenerator;
|
||||
|
||||
namespace ServiceLib.Handler.Fmt;
|
||||
public class AnytlsFmt : BaseFmt
|
||||
{
|
||||
public static ProfileItem? Resolve(string str, out string msg)
|
||||
{
|
||||
msg = ResUI.ConfigurationFormatIncorrect;
|
||||
|
||||
var parsedUrl = Utils.TryUri(str);
|
||||
if (parsedUrl == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ProfileItem item = new()
|
||||
{
|
||||
ConfigType = EConfigType.Anytls,
|
||||
Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
|
||||
Address = parsedUrl.IdnHost,
|
||||
Port = parsedUrl.Port,
|
||||
};
|
||||
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
|
||||
item.Id = rawUserInfo;
|
||||
|
||||
var query = Utils.ParseQueryString(parsedUrl.Query);
|
||||
item.Sni = query["sni"] ?? Global.None;
|
||||
item.AllowInsecure = (query["insecure"] ?? "") == "1" ? "true" : "false";
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public static string? ToUri(ProfileItem? item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var remark = string.Empty;
|
||||
if (item.Remarks.IsNotEmpty())
|
||||
{
|
||||
remark = "#" + Utils.UrlEncode(item.Remarks);
|
||||
}
|
||||
var pw = item.Id;
|
||||
var dicQuery = new Dictionary<string, string>();
|
||||
if (item.Sni.IsNotEmpty())
|
||||
{
|
||||
dicQuery.Add("sni", item.Sni);
|
||||
}
|
||||
dicQuery.Add("insecure", item.AllowInsecure.ToLower() == "true" ? "1" : "0");
|
||||
|
||||
return ToUri(EConfigType.Anytls, item.Address, item.Port, pw, dicQuery, remark);
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ public class FmtHandler
|
|||
EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item),
|
||||
EConfigType.TUIC => TuicFmt.ToUri(item),
|
||||
EConfigType.WireGuard => WireguardFmt.ToUri(item),
|
||||
EConfigType.Anytls => AnytlsFmt.ToUri(item),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
|
@ -75,6 +76,10 @@ public class FmtHandler
|
|||
{
|
||||
return WireguardFmt.Resolve(str, out msg);
|
||||
}
|
||||
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Anytls]))
|
||||
{
|
||||
return AnytlsFmt.Resolve(str, out msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = ResUI.NonvmessOrssProtocol;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ServiceLib.Models;
|
||||
|
||||
public class SingboxConfig
|
||||
|
@ -6,6 +8,7 @@ public class SingboxConfig
|
|||
public Dns4Sbox? dns { get; set; }
|
||||
public List<Inbound4Sbox> inbounds { get; set; }
|
||||
public List<Outbound4Sbox> outbounds { get; set; }
|
||||
public List<Endpoints4Sbox>? endpoints { get; set; }
|
||||
public Route4Sbox route { get; set; }
|
||||
public Experimental4Sbox? experimental { get; set; }
|
||||
}
|
||||
|
@ -37,6 +40,7 @@ public class Route4Sbox
|
|||
public bool? auto_detect_interface { get; set; }
|
||||
public List<Rule4Sbox> rules { get; set; }
|
||||
public List<Ruleset4Sbox>? rule_set { get; set; }
|
||||
public string? final { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
@ -67,6 +71,9 @@ public class Rule4Sbox
|
|||
public List<string>? process_name { get; set; }
|
||||
public List<string>? rule_set { get; set; }
|
||||
public List<Rule4Sbox>? rules { get; set; }
|
||||
public string? action { get; set; }
|
||||
public string? strategy { get; set; }
|
||||
public List<string>? sniffer { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
@ -76,7 +83,6 @@ public class Inbound4Sbox
|
|||
public string tag { get; set; }
|
||||
public string listen { get; set; }
|
||||
public int? listen_port { get; set; }
|
||||
public string? domain_strategy { get; set; }
|
||||
public string interface_name { get; set; }
|
||||
public List<string>? address { get; set; }
|
||||
public int? mtu { get; set; }
|
||||
|
@ -84,8 +90,6 @@ public class Inbound4Sbox
|
|||
public bool? strict_route { get; set; }
|
||||
public bool? endpoint_independent_nat { get; set; }
|
||||
public string? stack { get; set; }
|
||||
public bool? sniff { get; set; }
|
||||
public bool? sniff_override_destination { get; set; }
|
||||
public List<User4Sbox> users { get; set; }
|
||||
}
|
||||
|
||||
|
@ -121,11 +125,6 @@ public class Outbound4Sbox
|
|||
public string? version { get; set; }
|
||||
public string? network { get; set; }
|
||||
public string? packet_encoding { get; set; }
|
||||
public List<string>? local_address { get; set; }
|
||||
public string? private_key { get; set; }
|
||||
public string? peer_public_key { get; set; }
|
||||
public List<int>? reserved { get; set; }
|
||||
public int? mtu { get; set; }
|
||||
public string? plugin { get; set; }
|
||||
public string? plugin_opts { get; set; }
|
||||
public Tls4Sbox? tls { get; set; }
|
||||
|
@ -134,6 +133,35 @@ public class Outbound4Sbox
|
|||
public HyObfs4Sbox? obfs { get; set; }
|
||||
public List<string>? outbounds { get; set; }
|
||||
public bool? interrupt_exist_connections { get; set; }
|
||||
public Rule4Sbox? domain_resolver { get; set; }
|
||||
}
|
||||
|
||||
public class Endpoints4Sbox
|
||||
{
|
||||
public string type { get; set; }
|
||||
public string tag { get; set; }
|
||||
public bool? system { get; set; }
|
||||
public string? name { get; set; }
|
||||
public int? mtu { get; set; }
|
||||
public List<string> address { get; set; }
|
||||
public string private_key { get; set; }
|
||||
public int listen_port { get; set; }
|
||||
public string? udp_timeout { get; set; }
|
||||
public int? workers { get; set; }
|
||||
public List<Peer4Sbox> peers { get; set; }
|
||||
public string? detour { get; set; }
|
||||
public Rule4Sbox? domain_resolver { get; set; }
|
||||
}
|
||||
|
||||
public class Peer4Sbox
|
||||
{
|
||||
public string address { get; set; }
|
||||
public int port { get; set; }
|
||||
public string public_key { get; set; }
|
||||
public string? pre_shared_key { get; set; }
|
||||
public List<string> allowed_ips { get; set; }
|
||||
public int? persistent_keepalive_interval { get; set; }
|
||||
public List<int> reserved { get; set; }
|
||||
}
|
||||
|
||||
public class Tls4Sbox
|
||||
|
@ -194,12 +222,18 @@ public class HyObfs4Sbox
|
|||
public class Server4Sbox
|
||||
{
|
||||
public string? tag { get; set; }
|
||||
public string? detour { get; set; }
|
||||
public string? client_subnet { get; set; }
|
||||
public string? type { get; set; }
|
||||
public string? server { get; set; }
|
||||
public string? server_resolver { get; set; }
|
||||
[JsonPropertyName("interface")] public string? Interface { get; set; }
|
||||
// Deprecated
|
||||
public string? address { get; set; }
|
||||
public string? address_resolver { get; set; }
|
||||
public string? address_strategy { get; set; }
|
||||
public string? strategy { get; set; }
|
||||
public string? detour { get; set; }
|
||||
public string? client_subnet { get; set; }
|
||||
// Deprecated End
|
||||
}
|
||||
|
||||
public class Experimental4Sbox
|
||||
|
|
9
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
9
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
@ -672,6 +672,15 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add [Anytls] Configuration 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuAddAnytlsServer {
|
||||
get {
|
||||
return ResourceManager.GetString("menuAddAnytlsServer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add a custom configuration Configuration 的本地化字符串。
|
||||
/// </summary>
|
||||
|
|
|
@ -1416,4 +1416,7 @@
|
|||
<data name="menuExportConfig" xml:space="preserve">
|
||||
<value>صادر کردن سرور</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>Add [Anytls] Configuration</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1416,4 +1416,7 @@
|
|||
<data name="menuExportConfig" xml:space="preserve">
|
||||
<value>Export server</value>
|
||||
</data>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>Add [Anytls] Configuration</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1416,4 +1416,7 @@
|
|||
<data name="menuExportConfig" xml:space="preserve">
|
||||
<value>Export Configuration</value>
|
||||
</data>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>Add [Anytls] Configuration</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1416,4 +1416,7 @@
|
|||
<data name="menuExportConfig" xml:space="preserve">
|
||||
<value>Export server</value>
|
||||
</data>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>Add [Anytls] Configuration</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1071,13 +1071,13 @@
|
|||
<data name="TbHeaderType8" xml:space="preserve">
|
||||
<value>拥塞控制算法</value>
|
||||
</data>
|
||||
<data name="LvPrevProfile" xml:space="preserve">
|
||||
<data name="LvPrevProfile" xml:space="preserve">
|
||||
<value>前置代理配置文件别名</value>
|
||||
</data>
|
||||
<data name="LvNextProfile" xml:space="preserve">
|
||||
<data name="LvNextProfile" xml:space="preserve">
|
||||
<value>落地代理配置文件別名</value>
|
||||
</data>
|
||||
<data name="LvPrevProfileTip" xml:space="preserve">
|
||||
<data name="LvPrevProfileTip" xml:space="preserve">
|
||||
<value>请确保配置文件别名存在并唯一</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||
|
@ -1413,4 +1413,7 @@
|
|||
<data name="menuExportConfig" xml:space="preserve">
|
||||
<value>导出配置文件</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>添加 [Anytls] 配置文件</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1071,13 +1071,13 @@
|
|||
<data name="TbHeaderType8" xml:space="preserve">
|
||||
<value>擁塞控制算法</value>
|
||||
</data>
|
||||
<data name="LvPrevProfile" xml:space="preserve">
|
||||
<data name="LvPrevProfile" xml:space="preserve">
|
||||
<value>前置代理設定檔別名</value>
|
||||
</data>
|
||||
<data name="LvNextProfile" xml:space="preserve">
|
||||
<data name="LvNextProfile" xml:space="preserve">
|
||||
<value>落地代理設定檔別名</value>
|
||||
</data>
|
||||
<data name="LvPrevProfileTip" xml:space="preserve">
|
||||
<data name="LvPrevProfileTip" xml:space="preserve">
|
||||
<value>請確保設定檔別名存在並且唯一</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||
|
@ -1413,4 +1413,7 @@
|
|||
<data name="menuExportConfig" xml:space="preserve">
|
||||
<value>匯出設定檔</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>新增 [Anytls] 設定檔</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
{
|
||||
"log": {
|
||||
"level": "debug",
|
||||
"timestamp": true
|
||||
|
@ -14,22 +14,10 @@
|
|||
{
|
||||
"type": "direct",
|
||||
"tag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "block",
|
||||
"tag": "block"
|
||||
},
|
||||
{
|
||||
"tag": "dns_out",
|
||||
"type": "dns"
|
||||
}
|
||||
],
|
||||
"route": {
|
||||
"rules": [
|
||||
{
|
||||
"protocol": [ "dns" ],
|
||||
"outbound": "dns_out"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -2,28 +2,33 @@
|
|||
"servers": [
|
||||
{
|
||||
"tag": "remote",
|
||||
"address": "tcp://8.8.8.8",
|
||||
"strategy": "prefer_ipv4",
|
||||
"type": "tcp",
|
||||
"server": "8.8.8.8",
|
||||
"detour": "proxy"
|
||||
},
|
||||
{
|
||||
"tag": "local",
|
||||
"address": "223.5.5.5",
|
||||
"strategy": "prefer_ipv4",
|
||||
"detour": "direct"
|
||||
},
|
||||
{
|
||||
"tag": "block",
|
||||
"address": "rcode://success"
|
||||
"type": "udp",
|
||||
"server": "223.5.5.5"
|
||||
}
|
||||
],
|
||||
"rules": [
|
||||
{
|
||||
"domain_suffix": [
|
||||
"googleapis.cn",
|
||||
"gstatic.com"
|
||||
],
|
||||
"server": "remote",
|
||||
"strategy": "prefer_ipv4"
|
||||
},
|
||||
{
|
||||
"rule_set": [
|
||||
"geosite-cn"
|
||||
],
|
||||
"server": "local"
|
||||
"server": "local",
|
||||
"strategy": "prefer_ipv4"
|
||||
}
|
||||
],
|
||||
"final": "remote"
|
||||
"final": "remote",
|
||||
"strategy": "prefer_ipv4"
|
||||
}
|
||||
|
|
|
@ -2,29 +2,34 @@
|
|||
"servers": [
|
||||
{
|
||||
"tag": "remote",
|
||||
"address": "tcp://8.8.8.8",
|
||||
"strategy": "prefer_ipv4",
|
||||
"type": "tcp",
|
||||
"server": "8.8.8.8",
|
||||
"detour": "proxy"
|
||||
},
|
||||
{
|
||||
"tag": "local",
|
||||
"address": "223.5.5.5",
|
||||
"strategy": "prefer_ipv4",
|
||||
"detour": "direct"
|
||||
},
|
||||
{
|
||||
"tag": "block",
|
||||
"address": "rcode://success"
|
||||
"type": "udp",
|
||||
"server": "223.5.5.5"
|
||||
}
|
||||
],
|
||||
"rules": [
|
||||
{
|
||||
"domain_suffix": [
|
||||
"googleapis.cn",
|
||||
"gstatic.com"
|
||||
],
|
||||
"server": "remote",
|
||||
"strategy": "prefer_ipv4"
|
||||
},
|
||||
{
|
||||
"rule_set": [
|
||||
"geosite-cn",
|
||||
"geosite-geolocation-cn"
|
||||
],
|
||||
"server": "local"
|
||||
"server": "local",
|
||||
"strategy": "prefer_ipv4"
|
||||
}
|
||||
],
|
||||
"final": "remote"
|
||||
"final": "remote",
|
||||
"strategy": "prefer_ipv4"
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
139,
|
||||
5353
|
||||
],
|
||||
"outbound": "block"
|
||||
"action": "reject"
|
||||
},
|
||||
{
|
||||
"ip_cidr": [
|
||||
"224.0.0.0/3",
|
||||
"ff00::/8"
|
||||
],
|
||||
"outbound": "block"
|
||||
"action": "reject"
|
||||
}
|
||||
]
|
|
@ -1,6 +1,8 @@
|
|||
using System.Data;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using DynamicData;
|
||||
using ServiceLib.Models;
|
||||
|
||||
namespace ServiceLib.Services.CoreConfig;
|
||||
|
||||
|
@ -53,7 +55,18 @@ public class CoreConfigSingboxService
|
|||
|
||||
await GenInbounds(singboxConfig);
|
||||
|
||||
await GenOutbound(node, singboxConfig.outbounds.First());
|
||||
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());
|
||||
}
|
||||
|
||||
await GenMoreOutbounds(node, singboxConfig);
|
||||
|
||||
|
@ -202,16 +215,32 @@ public class CoreConfigSingboxService
|
|||
continue;
|
||||
}
|
||||
|
||||
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||
await GenOutbound(item, outbound);
|
||||
outbound.tag = Global.ProxyTag + inbound.listen_port.ToString();
|
||||
singboxConfig.outbounds.Add(outbound);
|
||||
var tag = string.Empty;
|
||||
if (item.ConfigType == EConfigType.WireGuard)
|
||||
{
|
||||
var endpoints = new Endpoints4Sbox();
|
||||
await GenEndpoint(item, endpoints);
|
||||
endpoints.tag = Global.ProxyTag + inbound.listen_port.ToString();
|
||||
singboxConfig.endpoints ??= new();
|
||||
singboxConfig.endpoints.Add(endpoints);
|
||||
|
||||
tag = endpoints.tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||
await GenOutbound(item, outbound);
|
||||
outbound.tag = Global.ProxyTag + inbound.listen_port.ToString();
|
||||
singboxConfig.outbounds.Add(outbound);
|
||||
|
||||
tag = outbound.tag;
|
||||
}
|
||||
|
||||
//rule
|
||||
Rule4Sbox rule = new()
|
||||
{
|
||||
inbound = new List<string> { inbound.tag },
|
||||
outbound = outbound.tag
|
||||
outbound = tag
|
||||
};
|
||||
singboxConfig.route.rules.Add(rule);
|
||||
}
|
||||
|
@ -275,7 +304,18 @@ public class CoreConfigSingboxService
|
|||
}
|
||||
|
||||
await GenLog(singboxConfig);
|
||||
await GenOutbound(node, singboxConfig.outbounds.First());
|
||||
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());
|
||||
}
|
||||
await GenMoreOutbounds(node, singboxConfig);
|
||||
await GenDnsDomains(null, singboxConfig, null);
|
||||
|
||||
|
@ -369,12 +409,26 @@ public class CoreConfigSingboxService
|
|||
continue;
|
||||
}
|
||||
|
||||
//outbound
|
||||
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||
await GenOutbound(item, outbound);
|
||||
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
|
||||
singboxConfig.outbounds.Insert(0, outbound);
|
||||
tagProxy.Add(outbound.tag);
|
||||
|
||||
if (item.ConfigType == EConfigType.WireGuard)
|
||||
{
|
||||
//endpoint
|
||||
var endpoints = new Endpoints4Sbox();
|
||||
await GenEndpoint(item, endpoints);
|
||||
endpoints.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
|
||||
singboxConfig.endpoints ??= new();
|
||||
singboxConfig.endpoints.Add(endpoints);
|
||||
tagProxy.Add(endpoints.tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
//outbound
|
||||
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||
await GenOutbound(item, outbound);
|
||||
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
|
||||
singboxConfig.outbounds.Insert(0, outbound);
|
||||
tagProxy.Add(outbound.tag);
|
||||
}
|
||||
}
|
||||
if (tagProxy.Count <= 0)
|
||||
{
|
||||
|
@ -558,15 +612,6 @@ public class CoreConfigSingboxService
|
|||
singboxConfig.inbounds.Add(inbound);
|
||||
|
||||
inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||
inbound.sniff = _config.Inbound.First().SniffingEnabled;
|
||||
inbound.sniff_override_destination = _config.Inbound.First().RouteOnly ? false : _config.Inbound.First().SniffingEnabled;
|
||||
inbound.domain_strategy = _config.RoutingBasicItem.DomainStrategy4Singbox.IsNullOrEmpty() ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
|
||||
|
||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||
if (routing.DomainStrategy4Singbox.IsNotEmpty())
|
||||
{
|
||||
inbound.domain_strategy = routing.DomainStrategy4Singbox;
|
||||
}
|
||||
|
||||
if (_config.Inbound.First().SecondLocalPortEnabled)
|
||||
{
|
||||
|
@ -611,8 +656,6 @@ public class CoreConfigSingboxService
|
|||
tunInbound.mtu = _config.TunModeItem.Mtu;
|
||||
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
||||
tunInbound.stack = _config.TunModeItem.Stack;
|
||||
tunInbound.sniff = _config.Inbound.First().SniffingEnabled;
|
||||
//tunInbound.sniff_override_destination = _config.inbound.First().routeOnly ? false : _config.inbound.First().sniffingEnabled;
|
||||
if (_config.TunModeItem.EnableIPv6Address == false)
|
||||
{
|
||||
tunInbound.address = ["172.18.0.1/30"];
|
||||
|
@ -645,6 +688,16 @@ public class CoreConfigSingboxService
|
|||
outbound.server_port = node.Port;
|
||||
outbound.type = Global.ProtocolTypes[node.ConfigType];
|
||||
|
||||
if (Utils.IsDomain(node.Address))
|
||||
{
|
||||
var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
|
||||
outbound.domain_resolver = new()
|
||||
{
|
||||
server = "local_local",
|
||||
strategy = string.IsNullOrEmpty(item?.DomainStrategy4Freedom) ? null : item?.DomainStrategy4Freedom
|
||||
};
|
||||
}
|
||||
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.VMess:
|
||||
|
@ -749,13 +802,9 @@ public class CoreConfigSingboxService
|
|||
outbound.congestion_control = node.HeaderType;
|
||||
break;
|
||||
}
|
||||
case EConfigType.WireGuard:
|
||||
case EConfigType.Anytls:
|
||||
{
|
||||
outbound.private_key = node.Id;
|
||||
outbound.peer_public_key = node.PublicKey;
|
||||
outbound.reserved = Utils.String2List(node.Path)?.Select(int.Parse).ToList();
|
||||
outbound.local_address = Utils.String2List(node.RequestHost);
|
||||
outbound.mtu = node.ShortId.IsNullOrEmpty() ? Global.TunMtus.First() : node.ShortId.ToInt();
|
||||
outbound.password = node.Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -771,6 +820,51 @@ public class CoreConfigSingboxService
|
|||
return 0;
|
||||
}
|
||||
|
||||
private async Task<int> GenEndpoint(ProfileItem node, Endpoints4Sbox endpoints)
|
||||
{
|
||||
try
|
||||
{
|
||||
endpoints.address = Utils.String2List(node.RequestHost);
|
||||
endpoints.listen_port = Utils.GetFreePort();
|
||||
endpoints.type = Global.ProtocolTypes[node.ConfigType];
|
||||
|
||||
if (Utils.IsDomain(node.Address))
|
||||
{
|
||||
var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
|
||||
endpoints.domain_resolver = new()
|
||||
{
|
||||
server = "local_local",
|
||||
strategy = string.IsNullOrEmpty(item?.DomainStrategy4Freedom) ? null : item?.DomainStrategy4Freedom
|
||||
};
|
||||
}
|
||||
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.WireGuard:
|
||||
{
|
||||
var peer = new Peer4Sbox
|
||||
{
|
||||
public_key = node.PublicKey,
|
||||
reserved = Utils.String2List(node.Path)?.Select(int.Parse).ToList(),
|
||||
address = node.Address,
|
||||
port = node.Port,
|
||||
// TODO default ["0.0.0.0/0", "::/0"]
|
||||
allowed_ips = new() { "0.0.0.0/0", "::/0" },
|
||||
};
|
||||
endpoints.private_key = node.Id;
|
||||
endpoints.mtu = node.ShortId.IsNullOrEmpty() ? Global.TunMtus.First() : node.ShortId.ToInt();
|
||||
endpoints.peers = new() { peer };
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
|
||||
{
|
||||
try
|
||||
|
@ -936,7 +1030,9 @@ public class CoreConfigSingboxService
|
|||
}
|
||||
|
||||
//current proxy
|
||||
var outbound = singboxConfig.outbounds.First();
|
||||
var endpoint = singboxConfig.endpoints?.FirstOrDefault(t => t.tag == Global.ProxyTag);
|
||||
var outbound = endpoint == null ? singboxConfig.outbounds.First() : null;
|
||||
|
||||
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||
|
||||
//Previous proxy
|
||||
|
@ -944,12 +1040,34 @@ public class CoreConfigSingboxService
|
|||
if (prevNode is not null
|
||||
&& prevNode.ConfigType != EConfigType.Custom)
|
||||
{
|
||||
var prevOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||
await GenOutbound(prevNode, prevOutbound);
|
||||
prevOutbound.tag = $"{Global.ProxyTag}2";
|
||||
singboxConfig.outbounds.Add(prevOutbound);
|
||||
var tag = string.Empty;
|
||||
if (prevNode.ConfigType == EConfigType.WireGuard)
|
||||
{
|
||||
var prevEndpoint = JsonUtils.Deserialize<Endpoints4Sbox>(txtOutbound);
|
||||
await GenEndpoint(prevNode, prevEndpoint);
|
||||
prevEndpoint.tag = $"{Global.ProxyTag}2";
|
||||
singboxConfig.endpoints ??= new();
|
||||
singboxConfig.endpoints.Add(prevEndpoint);
|
||||
|
||||
outbound.detour = prevOutbound.tag;
|
||||
tag = prevEndpoint.tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
var prevOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||
await GenOutbound(prevNode, prevOutbound);
|
||||
prevOutbound.tag = $"{Global.ProxyTag}2";
|
||||
singboxConfig.outbounds.Add(prevOutbound);
|
||||
|
||||
tag = prevOutbound.tag;
|
||||
}
|
||||
if (endpoint != null)
|
||||
{
|
||||
endpoint.detour = tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
outbound.detour = tag;
|
||||
}
|
||||
}
|
||||
|
||||
//Next proxy
|
||||
|
@ -957,13 +1075,35 @@ public class CoreConfigSingboxService
|
|||
if (nextNode is not null
|
||||
&& nextNode.ConfigType != EConfigType.Custom)
|
||||
{
|
||||
var nextOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||
await GenOutbound(nextNode, nextOutbound);
|
||||
nextOutbound.tag = Global.ProxyTag;
|
||||
singboxConfig.outbounds.Insert(0, nextOutbound);
|
||||
var tag = $"{Global.ProxyTag}1";
|
||||
if (endpoint != null)
|
||||
{
|
||||
endpoint.tag = tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
outbound.tag = tag;
|
||||
}
|
||||
if (nextNode.ConfigType == EConfigType.WireGuard)
|
||||
{
|
||||
var nextEndpoint = JsonUtils.Deserialize<Endpoints4Sbox>(txtOutbound);
|
||||
await GenEndpoint(nextNode, nextEndpoint);
|
||||
nextEndpoint.tag = Global.ProxyTag;
|
||||
singboxConfig.endpoints ??= new();
|
||||
singboxConfig.endpoints.Insert(0, nextEndpoint);
|
||||
|
||||
outbound.tag = $"{Global.ProxyTag}1";
|
||||
nextOutbound.detour = outbound.tag;
|
||||
nextEndpoint.detour = tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
var nextOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||
await GenOutbound(nextNode, nextOutbound);
|
||||
nextOutbound.tag = Global.ProxyTag;
|
||||
singboxConfig.outbounds ??= new();
|
||||
singboxConfig.outbounds.Insert(0, nextOutbound);
|
||||
|
||||
nextOutbound.detour = tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -978,17 +1118,7 @@ public class CoreConfigSingboxService
|
|||
{
|
||||
try
|
||||
{
|
||||
var dnsOutbound = "dns_out";
|
||||
if (!_config.Inbound.First().SniffingEnabled)
|
||||
{
|
||||
singboxConfig.route.rules.Add(new()
|
||||
{
|
||||
port = [53],
|
||||
network = ["udp"],
|
||||
outbound = dnsOutbound
|
||||
});
|
||||
}
|
||||
|
||||
singboxConfig.route.final = Global.ProxyTag;
|
||||
singboxConfig.route.rules.Insert(0, new()
|
||||
{
|
||||
outbound = Global.DirectTag,
|
||||
|
@ -1000,6 +1130,43 @@ public class CoreConfigSingboxService
|
|||
clash_mode = ERuleMode.Global.ToString()
|
||||
});
|
||||
|
||||
if (_config.Inbound.First().SniffingEnabled)
|
||||
{
|
||||
singboxConfig.route.rules.Add(new()
|
||||
{
|
||||
action = "sniff"
|
||||
});
|
||||
singboxConfig.route.rules.Add(new()
|
||||
{
|
||||
protocol = new() { "dns" },
|
||||
action = "hijack-dns"
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
singboxConfig.route.rules.Add(new()
|
||||
{
|
||||
port = new() { 53 },
|
||||
network = new() { "udp" },
|
||||
action = "hijack-dns"
|
||||
});
|
||||
}
|
||||
|
||||
if (!(_config.Inbound.First().RouteOnly || _config.TunModeItem.EnableTun))
|
||||
{
|
||||
var domainStrategy = _config.RoutingBasicItem.DomainStrategy4Singbox.IsNullOrEmpty() ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
|
||||
var defaultRouting = await ConfigHandler.GetDefaultRouting(_config);
|
||||
if (defaultRouting.DomainStrategy4Singbox.IsNotEmpty())
|
||||
{
|
||||
domainStrategy = defaultRouting.DomainStrategy4Singbox;
|
||||
}
|
||||
singboxConfig.route.rules.Add(new()
|
||||
{
|
||||
action = "resolve",
|
||||
strategy = domainStrategy
|
||||
});
|
||||
}
|
||||
|
||||
if (_config.TunModeItem.EnableTun)
|
||||
{
|
||||
singboxConfig.route.auto_detect_interface = true;
|
||||
|
@ -1014,7 +1181,7 @@ public class CoreConfigSingboxService
|
|||
singboxConfig.route.rules.Add(new()
|
||||
{
|
||||
port = new() { 53 },
|
||||
outbound = dnsOutbound,
|
||||
action = "hijack-dns",
|
||||
process_name = lstDnsExe
|
||||
});
|
||||
|
||||
|
@ -1080,10 +1247,15 @@ public class CoreConfigSingboxService
|
|||
return 0;
|
||||
}
|
||||
|
||||
var rule = new Rule4Sbox()
|
||||
var rule = new Rule4Sbox();
|
||||
if (item.OutboundTag == "block")
|
||||
{
|
||||
outbound = item.OutboundTag,
|
||||
};
|
||||
rule.action = "reject";
|
||||
}
|
||||
else
|
||||
{
|
||||
rule.outbound = item.OutboundTag;
|
||||
}
|
||||
|
||||
if (item.Port.IsNotEmpty())
|
||||
{
|
||||
|
@ -1210,24 +1382,28 @@ public class CoreConfigSingboxService
|
|||
{
|
||||
return false;
|
||||
}
|
||||
else if (address.StartsWith("geoip:!"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (address.Equals("geoip:private"))
|
||||
{
|
||||
rule.ip_is_private = true;
|
||||
}
|
||||
else if (address.StartsWith("geoip:"))
|
||||
{
|
||||
if (rule.geoip is null)
|
||||
{ rule.geoip = new(); }
|
||||
rule.geoip ??= new();
|
||||
rule.geoip?.Add(address.Substring(6));
|
||||
}
|
||||
else if (address.Equals("geoip:!private"))
|
||||
{
|
||||
rule.ip_is_private = false;
|
||||
}
|
||||
else if (address.StartsWith("geoip:!"))
|
||||
{
|
||||
rule.geoip ??= new();
|
||||
rule.geoip?.Add(address.Substring(6));
|
||||
rule.invert = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rule.ip_cidr is null)
|
||||
{ rule.ip_cidr = new(); }
|
||||
rule.ip_cidr ??= new();
|
||||
rule.ip_cidr?.Add(address);
|
||||
}
|
||||
return true;
|
||||
|
@ -1255,7 +1431,14 @@ public class CoreConfigSingboxService
|
|||
}
|
||||
singboxConfig.dns = dns4Sbox;
|
||||
|
||||
await GenDnsDomains(node, singboxConfig, item);
|
||||
if (dns4Sbox.servers != null && dns4Sbox.servers.Count > 0 && dns4Sbox.servers.First().address.IsNullOrEmpty())
|
||||
{
|
||||
await GenDnsDomains(node, singboxConfig, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
await GenDnsDomainsLegacy(node, singboxConfig, item);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1270,6 +1453,100 @@ public class CoreConfigSingboxService
|
|||
dns4Sbox.servers ??= [];
|
||||
dns4Sbox.rules ??= [];
|
||||
|
||||
var tag = "local_local";
|
||||
var localDnsAddress = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress;
|
||||
string? localDnsType = null;
|
||||
string? dhcpDnsInterface = null;
|
||||
var dnsProtocols = new List<string>
|
||||
{
|
||||
"dhcp",
|
||||
"https",
|
||||
"tcp",
|
||||
"tls",
|
||||
"quic",
|
||||
"h3",
|
||||
"udp"
|
||||
};
|
||||
if (localDnsAddress == "local")
|
||||
{
|
||||
localDnsType = "local";
|
||||
localDnsAddress = null;
|
||||
}
|
||||
else if (dnsProtocols.Any(protocol => localDnsAddress.StartsWith(protocol)))
|
||||
{
|
||||
var protocol = dnsProtocols.First(p => localDnsAddress.StartsWith(p));
|
||||
localDnsType = protocol;
|
||||
// +3 for "://"
|
||||
if (localDnsAddress.Length > protocol.Length + 3)
|
||||
{
|
||||
localDnsAddress = localDnsAddress.Substring(protocol.Length + 3);
|
||||
if (protocol == "dhcp")
|
||||
{
|
||||
dhcpDnsInterface = localDnsAddress;
|
||||
if (dhcpDnsInterface == "auto")
|
||||
{
|
||||
dhcpDnsInterface = null;
|
||||
}
|
||||
localDnsAddress = null;
|
||||
}
|
||||
else if (protocol is "https" or "h3")
|
||||
{
|
||||
if (localDnsAddress.Contains('/'))
|
||||
{
|
||||
localDnsAddress = localDnsAddress.Substring(0, localDnsAddress.IndexOf('/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
localDnsAddress = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
localDnsType = "udp";
|
||||
}
|
||||
|
||||
dns4Sbox.servers.Add(new()
|
||||
{
|
||||
tag = tag,
|
||||
type = localDnsType,
|
||||
server = localDnsAddress,
|
||||
Interface = dhcpDnsInterface
|
||||
});
|
||||
dns4Sbox.rules.Insert(0, new()
|
||||
{
|
||||
server = tag,
|
||||
clash_mode = ERuleMode.Direct.ToString(),
|
||||
strategy = string.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom
|
||||
});
|
||||
dns4Sbox.rules.Insert(0, new()
|
||||
{
|
||||
server = dns4Sbox.servers.Where(t => t.detour == Global.ProxyTag).Select(t => t.tag).FirstOrDefault() ?? "remote",
|
||||
clash_mode = ERuleMode.Global.ToString()
|
||||
});
|
||||
|
||||
//Tun2SocksAddress
|
||||
if (_config.TunModeItem.EnableTun && node?.ConfigType == EConfigType.SOCKS && Utils.IsDomain(node?.Sni))
|
||||
{
|
||||
dns4Sbox.rules.Insert(0, new()
|
||||
{
|
||||
server = tag,
|
||||
domain = [node?.Sni],
|
||||
strategy = string.IsNullOrEmpty(dNSItem?.DomainStrategy4Freedom) ? null : dNSItem?.DomainStrategy4Freedom
|
||||
});
|
||||
}
|
||||
|
||||
singboxConfig.dns = dns4Sbox;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenDnsDomainsLegacy(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
|
||||
{
|
||||
var dns4Sbox = singboxConfig.dns ?? new();
|
||||
dns4Sbox.servers ??= [];
|
||||
dns4Sbox.rules ??= [];
|
||||
|
||||
var tag = "local_local";
|
||||
dns4Sbox.servers.Add(new()
|
||||
{
|
||||
|
|
|
@ -1341,7 +1341,8 @@ public class CoreConfigV2rayService
|
|||
if (prevNode is not null
|
||||
&& prevNode.ConfigType != EConfigType.Custom
|
||||
&& prevNode.ConfigType != EConfigType.Hysteria2
|
||||
&& prevNode.ConfigType != EConfigType.TUIC)
|
||||
&& prevNode.ConfigType != EConfigType.TUIC
|
||||
&& prevNode.ConfigType != EConfigType.Anytls)
|
||||
{
|
||||
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||
await GenOutbound(prevNode, prevOutbound);
|
||||
|
@ -1359,7 +1360,8 @@ public class CoreConfigV2rayService
|
|||
if (nextNode is not null
|
||||
&& nextNode.ConfigType != EConfigType.Custom
|
||||
&& nextNode.ConfigType != EConfigType.Hysteria2
|
||||
&& nextNode.ConfigType != EConfigType.TUIC)
|
||||
&& nextNode.ConfigType != EConfigType.TUIC
|
||||
&& nextNode.ConfigType != EConfigType.Anytls)
|
||||
{
|
||||
var nextOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||
await GenOutbound(nextNode, nextOutbound);
|
||||
|
|
|
@ -357,8 +357,8 @@ public class SpeedtestService
|
|||
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
|
||||
{
|
||||
List<List<ServerTestItem>> lstTest = new();
|
||||
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC)).ToList();
|
||||
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC).ToList();
|
||||
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls)).ToList();
|
||||
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls).ToList();
|
||||
|
||||
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
public ReactiveCommand<Unit, Unit> AddHysteria2ServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddTuicServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddWireguardServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddAnytlsServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddCustomServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }
|
||||
|
@ -111,6 +112,10 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
{
|
||||
await AddServerAsync(true, EConfigType.WireGuard);
|
||||
});
|
||||
AddAnytlsServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await AddServerAsync(true, EConfigType.Anytls);
|
||||
});
|
||||
AddCustomServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await AddServerAsync(true, EConfigType.Custom);
|
||||
|
|
|
@ -481,6 +481,26 @@
|
|||
HorizontalAlignment="Left"
|
||||
Watermark="1500" />
|
||||
</Grid>
|
||||
<Grid
|
||||
x:Name="gridAnytls"
|
||||
Grid.Row="2"
|
||||
ColumnDefinitions="180,Auto"
|
||||
IsVisible="False"
|
||||
RowDefinitions="Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbId3}" />
|
||||
<TextBox
|
||||
x:Name="txtId10"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</Grid>
|
||||
|
||||
<Separator
|
||||
x:Name="sepa2"
|
||||
|
|
|
@ -133,6 +133,11 @@ public partial class AddServerWindow : ReactiveWindow<AddServerViewModel>
|
|||
gridTls.IsVisible = false;
|
||||
|
||||
break;
|
||||
|
||||
case EConfigType.Anytls:
|
||||
gridAnytls.IsVisible = true;
|
||||
cmbCoreType.IsEnabled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
gridTlsMore.IsVisible = false;
|
||||
|
@ -193,6 +198,10 @@ public partial class AddServerWindow : ReactiveWindow<AddServerViewModel>
|
|||
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost9.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables);
|
||||
break;
|
||||
|
||||
case EConfigType.Anytls:
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Id, v => v.txtId10.Text).DisposeWith(disposables);
|
||||
break;
|
||||
}
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.SelectedValue).DisposeWith(disposables);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
<Separator />
|
||||
<MenuItem x:Name="menuAddHysteria2Server" Header="{x:Static resx:ResUI.menuAddHysteria2Server}" />
|
||||
<MenuItem x:Name="menuAddTuicServer" Header="{x:Static resx:ResUI.menuAddTuicServer}" />
|
||||
<MenuItem x:Name="menuAddAnytlsServer" Header="{x:Static resx:ResUI.menuAddAnytlsServer}" />
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem Padding="8,0">
|
||||
|
|
|
@ -83,6 +83,7 @@ public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
|
|||
this.BindCommand(ViewModel, vm => vm.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
||||
|
|
|
@ -646,6 +646,35 @@
|
|||
materialDesign:HintAssist.Hint="1500"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</Grid>
|
||||
<Grid
|
||||
x:Name="gridAnytls"
|
||||
Grid.Row="2"
|
||||
Visibility="Hidden">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbId3}" />
|
||||
<TextBox
|
||||
x:Name="txtId10"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</Grid>
|
||||
|
||||
<Separator
|
||||
x:Name="sepa2"
|
||||
|
|
|
@ -126,6 +126,10 @@ public partial class AddServerWindow
|
|||
gridTransport.Visibility = Visibility.Collapsed;
|
||||
gridTls.Visibility = Visibility.Collapsed;
|
||||
|
||||
break;
|
||||
case EConfigType.Anytls:
|
||||
gridAnytls.Visibility = Visibility.Visible;
|
||||
cmbCoreType.IsEnabled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -187,6 +191,10 @@ public partial class AddServerWindow
|
|||
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost9.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables);
|
||||
break;
|
||||
|
||||
case EConfigType.Anytls:
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Id, v => v.txtId10.Text).DisposeWith(disposables);
|
||||
break;
|
||||
}
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.Text).DisposeWith(disposables);
|
||||
|
|
|
@ -107,6 +107,10 @@
|
|||
x:Name="menuAddTuicServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuAddTuicServer}" />
|
||||
<MenuItem
|
||||
x:Name="menuAddAnytlsServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuAddAnytlsServer}" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Separator />
|
||||
|
|
|
@ -80,6 +80,7 @@ public partial class MainWindow
|
|||
this.BindCommand(ViewModel, vm => vm.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
||||
|
|
Loading…
Reference in a new issue