mirror of
https://github.com/2dust/v2rayN.git
synced 2026-08-11 17:52:09 +03:00
Always route IPv6 into Xray TUN regardless of EnableIPv6Address (#9930)
* Always route IPv6 into Xray TUN regardless of EnableIPv6Address
EnableIPv6Address controls whether the TUN interface is assigned an IPv6
address, but it also gated whether ::/0 was added to autoSystemRoutingTable.
With the default (false), IPv6 had no route pointing at the TUN device and
followed the system default route instead, leaving the tunnel unproxied and
exposing the host's real IPv6 address.
The embedded template SampleTunInbound already declares both families; the
generated config discarded it. #9843 restored ::/0 only inside the
EnableIPv6Address == true branch, so the false branch still leaks.
Route both families unconditionally and let the option control only the
interface address. The same conditional existed a second time in the
RouteExcludeAddress branch and is fixed as well.
Fixes #9929
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Add regression tests for IPv6 routing in the Xray TUN inbound
Both assertions fail on 31044f44 and pass with the fix:
Tun_ShouldRouteIPv6IntoTunnel(enableIPv6Address: False)
Expected collection {"0.0.0.0/0"} to contain "::/0".
TunRouteExcludeAddress_ShouldIncludeIPv6Ranges
Expected collection {...44 IPv4 ranges...} to have an item matching x.Contains(:).
The theory also covers enableIPv6Address: true, which passes on both revisions,
so the tests only fail while the defect is present. The gateway count assertion
pins the intended split of responsibilities: EnableIPv6Address governs the
interface address, never the routing table.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: liuclare <177657698+liuclare@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -251,4 +251,12 @@ internal static class CoreConfigTestFactory
|
||||
config.TunModeItem.RouteExcludeAddress = ["10.0.0.1/32", "192.168.1.0/24", "fc00::/7"];
|
||||
return config;
|
||||
}
|
||||
|
||||
public static Config CreateConfigWithTun(ECoreType coreType, bool enableIPv6Address)
|
||||
{
|
||||
var config = CreateConfig(coreType);
|
||||
config.TunModeItem.EnableTun = true;
|
||||
config.TunModeItem.EnableIPv6Address = enableIPv6Address;
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,6 +570,51 @@ public class CoreConfigV2rayServiceTests
|
||||
directOutbound!.streamSettings.sockopt!.domainStrategy.Should().Be("UseIPv4");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void GenerateClientConfigContent_Tun_ShouldRouteIPv6IntoTunnel(bool enableIPv6Address)
|
||||
{
|
||||
var config = CoreConfigTestFactory.CreateConfigWithTun(ECoreType.Xray, enableIPv6Address);
|
||||
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().Contain("0.0.0.0/0");
|
||||
tunInbound.settings.autoSystemRoutingTable.Should().Contain("::/0");
|
||||
|
||||
// EnableIPv6Address governs the interface address only, never the routing table.
|
||||
tunInbound.settings.gateway.Should().HaveCount(enableIPv6Address ? 2 : 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateClientConfigContent_TunRouteExcludeAddress_ShouldIncludeIPv6Ranges()
|
||||
{
|
||||
var config = CoreConfigTestFactory.CreateConfigWithTunRouteExcludeAddress(ECoreType.Xray);
|
||||
config.TunModeItem.EnableIPv6Address = false;
|
||||
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().Contain(x => x.Contains(':'));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateClientConfigContent_TunRouteExcludeAddress()
|
||||
{
|
||||
|
||||
@@ -67,12 +67,14 @@ public partial class CoreConfigV2rayService
|
||||
|
||||
var address = _config.TunModeItem.IPv4Address.NullIfEmpty() ?? Global.TunIPv4Address.First();
|
||||
tunInbound.settings.gateway = [address];
|
||||
tunInbound.settings.autoSystemRoutingTable = ["0.0.0.0/0"];
|
||||
// Route both families into the tunnel regardless of EnableIPv6Address. That option only
|
||||
// controls whether the interface gets an IPv6 address; leaving ::/0 out of the routing
|
||||
// table makes IPv6 follow the system default route and bypass the tunnel entirely.
|
||||
tunInbound.settings.autoSystemRoutingTable = ["0.0.0.0/0", "::/0"];
|
||||
if (_config.TunModeItem.EnableIPv6Address == true)
|
||||
{
|
||||
var address6 = _config.TunModeItem.IPv6Address.NullIfEmpty() ?? Global.TunIPv6Address.First();
|
||||
tunInbound.settings.gateway.Add(address6);
|
||||
tunInbound.settings.autoSystemRoutingTable.Add("::/0");
|
||||
}
|
||||
|
||||
var bindInterface = _config.CoreBasicItem.BindInterface?.TrimEx();
|
||||
@@ -118,15 +120,8 @@ public partial class CoreConfigV2rayService
|
||||
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();
|
||||
}
|
||||
tunInbound.settings.autoSystemRoutingTable = includeList.Select(x => x.ToString())
|
||||
.Concat(includeListV6.Select(x => x.ToString())).ToList();
|
||||
}
|
||||
|
||||
_coreConfig.inbounds.Add(tunInbound);
|
||||
|
||||
Reference in New Issue
Block a user