mirror of
https://github.com/2dust/v2rayN.git
synced 2026-10-03 12:02:07 +03:00
Xray Route Exclude Address (#9469)
* Add IPNetwork2 package * Xray Route Exclude Address --------- Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.17" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.17" />
|
||||||
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
|
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
|
||||||
<PackageVersion Include="DialogHost.Avalonia" Version="0.11.0" />
|
<PackageVersion Include="DialogHost.Avalonia" Version="0.11.0" />
|
||||||
|
<PackageVersion Include="IPNetwork2" Version="4.3.0" />
|
||||||
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.4.13" />
|
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.4.13" />
|
||||||
<PackageVersion Include="CliWrap" Version="3.10.1" />
|
<PackageVersion Include="CliWrap" Version="3.10.1" />
|
||||||
<PackageVersion Include="Downloader" Version="5.7.0" />
|
<PackageVersion Include="Downloader" Version="5.7.0" />
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ internal static class CoreConfigTestFactory
|
|||||||
SimpleDnsItem = config.SimpleDNSItem,
|
SimpleDnsItem = config.SimpleDNSItem,
|
||||||
AllProxiesMap = new Dictionary<string, ProfileItem> { [node.IndexId] = node },
|
AllProxiesMap = new Dictionary<string, ProfileItem> { [node.IndexId] = node },
|
||||||
FullConfigTemplate = null,
|
FullConfigTemplate = null,
|
||||||
IsTunEnabled = false,
|
IsTunEnabled = config.TunModeItem.EnableTun,
|
||||||
ProtectDomainList = [],
|
ProtectDomainList = [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -206,4 +206,12 @@ internal static class CoreConfigTestFactory
|
|||||||
config.SimpleDNSItem.BootstrapDNS = bootstrapDns;
|
config.SimpleDNSItem.BootstrapDNS = bootstrapDns;
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Config CreateConfigWithTunRouteExcludeAddress(ECoreType coreType)
|
||||||
|
{
|
||||||
|
var config = CreateConfig(coreType);
|
||||||
|
config.TunModeItem.EnableTun = true;
|
||||||
|
config.TunModeItem.RouteExcludeAddress = ["10.0.0.1/32", "192.168.1.0/24", "fc00::/7"];
|
||||||
|
return config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -536,4 +536,27 @@ public class CoreConfigV2rayServiceTests
|
|||||||
directOutbound.Should().NotBeNull();
|
directOutbound.Should().NotBeNull();
|
||||||
directOutbound!.settings.domainStrategy.Should().Be("UseIPv4");
|
directOutbound!.settings.domainStrategy.Should().Be("UseIPv4");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GenerateClientConfigContent_TunRouteExcludeAddress()
|
||||||
|
{
|
||||||
|
var config = CoreConfigTestFactory.CreateConfigWithTunRouteExcludeAddress(ECoreType.Xray);
|
||||||
|
CoreConfigTestFactory.BindAppManagerConfig(config);
|
||||||
|
|
||||||
|
var node = CoreConfigTestFactory.CreateVmessNode(ECoreType.Xray, "n-main", "main");
|
||||||
|
var context = CoreConfigTestFactory.CreateContext(config, node, ECoreType.Xray);
|
||||||
|
|
||||||
|
var result = new CoreConfigV2rayService(context).GenerateClientConfigContent();
|
||||||
|
|
||||||
|
result.Success.Should().BeTrue();
|
||||||
|
|
||||||
|
var cfg = JsonUtils.Deserialize<V2rayConfig>(result.Data!.ToString())!;
|
||||||
|
var tunInbound = cfg.inbounds.FirstOrDefault(i => i.protocol == "tun");
|
||||||
|
|
||||||
|
tunInbound.Should().NotBeNull();
|
||||||
|
|
||||||
|
tunInbound!.settings.autoSystemRoutingTable.Should().NotContain("0.0.0.0/0");
|
||||||
|
tunInbound!.settings.autoSystemRoutingTable.Should().Contain("10.0.0.0/32");
|
||||||
|
tunInbound!.settings.autoSystemRoutingTable.Should().Contain("10.0.0.2/31");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,20 @@ public class CoreConfigContextBuilder
|
|||||||
context.AllProxiesMap[$"remark:{ruleItem.OutboundTag}"] = actRuleNode;
|
context.AllProxiesMap[$"remark:{ruleItem.OutboundTag}"] = actRuleNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (context.IsTunEnabled && context.AppConfig.TunModeItem.RouteExcludeAddress is { Count: > 0 })
|
||||||
|
{
|
||||||
|
foreach (var addr in context.AppConfig.TunModeItem.RouteExcludeAddress)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IPNetwork2.Parse(addr);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
validatorResult.Errors.Add(string.Format(ResUI.MsgTunRouteExcludeInvalidAddress, addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new CoreConfigContextBuilderResult(context, validatorResult);
|
return new CoreConfigContextBuilderResult(context, validatorResult);
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+9
@@ -2229,6 +2229,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Invalid address in TUN route exclude list: {0} 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string MsgTunRouteExcludeInvalidAddress {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("MsgTunRouteExcludeInvalidAddress", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Unpacking... 的本地化字符串。
|
/// 查找类似 Unpacking... 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1758,4 +1758,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
|||||||
<data name="TbRouteExcludeAddressTip" xml:space="preserve">
|
<data name="TbRouteExcludeAddressTip" xml:space="preserve">
|
||||||
<value>Use commas (,) to separate.</value>
|
<value>Use commas (,) to separate.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MsgTunRouteExcludeInvalidAddress" xml:space="preserve">
|
||||||
|
<value>Invalid address in TUN route exclude list: {0}</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1755,4 +1755,7 @@
|
|||||||
<data name="TbRouteExcludeAddressTip" xml:space="preserve">
|
<data name="TbRouteExcludeAddressTip" xml:space="preserve">
|
||||||
<value>使用逗号 (,) 分隔</value>
|
<value>使用逗号 (,) 分隔</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MsgTunRouteExcludeInvalidAddress" xml:space="preserve">
|
||||||
|
<value>TUN 路由排除列表包含无效地址:{0}</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Downloader" />
|
<PackageReference Include="Downloader" />
|
||||||
|
<PackageReference Include="IPNetwork2" />
|
||||||
<PackageReference Include="ReactiveUI">
|
<PackageReference Include="ReactiveUI">
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -30,14 +30,19 @@ public partial class CoreConfigV2rayService
|
|||||||
inbound3.listen = listen;
|
inbound3.listen = listen;
|
||||||
_coreConfig.inbounds.Add(inbound3);
|
_coreConfig.inbounds.Add(inbound3);
|
||||||
|
|
||||||
//auth
|
// auth
|
||||||
if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty())
|
if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty())
|
||||||
{
|
{
|
||||||
inbound3.settings.auth = "password";
|
inbound3.settings.auth = "password";
|
||||||
inbound3.settings.accounts = new List<AccountsItem4Ray>
|
inbound3.settings.accounts =
|
||||||
{
|
[
|
||||||
new() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass }
|
new()
|
||||||
};
|
{
|
||||||
|
user = _config.Inbound.First().User,
|
||||||
|
pass = _config.Inbound.First().Pass,
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -53,12 +58,15 @@ public partial class CoreConfigV2rayService
|
|||||||
{
|
{
|
||||||
_config.TunModeItem.Mtu = Global.TunMtus.First();
|
_config.TunModeItem.Mtu = Global.TunMtus.First();
|
||||||
}
|
}
|
||||||
var tunInbound = JsonUtils.Deserialize<Inbounds4Ray>(EmbedUtils.GetEmbedText(Global.V2raySampleTunInbound)) ?? new Inbounds4Ray { };
|
var tunInbound =
|
||||||
|
JsonUtils.Deserialize<Inbounds4Ray>(EmbedUtils.GetEmbedText(Global.V2raySampleTunInbound)) ??
|
||||||
|
new Inbounds4Ray();
|
||||||
tunInbound.settings.name = context.IsMacOS ? $"utun{new Random().Next(99)}" : "xray_tun";
|
tunInbound.settings.name = context.IsMacOS ? $"utun{new Random().Next(99)}" : "xray_tun";
|
||||||
tunInbound.settings.MTU = _config.TunModeItem.Mtu;
|
tunInbound.settings.MTU = _config.TunModeItem.Mtu;
|
||||||
if (_config.TunModeItem.EnableIPv6Address == false)
|
if (!_config.TunModeItem.EnableIPv6Address)
|
||||||
{
|
{
|
||||||
tunInbound.settings.gateway = ["172.18.0.1/30"];
|
tunInbound.settings.gateway = ["172.18.0.1/30"];
|
||||||
|
tunInbound.settings.autoSystemRoutingTable = ["0.0.0.0/0"];
|
||||||
}
|
}
|
||||||
var bindInterface = _config.CoreBasicItem.BindInterface?.TrimEx();
|
var bindInterface = _config.CoreBasicItem.BindInterface?.TrimEx();
|
||||||
if (!bindInterface.IsNullOrEmpty())
|
if (!bindInterface.IsNullOrEmpty())
|
||||||
@@ -66,6 +74,53 @@ public partial class CoreConfigV2rayService
|
|||||||
tunInbound.settings.autoOutboundsInterface = bindInterface;
|
tunInbound.settings.autoOutboundsInterface = bindInterface;
|
||||||
}
|
}
|
||||||
tunInbound.sniffing = inbound.sniffing;
|
tunInbound.sniffing = inbound.sniffing;
|
||||||
|
|
||||||
|
if (_config.TunModeItem.RouteExcludeAddress is { Count: > 0 })
|
||||||
|
{
|
||||||
|
var wholeInternet = IPNetwork2.Parse("0.0.0.0/0");
|
||||||
|
var wholeInternetV6 = IPNetwork2.Parse("::/0");
|
||||||
|
|
||||||
|
var excludeList = _config.TunModeItem.RouteExcludeAddress.Select(IPNetwork2.Parse)
|
||||||
|
.Where(x => x != null).ToList();
|
||||||
|
|
||||||
|
var includeList = new List<IPNetwork2> { wholeInternet };
|
||||||
|
var includeListV6 = new List<IPNetwork2> { wholeInternetV6 };
|
||||||
|
|
||||||
|
foreach (var exclude in excludeList)
|
||||||
|
{
|
||||||
|
var temp = new List<IPNetwork2>();
|
||||||
|
if (exclude.AddressFamily == AddressFamily.InterNetwork)
|
||||||
|
{
|
||||||
|
foreach (var net in includeList)
|
||||||
|
{
|
||||||
|
temp.AddRange(net.Subtract(exclude));
|
||||||
|
}
|
||||||
|
includeList = temp;
|
||||||
|
}
|
||||||
|
else if (exclude.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
foreach (var net in includeListV6)
|
||||||
|
{
|
||||||
|
temp.AddRange(net.Subtract(exclude));
|
||||||
|
}
|
||||||
|
includeListV6 = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
includeList = IPNetwork2.Supernet(includeList.ToArray()).ToList();
|
||||||
|
includeListV6 = IPNetwork2.Supernet(includeListV6.ToArray()).ToList();
|
||||||
|
|
||||||
|
if (_config.TunModeItem.EnableIPv6Address)
|
||||||
|
{
|
||||||
|
tunInbound.settings.autoSystemRoutingTable = includeList.Select(x => x.ToString())
|
||||||
|
.Concat(includeListV6.Select(x => x.ToString())).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tunInbound.settings.autoSystemRoutingTable = includeList.Select(x => x.ToString()).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_coreConfig.inbounds.Add(tunInbound);
|
_coreConfig.inbounds.Add(tunInbound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user