如何检查输入IP是否属于特定IP范围

Ric*_*cky 65 c# asp.net

如果我们让用户输入几个ip范围,例如172.16.11.5 - 100,我怎么能写一个函数来检查IP(172.16.11.50)是否属于范围?

是否有任何现有的.NET库可以利用?

Ric*_*lay 117

框架中没有任何内置,但创建一个IPAddressRange类不会花费太多精力.

您可以通过在较低地址,较高地址和比较地址上调用IPAddress.GetAddressBytes来比较范围.从第一个字节开始,检查比较地址是否在上/下地址范围内.

此方法适用于IPv4和IPv6地址.

public class IPAddressRange
{
    readonly AddressFamily addressFamily;
    readonly byte[] lowerBytes;
    readonly byte[] upperBytes;

    public IPAddressRange(IPAddress lowerInclusive, IPAddress upperInclusive)
    {
        // Assert that lower.AddressFamily == upper.AddressFamily

        this.addressFamily = lowerInclusive.AddressFamily;
        this.lowerBytes = lowerInclusive.GetAddressBytes();
        this.upperBytes = upperInclusive.GetAddressBytes();
    }

    public bool IsInRange(IPAddress address)
    {
        if (address.AddressFamily != addressFamily)
        {
            return false;
        }

        byte[] addressBytes = address.GetAddressBytes();

        bool lowerBoundary = true, upperBoundary = true;

        for (int i = 0; i < this.lowerBytes.Length && 
            (lowerBoundary || upperBoundary); i++)
        {
            if ((lowerBoundary && addressBytes[i] < lowerBytes[i]) ||
                (upperBoundary && addressBytes[i] > upperBytes[i]))
            {
                return false;
            }

            lowerBoundary &= (addressBytes[i] == lowerBytes[i]);
            upperBoundary &= (addressBytes[i] == upperBytes[i]);
        }

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:上面的代码可以扩展为添加公共静态工厂方法 FromCidr(IPAddress address, int bits)

  • 对于以下情况,这将是错误的:下限 - 222.168.2.1,上限 - 222.168.5.10 和目标 - 222.168.3.55 (2认同)
  • @Bombinosh 自从我查看这段代码以来已经有一段时间了,但是不,“&amp;=”确保一旦为假,它就保持为假。如果它是“=”,它可能会再次变成“true”。 (2认同)

Bud*_*hiP 49

您可能希望通过@jsakamoto考虑此库,它允许您解析IP地址字符串的范围,例如"192.168.0.0/24"和"192.168.0.0/255.255.255.0"和"192.168.0.0-192.168.0.255" ,并可以检查.该库支持IPv4和IPv6.

https://github.com/jsakamoto/ipaddressrange

它也可以通过NuGet安装:

http://www.nuget.org/packages/IPAddressRange/

using NetTools;
...
// rangeA.Begin is "192.168.0.0", and rangeA.End is "192.168.0.255".
var rangeA = IPAddressRange.Parse("192.168.0.0/255.255.255.0");
rangeA.Contains(IPAddress.Parse("192.168.0.34")); // is True.
rangeA.Contains(IPAddress.Parse("192.168.10.1")); // is False.
rangeA.ToCidrString(); // is 192.168.0.0/24

// rangeB.Begin is "192.168.0.10", and rangeB.End is "192.168.10.20".
var rangeB1 = IPAddressRange.Parse("192.168.0.10 - 192.168.10.20");
rangeB1.Contains(IPAddress.Parse("192.168.3.45")); // is True.
rangeB1.Contains(IPAddress.Parse("192.168.0.9")); // is False.

// Support shortcut range description. 
// ("192.168.10.10-20" means range of begin:192.168.10.10 to end:192.168.10.20.)
var rangeB2 = IPAddressRange.Parse("192.168.10.10-20");

// Support CIDR expression and IPv6.
var rangeC = IPAddressRange.Parse("fe80::/10"); 
rangeC.Contains(IPAddress.Parse("fe80::d503:4ee:3882:c586%3")); // is True.
rangeC.Contains(IPAddress.Parse("::1")); // is False.
Run Code Online (Sandbox Code Playgroud)


art*_*twl 15

public static bool IsInRange(string startIpAddr, string endIpAddr, string address)
{
    long ipStart = BitConverter.ToInt32(IPAddress.Parse(startIpAddr).GetAddressBytes().Reverse().ToArray(), 0);

    long ipEnd = BitConverter.ToInt32(IPAddress.Parse(endIpAddr).GetAddressBytes().Reverse().ToArray(), 0);

    long ip = BitConverter.ToInt32(IPAddress.Parse(address).GetAddressBytes().Reverse().ToArray(), 0);

    return ip >= ipStart && ip <= ipEnd; //edited
}

Console.WriteLine(IsInRange("100.0.0.1", "110.0.0.255", "102.0.0.4"));//true
Run Code Online (Sandbox Code Playgroud)

  • 我会说等于也落在范围内:return ip> = ipStart && ip <= ipEnd; (6认同)
  • 嗯,我们不应该使用`UInt32`而不是`long`或`Int32`?在任何地址范围桥接或高于128.0.0.0时,这不会失败吗? (3认同)

小智 9

最好是将这些地址转换为整数,然后执行比较.

示例来自:IP到整数

要将IP地址转换为整数,请将其分为四个八位字节.例如,您提供的IP地址可以分为:

First Octet:    217
Second Octet:   110
Third Octet:    18
Fourth Octet:   206
Run Code Online (Sandbox Code Playgroud)

要从虚线字符串计算小数地址,请执行以下计算.

    (first octet * 256³) + (second octet * 256²) + (third octet * 256) + (fourth octet)
=   (first octet * 16777216) + (second octet * 65536) + (third octet * 256) + (fourth octet)
=   (217 * 16777216) + (110 * 65536) + (18 * 256) + (206)
=   3647869646
Run Code Online (Sandbox Code Playgroud)

考虑到IPv6,您可以将它们转换为整数(128位与32位IPv4).看看这个问题:将IPv6格式化为C#中的int并将其存储在SQL Server中

最简单的方法是让框架为您完成此操作.使用 IPAddress.Parse解析地址,然后IPAddress.GetAddressBytes获得"数字"作为byte[].

  • 这不适用于`IPAddress`类支持的IPv6地址. (2认同)

ram*_*ram 3

从这里重新发布我的答案

不久前,我必须找到给定 IP 的位置。我们从请求中获取了 IP。有免费的数据库为我们提供了这种映射。在 IPv4 中,当我们将 IP 称为“abcd”时,它本质上是a * (256^3) + b * (256^2) + c * (256) + d

http://www.aboutmyip.com/AboutMyXApp/IP2Integer.jsp

因此,当您说需要以“a”开头的 IP 地址时,您正在寻找 a * 256^ 3 和 a * 256^3 + 256 * (256^2) (b = 256) + 256 *(256 之间的 IP ) (c=256) + 256( d=256) (下限/上限可能会略有不同,具体取决于您是否要包含/排除限制)。

也就是说,有一些为特定目的而保留的特定IP(例如127.0.0.1是本地主机,0.0.0.0不能是IP等)。

所以你的 linq 查询是

from i in iList where i >= MIN && i <= MAX select i;
Run Code Online (Sandbox Code Playgroud)

其中 iList 是您的初始列表 MIN 是范围的最小值 MAX 是范围的最大值

  • 这不适用于“IPAddress”类支持的 IPv6 地址。 (2认同)