mirror of
https://github.com/2dust/v2rayN.git
synced 2026-10-23 21:55:00 +03:00
fix(tun): automatically exclude proxy node IPs and resolved domains from TUN routing to prevent loops (#9974) (#10012)
This commit is contained in:
@@ -83,6 +83,96 @@ public class CoreConfigContextBuilderTests
|
||||
await groupA.GetProtocolExtra().ChildItems.Should().BeEqualTo(leaf.IndexId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Build_WhenTunEnabled_ShouldAutoExcludeProxyServerAddress()
|
||||
{
|
||||
var config = CoreConfigTestFactory.CreateConfig();
|
||||
config.TunModeItem.EnableTun = true;
|
||||
config.TunModeItem.RouteExcludeAddress = ["10.0.0.0/8"];
|
||||
CoreConfigTestFactory.BindAppManagerConfig(config);
|
||||
|
||||
var node = CoreConfigTestFactory.CreateVmessNode(ECoreType.Xray, "vmess-node");
|
||||
node.Address = "1.2.3.4";
|
||||
await UpsertProfilesAsync(node);
|
||||
|
||||
var result = await CoreConfigContextBuilder.Build(config, node);
|
||||
|
||||
await result.Success.Should().BeTrue();
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress.Should().Contain("10.0.0.0/8");
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress.Should().Contain("1.2.3.4/32");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Build_WhenTunEnabled_ShouldAutoExcludeProxyServerAddress_IPv6WithBrackets()
|
||||
{
|
||||
var config = CoreConfigTestFactory.CreateConfig();
|
||||
config.TunModeItem.EnableTun = true;
|
||||
CoreConfigTestFactory.BindAppManagerConfig(config);
|
||||
|
||||
var node = CoreConfigTestFactory.CreateVmessNode(ECoreType.Xray, "vmess-v6");
|
||||
node.Address = "[2001:db8::1]";
|
||||
await UpsertProfilesAsync(node);
|
||||
|
||||
var result = await CoreConfigContextBuilder.Build(config, node);
|
||||
|
||||
await result.Success.Should().BeTrue();
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress.Should().Contain("2001:db8::1/128");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Build_WhenTunEnabled_ShouldNotExcludeLoopbackAddress()
|
||||
{
|
||||
var config = CoreConfigTestFactory.CreateConfig();
|
||||
config.TunModeItem.EnableTun = true;
|
||||
CoreConfigTestFactory.BindAppManagerConfig(config);
|
||||
|
||||
var node = CoreConfigTestFactory.CreateVmessNode(ECoreType.Xray, "vmess-loopback");
|
||||
node.Address = "127.0.0.1";
|
||||
await UpsertProfilesAsync(node);
|
||||
|
||||
var result = await CoreConfigContextBuilder.Build(config, node);
|
||||
|
||||
await result.Success.Should().BeTrue();
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress.Should().NotContain("127.0.0.1/32");
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress.Should().NotContain("127.0.0.1");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Build_WhenTunEnabled_ShouldNotExcludeAnyOrNoneAddress()
|
||||
{
|
||||
var config = CoreConfigTestFactory.CreateConfig();
|
||||
config.TunModeItem.EnableTun = true;
|
||||
CoreConfigTestFactory.BindAppManagerConfig(config);
|
||||
|
||||
var node = CoreConfigTestFactory.CreateVmessNode(ECoreType.Xray, "vmess-any");
|
||||
node.Address = "0.0.0.0";
|
||||
await UpsertProfilesAsync(node);
|
||||
|
||||
var result = await CoreConfigContextBuilder.Build(config, node);
|
||||
|
||||
await result.Success.Should().BeTrue();
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress.Should().NotContain("0.0.0.0/32");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Build_WhenTunEnabled_WithDomainNode_ShouldExcludeResolvedIPs()
|
||||
{
|
||||
var config = CoreConfigTestFactory.CreateConfig();
|
||||
config.TunModeItem.EnableTun = true;
|
||||
CoreConfigTestFactory.BindAppManagerConfig(config);
|
||||
|
||||
var node = CoreConfigTestFactory.CreateVmessNode(ECoreType.Xray, "vmess-domain");
|
||||
node.Address = "one.one.one.one";
|
||||
await UpsertProfilesAsync(node);
|
||||
|
||||
var result = await CoreConfigContextBuilder.Build(config, node);
|
||||
|
||||
await result.Success.Should().BeTrue();
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress.Should().NotBeNull();
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress!.Count.Should().BeGreaterThan(0);
|
||||
await result.Context.AppConfig.TunModeItem.RouteExcludeAddress.Should().Contain(x => x.StartsWith("1.1.1.1") || x.StartsWith("1.0.0.1") || x.Contains(':'));
|
||||
}
|
||||
|
||||
private static string NewId(string prefix)
|
||||
{
|
||||
return $"{prefix}-{Guid.NewGuid():N}";
|
||||
@@ -96,12 +186,22 @@ public class CoreConfigContextBuilderTests
|
||||
|| message.Contains("циклическую зависимость", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static readonly SemaphoreSlim _dbLock = new(1, 1);
|
||||
|
||||
private static async Task UpsertProfilesAsync(params ProfileItem[] profiles)
|
||||
{
|
||||
SQLiteHelper.Instance.CreateTable<ProfileItem>();
|
||||
foreach (var profile in profiles)
|
||||
await _dbLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await SQLiteHelper.Instance.ReplaceAsync(profile);
|
||||
SQLiteHelper.Instance.CreateTable<ProfileItem>();
|
||||
foreach (var profile in profiles)
|
||||
{
|
||||
await SQLiteHelper.Instance.ReplaceAsync(profile);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_dbLock.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user