如何检查是否一个IP地址是一个特定的子网内(How to check if an IP addres

2019-07-20 06:30发布

我在格式10.132.0.0/20子网,并从ASP.Net请求对象的IP地址。

是否有一个.NET框架的功能检查,看看如果IP地址是在给定的子网内?

如果没有,怎么能做到呢? 位操作,我猜?

Answer 1:

看看IP地址计算与C#在MSDN博客。 它包含一个扩展方法( IsInSameSubnet )应该满足您的需求,以及一些其他的东西。

public static class IPAddressExtensions
{
    public static IPAddress GetBroadcastAddress(this IPAddress address, IPAddress subnetMask)
    {
        byte[] ipAdressBytes = address.GetAddressBytes();
        byte[] subnetMaskBytes = subnetMask.GetAddressBytes();

        if (ipAdressBytes.Length != subnetMaskBytes.Length)
            throw new ArgumentException("Lengths of IP address and subnet mask do not match.");

        byte[] broadcastAddress = new byte[ipAdressBytes.Length];
        for (int i = 0; i < broadcastAddress.Length; i++)
        {
            broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));
        }
        return new IPAddress(broadcastAddress);
    }

    public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask)
    {
        byte[] ipAdressBytes = address.GetAddressBytes();
        byte[] subnetMaskBytes = subnetMask.GetAddressBytes();

        if (ipAdressBytes.Length != subnetMaskBytes.Length)
            throw new ArgumentException("Lengths of IP address and subnet mask do not match.");

        byte[] broadcastAddress = new byte[ipAdressBytes.Length];
        for (int i = 0; i < broadcastAddress.Length; i++)
        {
            broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
        }
        return new IPAddress(broadcastAddress);
    }

    public static bool IsInSameSubnet(this IPAddress address2, IPAddress address, IPAddress subnetMask)
    {
        IPAddress network1 = address.GetNetworkAddress(subnetMask);
        IPAddress network2 = address2.GetNetworkAddress(subnetMask);

        return network1.Equals(network2);
    }
}


Answer 2:

位操作工作。 东西IP为32位无符号整数,做子网的地址相同, & -mask都与0xFFFFFFFF << (32-20)和比较:

unsigned int net = ..., ip = ...;
int network_bits = 20;
unsigned int mask = 0xFFFFFFFF << (32 - network_bits);
if ((net & mask) == (ip & mask)) {
  // ...
}


Answer 3:

由于MSDN博客代码依赖于广播和IPv6没有一个,我不知道这是否与IPv6的工作。

我结束了这些方法(感谢NU珠穆朗玛峰)。 你可以从CIDR标记(“1.2.3.4/5”)的子网和掩码,并检查了ADRESS是否是网络之内还是之外。

这适用于IPv4和IPv6:

public static class IpAddresses
{
    public static Tuple<IPAddress, IPAddress> GetSubnetAndMaskFromCidr(string cidr)
    {
        var delimiterIndex = cidr.IndexOf('/');
        string ipSubnet = cidr.Substring(0, delimiterIndex);
        string mask = cidr.Substring(delimiterIndex + 1);

        var subnetAddress = IPAddress.Parse(ipSubnet);

        if (subnetAddress.AddressFamily == AddressFamily.InterNetworkV6)
        {
            // ipv6
            var ip = BigInteger.Parse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber) << (128 - int.Parse(mask));

            var maskBytes = new[]
            {
                (byte)((ip & BigInteger.Parse("00FF000000000000000000000000000000", NumberStyles.HexNumber)) >> 120),
                (byte)((ip & BigInteger.Parse("0000FF0000000000000000000000000000", NumberStyles.HexNumber)) >> 112),
                (byte)((ip & BigInteger.Parse("000000FF00000000000000000000000000", NumberStyles.HexNumber)) >> 104),
                (byte)((ip & BigInteger.Parse("00000000FF000000000000000000000000", NumberStyles.HexNumber)) >> 96),
                (byte)((ip & BigInteger.Parse("0000000000FF0000000000000000000000", NumberStyles.HexNumber)) >> 88),
                (byte)((ip & BigInteger.Parse("000000000000FF00000000000000000000", NumberStyles.HexNumber)) >> 80),
                (byte)((ip & BigInteger.Parse("00000000000000FF000000000000000000", NumberStyles.HexNumber)) >> 72),
                (byte)((ip & BigInteger.Parse("0000000000000000FF0000000000000000", NumberStyles.HexNumber)) >> 64),
                (byte)((ip & BigInteger.Parse("000000000000000000FF00000000000000", NumberStyles.HexNumber)) >> 56),
                (byte)((ip & BigInteger.Parse("00000000000000000000FF000000000000", NumberStyles.HexNumber)) >> 48),
                (byte)((ip & BigInteger.Parse("0000000000000000000000FF0000000000", NumberStyles.HexNumber)) >> 40),
                (byte)((ip & BigInteger.Parse("000000000000000000000000FF00000000", NumberStyles.HexNumber)) >> 32),
                (byte)((ip & BigInteger.Parse("00000000000000000000000000FF000000", NumberStyles.HexNumber)) >> 24),
                (byte)((ip & BigInteger.Parse("0000000000000000000000000000FF0000", NumberStyles.HexNumber)) >> 16),
                (byte)((ip & BigInteger.Parse("000000000000000000000000000000FF00", NumberStyles.HexNumber)) >> 8),
                (byte)((ip & BigInteger.Parse("00000000000000000000000000000000FF", NumberStyles.HexNumber)) >> 0),
            };

            return Tuple.Create(subnetAddress, new IPAddress(maskBytes));
        }
        else
        {
            // ipv4
            uint ip = 0xFFFFFFFF << (32 - int.Parse(mask));

            var maskBytes = new[]
            {
                (byte)((ip & 0xFF000000) >> 24),
                (byte)((ip & 0x00FF0000) >> 16),
                (byte)((ip & 0x0000FF00) >> 8),
                (byte)((ip & 0x000000FF) >> 0),
            };

            return Tuple.Create(subnetAddress, new IPAddress(maskBytes));
        }
    }

    public static bool IsAddressOnSubnet(IPAddress address, IPAddress subnet, IPAddress mask)
    {
        byte[] addressOctets = address.GetAddressBytes();
        byte[] subnetOctets = mask.GetAddressBytes();
        byte[] networkOctets = subnet.GetAddressBytes();

        // ensure that IPv4 isn't mixed with IPv6
        if (addressOctets.Length != subnetOctets.Length
            || addressOctets.Length != networkOctets.Length)
        {
            return false;
        }

        for (int i = 0; i < addressOctets.Length; i += 1)
        {
            var addressOctet = addressOctets[i];
            var subnetOctet = subnetOctets[i];
            var networkOctet = networkOctets[i];

            if (networkOctet != (addressOctet & subnetOctet))
            {
                return false;
            }
        }
        return true;
    }
}

实例:

var subnetAndMask = IpAddresses.GetSubnetAndMaskFromCidr("10.132.0.0/20");
bool result = IpAddresses.IsAddressOnSubnet(
    IPAddress.Parse("10.132.12.34"),
    subnetAndMask.Item1,
    subnetAndMask.Item2);


Answer 4:

我迟到了这里,但也有类似的需求,并把一个快速包做正是这一点。

https://www.nuget.org/packages/IpMatcher/

和来源:

https://github.com/jchristn/IpMatcher

简单的使用方法:

using IpMatcher;

Matcher matcher = new Matcher();
matcher.Add("192.168.1.0", "255.255.255.0");
matcher.Add("192.168.2.0", "255.255.255.0");
matcher.Remove("192.168.2.0");
matcher.Exists("192.168.1.0", "255.255.255.0");  // true
matcher.Match("192.168.1.34"); // true
matcher.Match("10.10.10.10");  // false


Answer 5:

该解决方案是将IP地址转换成使用字节System.Net.IPAddress和地址,子网和掩码八位位组进行逐位比较。

在二进制码和操作员&如果它存在于两个操作数拷贝位结果。

代码:

using System.Net;   // Used to access IPAddress

bool IsAddressOnSubnet(string address, string subnet, string mask)
{
    try
    {
        IPAddress Address = IPAddress.Parse(address);
        IPAddress Subnet = IPAddress.Parse(subnet);
        IPAddress Mask = IPAddress.Parse(mask);            

        Byte[] addressOctets = Address.GetAddressBytes();
        Byte[] subnetOctets = Mask.GetAddressBytes();
        Byte[] networkOctets = Subnet.GetAddressBytes();

        return
            ((networkOctets[0] & subnetOctets[0]) == (addressOctets[0] & subnetOctets[0])) &&
            ((networkOctets[1] & subnetOctets[1]) == (addressOctets[1] & subnetOctets[1])) &&
            ((networkOctets[2] & subnetOctets[2]) == (addressOctets[2] & subnetOctets[2])) &&
            ((networkOctets[3] & subnetOctets[3]) == (addressOctets[3] & subnetOctets[3]));
    }
    catch (System.Exception ex)
    {
        return false;                
    }
}

特别感谢,谢谢! 完美的解决方案! 参考



文章来源: How to check if an IP address is within a particular subnet