mirror of
https://github.com/2dust/v2rayN.git
synced 2025-11-01 04:52:51 +00:00
Compare commits
33 commits
2093f716d4
...
4254c1c28e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4254c1c28e | ||
|
|
f635456508 | ||
|
|
ebf0e1715b | ||
|
|
8772e76067 | ||
|
|
d3fbaa3a91 | ||
|
|
7719123373 | ||
|
|
f28bc28394 | ||
|
|
9fa430dff7 | ||
|
|
aeb57a3c1c | ||
|
|
5db4bd158b | ||
|
|
6a6f4f5407 | ||
|
|
951eb2e1fd | ||
|
|
b0018c99ea | ||
|
|
892a5ef064 | ||
|
|
0d2eec6e36 | ||
|
|
e7607a9a6a | ||
|
|
730bb0521b | ||
|
|
1fbbcb046b | ||
|
|
33c2e00ebd | ||
|
|
3d0c78bdeb | ||
|
|
72695167ab | ||
|
|
64dc0ea0c2 | ||
|
|
3cb23e9f57 | ||
|
|
d30b9fc08b | ||
|
|
c230a183fb | ||
|
|
e9cced8e09 | ||
|
|
da3d4c36a9 | ||
|
|
1d01476523 | ||
|
|
75ceba1b08 | ||
|
|
493c37e7d5 | ||
|
|
6d686b284d | ||
|
|
60fcf6174e | ||
|
|
4141f451b7 |
41 changed files with 835 additions and 467 deletions
|
|
@ -5,22 +5,22 @@
|
||||||
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
|
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.1" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.2" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.1" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.3.2" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.1" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.2" />
|
||||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.1" />
|
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.2" />
|
||||||
<PackageVersion Include="CliWrap" Version="3.9.0" />
|
<PackageVersion Include="CliWrap" Version="3.9.0" />
|
||||||
<PackageVersion Include="Downloader" Version="3.3.4" />
|
<PackageVersion Include="Downloader" Version="3.3.4" />
|
||||||
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.3.0" />
|
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.3.0" />
|
||||||
<PackageVersion Include="MaterialDesignThemes" Version="5.2.1" />
|
<PackageVersion Include="MaterialDesignThemes" Version="5.2.1" />
|
||||||
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
|
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||||
<PackageVersion Include="QRCoder" Version="1.6.0" />
|
<PackageVersion Include="QRCoder" Version="1.6.0" />
|
||||||
<PackageVersion Include="ReactiveUI" Version="20.3.1" />
|
<PackageVersion Include="ReactiveUI" Version="20.4.1" />
|
||||||
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||||
<PackageVersion Include="ReactiveUI.WPF" Version="20.3.1" />
|
<PackageVersion Include="ReactiveUI.WPF" Version="20.4.1" />
|
||||||
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.8" />
|
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.8" />
|
||||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.8" />
|
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.8" />
|
||||||
<PackageVersion Include="Splat.NLog" Version="15.3.1" />
|
<PackageVersion Include="Splat.NLog" Version="15.4.1" />
|
||||||
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
|
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
|
||||||
<PackageVersion Include="TaskScheduler" Version="2.12.1" />
|
<PackageVersion Include="TaskScheduler" Version="2.12.1" />
|
||||||
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
||||||
|
|
|
||||||
|
|
@ -427,11 +427,11 @@ public class Utils
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetFreePort(int defaultPort = 9090)
|
public static int GetFreePort(int defaultPort = 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!Utils.PortInUse(defaultPort))
|
if (!(defaultPort == 0 || Utils.PortInUse(defaultPort)))
|
||||||
{
|
{
|
||||||
return defaultPort;
|
return defaultPort;
|
||||||
}
|
}
|
||||||
|
|
@ -816,18 +816,6 @@ public class Utils
|
||||||
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
|
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// var id = GetLinuxUserId().Result ?? "1000";
|
|
||||||
// if (int.TryParse(id, out var userId))
|
|
||||||
// {
|
|
||||||
// return userId == 0;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<string?> GetLinuxUserId()
|
private static async Task<string?> GetLinuxUserId()
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,6 @@ public enum EConfigType
|
||||||
Hysteria2 = 7,
|
Hysteria2 = 7,
|
||||||
TUIC = 8,
|
TUIC = 8,
|
||||||
WireGuard = 9,
|
WireGuard = 9,
|
||||||
HTTP = 10
|
HTTP = 10,
|
||||||
|
Anytls = 11
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,8 @@ public class Global
|
||||||
{ EConfigType.Trojan, "trojan://" },
|
{ EConfigType.Trojan, "trojan://" },
|
||||||
{ EConfigType.Hysteria2, "hysteria2://" },
|
{ EConfigType.Hysteria2, "hysteria2://" },
|
||||||
{ EConfigType.TUIC, "tuic://" },
|
{ EConfigType.TUIC, "tuic://" },
|
||||||
{ EConfigType.WireGuard, "wireguard://" }
|
{ EConfigType.WireGuard, "wireguard://" },
|
||||||
|
{ EConfigType.Anytls, "anytls://" }
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
|
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
|
||||||
|
|
@ -180,7 +181,8 @@ public class Global
|
||||||
{ EConfigType.Trojan, "trojan" },
|
{ EConfigType.Trojan, "trojan" },
|
||||||
{ EConfigType.Hysteria2, "hysteria2" },
|
{ EConfigType.Hysteria2, "hysteria2" },
|
||||||
{ EConfigType.TUIC, "tuic" },
|
{ EConfigType.TUIC, "tuic" },
|
||||||
{ EConfigType.WireGuard, "wireguard" }
|
{ EConfigType.WireGuard, "wireguard" },
|
||||||
|
{ EConfigType.Anytls, "anytls" }
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly List<string> VmessSecurities =
|
public static readonly List<string> VmessSecurities =
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,7 @@ public class ConfigHandler
|
||||||
EConfigType.Hysteria2 => await AddHysteria2Server(config, item),
|
EConfigType.Hysteria2 => await AddHysteria2Server(config, item),
|
||||||
EConfigType.TUIC => await AddTuicServer(config, item),
|
EConfigType.TUIC => await AddTuicServer(config, item),
|
||||||
EConfigType.WireGuard => await AddWireguardServer(config, item),
|
EConfigType.WireGuard => await AddWireguardServer(config, item),
|
||||||
|
EConfigType.Anytls => await AddAnytlsServer(config, item),
|
||||||
_ => -1,
|
_ => -1,
|
||||||
};
|
};
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -785,6 +786,35 @@ public class ConfigHandler
|
||||||
return 0;
|
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>
|
/// <summary>
|
||||||
/// Sort the server list by the specified column
|
/// Sort the server list by the specified column
|
||||||
/// Updates the sort order in the profile extension data
|
/// Updates the sort order in the profile extension data
|
||||||
|
|
@ -1294,6 +1324,7 @@ public class ConfigHandler
|
||||||
EConfigType.Hysteria2 => await AddHysteria2Server(config, profileItem, false),
|
EConfigType.Hysteria2 => await AddHysteria2Server(config, profileItem, false),
|
||||||
EConfigType.TUIC => await AddTuicServer(config, profileItem, false),
|
EConfigType.TUIC => await AddTuicServer(config, profileItem, false),
|
||||||
EConfigType.WireGuard => await AddWireguardServer(config, profileItem, false),
|
EConfigType.WireGuard => await AddWireguardServer(config, profileItem, false),
|
||||||
|
EConfigType.Anytls => await AddAnytlsServer(config, profileItem, false),
|
||||||
_ => -1,
|
_ => -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1857,12 +1888,25 @@ public class ConfigHandler
|
||||||
/// <returns>0 if successful</returns>
|
/// <returns>0 if successful</returns>
|
||||||
public static async Task<int> SetDefaultRouting(Config config, RoutingItem routingItem)
|
public static async Task<int> SetDefaultRouting(Config config, RoutingItem routingItem)
|
||||||
{
|
{
|
||||||
if (await SQLiteHelper.Instance.TableAsync<RoutingItem>().Where(t => t.Id == routingItem.Id).CountAsync() > 0)
|
var items = await AppHandler.Instance.RoutingItems();
|
||||||
|
if (items.Any(t => t.Id == routingItem.Id && t.IsActive == true))
|
||||||
{
|
{
|
||||||
config.RoutingBasicItem.RoutingIndexId = routingItem.Id;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
await SaveConfig(config);
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
if (item.Id == routingItem.Id)
|
||||||
|
{
|
||||||
|
item.IsActive = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.IsActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await SQLiteHelper.Instance.UpdateAllAsync(items);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1875,7 +1919,7 @@ public class ConfigHandler
|
||||||
/// <returns>The default routing item</returns>
|
/// <returns>The default routing item</returns>
|
||||||
public static async Task<RoutingItem> GetDefaultRouting(Config config)
|
public static async Task<RoutingItem> GetDefaultRouting(Config config)
|
||||||
{
|
{
|
||||||
var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId);
|
var item = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.IsActive == true);
|
||||||
if (item is null)
|
if (item is null)
|
||||||
{
|
{
|
||||||
var item2 = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync();
|
var item2 = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync();
|
||||||
|
|
@ -1983,6 +2027,18 @@ public class ConfigHandler
|
||||||
|
|
||||||
if (!blImportAdvancedRules && items.Count > 0)
|
if (!blImportAdvancedRules && items.Count > 0)
|
||||||
{
|
{
|
||||||
|
//migrate
|
||||||
|
//TODO Temporary code to be removed later
|
||||||
|
if (config.RoutingBasicItem.RoutingIndexId.IsNotEmpty())
|
||||||
|
{
|
||||||
|
var item = items.FirstOrDefault(t => t.Id == config.RoutingBasicItem.RoutingIndexId);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
await SetDefaultRouting(config, item);
|
||||||
|
}
|
||||||
|
config.RoutingBasicItem.RoutingIndexId = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2198,8 +2254,18 @@ public class ConfigHandler
|
||||||
config.UiItem.WindowSizeItem.Add(sizeItem);
|
config.UiItem.WindowSizeItem.Add(sizeItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
sizeItem.Width = width;
|
sizeItem.Width = (int)width;
|
||||||
sizeItem.Height = height;
|
sizeItem.Height = (int)height;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int SaveMainGirdHeight(Config config, double height1, double height2)
|
||||||
|
{
|
||||||
|
var uiItem = config.UiItem ?? new();
|
||||||
|
|
||||||
|
uiItem.MainGirdHeight1 = (int)(height1 + 0.1);
|
||||||
|
uiItem.MainGirdHeight2 = (int)(height2 + 0.1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ public class CoreHandler
|
||||||
|
|
||||||
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
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 fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
|
||||||
var configPath = Utils.GetBinConfigPath(fileName);
|
var configPath = Utils.GetBinConfigPath(fileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
||||||
|
|
|
||||||
49
v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs
Normal file
49
v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
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);
|
||||||
|
_ = ResolveStdTransport(query, ref item);
|
||||||
|
|
||||||
|
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>();
|
||||||
|
_ = GetStdTransport(item, Global.None, ref dicQuery);
|
||||||
|
|
||||||
|
return ToUri(EConfigType.Anytls, item.Address, item.Port, pw, dicQuery, remark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ public class FmtHandler
|
||||||
EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item),
|
EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item),
|
||||||
EConfigType.TUIC => TuicFmt.ToUri(item),
|
EConfigType.TUIC => TuicFmt.ToUri(item),
|
||||||
EConfigType.WireGuard => WireguardFmt.ToUri(item),
|
EConfigType.WireGuard => WireguardFmt.ToUri(item),
|
||||||
|
EConfigType.Anytls => AnytlsFmt.ToUri(item),
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -75,6 +76,10 @@ public class FmtHandler
|
||||||
{
|
{
|
||||||
return WireguardFmt.Resolve(str, out msg);
|
return WireguardFmt.Resolve(str, out msg);
|
||||||
}
|
}
|
||||||
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Anytls]))
|
||||||
|
{
|
||||||
|
return AnytlsFmt.Resolve(str, out msg);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg = ResUI.NonvmessOrssProtocol;
|
msg = ResUI.NonvmessOrssProtocol;
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ public class UIItem
|
||||||
{
|
{
|
||||||
public bool EnableAutoAdjustMainLvColWidth { get; set; }
|
public bool EnableAutoAdjustMainLvColWidth { get; set; }
|
||||||
public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
||||||
public double MainGirdHeight1 { get; set; }
|
public int MainGirdHeight1 { get; set; }
|
||||||
public double MainGirdHeight2 { get; set; }
|
public int MainGirdHeight2 { get; set; }
|
||||||
public EGirdOrientation MainGirdOrientation { get; set; } = EGirdOrientation.Vertical;
|
public EGirdOrientation MainGirdOrientation { get; set; } = EGirdOrientation.Vertical;
|
||||||
public string? ColorPrimaryName { get; set; }
|
public string? ColorPrimaryName { get; set; }
|
||||||
public string? CurrentTheme { get; set; }
|
public string? CurrentTheme { get; set; }
|
||||||
|
|
@ -250,6 +250,6 @@ public class Fragment4RayItem
|
||||||
public class WindowSizeItem
|
public class WindowSizeItem
|
||||||
{
|
{
|
||||||
public string TypeName { get; set; }
|
public string TypeName { get; set; }
|
||||||
public double Width { get; set; }
|
public int Width { get; set; }
|
||||||
public double Height { get; set; }
|
public int Height { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,5 @@ public class RoutingItem
|
||||||
public string DomainStrategy { get; set; }
|
public string DomainStrategy { get; set; }
|
||||||
public string DomainStrategy4Singbox { get; set; }
|
public string DomainStrategy4Singbox { get; set; }
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,4 @@ namespace ServiceLib.Models;
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class RoutingItemModel : RoutingItem
|
public class RoutingItemModel : RoutingItem
|
||||||
{
|
{
|
||||||
public bool IsActive { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace ServiceLib.Models;
|
namespace ServiceLib.Models;
|
||||||
|
|
||||||
public class SingboxConfig
|
public class SingboxConfig
|
||||||
|
|
@ -6,6 +8,7 @@ public class SingboxConfig
|
||||||
public Dns4Sbox? dns { get; set; }
|
public Dns4Sbox? dns { get; set; }
|
||||||
public List<Inbound4Sbox> inbounds { get; set; }
|
public List<Inbound4Sbox> inbounds { get; set; }
|
||||||
public List<Outbound4Sbox> outbounds { get; set; }
|
public List<Outbound4Sbox> outbounds { get; set; }
|
||||||
|
public List<Endpoints4Sbox>? endpoints { get; set; }
|
||||||
public Route4Sbox route { get; set; }
|
public Route4Sbox route { get; set; }
|
||||||
public Experimental4Sbox? experimental { get; set; }
|
public Experimental4Sbox? experimental { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +40,7 @@ public class Route4Sbox
|
||||||
public bool? auto_detect_interface { get; set; }
|
public bool? auto_detect_interface { get; set; }
|
||||||
public List<Rule4Sbox> rules { get; set; }
|
public List<Rule4Sbox> rules { get; set; }
|
||||||
public List<Ruleset4Sbox>? rule_set { get; set; }
|
public List<Ruleset4Sbox>? rule_set { get; set; }
|
||||||
|
public string? final { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|
@ -49,6 +53,7 @@ public class Rule4Sbox
|
||||||
public string? mode { get; set; }
|
public string? mode { get; set; }
|
||||||
public bool? ip_is_private { get; set; }
|
public bool? ip_is_private { get; set; }
|
||||||
public string? client_subnet { get; set; }
|
public string? client_subnet { get; set; }
|
||||||
|
public int? rewrite_ttl { get; set; }
|
||||||
public bool? invert { get; set; }
|
public bool? invert { get; set; }
|
||||||
public string? clash_mode { get; set; }
|
public string? clash_mode { get; set; }
|
||||||
public List<string>? inbound { get; set; }
|
public List<string>? inbound { get; set; }
|
||||||
|
|
@ -67,6 +72,27 @@ public class Rule4Sbox
|
||||||
public List<string>? process_name { get; set; }
|
public List<string>? process_name { get; set; }
|
||||||
public List<string>? rule_set { get; set; }
|
public List<string>? rule_set { get; set; }
|
||||||
public List<Rule4Sbox>? rules { get; set; }
|
public List<Rule4Sbox>? rules { get; set; }
|
||||||
|
public string? action { get; set; }
|
||||||
|
public string? strategy { get; set; }
|
||||||
|
public List<string>? sniffer { get; set; }
|
||||||
|
public string? rcode { get; set; }
|
||||||
|
public List<object>? query_type { get; set; }
|
||||||
|
public List<string>? answer { get; set; }
|
||||||
|
public List<string>? ns { get; set; }
|
||||||
|
public List<string>? extra { get; set; }
|
||||||
|
public string? method { get; set; }
|
||||||
|
public bool? no_drop { get; set; }
|
||||||
|
public bool? source_ip_is_private { get; set; }
|
||||||
|
public bool? ip_accept_any { get; set; }
|
||||||
|
public int? source_port { get; set; }
|
||||||
|
public List<string>? source_port_range { get; set; }
|
||||||
|
public List<string>? network_type { get; set; }
|
||||||
|
public bool? network_is_expensive { get; set; }
|
||||||
|
public bool? network_is_constrained { get; set; }
|
||||||
|
public List<string>? wifi_ssid { get; set; }
|
||||||
|
public List<string>? wifi_bssid { get; set; }
|
||||||
|
public bool? rule_set_ip_cidr_match_source { get; set; }
|
||||||
|
public bool? rule_set_ip_cidr_accept_empty { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|
@ -76,7 +102,6 @@ public class Inbound4Sbox
|
||||||
public string tag { get; set; }
|
public string tag { get; set; }
|
||||||
public string listen { get; set; }
|
public string listen { get; set; }
|
||||||
public int? listen_port { get; set; }
|
public int? listen_port { get; set; }
|
||||||
public string? domain_strategy { get; set; }
|
|
||||||
public string interface_name { get; set; }
|
public string interface_name { get; set; }
|
||||||
public List<string>? address { get; set; }
|
public List<string>? address { get; set; }
|
||||||
public int? mtu { get; set; }
|
public int? mtu { get; set; }
|
||||||
|
|
@ -84,8 +109,6 @@ public class Inbound4Sbox
|
||||||
public bool? strict_route { get; set; }
|
public bool? strict_route { get; set; }
|
||||||
public bool? endpoint_independent_nat { get; set; }
|
public bool? endpoint_independent_nat { get; set; }
|
||||||
public string? stack { 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; }
|
public List<User4Sbox> users { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,10 +118,8 @@ public class User4Sbox
|
||||||
public string password { get; set; }
|
public string password { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Outbound4Sbox
|
public class Outbound4Sbox : BaseServer4Sbox
|
||||||
{
|
{
|
||||||
public string type { get; set; }
|
|
||||||
public string tag { get; set; }
|
|
||||||
public string? server { get; set; }
|
public string? server { get; set; }
|
||||||
public int? server_port { get; set; }
|
public int? server_port { get; set; }
|
||||||
public List<string>? server_ports { get; set; }
|
public List<string>? server_ports { get; set; }
|
||||||
|
|
@ -113,7 +134,6 @@ public class Outbound4Sbox
|
||||||
public int? recv_window_conn { get; set; }
|
public int? recv_window_conn { get; set; }
|
||||||
public int? recv_window { get; set; }
|
public int? recv_window { get; set; }
|
||||||
public bool? disable_mtu_discovery { get; set; }
|
public bool? disable_mtu_discovery { get; set; }
|
||||||
public string? detour { get; set; }
|
|
||||||
public string? method { get; set; }
|
public string? method { get; set; }
|
||||||
public string? username { get; set; }
|
public string? username { get; set; }
|
||||||
public string? password { get; set; }
|
public string? password { get; set; }
|
||||||
|
|
@ -121,21 +141,36 @@ public class Outbound4Sbox
|
||||||
public string? version { get; set; }
|
public string? version { get; set; }
|
||||||
public string? network { get; set; }
|
public string? network { get; set; }
|
||||||
public string? packet_encoding { 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 { get; set; }
|
||||||
public string? plugin_opts { get; set; }
|
public string? plugin_opts { get; set; }
|
||||||
public Tls4Sbox? tls { get; set; }
|
|
||||||
public Multiplex4Sbox? multiplex { get; set; }
|
|
||||||
public Transport4Sbox? transport { get; set; }
|
|
||||||
public HyObfs4Sbox? obfs { get; set; }
|
|
||||||
public List<string>? outbounds { get; set; }
|
public List<string>? outbounds { get; set; }
|
||||||
public bool? interrupt_exist_connections { get; set; }
|
public bool? interrupt_exist_connections { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Endpoints4Sbox : BaseServer4Sbox
|
||||||
|
{
|
||||||
|
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 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
|
public class Tls4Sbox
|
||||||
{
|
{
|
||||||
public bool enabled { get; set; }
|
public bool enabled { get; set; }
|
||||||
|
|
@ -191,15 +226,23 @@ public class HyObfs4Sbox
|
||||||
public string? password { get; set; }
|
public string? password { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Server4Sbox
|
public class Server4Sbox : BaseServer4Sbox
|
||||||
{
|
{
|
||||||
public string? tag { get; set; }
|
public string? client_subnet { get; set; }
|
||||||
|
public string? server { get; set; }
|
||||||
|
public new string? domain_resolver { get; set; }
|
||||||
|
[JsonPropertyName("interface")] public string? Interface { get; set; }
|
||||||
|
public int? server_port { get; set; }
|
||||||
|
public string? path { get; set; }
|
||||||
|
public Headers4Sbox? headers { get; set; }
|
||||||
|
// public List<string>? path { get; set; } // hosts
|
||||||
|
public Dictionary<string, object>? predefined { get; set; }
|
||||||
|
// Deprecated
|
||||||
public string? address { get; set; }
|
public string? address { get; set; }
|
||||||
public string? address_resolver { get; set; }
|
public string? address_resolver { get; set; }
|
||||||
public string? address_strategy { get; set; }
|
public string? address_strategy { get; set; }
|
||||||
public string? strategy { get; set; }
|
public string? strategy { get; set; }
|
||||||
public string? detour { get; set; }
|
// Deprecated End
|
||||||
public string? client_subnet { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Experimental4Sbox
|
public class Experimental4Sbox
|
||||||
|
|
@ -254,3 +297,33 @@ public class Ruleset4Sbox
|
||||||
public string? download_detour { get; set; }
|
public string? download_detour { get; set; }
|
||||||
public string? update_interval { get; set; }
|
public string? update_interval { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract class DialFields4Sbox
|
||||||
|
{
|
||||||
|
public string? detour { get; set; }
|
||||||
|
public string? bind_interface { get; set; }
|
||||||
|
public string? inet4_bind_address { get; set; }
|
||||||
|
public string? inet6_bind_address { get; set; }
|
||||||
|
public int? routing_mark { get; set; }
|
||||||
|
public bool? reuse_addr { get; set; }
|
||||||
|
public string? netns { get; set; }
|
||||||
|
public string? connect_timeout { get; set; }
|
||||||
|
public bool? tcp_fast_open { get; set; }
|
||||||
|
public bool? tcp_multi_path { get; set; }
|
||||||
|
public bool? udp_fragment { get; set; }
|
||||||
|
public Rule4Sbox? domain_resolver { get; set; } // or string
|
||||||
|
public string? network_strategy { get; set; }
|
||||||
|
public List<string>? network_type { get; set; }
|
||||||
|
public List<string>? fallback_network_type { get; set; }
|
||||||
|
public string? fallback_delay { get; set; }
|
||||||
|
public Tls4Sbox? tls { get; set; }
|
||||||
|
public Multiplex4Sbox? multiplex { get; set; }
|
||||||
|
public Transport4Sbox? transport { get; set; }
|
||||||
|
public HyObfs4Sbox? obfs { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class BaseServer4Sbox : DialFields4Sbox
|
||||||
|
{
|
||||||
|
public string type { get; set; }
|
||||||
|
public string tag { get; set; }
|
||||||
|
}
|
||||||
|
|
|
||||||
90
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
90
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
|
@ -132,24 +132,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Download speed 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string downloadSpeed {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("downloadSpeed", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Do you want to download {0}? 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string DownloadYesNo {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("DownloadYesNo", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Failed to convert configuration file 的本地化字符串。
|
/// 查找类似 Failed to convert configuration file 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -672,6 +654,15 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Add [Anytls] Configuration 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuAddAnytlsServer {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuAddAnytlsServer", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Add a custom configuration Configuration 的本地化字符串。
|
/// 查找类似 Add a custom configuration Configuration 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1347,15 +1338,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Advanced Function 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string menuRoutingAdvanced {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("menuRoutingAdvanced", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Add 的本地化字符串。
|
/// 查找类似 Add 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -2715,33 +2697,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 3. Block Domain or IP 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbRoutingTabBlock {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbRoutingTabBlock", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 2. Direct Domain or IP 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbRoutingTabDirect {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbRoutingTabDirect", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 1. Proxy Domain or IP 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbRoutingTabProxy {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbRoutingTabProxy", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Pre-defined Rule Set List 的本地化字符串。
|
/// 查找类似 Pre-defined Rule Set List 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -3237,24 +3192,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Please set the sudo password in Tun mode settings first 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbSettingsLinuxSudoPasswordIsEmpty {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordIsEmpty", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Please do not run this app with sudo 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbSettingsLinuxSudoPasswordNotSudoRunApp {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordNotSudoRunApp", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 The password you entered cannot be verified, so make sure you enter it correctly. If the application does not work properly due to an incorrect input, please restart the application. The password will not be stored and you will need to enter it again after each restart. 的本地化字符串。
|
/// 查找类似 The password you entered cannot be verified, so make sure you enter it correctly. If the application does not work properly due to an incorrect input, please restart the application. The password will not be stored and you will need to enter it again after each restart. 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -3948,15 +3885,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Ungrouped 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string UngroupedServers {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("UngroupedServers", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Upgrade App does not exist 的本地化字符串。
|
/// 查找类似 Upgrade App does not exist 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -132,12 +132,6 @@
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>درحال دانلود...</value>
|
<value>درحال دانلود...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="downloadSpeed" xml:space="preserve">
|
|
||||||
<value>دانلود</value>
|
|
||||||
</data>
|
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
|
||||||
<value>آیا می خواهید {0} را دانلود کنید؟</value>
|
|
||||||
</data>
|
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>تبدیل فایل پیکربندی انجام نشد</value>
|
<value>تبدیل فایل پیکربندی انجام نشد</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -387,9 +381,6 @@
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>کلید میانبر جهانی {0} با موفقیت ثبت شد</value>
|
<value>کلید میانبر جهانی {0} با موفقیت ثبت شد</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UngroupedServers" xml:space="preserve">
|
|
||||||
<value>گروه بندی نشده</value>
|
|
||||||
</data>
|
|
||||||
<data name="AllGroupServers" xml:space="preserve">
|
<data name="AllGroupServers" xml:space="preserve">
|
||||||
<value>همه سرورها</value>
|
<value>همه سرورها</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -822,9 +813,6 @@
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} وب سایت</value>
|
<value>{0} وب سایت</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvanced" xml:space="preserve">
|
|
||||||
<value>عملکرد پیشرفته</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
||||||
<value>اضافه کردن</value>
|
<value>اضافه کردن</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -843,15 +831,6 @@
|
||||||
<data name="TbdomainStrategy" xml:space="preserve">
|
<data name="TbdomainStrategy" xml:space="preserve">
|
||||||
<value>استراتژی دامنه</value>
|
<value>استراتژی دامنه</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabBlock" xml:space="preserve">
|
|
||||||
<value>3. مسدود کردن دامنه یا آیپی</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabDirect" xml:space="preserve">
|
|
||||||
<value>2. دایرکت کردن دامنه یا IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabProxy" xml:space="preserve">
|
|
||||||
<value>1. پروکسی کردن دامنه یا IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
||||||
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
|
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1341,12 +1320,6 @@
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>رمز عبوری که وارد کرده اید تایید نمی شود، بنابراین مطمئن شوید که آن را به درستی وارد کرده اید. اگر برنامه به دلیل ورودی نادرست به درستی کار نمی کند، لطفاً برنامه را مجدداً راه اندازی کنید. رمز عبور ذخیره نمی شود و پس از هر بار راه اندازی مجدد باید آن را دوباره وارد کنید.</value>
|
<value>رمز عبوری که وارد کرده اید تایید نمی شود، بنابراین مطمئن شوید که آن را به درستی وارد کرده اید. اگر برنامه به دلیل ورودی نادرست به درستی کار نمی کند، لطفاً برنامه را مجدداً راه اندازی کنید. رمز عبور ذخیره نمی شود و پس از هر بار راه اندازی مجدد باید آن را دوباره وارد کنید.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
|
||||||
<value>لطفاً ابتدا رمز عبور sudo را در تنظیمات حالت Tun تنظیم کنید</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
|
||||||
<value>لطفا این برنامه را با sudo اجرا نکنید</value>
|
|
||||||
</data>
|
|
||||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
<value>*حالت xhttp</value>
|
<value>*حالت xhttp</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1419,4 +1392,7 @@
|
||||||
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
||||||
<value>URL آزمایش اطلاعات اتصال فعلی</value>
|
<value>URL آزمایش اطلاعات اتصال فعلی</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||||
|
<value>Add [Anytls] Configuration</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -132,12 +132,6 @@
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>Letöltés...</value>
|
<value>Letöltés...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="downloadSpeed" xml:space="preserve">
|
|
||||||
<value>Letöltés</value>
|
|
||||||
</data>
|
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
|
||||||
<value>Le szeretné tölteni? {0}</value>
|
|
||||||
</data>
|
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>Nem sikerült a konfigurációs fájl átalakítása</value>
|
<value>Nem sikerült a konfigurációs fájl átalakítása</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -387,9 +381,6 @@
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>A globális billentyűparancs {0} sikeresen bejegyezve</value>
|
<value>A globális billentyűparancs {0} sikeresen bejegyezve</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UngroupedServers" xml:space="preserve">
|
|
||||||
<value>Összegyűjtetlen</value>
|
|
||||||
</data>
|
|
||||||
<data name="AllGroupServers" xml:space="preserve">
|
<data name="AllGroupServers" xml:space="preserve">
|
||||||
<value>Összes</value>
|
<value>Összes</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -822,9 +813,6 @@
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} Weboldal</value>
|
<value>{0} Weboldal</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvanced" xml:space="preserve">
|
|
||||||
<value>Fejlett funkció</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
||||||
<value>Hozzáadás</value>
|
<value>Hozzáadás</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -843,15 +831,6 @@
|
||||||
<data name="TbdomainStrategy" xml:space="preserve">
|
<data name="TbdomainStrategy" xml:space="preserve">
|
||||||
<value>Domain stratégia</value>
|
<value>Domain stratégia</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabBlock" xml:space="preserve">
|
|
||||||
<value>3. Domain vagy IP blokkolása</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabDirect" xml:space="preserve">
|
|
||||||
<value>2. Közvetlen domain vagy IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabProxy" xml:space="preserve">
|
|
||||||
<value>1. Proxy domain vagy IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
||||||
<value>Előre definiált szabálykészletlista</value>
|
<value>Előre definiált szabálykészletlista</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1341,12 +1320,6 @@
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>The password you entered cannot be verified, so make sure you enter it correctly. If the application does not work properly due to an incorrect input, please restart the application. The password will not be stored and you will need to enter it again after each restart.</value>
|
<value>The password you entered cannot be verified, so make sure you enter it correctly. If the application does not work properly due to an incorrect input, please restart the application. The password will not be stored and you will need to enter it again after each restart.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
|
||||||
<value>Kérlek, először állítsd be a sudo jelszót a Tun módban</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
|
||||||
<value>Kérlek, ne futtasd ezt az alkalmazást sudo-ként</value>
|
|
||||||
</data>
|
|
||||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
<value>*xhttp mód</value>
|
<value>*xhttp mód</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1419,4 +1392,7 @@
|
||||||
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
||||||
<value>Current connection info test URL</value>
|
<value>Current connection info test URL</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||||
|
<value>Add [Anytls] Configuration</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -132,12 +132,6 @@
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>Downloading...</value>
|
<value>Downloading...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="downloadSpeed" xml:space="preserve">
|
|
||||||
<value>Download speed</value>
|
|
||||||
</data>
|
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
|
||||||
<value>Do you want to download {0}?</value>
|
|
||||||
</data>
|
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>Failed to convert configuration file</value>
|
<value>Failed to convert configuration file</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -387,9 +381,6 @@
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>Global hotkey {0} registered successfully</value>
|
<value>Global hotkey {0} registered successfully</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UngroupedServers" xml:space="preserve">
|
|
||||||
<value>Ungrouped</value>
|
|
||||||
</data>
|
|
||||||
<data name="AllGroupServers" xml:space="preserve">
|
<data name="AllGroupServers" xml:space="preserve">
|
||||||
<value>All</value>
|
<value>All</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -822,9 +813,6 @@
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} Website</value>
|
<value>{0} Website</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvanced" xml:space="preserve">
|
|
||||||
<value>Advanced Function</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
||||||
<value>Add</value>
|
<value>Add</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -843,15 +831,6 @@
|
||||||
<data name="TbdomainStrategy" xml:space="preserve">
|
<data name="TbdomainStrategy" xml:space="preserve">
|
||||||
<value>Domain strategy</value>
|
<value>Domain strategy</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabBlock" xml:space="preserve">
|
|
||||||
<value>3. Block Domain or IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabDirect" xml:space="preserve">
|
|
||||||
<value>2. Direct Domain or IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabProxy" xml:space="preserve">
|
|
||||||
<value>1. Proxy Domain or IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
||||||
<value>Pre-defined Rule Set List</value>
|
<value>Pre-defined Rule Set List</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1341,12 +1320,6 @@
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>The password you entered cannot be verified, so make sure you enter it correctly. If the application does not work properly due to an incorrect input, please restart the application. The password will not be stored and you will need to enter it again after each restart.</value>
|
<value>The password you entered cannot be verified, so make sure you enter it correctly. If the application does not work properly due to an incorrect input, please restart the application. The password will not be stored and you will need to enter it again after each restart.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
|
||||||
<value>Please set the sudo password in Tun mode settings first</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
|
||||||
<value>Please do not run this app with sudo</value>
|
|
||||||
</data>
|
|
||||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
<value>*xhttp mode</value>
|
<value>*xhttp mode</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1419,4 +1392,7 @@
|
||||||
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
||||||
<value>Current connection info test URL</value>
|
<value>Current connection info test URL</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||||
|
<value>Add [Anytls] Configuration</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -132,12 +132,6 @@
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>Загрузка...</value>
|
<value>Загрузка...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="downloadSpeed" xml:space="preserve">
|
|
||||||
<value>Скорость загрузки</value>
|
|
||||||
</data>
|
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
|
||||||
<value>Хотите загрузить {0}?</value>
|
|
||||||
</data>
|
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>Не удалось преобразовать файл конфигурации</value>
|
<value>Не удалось преобразовать файл конфигурации</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -387,9 +381,6 @@
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>Глобальная горячая клавиша {0} зарегистрирована успешно</value>
|
<value>Глобальная горячая клавиша {0} зарегистрирована успешно</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UngroupedServers" xml:space="preserve">
|
|
||||||
<value>Разгруппировано</value>
|
|
||||||
</data>
|
|
||||||
<data name="AllGroupServers" xml:space="preserve">
|
<data name="AllGroupServers" xml:space="preserve">
|
||||||
<value>Все серверы</value>
|
<value>Все серверы</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -825,9 +816,6 @@
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} веб-сайт</value>
|
<value>{0} веб-сайт</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvanced" xml:space="preserve">
|
|
||||||
<value>Расширенная функция</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
||||||
<value>Добавить</value>
|
<value>Добавить</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -846,15 +834,6 @@
|
||||||
<data name="TbdomainStrategy" xml:space="preserve">
|
<data name="TbdomainStrategy" xml:space="preserve">
|
||||||
<value>Доменная стратегия</value>
|
<value>Доменная стратегия</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabBlock" xml:space="preserve">
|
|
||||||
<value>3.Заблокировать домен или IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabDirect" xml:space="preserve">
|
|
||||||
<value>2.Прямой домен или IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabProxy" xml:space="preserve">
|
|
||||||
<value>1.Прокси домен или IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
||||||
<value>Предустановленный список наборов правил</value>
|
<value>Предустановленный список наборов правил</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1341,12 +1320,6 @@
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>Введенный вами пароль не может быть подтвержден, поэтому убедитесь, что вы ввели его правильно. Если приложение не работает должным образом из-за неправильного ввода, то перезапустите его. Пароль не будет сохранен, и вам придется вводить его заново после каждого перезапуска</value>
|
<value>Введенный вами пароль не может быть подтвержден, поэтому убедитесь, что вы ввели его правильно. Если приложение не работает должным образом из-за неправильного ввода, то перезапустите его. Пароль не будет сохранен, и вам придется вводить его заново после каждого перезапуска</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
|
||||||
<value>Сначала задайте пароль sudo в настройках TUN-режима</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
|
||||||
<value>Не запускайте программу как суперпользователь</value>
|
|
||||||
</data>
|
|
||||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
<value>*XHTTP-режим</value>
|
<value>*XHTTP-режим</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1419,4 +1392,7 @@
|
||||||
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
||||||
<value>URL для тестирования текущего соединения</value>
|
<value>URL для тестирования текущего соединения</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||||
|
<value>Add [Anytls] Configuration</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|
@ -132,12 +132,6 @@
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>下载开始...</value>
|
<value>下载开始...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="downloadSpeed" xml:space="preserve">
|
|
||||||
<value>下载</value>
|
|
||||||
</data>
|
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
|
||||||
<value>是否下载?{0}</value>
|
|
||||||
</data>
|
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>转换配置文件失败</value>
|
<value>转换配置文件失败</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -387,9 +381,6 @@
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>注册全局热键 {0} 成功</value>
|
<value>注册全局热键 {0} 成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UngroupedServers" xml:space="preserve">
|
|
||||||
<value>未分组配置文件</value>
|
|
||||||
</data>
|
|
||||||
<data name="AllGroupServers" xml:space="preserve">
|
<data name="AllGroupServers" xml:space="preserve">
|
||||||
<value>所有</value>
|
<value>所有</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -822,9 +813,6 @@
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} 官网</value>
|
<value>{0} 官网</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvanced" xml:space="preserve">
|
|
||||||
<value>高级功能</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
||||||
<value>添加规则集</value>
|
<value>添加规则集</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -843,15 +831,6 @@
|
||||||
<data name="TbdomainStrategy" xml:space="preserve">
|
<data name="TbdomainStrategy" xml:space="preserve">
|
||||||
<value>域名解析策略</value>
|
<value>域名解析策略</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabBlock" xml:space="preserve">
|
|
||||||
<value>3.阻止的 Domain 或 IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabDirect" xml:space="preserve">
|
|
||||||
<value>2.直连的 Domain 或 IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabProxy" xml:space="preserve">
|
|
||||||
<value>1.代理的 Domain 或 IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
||||||
<value>预定义规则集列表</value>
|
<value>预定义规则集列表</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1338,12 +1317,6 @@
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>输入的密码无法校验,所以请确保输入正确。如果因为输入错误导致无法正常运行时,请重启本应用。 密码不会存储,每次重启后都需要再次输入。</value>
|
<value>输入的密码无法校验,所以请确保输入正确。如果因为输入错误导致无法正常运行时,请重启本应用。 密码不会存储,每次重启后都需要再次输入。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
|
||||||
<value>请先在 Tun 模式设置中设置 sudo 密码</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
|
||||||
<value>请不要用 sudo 运行本程序</value>
|
|
||||||
</data>
|
|
||||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
<value>*xhttp 模式</value>
|
<value>*xhttp 模式</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1416,4 +1389,7 @@
|
||||||
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
||||||
<value>当前连接信息测试地址</value>
|
<value>当前连接信息测试地址</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||||
|
<value>添加 [Anytls] 配置文件</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -118,7 +118,7 @@
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="BatchExportURLSuccessfully" xml:space="preserve">
|
<data name="BatchExportURLSuccessfully" xml:space="preserve">
|
||||||
<value>匯出分享链接至剪貼簿成功</value>
|
<value>匯出分享連結至剪貼簿成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CheckServerSettings" xml:space="preserve">
|
<data name="CheckServerSettings" xml:space="preserve">
|
||||||
<value>請先檢查設定檔設定</value>
|
<value>請先檢查設定檔設定</value>
|
||||||
|
|
@ -132,12 +132,6 @@
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>下載開始...</value>
|
<value>下載開始...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="downloadSpeed" xml:space="preserve">
|
|
||||||
<value>下載</value>
|
|
||||||
</data>
|
|
||||||
<data name="DownloadYesNo" xml:space="preserve">
|
|
||||||
<value>是否下載?{0}</value>
|
|
||||||
</data>
|
|
||||||
<data name="FailedConversionConfiguration" xml:space="preserve">
|
<data name="FailedConversionConfiguration" xml:space="preserve">
|
||||||
<value>轉換設定檔失敗</value>
|
<value>轉換設定檔失敗</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -295,7 +289,7 @@
|
||||||
<value>成功從剪貼簿匯入 {0} 個設定檔</value>
|
<value>成功從剪貼簿匯入 {0} 個設定檔</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SuccessfullyImportedServerViaScan" xml:space="preserve">
|
<data name="SuccessfullyImportedServerViaScan" xml:space="preserve">
|
||||||
<value>掃描匯入分享链接成功</value>
|
<value>掃描匯入分享連結成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>目前延遲: {0} ms,{1}</value>
|
<value>目前延遲: {0} ms,{1}</value>
|
||||||
|
|
@ -387,9 +381,6 @@
|
||||||
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
|
||||||
<value>註冊全域快速鍵 {0} 成功</value>
|
<value>註冊全域快速鍵 {0} 成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UngroupedServers" xml:space="preserve">
|
|
||||||
<value>未分組設定檔</value>
|
|
||||||
</data>
|
|
||||||
<data name="AllGroupServers" xml:space="preserve">
|
<data name="AllGroupServers" xml:space="preserve">
|
||||||
<value>所有</value>
|
<value>所有</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -481,7 +472,7 @@
|
||||||
<value>語言 (需重啟)</value>
|
<value>語言 (需重啟)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuAddServerViaClipboard" xml:space="preserve">
|
<data name="menuAddServerViaClipboard" xml:space="preserve">
|
||||||
<value>從剪貼簿導入分享鏈接 (Ctrl+V)</value>
|
<value>從剪貼簿導入分享連結 (Ctrl+V)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuAddServerViaScan" xml:space="preserve">
|
<data name="menuAddServerViaScan" xml:space="preserve">
|
||||||
<value>掃描螢幕上的二維碼 (Ctrl+S)</value>
|
<value>掃描螢幕上的二維碼 (Ctrl+S)</value>
|
||||||
|
|
@ -517,7 +508,7 @@
|
||||||
<value>匯出所選設定檔完整設定</value>
|
<value>匯出所選設定檔完整設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuExport2ShareUrl" xml:space="preserve">
|
<data name="menuExport2ShareUrl" xml:space="preserve">
|
||||||
<value>匯出分享链接至剪貼簿 (多選) (Ctrl+C)</value>
|
<value>匯出分享連結至剪貼簿 (多選) (Ctrl+C)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuAddCustomServer" xml:space="preserve">
|
<data name="menuAddCustomServer" xml:space="preserve">
|
||||||
<value>新增自訂設定設定檔</value>
|
<value>新增自訂設定設定檔</value>
|
||||||
|
|
@ -822,9 +813,6 @@
|
||||||
<data name="menuWebsiteItem" xml:space="preserve">
|
<data name="menuWebsiteItem" xml:space="preserve">
|
||||||
<value>{0} 官網</value>
|
<value>{0} 官網</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingAdvanced" xml:space="preserve">
|
|
||||||
<value>進階功能</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
<data name="menuRoutingAdvancedAdd" xml:space="preserve">
|
||||||
<value>新增規則集</value>
|
<value>新增規則集</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -843,15 +831,6 @@
|
||||||
<data name="TbdomainStrategy" xml:space="preserve">
|
<data name="TbdomainStrategy" xml:space="preserve">
|
||||||
<value>域名解析策略</value>
|
<value>域名解析策略</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingTabBlock" xml:space="preserve">
|
|
||||||
<value>3.阻止的 Domain 或 IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabDirect" xml:space="preserve">
|
|
||||||
<value>2.直連的 Domain 或 IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabProxy" xml:space="preserve">
|
|
||||||
<value>1.代理的 Domain 或 IP</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
<data name="TbRoutingTabRuleList" xml:space="preserve">
|
||||||
<value>預定義規則集列表</value>
|
<value>預定義規則集列表</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -892,7 +871,7 @@
|
||||||
<value>規則詳細說明檔案</value>
|
<value>規則詳細說明檔案</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbDnsObjectDoc" xml:space="preserve">
|
<data name="TbDnsObjectDoc" xml:space="preserve">
|
||||||
<value>支援填寫 DnsObject,JSON 格式,點擊查看説明</value>
|
<value>支援填寫 DnsObject,JSON 格式,點擊查看說明</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SubUrlTips" xml:space="preserve">
|
<data name="SubUrlTips" xml:space="preserve">
|
||||||
<value>普通分組此處請留空</value>
|
<value>普通分組此處請留空</value>
|
||||||
|
|
@ -1003,7 +982,7 @@
|
||||||
<value>啟用硬體加速 (需重啟)</value>
|
<value>啟用硬體加速 (需重啟)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SpeedtestingWait" xml:space="preserve">
|
<data name="SpeedtestingWait" xml:space="preserve">
|
||||||
<value>等待测试中(按 ESC 终止)...</value>
|
<value>等待測試中(按 ESC 終止)...</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TipDisplayLog" xml:space="preserve">
|
<data name="TipDisplayLog" xml:space="preserve">
|
||||||
<value>當有異常斷流時請關閉</value>
|
<value>當有異常斷流時請關閉</value>
|
||||||
|
|
@ -1102,10 +1081,10 @@
|
||||||
<value>混淆密碼 (obfs password)</value>
|
<value>混淆密碼 (obfs password)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRuleMatchingTips" xml:space="preserve">
|
<data name="TbRuleMatchingTips" xml:space="preserve">
|
||||||
<value>(Domain 或 IP 或 行程名) 与 Port 与 Protocol 与 InboundTag => OutboundTag</value>
|
<value>(Domain 或 IP 或 行程名) 與 Port 與 Protocol 與 InboundTag => OutboundTag</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbAutoScrollToEnd" xml:space="preserve">
|
<data name="TbAutoScrollToEnd" xml:space="preserve">
|
||||||
<value>自动滚动到末尾</value>
|
<value>自動滾動到末尾</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
||||||
<value>真連線測試位址</value>
|
<value>真連線測試位址</value>
|
||||||
|
|
@ -1201,7 +1180,7 @@
|
||||||
<value>全局</value>
|
<value>全局</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuModeNothing" xml:space="preserve">
|
<data name="menuModeNothing" xml:space="preserve">
|
||||||
<value>随原配置</value>
|
<value>隨原配置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuModeRule" xml:space="preserve">
|
<data name="menuModeRule" xml:space="preserve">
|
||||||
<value>規則</value>
|
<value>規則</value>
|
||||||
|
|
@ -1231,7 +1210,7 @@
|
||||||
<value>自動調整列寬</value>
|
<value>自動調整列寬</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuExport2ShareUrlBase64" xml:space="preserve">
|
<data name="menuExport2ShareUrlBase64" xml:space="preserve">
|
||||||
<value>匯出分享链接至剪貼簿 (多選) Base64 编码</value>
|
<value>匯出分享連結至剪貼簿 (多選) Base64 編碼</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
|
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
|
||||||
<value>匯出所選設定檔完整設定至剪貼簿</value>
|
<value>匯出所選設定檔完整設定至剪貼簿</value>
|
||||||
|
|
@ -1267,7 +1246,7 @@
|
||||||
<value>WebDav 伺服器位址</value>
|
<value>WebDav 伺服器位址</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvWebDavUserName" xml:space="preserve">
|
<data name="LvWebDavUserName" xml:space="preserve">
|
||||||
<value>WebDav 賬戶</value>
|
<value>WebDav 帳戶</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LvWebDavPassword" xml:space="preserve">
|
<data name="LvWebDavPassword" xml:space="preserve">
|
||||||
<value>WebDav 密碼</value>
|
<value>WebDav 密碼</value>
|
||||||
|
|
@ -1336,13 +1315,7 @@
|
||||||
<value>系統的 sudo 密碼</value>
|
<value>系統的 sudo 密碼</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>輸入的密碼無法校驗,所以請確保輸入正確。如果因為輸入錯誤導致無法正常運作時,請重新啟動本應用。 密碼不會存儲,每次重啟後都需要再次輸入。</value>
|
<value>輸入的密碼無法校驗,所以請確保輸入正確。如果因為輸入錯誤導致無法正常運作時,請重新啟動本應用。 密碼不會儲存,每次重啟後都需要再次輸入。</value>
|
||||||
</data>
|
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
|
||||||
<value>請先在 Tun 模式設定中設定 sudo 密碼</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
|
||||||
<value>請不要用 sudo 來運行此 App</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||||
<value>*xhttp 模式</value>
|
<value>*xhttp 模式</value>
|
||||||
|
|
@ -1366,7 +1339,7 @@
|
||||||
<value>開啟第二個本機監聽埠</value>
|
<value>開啟第二個本機監聽埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||||
<value>socks:本地端口,socks2:第二個本地端口,socks3:區域網路端口</value>
|
<value>socks:本地埠,socks2:第二個本地埠,socks3:區域網路埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsTheme" xml:space="preserve">
|
<data name="TbSettingsTheme" xml:space="preserve">
|
||||||
<value>主題</value>
|
<value>主題</value>
|
||||||
|
|
@ -1387,10 +1360,10 @@
|
||||||
<value>移除無效測試結果 {0} 個。</value>
|
<value>移除無效測試結果 {0} 個。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbPorts7" xml:space="preserve">
|
<data name="TbPorts7" xml:space="preserve">
|
||||||
<value>跳躍端口範圍</value>
|
<value>跳躍埠範圍</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbPorts7Tips" xml:space="preserve">
|
<data name="TbPorts7Tips" xml:space="preserve">
|
||||||
<value>會覆蓋端口,多組時用逗號 (,) 隔開</value>
|
<value>會覆蓋埠,多組時用逗號 (,) 隔開</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
|
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
|
||||||
<value>多設定檔產生自訂配置 (多選)</value>
|
<value>多設定檔產生自訂配置 (多選)</value>
|
||||||
|
|
@ -1416,4 +1389,7 @@
|
||||||
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
<data name="TbSettingsIPAPIUrl" xml:space="preserve">
|
||||||
<value>目前連接資訊測試地址</value>
|
<value>目前連接資訊測試地址</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||||
|
<value>新增 [Anytls] 設定檔</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"log": {
|
"log": {
|
||||||
"level": "debug",
|
"level": "debug",
|
||||||
"timestamp": true
|
"timestamp": true
|
||||||
|
|
@ -14,22 +14,10 @@
|
||||||
{
|
{
|
||||||
"type": "direct",
|
"type": "direct",
|
||||||
"tag": "direct"
|
"tag": "direct"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "block",
|
|
||||||
"tag": "block"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag": "dns_out",
|
|
||||||
"type": "dns"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"route": {
|
"route": {
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
|
||||||
"protocol": [ "dns" ],
|
|
||||||
"outbound": "dns_out"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,28 +2,33 @@
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
"tag": "remote",
|
"tag": "remote",
|
||||||
"address": "tcp://8.8.8.8",
|
"type": "tcp",
|
||||||
"strategy": "prefer_ipv4",
|
"server": "8.8.8.8",
|
||||||
"detour": "proxy"
|
"detour": "proxy"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "local",
|
"tag": "local",
|
||||||
"address": "223.5.5.5",
|
"type": "udp",
|
||||||
"strategy": "prefer_ipv4",
|
"server": "223.5.5.5"
|
||||||
"detour": "direct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag": "block",
|
|
||||||
"address": "rcode://success"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rules": [
|
"rules": [
|
||||||
|
{
|
||||||
|
"domain_suffix": [
|
||||||
|
"googleapis.cn",
|
||||||
|
"gstatic.com"
|
||||||
|
],
|
||||||
|
"server": "remote",
|
||||||
|
"strategy": "prefer_ipv4"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"rule_set": [
|
"rule_set": [
|
||||||
"geosite-cn"
|
"geosite-cn"
|
||||||
],
|
],
|
||||||
"server": "local"
|
"server": "local",
|
||||||
|
"strategy": "prefer_ipv4"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"final": "remote"
|
"final": "remote",
|
||||||
|
"strategy": "prefer_ipv4"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,29 +2,33 @@
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
"tag": "remote",
|
"tag": "remote",
|
||||||
"address": "tcp://8.8.8.8",
|
"type": "tcp",
|
||||||
"strategy": "prefer_ipv4",
|
"server": "8.8.8.8",
|
||||||
"detour": "proxy"
|
"detour": "proxy"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "local",
|
"tag": "local",
|
||||||
"address": "223.5.5.5",
|
"type": "udp",
|
||||||
"strategy": "prefer_ipv4",
|
"server": "223.5.5.5"
|
||||||
"detour": "direct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag": "block",
|
|
||||||
"address": "rcode://success"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"rule_set": [
|
"domain_suffix": [
|
||||||
"geosite-cn",
|
"googleapis.cn",
|
||||||
"geosite-geolocation-cn"
|
"gstatic.com"
|
||||||
],
|
],
|
||||||
"server": "local"
|
"server": "remote",
|
||||||
|
"strategy": "prefer_ipv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule_set": [
|
||||||
|
"geosite-cn"
|
||||||
|
],
|
||||||
|
"server": "local",
|
||||||
|
"strategy": "prefer_ipv4"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"final": "remote"
|
"final": "remote",
|
||||||
}
|
"strategy": "prefer_ipv4"
|
||||||
|
}
|
||||||
|
|
@ -8,13 +8,13 @@
|
||||||
139,
|
139,
|
||||||
5353
|
5353
|
||||||
],
|
],
|
||||||
"outbound": "block"
|
"action": "reject"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ip_cidr": [
|
"ip_cidr": [
|
||||||
"224.0.0.0/3",
|
"224.0.0.0/3",
|
||||||
"ff00::/8"
|
"ff00::/8"
|
||||||
],
|
],
|
||||||
"outbound": "block"
|
"action": "reject"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Reactive;
|
||||||
|
using DynamicData;
|
||||||
|
using ServiceLib.Models;
|
||||||
|
|
||||||
namespace ServiceLib.Services.CoreConfig;
|
namespace ServiceLib.Services.CoreConfig;
|
||||||
|
|
||||||
|
|
@ -53,7 +56,18 @@ public class CoreConfigSingboxService
|
||||||
|
|
||||||
await GenInbounds(singboxConfig);
|
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);
|
await GenMoreOutbounds(node, singboxConfig);
|
||||||
|
|
||||||
|
|
@ -202,16 +216,29 @@ public class CoreConfigSingboxService
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
var server = await GenServer(item);
|
||||||
await GenOutbound(item, outbound);
|
if (server is null)
|
||||||
outbound.tag = Global.ProxyTag + inbound.listen_port.ToString();
|
{
|
||||||
singboxConfig.outbounds.Add(outbound);
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
var tag = Global.ProxyTag + inbound.listen_port.ToString();
|
||||||
|
server.tag = tag;
|
||||||
|
if (server is Endpoints4Sbox endpoint)
|
||||||
|
{
|
||||||
|
singboxConfig.endpoints ??= new();
|
||||||
|
singboxConfig.endpoints.Add(endpoint);
|
||||||
|
}
|
||||||
|
else if (server is Outbound4Sbox outbound)
|
||||||
|
{
|
||||||
|
singboxConfig.outbounds.Add(outbound);
|
||||||
|
}
|
||||||
|
|
||||||
//rule
|
//rule
|
||||||
Rule4Sbox rule = new()
|
Rule4Sbox rule = new()
|
||||||
{
|
{
|
||||||
inbound = new List<string> { inbound.tag },
|
inbound = new List<string> { inbound.tag },
|
||||||
outbound = outbound.tag
|
outbound = tag
|
||||||
};
|
};
|
||||||
singboxConfig.route.rules.Add(rule);
|
singboxConfig.route.rules.Add(rule);
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +302,18 @@ public class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
|
|
||||||
await GenLog(singboxConfig);
|
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 GenMoreOutbounds(node, singboxConfig);
|
||||||
await GenDnsDomains(null, singboxConfig, null);
|
await GenDnsDomains(null, singboxConfig, null);
|
||||||
|
|
||||||
|
|
@ -534,15 +572,6 @@ public class CoreConfigSingboxService
|
||||||
singboxConfig.inbounds.Add(inbound);
|
singboxConfig.inbounds.Add(inbound);
|
||||||
|
|
||||||
inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
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)
|
if (_config.Inbound.First().SecondLocalPortEnabled)
|
||||||
{
|
{
|
||||||
|
|
@ -587,8 +616,6 @@ public class CoreConfigSingboxService
|
||||||
tunInbound.mtu = _config.TunModeItem.Mtu;
|
tunInbound.mtu = _config.TunModeItem.Mtu;
|
||||||
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
||||||
tunInbound.stack = _config.TunModeItem.Stack;
|
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)
|
if (_config.TunModeItem.EnableIPv6Address == false)
|
||||||
{
|
{
|
||||||
tunInbound.address = ["172.18.0.1/30"];
|
tunInbound.address = ["172.18.0.1/30"];
|
||||||
|
|
@ -621,6 +648,17 @@ public class CoreConfigSingboxService
|
||||||
outbound.server_port = node.Port;
|
outbound.server_port = node.Port;
|
||||||
outbound.type = Global.ProtocolTypes[node.ConfigType];
|
outbound.type = Global.ProtocolTypes[node.ConfigType];
|
||||||
|
|
||||||
|
if (Utils.IsDomain(node.Address))
|
||||||
|
{
|
||||||
|
var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
|
||||||
|
var localDnsAddress = string.IsNullOrEmpty(item?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : item?.DomainDNSAddress;
|
||||||
|
outbound.domain_resolver = new()
|
||||||
|
{
|
||||||
|
server = localDnsAddress.StartsWith("tag://") ? localDnsAddress.Substring(6) : "local_resolver",
|
||||||
|
strategy = string.IsNullOrEmpty(item?.DomainStrategy4Freedom) ? null : item?.DomainStrategy4Freedom
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
switch (node.ConfigType)
|
switch (node.ConfigType)
|
||||||
{
|
{
|
||||||
case EConfigType.VMess:
|
case EConfigType.VMess:
|
||||||
|
|
@ -725,13 +763,9 @@ public class CoreConfigSingboxService
|
||||||
outbound.congestion_control = node.HeaderType;
|
outbound.congestion_control = node.HeaderType;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EConfigType.WireGuard:
|
case EConfigType.Anytls:
|
||||||
{
|
{
|
||||||
outbound.private_key = node.Id;
|
outbound.password = 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();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -747,6 +781,76 @@ public class CoreConfigSingboxService
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<int> GenEndpoint(ProfileItem node, Endpoints4Sbox endpoint)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
endpoint.address = Utils.String2List(node.RequestHost);
|
||||||
|
endpoint.type = Global.ProtocolTypes[node.ConfigType];
|
||||||
|
|
||||||
|
if (Utils.IsDomain(node.Address))
|
||||||
|
{
|
||||||
|
var item = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
|
||||||
|
var localDnsAddress = string.IsNullOrEmpty(item?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : item?.DomainDNSAddress;
|
||||||
|
endpoint.domain_resolver = new()
|
||||||
|
{
|
||||||
|
server = localDnsAddress.StartsWith("tag://") ? localDnsAddress.Substring(6) : "local_resolver",
|
||||||
|
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" },
|
||||||
|
};
|
||||||
|
endpoint.private_key = node.Id;
|
||||||
|
endpoint.mtu = node.ShortId.IsNullOrEmpty() ? Global.TunMtus.First() : node.ShortId.ToInt();
|
||||||
|
endpoint.peers = new() { peer };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
return await Task.FromResult(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<BaseServer4Sbox?> GenServer(ProfileItem node)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||||
|
if (node.ConfigType == EConfigType.WireGuard)
|
||||||
|
{
|
||||||
|
var endpoint = JsonUtils.Deserialize<Endpoints4Sbox>(txtOutbound);
|
||||||
|
await GenEndpoint(node, endpoint);
|
||||||
|
return endpoint;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
||||||
|
await GenOutbound(node, outbound);
|
||||||
|
return outbound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
return await Task.FromResult<BaseServer4Sbox?>(null);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
|
private async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -913,7 +1017,8 @@ public class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
|
|
||||||
//current proxy
|
//current proxy
|
||||||
var outbound = singboxConfig.outbounds.First();
|
BaseServer4Sbox? outbound = singboxConfig.endpoints?.FirstOrDefault(t => t.tag == Global.ProxyTag) == null ? singboxConfig.outbounds.First() : null;
|
||||||
|
|
||||||
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
|
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||||
|
|
||||||
//Previous proxy
|
//Previous proxy
|
||||||
|
|
@ -922,17 +1027,32 @@ public class CoreConfigSingboxService
|
||||||
if (prevNode is not null
|
if (prevNode is not null
|
||||||
&& prevNode.ConfigType != EConfigType.Custom)
|
&& prevNode.ConfigType != EConfigType.Custom)
|
||||||
{
|
{
|
||||||
var prevOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
|
||||||
await GenOutbound(prevNode, prevOutbound);
|
|
||||||
prevOutboundTag = $"prev-{Global.ProxyTag}";
|
prevOutboundTag = $"prev-{Global.ProxyTag}";
|
||||||
prevOutbound.tag = prevOutboundTag;
|
var prevServer = await GenServer(prevNode);
|
||||||
singboxConfig.outbounds.Add(prevOutbound);
|
prevServer.tag = prevOutboundTag;
|
||||||
|
if (prevServer is Endpoints4Sbox endpoint)
|
||||||
|
{
|
||||||
|
singboxConfig.endpoints ??= new();
|
||||||
|
singboxConfig.endpoints.Add(endpoint);
|
||||||
|
}
|
||||||
|
else if (prevServer is Outbound4Sbox outboundPrev)
|
||||||
|
{
|
||||||
|
singboxConfig.outbounds.Add(outboundPrev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var nextOutbound = await GenChainOutbounds(subItem, outbound, prevOutboundTag);
|
var nextServer = await GenChainOutbounds(subItem, outbound, prevOutboundTag);
|
||||||
|
|
||||||
if (nextOutbound is not null)
|
if (nextServer is not null)
|
||||||
{
|
{
|
||||||
singboxConfig.outbounds.Insert(0, nextOutbound);
|
if (nextServer is Endpoints4Sbox endpoint)
|
||||||
|
{
|
||||||
|
singboxConfig.endpoints ??= new();
|
||||||
|
singboxConfig.endpoints.Insert(0, endpoint);
|
||||||
|
}
|
||||||
|
else if (nextServer is Outbound4Sbox outboundNext)
|
||||||
|
{
|
||||||
|
singboxConfig.outbounds.Insert(0, outboundNext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -955,11 +1075,13 @@ public class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultOutbounds = new List<Outbound4Sbox>();
|
var resultOutbounds = new List<Outbound4Sbox>();
|
||||||
|
var resultEndpoints = new List<Endpoints4Sbox>(); // For endpoints
|
||||||
var prevOutbounds = new List<Outbound4Sbox>(); // Separate list for prev outbounds
|
var prevOutbounds = new List<Outbound4Sbox>(); // Separate list for prev outbounds
|
||||||
|
var prevEndpoints = new List<Endpoints4Sbox>(); // Separate list for prev endpoints
|
||||||
var proxyTags = new List<string>(); // For selector and urltest outbounds
|
var proxyTags = new List<string>(); // For selector and urltest outbounds
|
||||||
|
|
||||||
// Cache for chain proxies to avoid duplicate generation
|
// Cache for chain proxies to avoid duplicate generation
|
||||||
var nextProxyCache = new Dictionary<string, Outbound4Sbox?>();
|
var nextProxyCache = new Dictionary<string, BaseServer4Sbox?>();
|
||||||
var prevProxyTags = new Dictionary<string, string?>(); // Map from profile name to tag
|
var prevProxyTags = new Dictionary<string, string?>(); // Map from profile name to tag
|
||||||
int prevIndex = 0; // Index for prev outbounds
|
int prevIndex = 0; // Index for prev outbounds
|
||||||
|
|
||||||
|
|
@ -971,19 +1093,18 @@ public class CoreConfigSingboxService
|
||||||
|
|
||||||
// Handle proxy chain
|
// Handle proxy chain
|
||||||
string? prevTag = null;
|
string? prevTag = null;
|
||||||
var currentOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
var currentServer = await GenServer(node);
|
||||||
var nextOutbound = nextProxyCache.GetValueOrDefault(node.Subid, null);
|
var nextServer = nextProxyCache.GetValueOrDefault(node.Subid, null);
|
||||||
if (nextOutbound != null)
|
if (nextServer != null)
|
||||||
{
|
{
|
||||||
nextOutbound = JsonUtils.DeepCopy(nextOutbound);
|
nextServer = JsonUtils.DeepCopy(nextServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
var subItem = await AppHandler.Instance.GetSubItem(node.Subid);
|
var subItem = await AppHandler.Instance.GetSubItem(node.Subid);
|
||||||
|
|
||||||
// current proxy
|
// current proxy
|
||||||
await GenOutbound(node, currentOutbound);
|
currentServer.tag = $"{Global.ProxyTag}-{index}";
|
||||||
currentOutbound.tag = $"{Global.ProxyTag}-{index}";
|
proxyTags.Add(currentServer.tag);
|
||||||
proxyTags.Add(currentOutbound.tag);
|
|
||||||
|
|
||||||
if (!node.Subid.IsNullOrEmpty())
|
if (!node.Subid.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
|
|
@ -1006,18 +1127,32 @@ public class CoreConfigSingboxService
|
||||||
prevProxyTags[node.Subid] = prevTag;
|
prevProxyTags[node.Subid] = prevTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextOutbound = await GenChainOutbounds(subItem, currentOutbound, prevTag, nextOutbound);
|
nextServer = await GenChainOutbounds(subItem, currentServer, prevTag, nextServer);
|
||||||
if (!nextProxyCache.ContainsKey(node.Subid))
|
if (!nextProxyCache.ContainsKey(node.Subid))
|
||||||
{
|
{
|
||||||
nextProxyCache[node.Subid] = nextOutbound;
|
nextProxyCache[node.Subid] = nextServer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextOutbound is not null)
|
if (nextServer is not null)
|
||||||
{
|
{
|
||||||
resultOutbounds.Add(nextOutbound);
|
if (nextServer is Endpoints4Sbox nextEndpoint)
|
||||||
|
{
|
||||||
|
resultEndpoints.Add(nextEndpoint);
|
||||||
|
}
|
||||||
|
else if (nextServer is Outbound4Sbox nextOutbound)
|
||||||
|
{
|
||||||
|
resultOutbounds.Add(nextOutbound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentServer is Endpoints4Sbox currentEndpoint)
|
||||||
|
{
|
||||||
|
resultEndpoints.Add(currentEndpoint);
|
||||||
|
}
|
||||||
|
else if (currentServer is Outbound4Sbox currentOutbound)
|
||||||
|
{
|
||||||
|
resultOutbounds.Add(currentOutbound);
|
||||||
}
|
}
|
||||||
resultOutbounds.Add(currentOutbound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add urltest outbound (auto selection based on latency)
|
// Add urltest outbound (auto selection based on latency)
|
||||||
|
|
@ -1050,6 +1185,9 @@ public class CoreConfigSingboxService
|
||||||
resultOutbounds.AddRange(prevOutbounds);
|
resultOutbounds.AddRange(prevOutbounds);
|
||||||
resultOutbounds.AddRange(singboxConfig.outbounds);
|
resultOutbounds.AddRange(singboxConfig.outbounds);
|
||||||
singboxConfig.outbounds = resultOutbounds;
|
singboxConfig.outbounds = resultOutbounds;
|
||||||
|
singboxConfig.endpoints ??= new List<Endpoints4Sbox>();
|
||||||
|
resultEndpoints.AddRange(singboxConfig.endpoints);
|
||||||
|
singboxConfig.endpoints = resultEndpoints;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -1071,7 +1209,7 @@ public class CoreConfigSingboxService
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// The outbound configuration for the next proxy in the chain, or null if no next proxy exists.
|
/// The outbound configuration for the next proxy in the chain, or null if no next proxy exists.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
private async Task<Outbound4Sbox?> GenChainOutbounds(SubItem subItem, Outbound4Sbox outbound, string? prevOutboundTag, Outbound4Sbox? nextOutbound = null)
|
private async Task<BaseServer4Sbox?> GenChainOutbounds(SubItem subItem, BaseServer4Sbox outbound, string? prevOutboundTag, BaseServer4Sbox? nextOutbound = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -1087,11 +1225,7 @@ public class CoreConfigSingboxService
|
||||||
if (nextNode is not null
|
if (nextNode is not null
|
||||||
&& nextNode.ConfigType != EConfigType.Custom)
|
&& nextNode.ConfigType != EConfigType.Custom)
|
||||||
{
|
{
|
||||||
if (nextOutbound == null)
|
nextOutbound ??= await GenServer(nextNode);
|
||||||
{
|
|
||||||
nextOutbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
|
|
||||||
await GenOutbound(nextNode, nextOutbound);
|
|
||||||
}
|
|
||||||
nextOutbound.tag = outbound.tag;
|
nextOutbound.tag = outbound.tag;
|
||||||
|
|
||||||
outbound.tag = $"mid-{outbound.tag}";
|
outbound.tag = $"mid-{outbound.tag}";
|
||||||
|
|
@ -1110,7 +1244,7 @@ public class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dnsOutbound = "dns_out";
|
singboxConfig.route.final = Global.ProxyTag;
|
||||||
|
|
||||||
if (_config.TunModeItem.EnableTun)
|
if (_config.TunModeItem.EnableTun)
|
||||||
{
|
{
|
||||||
|
|
@ -1126,7 +1260,7 @@ public class CoreConfigSingboxService
|
||||||
singboxConfig.route.rules.Add(new()
|
singboxConfig.route.rules.Add(new()
|
||||||
{
|
{
|
||||||
port = new() { 53 },
|
port = new() { 53 },
|
||||||
outbound = dnsOutbound,
|
action = "hijack-dns",
|
||||||
process_name = lstDnsExe
|
process_name = lstDnsExe
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1137,13 +1271,25 @@ public class CoreConfigSingboxService
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_config.Inbound.First().SniffingEnabled)
|
if (_config.Inbound.First().SniffingEnabled)
|
||||||
{
|
{
|
||||||
singboxConfig.route.rules.Add(new()
|
singboxConfig.route.rules.Add(new()
|
||||||
{
|
{
|
||||||
port = [53],
|
action = "sniff"
|
||||||
network = ["udp"],
|
});
|
||||||
outbound = dnsOutbound
|
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"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1158,7 +1304,24 @@ public class CoreConfigSingboxService
|
||||||
clash_mode = ERuleMode.Global.ToString()
|
clash_mode = ERuleMode.Global.ToString()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var domainStrategy = _config.RoutingBasicItem.DomainStrategy4Singbox.IsNullOrEmpty() ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
|
||||||
|
var defaultRouting = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (defaultRouting.DomainStrategy4Singbox.IsNotEmpty())
|
||||||
|
{
|
||||||
|
domainStrategy = defaultRouting.DomainStrategy4Singbox;
|
||||||
|
}
|
||||||
|
var resolveRule = new Rule4Sbox
|
||||||
|
{
|
||||||
|
action = "resolve",
|
||||||
|
strategy = domainStrategy
|
||||||
|
};
|
||||||
|
if (_config.RoutingBasicItem.DomainStrategy == "IPOnDemand")
|
||||||
|
{
|
||||||
|
singboxConfig.route.rules.Add(resolveRule);
|
||||||
|
}
|
||||||
|
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
var ipRules = new List<RulesItem>();
|
||||||
if (routing != null)
|
if (routing != null)
|
||||||
{
|
{
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
||||||
|
|
@ -1167,9 +1330,21 @@ public class CoreConfigSingboxService
|
||||||
if (item.Enabled)
|
if (item.Enabled)
|
||||||
{
|
{
|
||||||
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
||||||
|
if (item.Ip != null && item.Ip.Count > 0)
|
||||||
|
{
|
||||||
|
ipRules.Add(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_config.RoutingBasicItem.DomainStrategy == "IPIfNonMatch")
|
||||||
|
{
|
||||||
|
singboxConfig.route.rules.Add(resolveRule);
|
||||||
|
foreach (var item in ipRules)
|
||||||
|
{
|
||||||
|
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -1215,10 +1390,15 @@ public class CoreConfigSingboxService
|
||||||
return 0;
|
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())
|
if (item.Port.IsNotEmpty())
|
||||||
{
|
{
|
||||||
|
|
@ -1342,24 +1522,28 @@ public class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (address.StartsWith("geoip:!"))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (address.Equals("geoip:private"))
|
else if (address.Equals("geoip:private"))
|
||||||
{
|
{
|
||||||
rule.ip_is_private = true;
|
rule.ip_is_private = true;
|
||||||
}
|
}
|
||||||
else if (address.StartsWith("geoip:"))
|
else if (address.StartsWith("geoip:"))
|
||||||
{
|
{
|
||||||
if (rule.geoip is null)
|
rule.geoip ??= new();
|
||||||
{ rule.geoip = new(); }
|
|
||||||
rule.geoip?.Add(address.Substring(6));
|
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
|
else
|
||||||
{
|
{
|
||||||
if (rule.ip_cidr is null)
|
rule.ip_cidr ??= new();
|
||||||
{ rule.ip_cidr = new(); }
|
|
||||||
rule.ip_cidr?.Add(address);
|
rule.ip_cidr?.Add(address);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1387,7 +1571,14 @@ public class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
singboxConfig.dns = dns4Sbox;
|
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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -1402,6 +1593,75 @@ public class CoreConfigSingboxService
|
||||||
dns4Sbox.servers ??= [];
|
dns4Sbox.servers ??= [];
|
||||||
dns4Sbox.rules ??= [];
|
dns4Sbox.rules ??= [];
|
||||||
|
|
||||||
|
var tag = "local_resolver";
|
||||||
|
var localDnsAddress = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.SingboxDomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress;
|
||||||
|
|
||||||
|
if (localDnsAddress.StartsWith("tag://"))
|
||||||
|
{
|
||||||
|
tag = localDnsAddress.Substring(6);
|
||||||
|
|
||||||
|
var localDnsTag = "local_local";
|
||||||
|
|
||||||
|
dns4Sbox.servers.Add(new()
|
||||||
|
{
|
||||||
|
tag = localDnsTag,
|
||||||
|
type = "local"
|
||||||
|
});
|
||||||
|
|
||||||
|
dns4Sbox.rules.Insert(0, new()
|
||||||
|
{
|
||||||
|
server = localDnsTag,
|
||||||
|
clash_mode = ERuleMode.Direct.ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var (dnsType, dnsHost, dnsPort, dnsPath) = ParseDnsAddress(localDnsAddress);
|
||||||
|
|
||||||
|
dns4Sbox.servers.Add(new()
|
||||||
|
{
|
||||||
|
tag = tag,
|
||||||
|
type = dnsType,
|
||||||
|
server = dnsHost,
|
||||||
|
Interface = dnsType == "dhcp" ? dnsHost : null,
|
||||||
|
server_port = dnsPort,
|
||||||
|
path = dnsPath
|
||||||
|
});
|
||||||
|
|
||||||
|
dns4Sbox.rules.Insert(0, new()
|
||||||
|
{
|
||||||
|
server = tag,
|
||||||
|
clash_mode = ERuleMode.Direct.ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
var tag = "local_local";
|
||||||
dns4Sbox.servers.Add(new()
|
dns4Sbox.servers.Add(new()
|
||||||
{
|
{
|
||||||
|
|
@ -1449,6 +1709,91 @@ public class CoreConfigSingboxService
|
||||||
return await Task.FromResult(0);
|
return await Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private (string type, string? host, int? port, string? path) ParseDnsAddress(string address)
|
||||||
|
{
|
||||||
|
string type = "udp";
|
||||||
|
string? host = null;
|
||||||
|
int? port = null;
|
||||||
|
string? path = null;
|
||||||
|
|
||||||
|
if (address is "local" or "localhost")
|
||||||
|
{
|
||||||
|
return ("local", null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address.StartsWith("dhcp://", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
string interface_name = address.Substring(7);
|
||||||
|
return ("dhcp", interface_name == "auto" ? null : interface_name, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!address.Contains("://"))
|
||||||
|
{
|
||||||
|
// udp dns
|
||||||
|
host = address;
|
||||||
|
return (type, host, port, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int protocolEndIndex = address.IndexOf("://", StringComparison.Ordinal);
|
||||||
|
type = address.Substring(0, protocolEndIndex).ToLower();
|
||||||
|
|
||||||
|
var uri = new Uri(address);
|
||||||
|
host = uri.Host;
|
||||||
|
|
||||||
|
if (!uri.IsDefaultPort)
|
||||||
|
{
|
||||||
|
port = uri.Port;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type == "https" || type == "h3") && !string.IsNullOrEmpty(uri.AbsolutePath) && uri.AbsolutePath != "/")
|
||||||
|
{
|
||||||
|
path = uri.AbsolutePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UriFormatException)
|
||||||
|
{
|
||||||
|
int protocolEndIndex = address.IndexOf("://", StringComparison.Ordinal);
|
||||||
|
if (protocolEndIndex > 0)
|
||||||
|
{
|
||||||
|
type = address.Substring(0, protocolEndIndex).ToLower();
|
||||||
|
string remaining = address.Substring(protocolEndIndex + 3);
|
||||||
|
|
||||||
|
int portIndex = remaining.IndexOf(':');
|
||||||
|
int pathIndex = remaining.IndexOf('/');
|
||||||
|
|
||||||
|
if (portIndex > 0)
|
||||||
|
{
|
||||||
|
host = remaining.Substring(0, portIndex);
|
||||||
|
string portPart = pathIndex > portIndex
|
||||||
|
? remaining.Substring(portIndex + 1, pathIndex - portIndex - 1)
|
||||||
|
: remaining.Substring(portIndex + 1);
|
||||||
|
|
||||||
|
if (int.TryParse(portPart, out int parsedPort))
|
||||||
|
{
|
||||||
|
port = parsedPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pathIndex > 0)
|
||||||
|
{
|
||||||
|
host = remaining.Substring(0, pathIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
host = remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathIndex > 0 && (type == "https" || type == "h3"))
|
||||||
|
{
|
||||||
|
path = remaining.Substring(pathIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (type, host, port, path);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<int> GenExperimental(SingboxConfig singboxConfig)
|
private async Task<int> GenExperimental(SingboxConfig singboxConfig)
|
||||||
{
|
{
|
||||||
//if (_config.guiItem.enableStatistics)
|
//if (_config.guiItem.enableStatistics)
|
||||||
|
|
|
||||||
|
|
@ -1322,7 +1322,8 @@ public class CoreConfigV2rayService
|
||||||
if (prevNode is not null
|
if (prevNode is not null
|
||||||
&& prevNode.ConfigType != EConfigType.Custom
|
&& prevNode.ConfigType != EConfigType.Custom
|
||||||
&& prevNode.ConfigType != EConfigType.Hysteria2
|
&& prevNode.ConfigType != EConfigType.Hysteria2
|
||||||
&& prevNode.ConfigType != EConfigType.TUIC)
|
&& prevNode.ConfigType != EConfigType.TUIC
|
||||||
|
&& prevNode.ConfigType != EConfigType.Anytls)
|
||||||
{
|
{
|
||||||
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||||
await GenOutbound(prevNode, prevOutbound);
|
await GenOutbound(prevNode, prevOutbound);
|
||||||
|
|
@ -1397,7 +1398,8 @@ public class CoreConfigV2rayService
|
||||||
if (prevNode is not null
|
if (prevNode is not null
|
||||||
&& prevNode.ConfigType != EConfigType.Custom
|
&& prevNode.ConfigType != EConfigType.Custom
|
||||||
&& prevNode.ConfigType != EConfigType.Hysteria2
|
&& prevNode.ConfigType != EConfigType.Hysteria2
|
||||||
&& prevNode.ConfigType != EConfigType.TUIC)
|
&& prevNode.ConfigType != EConfigType.TUIC
|
||||||
|
&& prevNode.ConfigType != EConfigType.Anytls)
|
||||||
{
|
{
|
||||||
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||||
await GenOutbound(prevNode, prevOutbound);
|
await GenOutbound(prevNode, prevOutbound);
|
||||||
|
|
@ -1466,7 +1468,8 @@ public class CoreConfigV2rayService
|
||||||
if (nextNode is not null
|
if (nextNode is not null
|
||||||
&& nextNode.ConfigType != EConfigType.Custom
|
&& nextNode.ConfigType != EConfigType.Custom
|
||||||
&& nextNode.ConfigType != EConfigType.Hysteria2
|
&& nextNode.ConfigType != EConfigType.Hysteria2
|
||||||
&& nextNode.ConfigType != EConfigType.TUIC)
|
&& nextNode.ConfigType != EConfigType.TUIC
|
||||||
|
&& nextNode.ConfigType != EConfigType.Anytls)
|
||||||
{
|
{
|
||||||
if (nextOutbound == null)
|
if (nextOutbound == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -358,8 +358,8 @@ public class SpeedtestService
|
||||||
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
|
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
|
||||||
{
|
{
|
||||||
List<List<ServerTestItem>> lstTest = new();
|
List<List<ServerTestItem>> lstTest = new();
|
||||||
var lst1 = lstSelected.Where(t => t.ConfigType is not (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).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++)
|
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> AddHysteria2ServerCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> AddTuicServerCmd { get; }
|
public ReactiveCommand<Unit, Unit> AddTuicServerCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> AddWireguardServerCmd { get; }
|
public ReactiveCommand<Unit, Unit> AddWireguardServerCmd { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> AddAnytlsServerCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> AddCustomServerCmd { get; }
|
public ReactiveCommand<Unit, Unit> AddCustomServerCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; }
|
public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }
|
public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }
|
||||||
|
|
@ -111,6 +112,10 @@ public class MainWindowViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
await AddServerAsync(true, EConfigType.WireGuard);
|
await AddServerAsync(true, EConfigType.WireGuard);
|
||||||
});
|
});
|
||||||
|
AddAnytlsServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
|
{
|
||||||
|
await AddServerAsync(true, EConfigType.Anytls);
|
||||||
|
});
|
||||||
AddCustomServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
AddCustomServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
{
|
{
|
||||||
await AddServerAsync(true, EConfigType.Custom);
|
await AddServerAsync(true, EConfigType.Custom);
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,9 @@ public class RoutingSettingViewModel : MyReactiveObject
|
||||||
var routings = await AppHandler.Instance.RoutingItems();
|
var routings = await AppHandler.Instance.RoutingItems();
|
||||||
foreach (var item in routings)
|
foreach (var item in routings)
|
||||||
{
|
{
|
||||||
var def = item.Id == _config.RoutingBasicItem.RoutingIndexId;
|
|
||||||
|
|
||||||
var it = new RoutingItemModel()
|
var it = new RoutingItemModel()
|
||||||
{
|
{
|
||||||
IsActive = def,
|
IsActive = item.IsActive,
|
||||||
RuleNum = item.RuleNum,
|
RuleNum = item.RuleNum,
|
||||||
Id = item.Id,
|
Id = item.Id,
|
||||||
Remarks = item.Remarks,
|
Remarks = item.Remarks,
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ public class StatusBarViewModel : MyReactiveObject
|
||||||
foreach (var item in routings)
|
foreach (var item in routings)
|
||||||
{
|
{
|
||||||
_routingItems.Add(item);
|
_routingItems.Add(item);
|
||||||
if (item.Id == _config.RoutingBasicItem.RoutingIndexId)
|
if (item.IsActive)
|
||||||
{
|
{
|
||||||
SelectedRouting = item;
|
SelectedRouting = item;
|
||||||
}
|
}
|
||||||
|
|
@ -396,10 +396,6 @@ public class StatusBarViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_config.RoutingBasicItem.RoutingIndexId == item.Id)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await ConfigHandler.SetDefaultRouting(_config, item) == 0)
|
if (await ConfigHandler.SetDefaultRouting(_config, item) == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public class WindowBase<TViewModel> : ReactiveWindow<TViewModel> where TViewMode
|
||||||
Height = sizeItem.Height;
|
Height = sizeItem.Height;
|
||||||
|
|
||||||
var workingArea = (Screens.ScreenFromWindow(this) ?? Screens.Primary).WorkingArea;
|
var workingArea = (Screens.ScreenFromWindow(this) ?? Screens.Primary).WorkingArea;
|
||||||
var scaling = VisualRoot is not null ? VisualRoot.RenderScaling : 1.0;
|
var scaling = (Utils.IsOSX() ? null : VisualRoot?.RenderScaling) ?? 1.0;
|
||||||
|
|
||||||
var x = workingArea.X + ((workingArea.Width - (Width * scaling)) / 2);
|
var x = workingArea.X + ((workingArea.Width - (Width * scaling)) / 2);
|
||||||
var y = workingArea.Y + ((workingArea.Height - (Height * scaling)) / 2);
|
var y = workingArea.Y + ((workingArea.Height - (Height * scaling)) / 2);
|
||||||
|
|
|
||||||
|
|
@ -533,6 +533,26 @@
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Watermark="1500" />
|
Watermark="1500" />
|
||||||
</Grid>
|
</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
|
<Separator
|
||||||
x:Name="sepa2"
|
x:Name="sepa2"
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,11 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||||
gridTls.IsVisible = false;
|
gridTls.IsVisible = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EConfigType.Anytls:
|
||||||
|
gridAnytls.IsVisible = true;
|
||||||
|
cmbCoreType.IsEnabled = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
gridTlsMore.IsVisible = false;
|
gridTlsMore.IsVisible = false;
|
||||||
|
|
@ -197,6 +202,10 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost9.Text).DisposeWith(disposables);
|
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);
|
this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables);
|
||||||
break;
|
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.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.SelectedValue).DisposeWith(disposables);
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem x:Name="menuAddHysteria2Server" Header="{x:Static resx:ResUI.menuAddHysteria2Server}" />
|
<MenuItem x:Name="menuAddHysteria2Server" Header="{x:Static resx:ResUI.menuAddHysteria2Server}" />
|
||||||
<MenuItem x:Name="menuAddTuicServer" Header="{x:Static resx:ResUI.menuAddTuicServer}" />
|
<MenuItem x:Name="menuAddTuicServer" Header="{x:Static resx:ResUI.menuAddTuicServer}" />
|
||||||
|
<MenuItem x:Name="menuAddAnytlsServer" Header="{x:Static resx:ResUI.menuAddAnytlsServer}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
<MenuItem Padding="8,0">
|
<MenuItem Padding="8,0">
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||||
this.BindCommand(ViewModel, vm => vm.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables);
|
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.AddTuicServerCmd, v => v.menuAddTuicServer).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).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.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
||||||
|
|
@ -134,20 +135,19 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
this.Title = $"{Utils.GetVersion()}";
|
|
||||||
if (Utils.IsWindows())
|
if (Utils.IsWindows())
|
||||||
{
|
{
|
||||||
|
this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
||||||
|
|
||||||
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
|
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
|
||||||
HotkeyHandler.Instance.Init(_config, OnHotkeyHandler);
|
HotkeyHandler.Instance.Init(_config, OnHotkeyHandler);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Utils.IsAdministrator())
|
this.Title = $"{Utils.GetVersion()}";
|
||||||
{
|
|
||||||
this.Title = $"{Utils.GetVersion()} - {ResUI.TbSettingsLinuxSudoPasswordNotSudoRunApp}";
|
|
||||||
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordNotSudoRunApp);
|
|
||||||
}
|
|
||||||
menuRebootAsAdmin.IsVisible = false;
|
menuRebootAsAdmin.IsVisible = false;
|
||||||
menuSettingsSetUWP.IsVisible = false;
|
menuSettingsSetUWP.IsVisible = false;
|
||||||
menuGlobalHotkeySetting.IsVisible = false;
|
menuGlobalHotkeySetting.IsVisible = false;
|
||||||
|
|
@ -464,13 +464,11 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||||
|
|
||||||
if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal)
|
if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal)
|
||||||
{
|
{
|
||||||
_config.UiItem.MainGirdHeight1 = Math.Ceiling(gridMain.ColumnDefinitions[0].ActualWidth + 0.1);
|
ConfigHandler.SaveMainGirdHeight(_config, gridMain.ColumnDefinitions[0].ActualWidth, gridMain.ColumnDefinitions[2].ActualWidth);
|
||||||
_config.UiItem.MainGirdHeight2 = Math.Ceiling(gridMain.ColumnDefinitions[2].ActualWidth + 0.1);
|
|
||||||
}
|
}
|
||||||
else if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Vertical)
|
else if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Vertical)
|
||||||
{
|
{
|
||||||
_config.UiItem.MainGirdHeight1 = Math.Ceiling(gridMain1.RowDefinitions[0].ActualHeight + 0.1);
|
ConfigHandler.SaveMainGirdHeight(_config, gridMain1.RowDefinitions[0].ActualHeight, gridMain1.RowDefinitions[2].ActualHeight);
|
||||||
_config.UiItem.MainGirdHeight2 = Math.Ceiling(gridMain1.RowDefinitions[2].ActualHeight + 0.1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,6 @@
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
DockPanel.Dock="Bottom"
|
DockPanel.Dock="Bottom"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<StackPanel
|
|
||||||
Width="600"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
VerticalAlignment="Center">
|
|
||||||
<TextBlock Text="{x:Static resx:ResUI.TbRoutingTips}" />
|
|
||||||
</StackPanel>
|
|
||||||
<Button
|
<Button
|
||||||
x:Name="btnSave"
|
x:Name="btnSave"
|
||||||
Width="100"
|
Width="100"
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,6 @@ public partial class StatusBarView : ReactiveUserControl<StatusBarViewModel>
|
||||||
|
|
||||||
case EViewAction.PasswordInput:
|
case EViewAction.PasswordInput:
|
||||||
return await PasswordInputAsync();
|
return await PasswordInputAsync();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -707,6 +707,35 @@
|
||||||
materialDesign:HintAssist.Hint="1500"
|
materialDesign:HintAssist.Hint="1500"
|
||||||
Style="{StaticResource DefTextBox}" />
|
Style="{StaticResource DefTextBox}" />
|
||||||
</Grid>
|
</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
|
<Separator
|
||||||
x:Name="sepa2"
|
x:Name="sepa2"
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,11 @@ public partial class AddServerWindow
|
||||||
gridTransport.Visibility = Visibility.Collapsed;
|
gridTransport.Visibility = Visibility.Collapsed;
|
||||||
gridTls.Visibility = Visibility.Collapsed;
|
gridTls.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case EConfigType.Anytls:
|
||||||
|
gridAnytls.Visibility = Visibility.Visible;
|
||||||
|
cmbCoreType.IsEnabled = false;
|
||||||
|
cmbStreamSecurity.Items.Add(Global.StreamSecurityReality);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,6 +196,10 @@ public partial class AddServerWindow
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost9.Text).DisposeWith(disposables);
|
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);
|
this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables);
|
||||||
break;
|
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.Network, v => v.cmbNetwork.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.Text).DisposeWith(disposables);
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,10 @@
|
||||||
x:Name="menuAddTuicServer"
|
x:Name="menuAddTuicServer"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuAddTuicServer}" />
|
Header="{x:Static resx:ResUI.menuAddTuicServer}" />
|
||||||
|
<MenuItem
|
||||||
|
x:Name="menuAddAnytlsServer"
|
||||||
|
Height="{StaticResource MenuItemHeight}"
|
||||||
|
Header="{x:Static resx:ResUI.menuAddAnytlsServer}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
<Separator />
|
<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.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).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.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.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
||||||
|
|
@ -423,13 +424,11 @@ public partial class MainWindow
|
||||||
|
|
||||||
if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal)
|
if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal)
|
||||||
{
|
{
|
||||||
_config.UiItem.MainGirdHeight1 = Math.Ceiling(gridMain.ColumnDefinitions[0].ActualWidth + 0.1);
|
ConfigHandler.SaveMainGirdHeight(_config, gridMain.ColumnDefinitions[0].ActualWidth, gridMain.ColumnDefinitions[2].ActualWidth);
|
||||||
_config.UiItem.MainGirdHeight2 = Math.Ceiling(gridMain.ColumnDefinitions[2].ActualWidth + 0.1);
|
|
||||||
}
|
}
|
||||||
else if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Vertical)
|
else if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Vertical)
|
||||||
{
|
{
|
||||||
_config.UiItem.MainGirdHeight1 = Math.Ceiling(gridMain1.RowDefinitions[0].ActualHeight + 0.1);
|
ConfigHandler.SaveMainGirdHeight(_config, gridMain1.RowDefinitions[0].ActualHeight, gridMain1.RowDefinitions[2].ActualHeight);
|
||||||
_config.UiItem.MainGirdHeight2 = Math.Ceiling(gridMain1.RowDefinitions[2].ActualHeight + 0.1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,6 @@
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
DockPanel.Dock="Bottom"
|
DockPanel.Dock="Bottom"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<StackPanel
|
|
||||||
Width="600"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
VerticalAlignment="Center">
|
|
||||||
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.TbRoutingTips}" />
|
|
||||||
</StackPanel>
|
|
||||||
<Button
|
<Button
|
||||||
x:Name="btnSave"
|
x:Name="btnSave"
|
||||||
Width="100"
|
Width="100"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue