mirror of
https://github.com/2dust/v2rayN.git
synced 2026-02-28 13:13:04 +00:00
Compare commits
10 commits
cd04e170d3
...
6143fdad90
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6143fdad90 | ||
|
|
152e3dc4aa | ||
|
|
d6ee3a4f38 | ||
|
|
12a46990b5 | ||
|
|
b53507f486 | ||
|
|
68ea10158a | ||
|
|
2f35e7a99c | ||
|
|
3c1ecf085b | ||
|
|
3a5293bf87 | ||
|
|
ac43bb051d |
31 changed files with 428 additions and 255 deletions
|
|
@ -5,10 +5,10 @@
|
||||||
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
|
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.4.0" />
|
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.4.1" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.11" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.12" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.11" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.3.12" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.11" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.12" />
|
||||||
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.3.8" />
|
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.3.8" />
|
||||||
<PackageVersion Include="CliWrap" Version="3.10.0" />
|
<PackageVersion Include="CliWrap" Version="3.10.0" />
|
||||||
<PackageVersion Include="Downloader" Version="4.0.3" />
|
<PackageVersion Include="Downloader" Version="4.0.3" />
|
||||||
|
|
@ -19,9 +19,9 @@
|
||||||
<PackageVersion Include="ReactiveUI" Version="22.3.1" />
|
<PackageVersion Include="ReactiveUI" Version="22.3.1" />
|
||||||
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||||
<PackageVersion Include="ReactiveUI.WPF" Version="22.3.1" />
|
<PackageVersion Include="ReactiveUI.WPF" Version="22.3.1" />
|
||||||
<PackageVersion Include="Semi.Avalonia" Version="11.3.7.2" />
|
<PackageVersion Include="Semi.Avalonia" Version="11.3.7.3" />
|
||||||
<PackageVersion Include="Semi.Avalonia.AvaloniaEdit" Version="11.2.0.1" />
|
<PackageVersion Include="Semi.Avalonia.AvaloniaEdit" Version="11.2.0.1" />
|
||||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7.2" />
|
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7.3" />
|
||||||
<PackageVersion Include="NLog" Version="6.1.0" />
|
<PackageVersion Include="NLog" Version="6.1.0" />
|
||||||
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
|
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
|
||||||
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
||||||
|
|
@ -29,4 +29,4 @@
|
||||||
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
||||||
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
|
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ public class Global
|
||||||
public const string DirectTag = "direct";
|
public const string DirectTag = "direct";
|
||||||
public const string BlockTag = "block";
|
public const string BlockTag = "block";
|
||||||
public const string DnsTag = "dns-module";
|
public const string DnsTag = "dns-module";
|
||||||
|
public const string DirectDnsTag = "direct-dns";
|
||||||
public const string BalancerTagSuffix = "-round";
|
public const string BalancerTagSuffix = "-round";
|
||||||
public const string StreamSecurity = "tls";
|
public const string StreamSecurity = "tls";
|
||||||
public const string StreamSecurityReality = "reality";
|
public const string StreamSecurityReality = "reality";
|
||||||
|
|
|
||||||
|
|
@ -1235,31 +1235,63 @@ public static class ConfigHandler
|
||||||
/// <returns>A SOCKS profile item or null if not needed</returns>
|
/// <returns>A SOCKS profile item or null if not needed</returns>
|
||||||
public static ProfileItem? GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
|
public static ProfileItem? GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
|
||||||
{
|
{
|
||||||
|
if (node.ConfigType != EConfigType.Custom || !(node.PreSocksPort > 0))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
ProfileItem? itemSocks = null;
|
ProfileItem? itemSocks = null;
|
||||||
if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun)
|
var preCoreType = AppManager.Instance.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
|
||||||
|
itemSocks = new ProfileItem()
|
||||||
{
|
{
|
||||||
itemSocks = new ProfileItem()
|
CoreType = preCoreType,
|
||||||
{
|
ConfigType = EConfigType.SOCKS,
|
||||||
CoreType = ECoreType.sing_box,
|
Address = Global.Loopback,
|
||||||
ConfigType = EConfigType.SOCKS,
|
Port = node.PreSocksPort.Value,
|
||||||
Address = Global.Loopback,
|
};
|
||||||
Port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0)
|
|
||||||
{
|
|
||||||
var preCoreType = AppManager.Instance.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
|
|
||||||
itemSocks = new ProfileItem()
|
|
||||||
{
|
|
||||||
CoreType = preCoreType,
|
|
||||||
ConfigType = EConfigType.SOCKS,
|
|
||||||
Address = Global.Loopback,
|
|
||||||
Port = node.PreSocksPort.Value,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return itemSocks;
|
return itemSocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CoreConfigContext? GetPreSocksCoreConfigContext(CoreConfigContext nodeContext)
|
||||||
|
{
|
||||||
|
var config = nodeContext.AppConfig;
|
||||||
|
var node = nodeContext.Node;
|
||||||
|
var coreType = AppManager.Instance.GetCoreType(node, node.ConfigType);
|
||||||
|
|
||||||
|
var preSocksItem = GetPreSocksItem(config, node, coreType);
|
||||||
|
if (preSocksItem != null)
|
||||||
|
{
|
||||||
|
return nodeContext with { Node = preSocksItem, };
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!nodeContext.IsTunEnabled)
|
||||||
|
|| coreType != ECoreType.Xray
|
||||||
|
|| node.ConfigType == EConfigType.Custom)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var tunProtectSsPort = Utils.GetFreePort();
|
||||||
|
var proxyRelaySsPort = Utils.GetFreePort();
|
||||||
|
var preItem = new ProfileItem()
|
||||||
|
{
|
||||||
|
CoreType = ECoreType.sing_box,
|
||||||
|
ConfigType = EConfigType.Shadowsocks,
|
||||||
|
Address = Global.Loopback,
|
||||||
|
Port = proxyRelaySsPort,
|
||||||
|
Password = Global.None,
|
||||||
|
};
|
||||||
|
preItem.SetProtocolExtra(preItem.GetProtocolExtra() with
|
||||||
|
{
|
||||||
|
SsMethod = Global.None,
|
||||||
|
});
|
||||||
|
var preContext = nodeContext with
|
||||||
|
{
|
||||||
|
Node = preItem,
|
||||||
|
TunProtectSsPort = tunProtectSsPort,
|
||||||
|
ProxyRelaySsPort = proxyRelaySsPort,
|
||||||
|
};
|
||||||
|
return preContext;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remove servers with invalid test results (timeout)
|
/// Remove servers with invalid test results (timeout)
|
||||||
/// Useful for cleaning up subscription lists
|
/// Useful for cleaning up subscription lists
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,12 @@ public static class CoreConfigHandler
|
||||||
var nodes = await AppManager.Instance.GetProfileItemsByIndexIds(ids);
|
var nodes = await AppManager.Instance.GetProfileItemsByIndexIds(ids);
|
||||||
foreach (var node in nodes)
|
foreach (var node in nodes)
|
||||||
{
|
{
|
||||||
await FillNodeContext(context, node, false);
|
var actNode = await FillNodeContext(context, node, true);
|
||||||
|
if (node.IndexId == actNode.IndexId)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
context.ServerTestItemMap[node.IndexId] = actNode.IndexId;
|
||||||
}
|
}
|
||||||
if (coreType == ECoreType.sing_box)
|
if (coreType == ECoreType.sing_box)
|
||||||
{
|
{
|
||||||
|
|
@ -154,7 +159,8 @@ public static class CoreConfigHandler
|
||||||
IsTunEnabled = config.TunModeItem.EnableTun,
|
IsTunEnabled = config.TunModeItem.EnableTun,
|
||||||
SimpleDnsItem = config.SimpleDNSItem,
|
SimpleDnsItem = config.SimpleDNSItem,
|
||||||
ProtectDomainList = [],
|
ProtectDomainList = [],
|
||||||
ProtectSocksPort = 0,
|
TunProtectSsPort = 0,
|
||||||
|
ProxyRelaySsPort = 0,
|
||||||
RawDnsItem = await AppManager.Instance.GetDNSItem(coreType),
|
RawDnsItem = await AppManager.Instance.GetDNSItem(coreType),
|
||||||
RoutingItem = await ConfigHandler.GetDefaultRouting(config),
|
RoutingItem = await ConfigHandler.GetDefaultRouting(config),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ public class Hysteria2Fmt : BaseFmt
|
||||||
if (!item.CertSha.IsNullOrEmpty())
|
if (!item.CertSha.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
var sha = item.CertSha;
|
var sha = item.CertSha;
|
||||||
var idx = sha.IndexOf('~');
|
var idx = sha.IndexOf(',');
|
||||||
if (idx > 0)
|
if (idx > 0)
|
||||||
{
|
{
|
||||||
sha = sha[..idx];
|
sha = sha[..idx];
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,14 @@ public class CoreManager
|
||||||
|
|
||||||
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);
|
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);
|
||||||
var context = await CoreConfigHandler.BuildCoreConfigContext(_config, node);
|
var context = await CoreConfigHandler.BuildCoreConfigContext(_config, node);
|
||||||
context = context with { IsTunEnabled = _config.TunModeItem.EnableTun };
|
var preContext = ConfigHandler.GetPreSocksCoreConfigContext(context);
|
||||||
|
if (preContext is not null)
|
||||||
|
{
|
||||||
|
context = context with
|
||||||
|
{
|
||||||
|
TunProtectSsPort = preContext.TunProtectSsPort, ProxyRelaySsPort = preContext.ProxyRelaySsPort,
|
||||||
|
};
|
||||||
|
}
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(context, fileName);
|
var result = await CoreConfigHandler.GenerateClientConfig(context, fileName);
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
{
|
{
|
||||||
|
|
@ -88,7 +95,7 @@ public class CoreManager
|
||||||
}
|
}
|
||||||
|
|
||||||
await CoreStart(context);
|
await CoreStart(context);
|
||||||
await CoreStartPreService(context);
|
await CoreStartPreService(preContext);
|
||||||
if (_processService != null)
|
if (_processService != null)
|
||||||
{
|
{
|
||||||
await UpdateFunc(true, $"{node.GetSummary()}");
|
await UpdateFunc(true, $"{node.GetSummary()}");
|
||||||
|
|
@ -183,30 +190,22 @@ public class CoreManager
|
||||||
_processService = proc;
|
_processService = proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CoreStartPreService(CoreConfigContext context)
|
private async Task CoreStartPreService(CoreConfigContext? preContext)
|
||||||
{
|
{
|
||||||
var node = context.Node;
|
if (_processService is { HasExited: false } && preContext != null)
|
||||||
if (_processService != null && !_processService.HasExited)
|
|
||||||
{
|
{
|
||||||
var coreType = AppManager.Instance.GetCoreType(node, node.ConfigType);
|
var preCoreType = preContext?.Node?.CoreType ?? ECoreType.sing_box;
|
||||||
var itemSocks = ConfigHandler.GetPreSocksItem(_config, node, coreType);
|
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
|
||||||
if (itemSocks != null)
|
var result = await CoreConfigHandler.GenerateClientConfig(preContext, fileName);
|
||||||
|
if (result.Success)
|
||||||
{
|
{
|
||||||
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
|
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(preCoreType);
|
||||||
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
|
var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true);
|
||||||
var itemSocksContext = await CoreConfigHandler.BuildCoreConfigContext(_config, itemSocks);
|
if (proc is null)
|
||||||
itemSocksContext.ProtectDomainList.AddRangeSafe(context.ProtectDomainList);
|
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(itemSocksContext, fileName);
|
|
||||||
if (result.Success)
|
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(preCoreType);
|
return;
|
||||||
var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true);
|
|
||||||
if (proc is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_processPreService = proc;
|
|
||||||
}
|
}
|
||||||
|
_processPreService = proc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,6 @@ public class TunModeItem
|
||||||
public bool StrictRoute { get; set; } = true;
|
public bool StrictRoute { get; set; } = true;
|
||||||
public string Stack { get; set; }
|
public string Stack { get; set; }
|
||||||
public int Mtu { get; set; }
|
public int Mtu { get; set; }
|
||||||
public bool EnableExInbound { get; set; }
|
|
||||||
public bool EnableIPv6Address { get; set; }
|
public bool EnableIPv6Address { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,15 @@ public record CoreConfigContext
|
||||||
public Config AppConfig { get; init; } = new();
|
public Config AppConfig { get; init; } = new();
|
||||||
public FullConfigTemplateItem? FullConfigTemplate { get; init; } = new();
|
public FullConfigTemplateItem? FullConfigTemplate { get; init; } = new();
|
||||||
|
|
||||||
|
// Test ServerTestItem Map
|
||||||
|
public Dictionary<string, string> ServerTestItemMap { get; init; } = new();
|
||||||
|
|
||||||
// TUN Compatibility
|
// TUN Compatibility
|
||||||
public bool IsTunEnabled { get; init; } = false;
|
public bool IsTunEnabled { get; init; } = false;
|
||||||
public HashSet<string> ProtectDomainList { get; init; } = new();
|
public HashSet<string> ProtectDomainList { get; init; } = new();
|
||||||
public int ProtectSocksPort { get; init; } = 0;
|
// -> tun inbound --(if routing proxy)--> relay outbound
|
||||||
|
// -> proxy core (relay inbound --> proxy outbound --(dialerProxy)--> protect outbound)
|
||||||
|
// -> protect inbound -> direct proxy outbound data -> internet
|
||||||
|
public int TunProtectSsPort { get; init; } = 0;
|
||||||
|
public int ProxyRelaySsPort { get; init; } = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -220,12 +220,6 @@ public class DnsServer4Ray
|
||||||
public List<string>? domains { get; set; }
|
public List<string>? domains { get; set; }
|
||||||
public bool? skipFallback { get; set; }
|
public bool? skipFallback { get; set; }
|
||||||
public List<string>? expectedIPs { get; set; }
|
public List<string>? expectedIPs { get; set; }
|
||||||
public List<string>? unexpectedIPs { get; set; }
|
|
||||||
public string? clientIp { get; set; }
|
|
||||||
public string? queryStrategy { get; set; }
|
|
||||||
public int? timeoutMs { get; set; }
|
|
||||||
public bool? disableCache { get; set; }
|
|
||||||
public bool? finalQuery { get; set; }
|
|
||||||
public string? tag { get; set; }
|
public string? tag { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,7 +466,7 @@ public class HysteriaSettings4Ray
|
||||||
|
|
||||||
public class HysteriaUdpHop4Ray
|
public class HysteriaUdpHop4Ray
|
||||||
{
|
{
|
||||||
public string? ports { get; set; }
|
public string? port { get; set; }
|
||||||
public string? interval { get; set; }
|
public string? interval { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
18
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
18
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
|
@ -3780,15 +3780,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Enable additional Inbound 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbSettingsEnableExInbound {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbSettingsEnableExInbound", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Enable fragment 的本地化字符串。
|
/// 查找类似 Enable fragment 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -3798,15 +3789,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 which conflicts with the group previous proxy 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string TbSettingsEnableFragmentTips {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("TbSettingsEnableFragmentTips", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Enable hardware acceleration (requires restart) 的本地化字符串。
|
/// 查找类似 Enable hardware acceleration (requires restart) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1071,9 +1071,6 @@
|
||||||
<data name="TbSettingsTunMtu" xml:space="preserve">
|
<data name="TbSettingsTunMtu" xml:space="preserve">
|
||||||
<value>MTU</value>
|
<value>MTU</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
|
||||||
<value>فعال سازی additional Inbound</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>فعال سازی آدرس IPv6</value>
|
<value>فعال سازی آدرس IPv6</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1113,9 +1110,6 @@
|
||||||
<data name="menuAddHttpServer" xml:space="preserve">
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
<value>افزودن سرور [HTTP]</value>
|
<value>افزودن سرور [HTTP]</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
|
||||||
<value>which conflicts with the group previous proxy</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
<value>فعال کردن فرگمنت</value>
|
<value>فعال کردن فرگمنت</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -1068,9 +1068,6 @@
|
||||||
<data name="TbSettingsTunMtu" xml:space="preserve">
|
<data name="TbSettingsTunMtu" xml:space="preserve">
|
||||||
<value>MTU</value>
|
<value>MTU</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
|
||||||
<value>Activer un port d’écoute supplémentaire</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>Activer IPv6</value>
|
<value>Activer IPv6</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1110,9 +1107,6 @@
|
||||||
<data name="menuAddHttpServer" xml:space="preserve">
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
<value>Ajouter [HTTP]</value>
|
<value>Ajouter [HTTP]</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
|
||||||
<value>En conflit avec le proxy amont de groupe</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
<value>Activer le fragmentation (Fragment)</value>
|
<value>Activer le fragmentation (Fragment)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -1071,9 +1071,6 @@
|
||||||
<data name="TbSettingsTunMtu" xml:space="preserve">
|
<data name="TbSettingsTunMtu" xml:space="preserve">
|
||||||
<value>MTU</value>
|
<value>MTU</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
|
||||||
<value>További bejövő engedélyezése</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>IPv6 cím engedélyezése</value>
|
<value>IPv6 cím engedélyezése</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1113,9 +1110,6 @@
|
||||||
<data name="menuAddHttpServer" xml:space="preserve">
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
<value>HTTP konfiguráció hozzáadása</value>
|
<value>HTTP konfiguráció hozzáadása</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
|
||||||
<value>which conflicts with the group previous proxy</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
<value>Fragment engedélyezése</value>
|
<value>Fragment engedélyezése</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -1071,9 +1071,6 @@
|
||||||
<data name="TbSettingsTunMtu" xml:space="preserve">
|
<data name="TbSettingsTunMtu" xml:space="preserve">
|
||||||
<value>MTU</value>
|
<value>MTU</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
|
||||||
<value>Enable additional Inbound</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>Enable IPv6 Address</value>
|
<value>Enable IPv6 Address</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1113,9 +1110,6 @@
|
||||||
<data name="menuAddHttpServer" xml:space="preserve">
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
<value>Add [HTTP]</value>
|
<value>Add [HTTP]</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
|
||||||
<value>which conflicts with the group previous proxy</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
<value>Enable fragment</value>
|
<value>Enable fragment</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -1071,9 +1071,6 @@
|
||||||
<data name="TbSettingsTunMtu" xml:space="preserve">
|
<data name="TbSettingsTunMtu" xml:space="preserve">
|
||||||
<value>MTU</value>
|
<value>MTU</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
|
||||||
<value>Включить дополнительный входящий канал</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>Включить IPv6 адреса</value>
|
<value>Включить IPv6 адреса</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1113,9 +1110,6 @@
|
||||||
<data name="menuAddHttpServer" xml:space="preserve">
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
<value>Добавить сервер [HTTP]</value>
|
<value>Добавить сервер [HTTP]</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
|
||||||
<value>что конфликтует с предыдущим прокси группы</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
<value>Включить фрагментацию (Fragment)</value>
|
<value>Включить фрагментацию (Fragment)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -1068,9 +1068,6 @@
|
||||||
<data name="TbSettingsTunMtu" xml:space="preserve">
|
<data name="TbSettingsTunMtu" xml:space="preserve">
|
||||||
<value>MTU</value>
|
<value>MTU</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
|
||||||
<value>启用额外监听端口</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>启用 IPv6</value>
|
<value>启用 IPv6</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1110,9 +1107,6 @@
|
||||||
<data name="menuAddHttpServer" xml:space="preserve">
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
<value>添加 [HTTP] </value>
|
<value>添加 [HTTP] </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
|
||||||
<value>和分组前置代理冲突</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
<value>启用分片 (Fragment)</value>
|
<value>启用分片 (Fragment)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -1068,9 +1068,6 @@
|
||||||
<data name="TbSettingsTunMtu" xml:space="preserve">
|
<data name="TbSettingsTunMtu" xml:space="preserve">
|
||||||
<value>MTU</value>
|
<value>MTU</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
|
||||||
<value>啟用額外偵聽連接埠</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>啟用 IPv6</value>
|
<value>啟用 IPv6</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -1110,9 +1107,6 @@
|
||||||
<data name="menuAddHttpServer" xml:space="preserve">
|
<data name="menuAddHttpServer" xml:space="preserve">
|
||||||
<value>新增 [HTTP] 節點</value>
|
<value>新增 [HTTP] 節點</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
|
||||||
<value>和分組前置代理衝突</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||||
<value>啟用分片(Fragment)</value>
|
<value>啟用分片(Fragment)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,51 @@ public partial class CoreConfigSingboxService(CoreConfigContext context)
|
||||||
ret.Success = true;
|
ret.Success = true;
|
||||||
|
|
||||||
ret.Data = ApplyFullConfigTemplate();
|
ret.Data = ApplyFullConfigTemplate();
|
||||||
|
if (context.TunProtectSsPort is > 0 and <= 65535)
|
||||||
|
{
|
||||||
|
var ssInbound = new
|
||||||
|
{
|
||||||
|
type = "shadowsocks",
|
||||||
|
tag = "tun-protect-ss",
|
||||||
|
listen = Global.Loopback,
|
||||||
|
listen_port = context.TunProtectSsPort,
|
||||||
|
method = "none",
|
||||||
|
password = "none",
|
||||||
|
};
|
||||||
|
var directRule = new Rule4Sbox()
|
||||||
|
{
|
||||||
|
inbound = new List<string> { ssInbound.tag },
|
||||||
|
outbound = Global.DirectTag,
|
||||||
|
};
|
||||||
|
var singboxConfigNode = JsonUtils.ParseJson(ret.Data.ToString())!.AsObject();
|
||||||
|
var inboundsNode = singboxConfigNode["inbounds"]!.AsArray();
|
||||||
|
inboundsNode.Add(JsonUtils.SerializeToNode(ssInbound, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||||
|
}));
|
||||||
|
var routeNode = singboxConfigNode["route"]?.AsObject();
|
||||||
|
var rulesNode = routeNode?["rules"]?.AsArray();
|
||||||
|
var protectRuleNode = JsonUtils.SerializeToNode(directRule,
|
||||||
|
new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });
|
||||||
|
if (rulesNode != null)
|
||||||
|
{
|
||||||
|
rulesNode.Insert(0, protectRuleNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var newRulesNode = new JsonArray() { protectRuleNode };
|
||||||
|
if (routeNode is null)
|
||||||
|
{
|
||||||
|
var newRouteNode = new JsonObject() { ["rules"] = newRulesNode };
|
||||||
|
singboxConfigNode["route"] = newRouteNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
routeNode["rules"] = newRulesNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.Data = JsonUtils.Serialize(singboxConfigNode);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -122,8 +167,9 @@ public partial class CoreConfigSingboxService(CoreConfigContext context)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var item = context.AllProxiesMap.GetValueOrDefault(it.IndexId);
|
var actIndexId = context.ServerTestItemMap.GetValueOrDefault(it.IndexId, it.IndexId);
|
||||||
if (item is null || item.IsComplex() || !item.IsValid())
|
var item = context.AllProxiesMap.GetValueOrDefault(actIndexId);
|
||||||
|
if (item is null || item.ConfigType is EConfigType.Custom || !item.IsValid())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,15 @@ public partial class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];
|
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];
|
||||||
|
|
||||||
useDirectDns = rules?.LastOrDefault() is { } lastRule &&
|
if (rules?.LastOrDefault() is { } lastRule && lastRule.OutboundTag == Global.DirectTag)
|
||||||
lastRule.OutboundTag == Global.DirectTag &&
|
{
|
||||||
(lastRule.Port == "0-65535" ||
|
var noDomain = lastRule.Domain == null || lastRule.Domain.Count == 0;
|
||||||
lastRule.Network == "tcp,udp" ||
|
var noProcess = lastRule.Process == null || lastRule.Process.Count == 0;
|
||||||
lastRule.Ip?.Contains("0.0.0.0/0") == true);
|
var isAnyIp = lastRule.Ip == null || lastRule.Ip.Count == 0 || lastRule.Ip.Contains("0.0.0.0/0");
|
||||||
|
var isAnyPort = string.IsNullOrEmpty(lastRule.Port) || lastRule.Port == "0-65535";
|
||||||
|
var isAnyNetwork = string.IsNullOrEmpty(lastRule.Network) || lastRule.Network == "tcp,udp";
|
||||||
|
useDirectDns = noDomain && noProcess && isAnyIp && isAnyPort && isAnyNetwork;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_coreConfig.dns.final = useDirectDns ? Global.SingboxDirectDNSTag : Global.SingboxRemoteDNSTag;
|
_coreConfig.dns.final = useDirectDns ? Global.SingboxDirectDNSTag : Global.SingboxRemoteDNSTag;
|
||||||
var simpleDnsItem = context.SimpleDnsItem;
|
var simpleDnsItem = context.SimpleDnsItem;
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@ public partial class CoreConfigSingboxService
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var listen = "0.0.0.0";
|
var listen = "0.0.0.0";
|
||||||
|
var listenPort = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||||
_coreConfig.inbounds = [];
|
_coreConfig.inbounds = [];
|
||||||
|
|
||||||
if (!_config.TunModeItem.EnableTun
|
if (!context.IsTunEnabled
|
||||||
|| (_config.TunModeItem.EnableTun && _config.TunModeItem.EnableExInbound && AppManager.Instance.RunningCoreType == ECoreType.sing_box))
|
|| (context.IsTunEnabled && _node.Port != listenPort))
|
||||||
{
|
{
|
||||||
var inbound = new Inbound4Sbox()
|
var inbound = new Inbound4Sbox()
|
||||||
{
|
{
|
||||||
|
|
@ -20,7 +21,7 @@ public partial class CoreConfigSingboxService
|
||||||
};
|
};
|
||||||
_coreConfig.inbounds.Add(inbound);
|
_coreConfig.inbounds.Add(inbound);
|
||||||
|
|
||||||
inbound.listen_port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
inbound.listen_port = listenPort;
|
||||||
|
|
||||||
if (_config.Inbound.First().SecondLocalPortEnabled)
|
if (_config.Inbound.First().SecondLocalPortEnabled)
|
||||||
{
|
{
|
||||||
|
|
@ -49,7 +50,7 @@ public partial class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config.TunModeItem.EnableTun)
|
if (context.IsTunEnabled)
|
||||||
{
|
{
|
||||||
if (_config.TunModeItem.Mtu <= 0)
|
if (_config.TunModeItem.Mtu <= 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,13 @@ public partial class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
proxyOutboundList.AddRange(BuildGroupProxyOutbounds(baseTagName));
|
proxyOutboundList.AddRange(BuildGroupProxyOutbounds(baseTagName));
|
||||||
}
|
}
|
||||||
var proxyTags = proxyOutboundList.Where(n => n.tag.StartsWith(Global.ProxyTag)).Select(n => n.tag).ToList();
|
if (withSelector)
|
||||||
if (proxyTags.Count > 1)
|
|
||||||
{
|
{
|
||||||
proxyOutboundList.InsertRange(0, BuildSelectorOutbounds(proxyTags, baseTagName));
|
var proxyTags = proxyOutboundList.Where(n => n.tag.StartsWith(Global.ProxyTag)).Select(n => n.tag).ToList();
|
||||||
|
if (proxyTags.Count > 1)
|
||||||
|
{
|
||||||
|
proxyOutboundList.InsertRange(0, BuildSelectorOutbounds(proxyTags, baseTagName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return proxyOutboundList;
|
return proxyOutboundList;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
var ret = new RetResult();
|
var ret = new RetResult();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (context.IsTunEnabled && context.TunProtectSsPort > 0 && context.ProxyRelaySsPort > 0)
|
||||||
|
{
|
||||||
|
return GenerateClientProxyRelayConfig();
|
||||||
|
}
|
||||||
if (_node == null
|
if (_node == null
|
||||||
|| !_node.IsValid())
|
|| !_node.IsValid())
|
||||||
{
|
{
|
||||||
|
|
@ -56,6 +60,12 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
|
|
||||||
GenStatistic();
|
GenStatistic();
|
||||||
|
|
||||||
|
var finalRule = BuildFinalRule();
|
||||||
|
if (!string.IsNullOrEmpty(finalRule?.balancerTag))
|
||||||
|
{
|
||||||
|
_coreConfig.routing.rules.Add(finalRule);
|
||||||
|
}
|
||||||
|
|
||||||
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
ret.Success = true;
|
ret.Success = true;
|
||||||
ret.Data = ApplyFullConfigTemplate();
|
ret.Data = ApplyFullConfigTemplate();
|
||||||
|
|
@ -120,8 +130,9 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var item = context.AllProxiesMap.GetValueOrDefault(it.IndexId);
|
var actIndexId = context.ServerTestItemMap.GetValueOrDefault(it.IndexId, it.IndexId);
|
||||||
if (item is null || item.IsComplex() || !item.IsValid())
|
var item = context.AllProxiesMap.GetValueOrDefault(actIndexId);
|
||||||
|
if (item is null || item.ConfigType is EConfigType.Custom || !item.IsValid())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -239,6 +250,7 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
GenLog();
|
GenLog();
|
||||||
GenOutbounds();
|
GenOutbounds();
|
||||||
|
|
||||||
|
_coreConfig.routing.domainStrategy = Global.AsIs;
|
||||||
_coreConfig.routing.rules.Clear();
|
_coreConfig.routing.rules.Clear();
|
||||||
_coreConfig.inbounds.Clear();
|
_coreConfig.inbounds.Clear();
|
||||||
_coreConfig.inbounds.Add(new()
|
_coreConfig.inbounds.Add(new()
|
||||||
|
|
@ -249,6 +261,8 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
protocol = EInboundProtocol.mixed.ToString(),
|
protocol = EInboundProtocol.mixed.ToString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_coreConfig.routing.rules.Add(BuildFinalRule());
|
||||||
|
|
||||||
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
ret.Success = true;
|
ret.Success = true;
|
||||||
ret.Data = JsonUtils.Serialize(_coreConfig);
|
ret.Data = JsonUtils.Serialize(_coreConfig);
|
||||||
|
|
@ -262,5 +276,106 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RetResult GenerateClientProxyRelayConfig()
|
||||||
|
{
|
||||||
|
var ret = new RetResult();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_node == null
|
||||||
|
|| !_node.IsValid())
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.CheckServerSettings;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_node.GetNetwork() is nameof(ETransport.quic))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.Incorrectconfiguration + $" - {_node.GetNetwork()}";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
|
if (result.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
_coreConfig = JsonUtils.Deserialize<V2rayConfig>(result);
|
||||||
|
if (_coreConfig == null)
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenLog();
|
||||||
|
_coreConfig.outbounds.Clear();
|
||||||
|
GenOutbounds();
|
||||||
|
|
||||||
|
var protectNode = new ProfileItem()
|
||||||
|
{
|
||||||
|
CoreType = ECoreType.Xray,
|
||||||
|
ConfigType = EConfigType.Shadowsocks,
|
||||||
|
Address = Global.Loopback,
|
||||||
|
Port = context.TunProtectSsPort,
|
||||||
|
Password = Global.None,
|
||||||
|
};
|
||||||
|
protectNode.SetProtocolExtra(protectNode.GetProtocolExtra() with
|
||||||
|
{
|
||||||
|
SsMethod = Global.None,
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var outbound in _coreConfig.outbounds.Where(outbound => outbound.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true))
|
||||||
|
{
|
||||||
|
outbound.streamSettings ??= new StreamSettings4Ray();
|
||||||
|
outbound.streamSettings.sockopt ??= new Sockopt4Ray();
|
||||||
|
outbound.streamSettings.sockopt.dialerProxy = "tun-project-ss";
|
||||||
|
}
|
||||||
|
_coreConfig.outbounds.Add(new CoreConfigV2rayService(context with
|
||||||
|
{
|
||||||
|
Node = protectNode,
|
||||||
|
}).BuildProxyOutbound("tun-project-ss"));
|
||||||
|
|
||||||
|
var hasBalancer = _coreConfig.routing.balancers is { Count: > 0 };
|
||||||
|
_coreConfig.routing.rules =
|
||||||
|
[
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
inboundTag = new List<string> { "proxy-relay-ss" },
|
||||||
|
outboundTag = hasBalancer ? null : Global.ProxyTag,
|
||||||
|
balancerTag = hasBalancer ? Global.ProxyTag + Global.BalancerTagSuffix: null,
|
||||||
|
type = "field"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
_coreConfig.inbounds.Clear();
|
||||||
|
|
||||||
|
var configNode = JsonUtils.ParseJson(JsonUtils.Serialize(_coreConfig))!;
|
||||||
|
configNode["inbounds"]!.AsArray().Add(new
|
||||||
|
{
|
||||||
|
listen = Global.Loopback,
|
||||||
|
port = context.ProxyRelaySsPort,
|
||||||
|
protocol = "shadowsocks",
|
||||||
|
settings = new
|
||||||
|
{
|
||||||
|
network = "tcp,udp",
|
||||||
|
method = Global.None,
|
||||||
|
password = Global.None,
|
||||||
|
},
|
||||||
|
tag = "proxy-relay-ss",
|
||||||
|
});
|
||||||
|
|
||||||
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
|
ret.Success = true;
|
||||||
|
ret.Data = JsonUtils.Serialize(configNode);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion public gen function
|
#endregion public gen function
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,18 +70,36 @@ public partial class CoreConfigV2rayService
|
||||||
dnsItem.serveStale = simpleDnsItem?.ServeStale is true ? true : null;
|
dnsItem.serveStale = simpleDnsItem?.ServeStale is true ? true : null;
|
||||||
dnsItem.enableParallelQuery = simpleDnsItem?.ParallelQuery is true ? true : null;
|
dnsItem.enableParallelQuery = simpleDnsItem?.ParallelQuery is true ? true : null;
|
||||||
|
|
||||||
if (_coreConfig.routing.domainStrategy == Global.IPIfNonMatch)
|
// DNS routing
|
||||||
|
var directDnsTags = dnsItem.servers
|
||||||
|
.Select(server =>
|
||||||
|
{
|
||||||
|
var tagNode = (server as JsonObject)?["tag"];
|
||||||
|
return tagNode is JsonValue value && value.TryGetValue<string>(out var tag) ? tag : null;
|
||||||
|
})
|
||||||
|
.Where(tag => tag is not null && tag.StartsWith(Global.DirectDnsTag, StringComparison.Ordinal))
|
||||||
|
.Select(tag => tag!)
|
||||||
|
.ToList();
|
||||||
|
if (directDnsTags.Count > 0)
|
||||||
{
|
{
|
||||||
// DNS routing
|
_coreConfig.routing.rules.Add(new()
|
||||||
dnsItem.tag = Global.DnsTag;
|
|
||||||
_coreConfig.routing.rules.Add(new RulesItem4Ray
|
|
||||||
{
|
{
|
||||||
type = "field",
|
type = "field",
|
||||||
inboundTag = new List<string> { Global.DnsTag },
|
inboundTag = directDnsTags,
|
||||||
outboundTag = Global.ProxyTag,
|
outboundTag = Global.DirectTag,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var finalRule = BuildFinalRule();
|
||||||
|
dnsItem.tag = Global.DnsTag;
|
||||||
|
_coreConfig.routing.rules.Add(new()
|
||||||
|
{
|
||||||
|
type = "field",
|
||||||
|
inboundTag = [Global.DnsTag],
|
||||||
|
outboundTag = finalRule.outboundTag,
|
||||||
|
balancerTag = finalRule.balancerTag,
|
||||||
|
});
|
||||||
|
|
||||||
_coreConfig.dns = dnsItem;
|
_coreConfig.dns = dnsItem;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -93,45 +111,6 @@ public partial class CoreConfigV2rayService
|
||||||
private void FillDnsServers(Dns4Ray dnsItem)
|
private void FillDnsServers(Dns4Ray dnsItem)
|
||||||
{
|
{
|
||||||
var simpleDNSItem = context.SimpleDnsItem;
|
var simpleDNSItem = context.SimpleDnsItem;
|
||||||
static List<string> ParseDnsAddresses(string? dnsInput, string defaultAddress)
|
|
||||||
{
|
|
||||||
var addresses = dnsInput?.Split(dnsInput.Contains(',') ? ',' : ';')
|
|
||||||
.Select(addr => addr.Trim())
|
|
||||||
.Where(addr => !string.IsNullOrEmpty(addr))
|
|
||||||
.Select(addr => addr.StartsWith("dhcp", StringComparison.OrdinalIgnoreCase) ? "localhost" : addr)
|
|
||||||
.Distinct()
|
|
||||||
.ToList() ?? new List<string> { defaultAddress };
|
|
||||||
return addresses.Count > 0 ? addresses : new List<string> { defaultAddress };
|
|
||||||
}
|
|
||||||
|
|
||||||
static object? CreateDnsServer(string dnsAddress, List<string> domains, List<string>? expectedIPs = null)
|
|
||||||
{
|
|
||||||
var (domain, scheme, port, path) = Utils.ParseUrl(dnsAddress);
|
|
||||||
var domainFinal = dnsAddress;
|
|
||||||
int? portFinal = null;
|
|
||||||
if (scheme.IsNullOrEmpty() || scheme.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
domainFinal = domain;
|
|
||||||
portFinal = port > 0 ? port : null;
|
|
||||||
}
|
|
||||||
else if (scheme.StartsWith("tcp", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
domainFinal = scheme + "://" + domain;
|
|
||||||
portFinal = port > 0 ? port : null;
|
|
||||||
}
|
|
||||||
var dnsServer = new DnsServer4Ray
|
|
||||||
{
|
|
||||||
address = domainFinal,
|
|
||||||
port = portFinal,
|
|
||||||
skipFallback = true,
|
|
||||||
domains = domains.Count > 0 ? domains : null,
|
|
||||||
expectedIPs = expectedIPs?.Count > 0 ? expectedIPs : null
|
|
||||||
};
|
|
||||||
return JsonUtils.SerializeToNode(dnsServer, new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.First());
|
var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.First());
|
||||||
var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.First());
|
var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.First());
|
||||||
|
|
@ -252,35 +231,102 @@ public partial class CoreConfigV2rayService
|
||||||
|
|
||||||
dnsItem.servers ??= [];
|
dnsItem.servers ??= [];
|
||||||
|
|
||||||
void AddDnsServers(List<string> dnsAddresses, List<string> domains, List<string>? expectedIPs = null)
|
var directDnsTagIndex = 1;
|
||||||
{
|
|
||||||
if (domains.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var dnsAddress in dnsAddresses)
|
|
||||||
{
|
|
||||||
dnsItem.servers.Add(CreateDnsServer(dnsAddress, domains, expectedIPs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AddDnsServers(remoteDNSAddress, proxyDomainList);
|
AddDnsServers(remoteDNSAddress, proxyDomainList);
|
||||||
AddDnsServers(directDNSAddress, directDomainList);
|
AddDnsServers(directDNSAddress, directDomainList, true);
|
||||||
AddDnsServers(remoteDNSAddress, proxyGeositeList);
|
AddDnsServers(remoteDNSAddress, proxyGeositeList);
|
||||||
AddDnsServers(directDNSAddress, directGeositeList);
|
AddDnsServers(directDNSAddress, directGeositeList, true);
|
||||||
AddDnsServers(directDNSAddress, expectedDomainList, expectedIPs);
|
AddDnsServers(directDNSAddress, expectedDomainList, true, expectedIPs);
|
||||||
if (dnsServerDomains.Count > 0)
|
if (dnsServerDomains.Count > 0)
|
||||||
{
|
{
|
||||||
AddDnsServers(bootstrapDNSAddress, dnsServerDomains);
|
AddDnsServers(bootstrapDNSAddress, dnsServerDomains);
|
||||||
}
|
}
|
||||||
|
|
||||||
var useDirectDns = rules?.LastOrDefault() is { } lastRule
|
var useDirectDns = false;
|
||||||
&& lastRule.OutboundTag == Global.DirectTag
|
|
||||||
&& (lastRule.Port == "0-65535"
|
|
||||||
|| lastRule.Network == "tcp,udp"
|
|
||||||
|| lastRule.Ip?.Contains("0.0.0.0/0") == true);
|
|
||||||
|
|
||||||
var defaultDnsServers = useDirectDns ? directDNSAddress : remoteDNSAddress;
|
if (rules?.LastOrDefault() is { } lastRule && lastRule.OutboundTag == Global.DirectTag)
|
||||||
dnsItem.servers.AddRange(defaultDnsServers);
|
{
|
||||||
|
var noDomain = lastRule.Domain == null || lastRule.Domain.Count == 0;
|
||||||
|
var noProcess = lastRule.Process == null || lastRule.Process.Count == 0;
|
||||||
|
var isAnyIp = lastRule.Ip == null || lastRule.Ip.Count == 0 || lastRule.Ip.Contains("0.0.0.0/0");
|
||||||
|
var isAnyPort = string.IsNullOrEmpty(lastRule.Port) || lastRule.Port == "0-65535";
|
||||||
|
var isAnyNetwork = string.IsNullOrEmpty(lastRule.Network) || lastRule.Network == "tcp,udp";
|
||||||
|
useDirectDns = noDomain && noProcess && isAnyIp && isAnyPort && isAnyNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!useDirectDns)
|
||||||
|
{
|
||||||
|
dnsItem.servers.AddRange(remoteDNSAddress);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var dns in directDNSAddress)
|
||||||
|
{
|
||||||
|
var dnsServer = CreateDnsServer(dns, []);
|
||||||
|
dnsServer.tag = $"{Global.DirectDnsTag}-{directDnsTagIndex++}";
|
||||||
|
dnsServer.skipFallback = false;
|
||||||
|
dnsItem.servers.Add(JsonUtils.SerializeToNode(dnsServer,
|
||||||
|
new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
static List<string> ParseDnsAddresses(string? dnsInput, string defaultAddress)
|
||||||
|
{
|
||||||
|
var addresses = dnsInput?.Split(dnsInput.Contains(',') ? ',' : ';')
|
||||||
|
.Select(addr => addr.Trim())
|
||||||
|
.Where(addr => !string.IsNullOrEmpty(addr))
|
||||||
|
.Select(addr => addr.StartsWith("dhcp", StringComparison.OrdinalIgnoreCase) ? "localhost" : addr)
|
||||||
|
.Distinct()
|
||||||
|
.ToList() ?? [defaultAddress];
|
||||||
|
return addresses.Count > 0 ? addresses : new List<string> { defaultAddress };
|
||||||
|
}
|
||||||
|
|
||||||
|
static DnsServer4Ray CreateDnsServer(string dnsAddress, List<string> domains, List<string>? expectedIPs = null)
|
||||||
|
{
|
||||||
|
var (domain, scheme, port, path) = Utils.ParseUrl(dnsAddress);
|
||||||
|
var domainFinal = dnsAddress;
|
||||||
|
int? portFinal = null;
|
||||||
|
if (scheme.IsNullOrEmpty() || scheme.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
domainFinal = domain;
|
||||||
|
portFinal = port > 0 ? port : null;
|
||||||
|
}
|
||||||
|
else if (scheme.StartsWith("tcp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
domainFinal = scheme + "://" + domain;
|
||||||
|
portFinal = port > 0 ? port : null;
|
||||||
|
}
|
||||||
|
var dnsServer = new DnsServer4Ray
|
||||||
|
{
|
||||||
|
address = domainFinal,
|
||||||
|
port = portFinal,
|
||||||
|
skipFallback = true,
|
||||||
|
domains = domains.Count > 0 ? domains : null,
|
||||||
|
expectedIPs = expectedIPs?.Count > 0 ? expectedIPs : null
|
||||||
|
};
|
||||||
|
return dnsServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddDnsServers(List<string> dnsAddresses, List<string> domains, bool isDirectDns = false, List<string>? expectedIPs = null)
|
||||||
|
{
|
||||||
|
if (domains.Count <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (var dnsAddress in dnsAddresses)
|
||||||
|
{
|
||||||
|
var dnsServer = CreateDnsServer(dnsAddress, domains, expectedIPs);
|
||||||
|
if (isDirectDns)
|
||||||
|
{
|
||||||
|
dnsServer.tag = $"{Global.DirectDnsTag}-{directDnsTagIndex++}";
|
||||||
|
}
|
||||||
|
var dnsServerNode = JsonUtils.SerializeToNode(dnsServer,
|
||||||
|
new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });
|
||||||
|
dnsItem.servers.Add(dnsServerNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FillDnsHosts(Dns4Ray dnsItem)
|
private void FillDnsHosts(Dns4Ray dnsItem)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ public partial class CoreConfigV2rayService
|
||||||
var fragmentOutbound = new Outbounds4Ray
|
var fragmentOutbound = new Outbounds4Ray
|
||||||
{
|
{
|
||||||
protocol = "freedom",
|
protocol = "freedom",
|
||||||
tag = $"frag-{Global.ProxyTag}",
|
tag = $"frag-{baseTagName}",
|
||||||
settings = new()
|
settings = new()
|
||||||
{
|
{
|
||||||
fragment = new()
|
fragment = new()
|
||||||
|
|
@ -44,16 +44,17 @@ public partial class CoreConfigV2rayService
|
||||||
};
|
};
|
||||||
var actOutboundWithTlsList =
|
var actOutboundWithTlsList =
|
||||||
proxyOutboundList.Where(n => n.streamSettings?.security.IsNullOrEmpty() == false
|
proxyOutboundList.Where(n => n.streamSettings?.security.IsNullOrEmpty() == false
|
||||||
&& (n.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true));
|
&& (n.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true)).ToList();
|
||||||
|
if (actOutboundWithTlsList.Count > 0)
|
||||||
|
{
|
||||||
|
proxyOutboundList.Add(fragmentOutbound);
|
||||||
|
}
|
||||||
foreach (var outbound in actOutboundWithTlsList)
|
foreach (var outbound in actOutboundWithTlsList)
|
||||||
{
|
{
|
||||||
var fragmentOutboundClone = JsonUtils.DeepCopy(fragmentOutbound);
|
|
||||||
fragmentOutboundClone.tag = $"frag-{outbound.tag}";
|
|
||||||
outbound.streamSettings.sockopt = new()
|
outbound.streamSettings.sockopt = new()
|
||||||
{
|
{
|
||||||
dialerProxy = fragmentOutboundClone.tag
|
dialerProxy = fragmentOutbound.tag
|
||||||
};
|
};
|
||||||
proxyOutboundList.Add(fragmentOutboundClone);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return proxyOutboundList;
|
return proxyOutboundList;
|
||||||
|
|
@ -601,7 +602,7 @@ public partial class CoreConfigV2rayService
|
||||||
{
|
{
|
||||||
udpHop = new HysteriaUdpHop4Ray
|
udpHop = new HysteriaUdpHop4Ray
|
||||||
{
|
{
|
||||||
ports = ports.Replace(':', '-'),
|
port = ports.Replace(':', '-'),
|
||||||
interval = hopInterval,
|
interval = hopInterval,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -181,4 +181,28 @@ public partial class CoreConfigV2rayService
|
||||||
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RulesItem4Ray BuildFinalRule()
|
||||||
|
{
|
||||||
|
var finalRule = new RulesItem4Ray()
|
||||||
|
{
|
||||||
|
type = "field",
|
||||||
|
network = "tcp,udp",
|
||||||
|
outboundTag = Global.ProxyTag,
|
||||||
|
};
|
||||||
|
var balancer =
|
||||||
|
_coreConfig?.routing?.balancers?.FirstOrDefault(b => b.tag == Global.ProxyTag + Global.BalancerTagSuffix, null);
|
||||||
|
var domainStrategy = _coreConfig.routing?.domainStrategy ?? Global.AsIs;
|
||||||
|
if (balancer is not null)
|
||||||
|
{
|
||||||
|
finalRule.outboundTag = null;
|
||||||
|
finalRule.balancerTag = balancer.tag;
|
||||||
|
}
|
||||||
|
if (domainStrategy == Global.IPIfNonMatch)
|
||||||
|
{
|
||||||
|
finalRule.network = null;
|
||||||
|
finalRule.ip = ["0.0.0.0/0", "::/0"];
|
||||||
|
}
|
||||||
|
return finalRule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ public class AddServerViewModel : MyReactiveObject
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> shaList = new();
|
List<string> shaList = [];
|
||||||
foreach (var cert in certList)
|
foreach (var cert in certList)
|
||||||
{
|
{
|
||||||
var sha = CertPemManager.GetCertSha256Thumbprint(cert);
|
var sha = CertPemManager.GetCertSha256Thumbprint(cert);
|
||||||
|
|
@ -228,7 +228,7 @@ public class AddServerViewModel : MyReactiveObject
|
||||||
}
|
}
|
||||||
shaList.Add(sha);
|
shaList.Add(sha);
|
||||||
}
|
}
|
||||||
CertSha = string.Join('~', shaList);
|
CertSha = string.Join(',', shaList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FetchCert()
|
private async Task FetchCert()
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,6 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
[Reactive] public bool TunStrictRoute { get; set; }
|
[Reactive] public bool TunStrictRoute { get; set; }
|
||||||
[Reactive] public string TunStack { get; set; }
|
[Reactive] public string TunStack { get; set; }
|
||||||
[Reactive] public int TunMtu { get; set; }
|
[Reactive] public int TunMtu { get; set; }
|
||||||
[Reactive] public bool TunEnableExInbound { get; set; }
|
|
||||||
[Reactive] public bool TunEnableIPv6Address { get; set; }
|
[Reactive] public bool TunEnableIPv6Address { get; set; }
|
||||||
|
|
||||||
#endregion Tun mode
|
#endregion Tun mode
|
||||||
|
|
@ -220,7 +219,6 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
TunStrictRoute = _config.TunModeItem.StrictRoute;
|
TunStrictRoute = _config.TunModeItem.StrictRoute;
|
||||||
TunStack = _config.TunModeItem.Stack;
|
TunStack = _config.TunModeItem.Stack;
|
||||||
TunMtu = _config.TunModeItem.Mtu;
|
TunMtu = _config.TunModeItem.Mtu;
|
||||||
TunEnableExInbound = _config.TunModeItem.EnableExInbound;
|
|
||||||
TunEnableIPv6Address = _config.TunModeItem.EnableIPv6Address;
|
TunEnableIPv6Address = _config.TunModeItem.EnableIPv6Address;
|
||||||
|
|
||||||
#endregion Tun mode
|
#endregion Tun mode
|
||||||
|
|
@ -380,7 +378,6 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
_config.TunModeItem.StrictRoute = TunStrictRoute;
|
_config.TunModeItem.StrictRoute = TunStrictRoute;
|
||||||
_config.TunModeItem.Stack = TunStack;
|
_config.TunModeItem.Stack = TunStack;
|
||||||
_config.TunModeItem.Mtu = TunMtu;
|
_config.TunModeItem.Mtu = TunMtu;
|
||||||
_config.TunModeItem.EnableExInbound = TunEnableExInbound;
|
|
||||||
_config.TunModeItem.EnableIPv6Address = TunEnableIPv6Address;
|
_config.TunModeItem.EnableIPv6Address = TunEnableIPv6Address;
|
||||||
|
|
||||||
//coreType
|
//coreType
|
||||||
|
|
|
||||||
|
|
@ -325,12 +325,6 @@
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
HorizontalAlignment="Left" />
|
HorizontalAlignment="Left" />
|
||||||
<TextBlock
|
|
||||||
Grid.Row="20"
|
|
||||||
Grid.Column="2"
|
|
||||||
Margin="{StaticResource Margin4}"
|
|
||||||
Text="{x:Static resx:ResUI.TbSettingsEnableFragmentTips}"
|
|
||||||
TextWrapping="Wrap" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
@ -843,19 +837,6 @@
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
HorizontalAlignment="Left" />
|
HorizontalAlignment="Left" />
|
||||||
|
|
||||||
<TextBlock
|
|
||||||
Grid.Row="6"
|
|
||||||
Grid.Column="0"
|
|
||||||
Margin="{StaticResource Margin4}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
|
|
||||||
<ToggleSwitch
|
|
||||||
x:Name="togEnableExInbound"
|
|
||||||
Grid.Row="6"
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="{StaticResource Margin4}"
|
|
||||||
HorizontalAlignment="Left" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="7"
|
Grid.Row="7"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,6 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||||
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableExInbound, v => v.togEnableExInbound.IsChecked).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
|
||||||
|
|
|
||||||
|
|
@ -391,13 +391,6 @@
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="{StaticResource Margin8}"
|
Margin="{StaticResource Margin8}"
|
||||||
HorizontalAlignment="Left" />
|
HorizontalAlignment="Left" />
|
||||||
<TextBlock
|
|
||||||
Grid.Row="20"
|
|
||||||
Grid.Column="2"
|
|
||||||
Margin="{StaticResource Margin8}"
|
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
|
||||||
Text="{x:Static resx:ResUI.TbSettingsEnableFragmentTips}"
|
|
||||||
TextWrapping="Wrap" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
@ -1097,20 +1090,6 @@
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Style="{StaticResource DefComboBox}" />
|
Style="{StaticResource DefComboBox}" />
|
||||||
|
|
||||||
<TextBlock
|
|
||||||
Grid.Row="6"
|
|
||||||
Grid.Column="0"
|
|
||||||
Margin="{StaticResource Margin8}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
|
||||||
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
|
|
||||||
<ToggleButton
|
|
||||||
x:Name="togEnableExInbound"
|
|
||||||
Grid.Row="6"
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="{StaticResource Margin8}"
|
|
||||||
HorizontalAlignment="Left" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="7"
|
Grid.Row="7"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,6 @@ public partial class OptionSettingWindow
|
||||||
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableExInbound, v => v.togEnableExInbound.IsChecked).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.Text).DisposeWith(disposables);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue