This commit is contained in:
snltty
2024-08-19 17:11:27 +08:00
parent 360bd70679
commit 7c89853e41
9 changed files with 38 additions and 93 deletions

View File

@@ -133,7 +133,7 @@ namespace linker.libs
try try
{ {
return Dns.GetHostAddresses(Dns.GetHostName()) return Dns.GetHostAddresses(Dns.GetHostName())
.Where(c => c.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) .Where(c => c.AddressFamily == AddressFamily.InterNetworkV6)
.Where(c => c.GetAddressBytes().AsSpan(0, 8).SequenceEqual(ipv6LocalBytes) == false).Distinct().ToArray(); .Where(c => c.GetAddressBytes().AsSpan(0, 8).SequenceEqual(ipv6LocalBytes) == false).Distinct().ToArray();
} }
catch (Exception) catch (Exception)
@@ -157,7 +157,7 @@ namespace linker.libs
return Array.Empty<IPAddress>(); return Array.Empty<IPAddress>();
} }
public static byte MaskLength(uint ip) public static byte GetPrefixLength(uint ip)
{ {
byte maskLength = 32; byte maskLength = 32;
for (int i = 0; i < sizeof(uint); i++) for (int i = 0; i < sizeof(uint); i++)
@@ -171,42 +171,37 @@ namespace linker.libs
return maskLength; return maskLength;
} }
public static uint MaskValue(byte maskLength) public static uint GetPrefixIP(byte prefixLength)
{ {
//最多<<31 所以0需要单独计算 //最多<<31 所以0需要单独计算
if (maskLength < 1) return 0; if (prefixLength < 1) return 0;
return 0xffffffff << (32 - maskLength); return 0xffffffff << (32 - prefixLength);
} }
public static IPAddress GetMaskIp(uint maskValue) public static IPAddress GetPrefixIp(uint prefixIP)
{ {
return new IPAddress(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(maskValue))); return new IPAddress(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(prefixIP)));
} }
public static IPAddress ToNetworkIp(IPAddress ip, uint maskvalue) public static IPAddress ToNetworkIp(IPAddress ip, uint prefixIP)
{ {
return ToNetworkIp(BinaryPrimitives.ReadUInt32BigEndian(ip.GetAddressBytes()), maskvalue); return ToNetworkIp(BinaryPrimitives.ReadUInt32BigEndian(ip.GetAddressBytes()), prefixIP);
} }
public static IPAddress ToNetworkIp(uint ip, uint maskvalue) public static IPAddress ToNetworkIp(uint ip, uint prefixIP)
{ {
return new IPAddress(BinaryPrimitives.ReverseEndianness(ip & maskvalue).ToBytes()); return new IPAddress(BinaryPrimitives.ReverseEndianness(ip & prefixIP).ToBytes());
} }
public static IPAddress ToGatewayIP(IPAddress ip, byte maskLength) public static IPAddress ToGatewayIP(IPAddress ip, byte prefixLength)
{ {
uint network = BinaryPrimitives.ReadUInt32BigEndian(ToNetworkIp(ip, NetworkHelper.MaskValue(maskLength)).GetAddressBytes()); uint network = BinaryPrimitives.ReadUInt32BigEndian(ToNetworkIp(ip, NetworkHelper.GetPrefixIP(prefixLength)).GetAddressBytes());
IPAddress gateway = new IPAddress(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(network + 1))); IPAddress gateway = new IPAddress(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(network + 1)));
return gateway; return gateway;
} }
public static IPAddress ToGatewayIP(uint ip, uint maskValue) public static IPAddress ToGatewayIP(uint ip, uint prefixIP)
{ {
uint network = BinaryPrimitives.ReadUInt32BigEndian(ToNetworkIp(ip, maskValue).GetAddressBytes()); uint network = BinaryPrimitives.ReadUInt32BigEndian(ToNetworkIp(ip, prefixIP).GetAddressBytes());
IPAddress gateway = new IPAddress(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(network + 1))); IPAddress gateway = new IPAddress(BitConverter.GetBytes(BinaryPrimitives.ReverseEndianness(network + 1)));
return gateway; return gateway;
} }
public static bool NotIPv6Support(IPAddress ip)
{
return ip.AddressFamily == AddressFamily.InterNetworkV6 && (IPv6Support == false);
}
#if DISABLE_IPV6 || (!UNITY_EDITOR && ENABLE_IL2CPP && !UNITY_2018_3_OR_NEWER) #if DISABLE_IPV6 || (!UNITY_EDITOR && ENABLE_IL2CPP && !UNITY_2018_3_OR_NEWER)
public static bool IPv6Support = false; public static bool IPv6Support = false;

View File

@@ -1,49 +1,11 @@
using System; using System;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Linq;
using System.Net; using System.Net;
namespace linker.libs.extends namespace linker.libs.extends
{ {
public static class IPEndPointExtends public static class IPEndPointExtends
{ {
public static Memory<byte> ipv6Loopback = IPAddress.IPv6Loopback.GetAddressBytes();
public static Memory<byte> ipv6Multicast = IPAddress.Parse("ff00::").GetAddressBytes();
public static Memory<byte> ipv6Local = IPAddress.Parse("fe80::").GetAddressBytes();
public static byte[] anyIpArray = IPAddress.Any.GetAddressBytes();
public static byte[] anyIpv6Array = IPAddress.IPv6Any.GetAddressBytes();
public static bool IsLan(this IPEndPoint endPoint)
{
if (endPoint == null) return false;
return endPoint.Address.IsLan();
}
public static bool IsLan(this IPAddress address)
{
if (address == null) return false;
return IsLan(address.GetAddressBytes().AsSpan());
}
public static bool IsLan(this Memory<byte> address)
{
return IsLan(address.Span);
}
public static bool IsLan(Span<byte> address)
{
if (address.Length < 4) return false;
if (address.Length == 4)
{
return address[0] == 127
|| address[0] == 10
|| (address[0] == 172 && address[1] >= 16 && address[1] <= 31)
|| (address[0] == 192 && address[1] == 168);
}
return address.Length == ipv6Loopback.Length && (address.SequenceEqual(ipv6Loopback.Span)
|| address.SequenceEqual(ipv6Multicast.Span)
|| (address[0] == ipv6Local.Span[0] && address[1] == ipv6Local.Span[1]));
}
public static bool GetIsBroadcastAddress(this IPAddress address) public static bool GetIsBroadcastAddress(this IPAddress address)
{ {
return new ReadOnlySpan<byte>(address.GetAddressBytes()).GetIsBroadcastAddress(); return new ReadOnlySpan<byte>(address.GetAddressBytes()).GetIsBroadcastAddress();
@@ -57,20 +19,5 @@ namespace linker.libs.extends
uint ip = BinaryPrimitives.ReadUInt32BigEndian(address); uint ip = BinaryPrimitives.ReadUInt32BigEndian(address);
return address[3] == 255 || (ip >= 0xE0000000 && ip <= 0xEFFFFFFF) || ip == 0xFFFFFFFF; return address[3] == 255 || (ip >= 0xE0000000 && ip <= 0xEFFFFFFF) || ip == 0xFFFFFFFF;
} }
public static bool GetIsAnyAddress(this IPAddress address)
{
return address.GetAddressBytes().AsSpan().GetIsAnyAddress();
}
public static bool GetIsAnyAddress(this Memory<byte> address)
{
return address.Span.GetIsAnyAddress();
}
public static bool GetIsAnyAddress(this Span<byte> address)
{
return (address.Length == 4 && address.SequenceEqual(anyIpArray))
|| (address.Length == 6 && address.SequenceEqual(anyIpv6Array));
}
} }
} }

View File

@@ -165,6 +165,9 @@ namespace linker.tun
/// </summary> /// </summary>
public readonly IPEndPoint Dist => new IPEndPoint(new IPAddress(DistIPAddress.Span), DistPort); public readonly IPEndPoint Dist => new IPEndPoint(new IPAddress(DistIPAddress.Span), DistPort);
public readonly bool IPV4Broadcast => Version == 4 && DistIPAddress.GetIsBroadcastAddress();
public readonly bool IPV6Multicast => Version == 6 && (DistIPAddress.Span[0] & 0xFF) == 0xFF;
public void Unpacket(ReadOnlyMemory<byte> buffer) public void Unpacket(ReadOnlyMemory<byte> buffer)
{ {
Packet = buffer; Packet = buffer;

View File

@@ -133,7 +133,7 @@ namespace linker.tun
error = string.Empty; error = string.Empty;
try try
{ {
IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.MaskValue(prefixLength)); IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.GetPrefixIP(prefixLength));
CommandHelper.Linux(string.Empty, new string[] { CommandHelper.Linux(string.Empty, new string[] {
$"sysctl -w net.ipv4.ip_forward=1", $"sysctl -w net.ipv4.ip_forward=1",
$"iptables -A FORWARD -i {Name} -j ACCEPT", $"iptables -A FORWARD -i {Name} -j ACCEPT",
@@ -156,7 +156,7 @@ namespace linker.tun
$"iptables -D FORWARD -o {Name} -m state --state ESTABLISHED,RELATED -j ACCEPT" $"iptables -D FORWARD -o {Name} -m state --state ESTABLISHED,RELATED -j ACCEPT"
}); });
IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.MaskValue(prefixLength)); IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.GetPrefixIP(prefixLength));
string iptableLineNumbers = CommandHelper.Linux(string.Empty, new string[] { $"iptables -t nat -L --line-numbers | grep {network}/{prefixLength} | cut -d' ' -f1" }); string iptableLineNumbers = CommandHelper.Linux(string.Empty, new string[] { $"iptables -t nat -L --line-numbers | grep {network}/{prefixLength} | cut -d' ' -f1" });
if (string.IsNullOrWhiteSpace(iptableLineNumbers) == false) if (string.IsNullOrWhiteSpace(iptableLineNumbers) == false)
{ {
@@ -211,8 +211,8 @@ namespace linker.tun
{ {
var commands = ips.Select(c => var commands = ips.Select(c =>
{ {
uint maskValue = NetworkHelper.MaskValue(c.PrefixLength); uint prefixValue = NetworkHelper.GetPrefixIP(c.PrefixLength);
IPAddress network = NetworkHelper.ToNetworkIp(c.Address, maskValue); IPAddress network = NetworkHelper.ToNetworkIp(c.Address, prefixValue);
return $"iptables -t nat -A POSTROUTING -o {Name} -s {network}/{c.PrefixLength} -j MASQUERADE"; return $"iptables -t nat -A POSTROUTING -o {Name} -s {network}/{c.PrefixLength} -j MASQUERADE";
}).ToList(); }).ToList();
commands.Insert(0, "sysctl -w net.ipv4.ip_forward=1"); commands.Insert(0, "sysctl -w net.ipv4.ip_forward=1");
@@ -223,8 +223,8 @@ namespace linker.tun
{ {
string[] commands = ips.Select(item => string[] commands = ips.Select(item =>
{ {
uint maskValue = NetworkHelper.MaskValue(item.PrefixLength); uint prefixValue = NetworkHelper.GetPrefixIP(item.PrefixLength);
IPAddress network = NetworkHelper.ToNetworkIp(item.Address, maskValue); IPAddress network = NetworkHelper.ToNetworkIp(item.Address, prefixValue);
return $"ip route add {network}/{item.PrefixLength} via {ip} dev {Name} metric 1 "; return $"ip route add {network}/{item.PrefixLength} via {ip} dev {Name} metric 1 ";
}).ToArray(); }).ToArray();
@@ -240,7 +240,7 @@ namespace linker.tun
{ {
foreach (var item in ip) foreach (var item in ip)
{ {
IPAddress network = NetworkHelper.ToNetworkIp(item.Address, NetworkHelper.MaskValue(item.PrefixLength)); IPAddress network = NetworkHelper.ToNetworkIp(item.Address, NetworkHelper.GetPrefixIP(item.PrefixLength));
string iptableLineNumbers = CommandHelper.Linux(string.Empty, new string[] { $"iptables -t nat -L --line-numbers | grep {network}/{item.PrefixLength} | cut -d' ' -f1" }); string iptableLineNumbers = CommandHelper.Linux(string.Empty, new string[] { $"iptables -t nat -L --line-numbers | grep {network}/{item.PrefixLength} | cut -d' ' -f1" });
if (string.IsNullOrWhiteSpace(iptableLineNumbers) == false) if (string.IsNullOrWhiteSpace(iptableLineNumbers) == false)
{ {
@@ -255,8 +255,8 @@ namespace linker.tun
{ {
string[] commands = ip.Select(item => string[] commands = ip.Select(item =>
{ {
uint maskValue = NetworkHelper.MaskValue(item.PrefixLength); uint prefixValue = NetworkHelper.GetPrefixIP(item.PrefixLength);
IPAddress network = NetworkHelper.ToNetworkIp(item.Address, maskValue); IPAddress network = NetworkHelper.ToNetworkIp(item.Address, prefixValue);
return $"ip route del {network}/{item.PrefixLength}"; return $"ip route del {network}/{item.PrefixLength}";
}).ToArray(); }).ToArray();
CommandHelper.Linux(string.Empty, commands); CommandHelper.Linux(string.Empty, commands);

View File

@@ -35,7 +35,7 @@ namespace linker.tun
safeFileHandle = File.OpenHandle($"/dev/{Name}", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, FileOptions.Asynchronous); safeFileHandle = File.OpenHandle($"/dev/{Name}", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, FileOptions.Asynchronous);
fs = new FileStream(safeFileHandle, FileAccess.ReadWrite, 1500); fs = new FileStream(safeFileHandle, FileAccess.ReadWrite, 1500);
IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.MaskValue(prefixLength)); IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.GetPrefixIP(prefixLength));
CommandHelper.Osx(string.Empty, new string[] { CommandHelper.Osx(string.Empty, new string[] {
$"route delete -net {network}/{prefixLength} {address}", $"route delete -net {network}/{prefixLength} {address}",
$"ifconfig {Name} {address} {address} up", $"ifconfig {Name} {address} {address} up",
@@ -55,7 +55,7 @@ namespace linker.tun
fs.Dispose(); fs.Dispose();
fs = null; fs = null;
} }
IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.MaskValue(this.prefixLength)); IPAddress network = NetworkHelper.ToNetworkIp(address, NetworkHelper.GetPrefixIP(this.prefixLength));
CommandHelper.Osx(string.Empty, new string[] { $"route delete -net {network}/{prefixLength} {address}" }); CommandHelper.Osx(string.Empty, new string[] { $"route delete -net {network}/{prefixLength} {address}" });
} }

View File

@@ -153,7 +153,7 @@ namespace linker.tun
try try
{ {
CommandHelper.PowerShell($"start-service WinNat", [], out error); CommandHelper.PowerShell($"start-service WinNat", [], out error);
IPAddress network = NetworkHelper.ToNetworkIp(this.address, NetworkHelper.MaskValue(prefixLength)); IPAddress network = NetworkHelper.ToNetworkIp(this.address, NetworkHelper.GetPrefixIP(prefixLength));
CommandHelper.PowerShell($"New-NetNat -Name {Name} -InternalIPInterfaceAddressPrefix {network}/{prefixLength}", [], out error); CommandHelper.PowerShell($"New-NetNat -Name {Name} -InternalIPInterfaceAddressPrefix {network}/{prefixLength}", [], out error);
if (string.IsNullOrWhiteSpace(error) == false) if (string.IsNullOrWhiteSpace(error) == false)
@@ -215,8 +215,8 @@ namespace linker.tun
{ {
string[] commands = ips.Select(item => string[] commands = ips.Select(item =>
{ {
uint maskValue = NetworkHelper.MaskValue(item.PrefixLength); uint maskValue = NetworkHelper.GetPrefixIP(item.PrefixLength);
IPAddress mask = NetworkHelper.GetMaskIp(maskValue); IPAddress mask = NetworkHelper.GetPrefixIp(maskValue);
IPAddress _ip = NetworkHelper.ToNetworkIp(item.Address, maskValue); IPAddress _ip = NetworkHelper.ToNetworkIp(item.Address, maskValue);
return $"route add {_ip} mask {mask} {ip} metric 5 if {interfaceNumber}"; return $"route add {_ip} mask {mask} {ip} metric 5 if {interfaceNumber}";
@@ -231,8 +231,8 @@ namespace linker.tun
{ {
string[] commands = ip.Select(item => string[] commands = ip.Select(item =>
{ {
uint maskValue = NetworkHelper.MaskValue(item.PrefixLength); uint maskValue = NetworkHelper.GetPrefixIP(item.PrefixLength);
IPAddress mask = NetworkHelper.GetMaskIp(maskValue); IPAddress mask = NetworkHelper.GetPrefixIp(maskValue);
IPAddress _ip = NetworkHelper.ToNetworkIp(item.Address, maskValue); IPAddress _ip = NetworkHelper.ToNetworkIp(item.Address, maskValue);
return $"route delete {_ip}"; return $"route delete {_ip}";
}).ToArray(); }).ToArray();

View File

@@ -116,7 +116,7 @@ namespace linker.plugins.tunnel
uint ip = BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes()); uint ip = BinaryPrimitives.ReadUInt32BigEndian(c.GetAddressBytes());
foreach (var item in excludeips) foreach (var item in excludeips)
{ {
uint maskValue = NetworkHelper.MaskValue(item.Mask); uint maskValue = NetworkHelper.GetPrefixIP(item.Mask);
uint ip1 = BinaryPrimitives.ReadUInt32BigEndian(item.IPAddress.GetAddressBytes()); uint ip1 = BinaryPrimitives.ReadUInt32BigEndian(item.IPAddress.GetAddressBytes());
if ((ip & maskValue) == (ip1 & maskValue)) if ((ip & maskValue) == (ip1 & maskValue))
{ {

View File

@@ -390,7 +390,7 @@ namespace linker.plugins.tuntap
{ {
uint ipInt = BinaryPrimitives.ReadUInt32BigEndian(ip.GetAddressBytes()); uint ipInt = BinaryPrimitives.ReadUInt32BigEndian(ip.GetAddressBytes());
//掩码十进制 //掩码十进制
uint maskValue = NetworkHelper.MaskValue(maskLength); uint maskValue = NetworkHelper.GetPrefixIP(maskLength);
return new TuntapVeaLanIPAddress return new TuntapVeaLanIPAddress
{ {
IPAddress = ipInt, IPAddress = ipInt,

View File

@@ -79,7 +79,7 @@ namespace linker.plugins.tuntap.proxy
public async Task Callback(LinkerTunDevicPacket packet) public async Task Callback(LinkerTunDevicPacket packet)
{ {
//IPV4广播组播 //IPV4广播组播
if (packet.Version == 4 && packet.DistIPAddress.GetIsBroadcastAddress()) if (packet.IPV4Broadcast)
{ {
if (connections.IsEmpty == false) if (connections.IsEmpty == false)
{ {
@@ -88,7 +88,7 @@ namespace linker.plugins.tuntap.proxy
return; return;
} }
//IPV6 多播 //IPV6 多播
else if (packet.Version == 6 && (packet.DistIPAddress.Span[0] & 0xFF) == 0xFF) else if (packet.IPV6Multicast)
{ {
if (connections.IsEmpty == false) if (connections.IsEmpty == false)
{ {