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

时间:2010-01-26 10:15:00

标签: c# asp.net

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

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

9 个答案:

答案 0 :(得分:114)

框架中没有任何内置,但创建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;
    }
}

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

答案 1 :(得分:45)

您可能希望通过@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.

答案 2 :(得分:12)

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

答案 3 :(得分:8)

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

此处的示例:IP to Integer

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

First Octet:    217
Second Octet:   110
Third Octet:    18
Fourth Octet:   206

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

    (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

考虑到IPv6,您也可以将它们转换为整数(128位与32位IPv4)。看看这个问题:Formatting IPv6 as an int in C# and storing it in SQL Server

  

最简单的方法是获得   框架为您做到这一点。使用   IPAddress.Parse解析地址,   然后IPAddress.GetAddressBytes得到   “数字”为byte[]

答案 4 :(得分:4)

之前我在codeproject上使用过这段代码,这可能对你有用。

http://www.codeproject.com/KB/IP/ipnumbers.aspx

您可以向IPList添加由From IP和To IP号码定义的一系列IP号码。该方法将范围分解为标准IP范围并查找其掩码。因此,范围“10.0.0.5”到“10.0.0.20”将被分解为以下范围并添加到列表中:10.0.0.5,10.0.0.20,10.0.0.6 / 31,10.0.0.16 / 30和10.0。 0.8 / 29,您将有可能对此进行检查。

  

免责声明:该类仅使用简单的数据集进行测试   Class缺乏对提供的IP号和IP掩码的验证。这个   应该在生产环境中使用之前修复。

答案 5 :(得分:3)

here

重新发布我的回答

不久前,我必须找到给定IP的位置。我们从请求中获得了IP。有免费的数据库给了我们这个映射。在IPv4中,当我们将IP称为“a.b.c.d”时,它基本上是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之间的IP *(256)(c = 256)+ 256(d = 256)(下限/上限可能会略有不同,具体取决于您是否要包含/排除限制)。

也就是说,为特定目的保留了特定的IP(如127.0.0.1,即localhost,0.0.0.0不能是IP等)。

所以你的linq查询将是

from i in iList where i >= MIN && i <= MAX select i;

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

答案 6 :(得分:1)

你能从你的IP范围中找出subnet mask吗?

如果是这样,那么也许你可以使用这个IsInSameSubnet方法..

答案 7 :(得分:1)

你可以先把中间的点去掉,然后把所有的IP都转成long, 然后在 if 中检查它们:

var givenIp = Convert.ToInt64(clientIp.Replace(".", ""));
var startIp = Convert.ToInt64(startRange.Replace(".", ""));
var endIp = Convert.ToInt64(endRange.Replace(".", ""));

if (givenIp != startIp && givenIp != endIp && (givenIp < startIp || givenIp > endIp))
{
   Console.WriteLine("your ip does not allow to access!");
}

答案 8 :(得分:0)

我想+1上面BuddhiP的答案,该答案推荐了NuGet的IPAddressRange软件包:https://www.nuget.org/packages/IPAddressRange/

但是由于注释中很难进行代码格式化,因此我将在此处添加一个有关如何使用IPAddressRange的实用代码示例。

CheckIPWhitelist读取一个名为IPWhitelist的设置,并假定IPAddressRange可以解析的IP范围(例如“ 192.168.10.10-20; 192.168.125.1-150; 192.168.123.1-150”)以分号分隔的列表。该函数对范围进行迭代,并且将存在,如果存在则返回true,否则返回false。

此功能是VB.NET,并假定存在一些ASP.NET依赖项(例如System.Web.HttpRequest命名空间)

TextSlider.SendKeys(Keys.Backspace + Keys.Backspace);