如何检查输入的IP是否在特定IP范围内


73

如果我们让用户输入几个IP范围,例如172.16.11.5-100,我该如何编写一个函数来检查IP(172.16.11.50)是否在该范围内?

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


注意事项-如果要实现此目的是为了查看IP是否在特定的子网上,那么如果不考虑子网掩码,就无法可靠地执行此操作。
罗布·莱文

看起来他没有指定子网掩码。如果是他,那么您将使用单个IP并指定子网,而不是IP地址范围。通常使用范围,因为很多人不知道什么是子网...
Ian 2010年

Answers:


122

框架中没有内置任何东西,但是创建一个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
对于这种情况将是错误的:较低-222.168.2.1,较高-222.168.5.10和目标-222.168.3.55
Ricky

设置边界时,为简单起见,可以用=替换&=。
Bombinosh's

1
@Bombinosh自从我看过这段代码已经有一段时间了,但是没有,&=确保一旦为假,它就保持为假。如果是的话=,它可能会true再次变成。
理查德·萨雷

@Richard,感谢您提供的代码,但是它是包含性的还是排他性的?
Soroush Falahati 2016年

代码中的“下部”是什么?我的意思是,这一行中有未定义的值;this.addressFamily = lower.AddressFamily;
Lost_In_Library '17

55

您可能要考虑使用@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.

1
Nuget的IPAddressRange是一个易于使用的选项。我将在下面添加一个代码示例。
杰夫·梅格勒

同意Jeff,非常易于使用并推荐。
阿彻博士

21
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

6
我想说equal也落在范围内:return ip> = ipStart && ip <= ipEnd;
Jannes 2013年

完美的答案!这通过了我所有的单元测试,尤其是对于该范围的较低端。
伊戈尔·图尔曼

3
恩,我们不应该使用UInt32而不是longInt32吗?这不会在任何桥接或高于128.0.0.0的地址范围上失败吗?
培根钻头

9

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

这里的示例:IP到整数

要将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)。看一下这个问题:在C#中将IPv6格式化为int并将其存储在SQL Server中

最简单的方法是获取框架为您执行此操作。使用 IPAddress.Parse解析地址,然后IPAddress.GetAddressBytes将取得“数字” byte[]


3
该功能不适用于IPAddress该类支持的IPv6地址。
理查德·萨雷

4

我以前在codeproject上使用过此代码,可能对您有用。

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

您可以添加到IPList由“从IP”和“到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,您将有可能对此进行检查。

免责声明:该类仅使用简单的数据集进行测试,并且该类缺乏对所提供IP地址和IP掩码的验证。在生产环境中使用之前,应先修复此问题。


3

这里重新发布我的答案

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

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

因此,当您说要以“ a”开头的IP地址时,您正在寻找的IP地址介于* 256 ^ 3和* 256 ^ 3 + 256 *(256 ^ 2)(b = 256)+ 256 *(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是您的范围的最大值


该功能不适用于IPAddress该类支持的IPv6地址。
拉兹万·杜米特鲁


1

我想+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命名空间)

Imports NetTools ' ref. https://www.nuget.org/packages/IPAddressRange/

Function CheckIPWhitelist() As Boolean
    Dim match As Boolean = False
    Dim SourceIP As String = Request.UserHostAddress()

    ' Examples of valid IPWhitelist ranges 
    ' one range in longhand range format: "192.168.0.10 - 192.168.10.20"
    ' one range in shorthand range format: "192.168.10.10-20"
    ' multiple ranges separated by semicolons in shorthand range format: "192.168.10.10-20;192.168.125.1-150;192.168.123.1-150"
    Dim IPWhitelist As String = ConfigurationManager.AppSettings("IPWhitelist")

    Dim arrRanges As String() = IPWhitelist.Split(";")
    For i As Integer = 0 To arrRanges.Length - 1
        If arrRanges(i) IsNot Nothing Then
            Dim range As NetTools.IPAddressRange = IPAddressRange.Parse(arrRanges(i))
            If range.Contains(IPAddressRange.Parse(SourceIP)) = True Then
                match = True ' IP is in the whitelist, set a boolean
                Exit For
            End If
        End If
    Next
    Return match
End Function
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.