mirror of
https://github.com/2dust/v2rayN.git
synced 2026-11-03 02:55:01 +03:00
Skip the TUN IPv6 route when the host has no global IPv6 address (#10080)
#9930 made the Xray TUN inbound always request ::/0 in autoSystemRoutingTable so that IPv6 stops bypassing the tunnel. That only helps a host which actually holds a globally routable IPv6 address. On any other host it does harm. With IPv6 disabled the TUN device gets no IPv6 address at all, the kernel rejects the route with EACCES and the whole inbound fails to start: Failed to start: app/proxyman/inbound: failed to start proxy > proxy/tun: failed to add system route ::/0 > permission denied With IPv6 enabled but no global address the route is accepted and the host gains an IPv6 default route it cannot use. The TUN completes the TCP handshake locally before dialing the outbound, so IPv6 destinations start to look reachable and get picked, and the connection then dies at the outbound instead of failing fast (#10051). Neither host has IPv6 traffic that could bypass the tunnel, so ::/0 buys them nothing. Detect a global IPv6 address once while building the config context and drop ::/0 when there is none. Link-local and unique local addresses do not count: they never reach the IPv6 internet. Co-authored-by: liuclare <177657698+liuclare@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -815,6 +815,40 @@ public class Utils
|
||||
.Any(ni => ni.Name.Equals(inInterfaceName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the host holds a globally routable IPv6 address, that is one inside 2000::/3.
|
||||
/// Link-local and unique local addresses are excluded: they never reach the IPv6 internet,
|
||||
/// so a host holding only those has no IPv6 traffic that could bypass the tunnel, and no
|
||||
/// IPv6 path that traffic sent into the tunnel could come back out of.
|
||||
/// </summary>
|
||||
public static bool HasGlobalIPv6Address()
|
||||
{
|
||||
try
|
||||
{
|
||||
return NetworkInterface.GetAllNetworkInterfaces()
|
||||
.Where(ni => ni.OperationalStatus == OperationalStatus.Up
|
||||
&& ni.NetworkInterfaceType != NetworkInterfaceType.Loopback)
|
||||
.SelectMany(ni => ni.GetIPProperties().UnicastAddresses)
|
||||
.Any(ua => IsGlobalUnicastIPv6(ua.Address));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsGlobalUnicastIPv6(IPAddress address)
|
||||
{
|
||||
if (address.AddressFamily != AddressFamily.InterNetworkV6)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2000::/3 is the only range currently assigned for global unicast, which leaves out
|
||||
// ::1, fe80::/10, fc00::/7 and ff00::/8 in a single test.
|
||||
return (address.GetAddressBytes()[0] & 0xE0) == 0x20;
|
||||
}
|
||||
|
||||
#endregion Speed Test
|
||||
|
||||
#region Miscellaneous
|
||||
|
||||
Reference in New Issue
Block a user