简体   繁体   English

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

[英]How to check a input IP fall in a specific IP range

If we let users input a couple of ip ranges, eg, 172.16.11.5 - 100, how could I write a function to check if a IP (172.16.11.50) falls in the ranges? If we let users input a couple of ip ranges, eg, 172.16.11.5 - 100, how could I write a function to check if a IP (172.16.11.50) falls in the ranges?

Is there any existing library in .NET to leverage? .NET 中是否有任何现有的库可供利用?

There's nothing built into the framework, but it wouldn't take much effort to create an IPAddressRange class.框架中没有内置任何内容,但创建IPAddressRange类不会花费太多精力。

You'd compare the ranges by calling IPAddress.GetAddressBytes on the lower address, upper address and comparison address.您可以通过在低地址、高地址和比较地址上调用IPAddress.GetAddressBytes来比较范围。 Starting at the first byte, check if the comparison address is in the range of the upper/lower address.从第一个字节开始,检查比较地址是否在高/低地址范围内。

This method works for both IPv4 and IPv6 addresses.此方法适用于 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;
    }
}

NB: The above code could be extended to add public static factory methods FromCidr(IPAddress address, int bits)注意:上面的代码可以扩展为添加公共静态工厂方法FromCidr(IPAddress address, int bits)

You might want to consider this library by @jsakamoto, which allows you to parse range of IP address strings such as "192.168.0.0/24" and "192.168.0.0/255.255.255.0" and "192.168.0.0-192.168.0.255", and can contains check.您可能需要考虑@jsakamoto 的这个库,它允许您解析 IP 地址字符串的范围,例如“192.168.0.0/24”和“192.168.0.0/255.255.255.0”和“192.168.0.0-192.168.0.255” , 并且可以包含检查。 This library supports both IPv4 and IPv6.该库支持 IPv4 和 IPv6。

https://github.com/jsakamoto/ipaddressrange https://github.com/jsakamoto/ipaddressrange

It can also be installed via NuGet:它也可以通过 NuGet 安装:

http://www.nuget.org/packages/IPAddressRange/ 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.
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

The best is to convert these addresses to an integer and then perform comparisons.最好的办法是将这些地址转换为整数,然后进行比较。

Example from here: IP to Integer此处的示例: IP 到整数

To convert an IP address to integer, break it into four octets.要将 IP 地址转换为整数,请将其分成四个八位字节。 For example, the ip address you provided can be broken into:例如,您提供的 ip 地址可以分解为:

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

To calculate the decimal address from a dotted string, perform the following calculation.要从点分字符串计算十进制地址,请执行以下计算。

    (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

Considering IPv6, you can convert them to integers (128bit vs 32bit IPv4) as well.考虑到 IPv6,您也可以将它们转换为整数(128 位与 32 位 IPv4)。 Have a look at this question: Formatting IPv6 as an int in C# and storing it in SQL Server看看这个问题: Formatting IPv6 as an int in C# and storage it in SQL Server

The simplest route is to get the framework to do this for you.最简单的方法是让框架为您执行此操作。 Use IPAddress.Parse to parse the address, then IPAddress.GetAddressBytes to get the "number" as byte[] .使用IPAddress.Parse解析地址,然后使用IPAddress.GetAddressBytes将“数字”作为byte[]获取。

I used this code on codeproject before, which may be of use to you.我之前在codeproject上使用过这段代码,可能对你有用。

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

You have the possibility to add to IPList a range of IP numbers defined by a From IP and a To IP number.您可以向IPList添加由 From IP 和 To IP 号码定义的 IP 号码范围。 The method breaks up the range into standard IP ranges and finds their masks.该方法将范围分解为标准 IP 范围并找到它们的掩码。 So the range "10.0.0.5" to "10.0.0.20" will be broken up to the following ranges and added to the list: 10.0.0.5, 10.0.0.20, 10.0.0.6/31, 10.0.0.16/30 and 10.0.0.8/29 and you'll have the possibility to check against that.因此,“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,您将有可能对此进行检查。

Disclaimer: The Class is only tested with simple data sets, and the Class lacks validation of the IP numbers and IP masks provided.免责声明:该类仅使用简单的数据集进行测试,并且该类缺乏对提供的 IP 编号和 IP 掩码的验证。 This should be fixed before it is used in production environments.这应该在用于生产环境之前修复。

reposting my answer from here这里重新发布我的答案

A while ago, I had to find the location of a given IP.不久前,我必须找到给定 IP 的位置。 We got the IP from the request.我们从请求中获得了 IP。 There are free databases which gave us this mapping.有免费的数据库给了我们这个映射。 In IPv4, when we say the IP as "abcd" it is essentially a * (256^3) + b * (256^2) + c * (256) + d .在 IPv4 中,当我们将 IP 称为“abcd”时,它本质上是a * (256^3) + b * (256^2) + c * (256) + d

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

so when you say you want an IP address starting with "a", you are looking for IPs between a * 256^ 3 and a * 256^3 + 256 * (256^2) (b = 256) + 256 *(256) (c=256) + 256( d=256) (lower / upper limit may vary a little bit depending on whether you want to include/exclude the limits).所以当你说你想要一个以“a”开头的IP地址时,你正在寻找a * 256^ 3和a * 256^3 + 256 * (256^2) (b = 256) + 256 *(256 ) (c=256) + 256( d=256) (下限/上限可能会有所不同,具体取决于您是否要包括/排除限制)。

That said, there are specific IPs reserved for specific purposes(like 127.0.0.1 which is localhost, 0.0.0.0 cannot be an IP etc).也就是说,为特定目的保留了特定的 IP(例如 127.0.0.1 是 localhost,0.0.0.0 不能是 IP 等)。

So your linq query would be所以你的 linq 查询将是

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

where iList is your initial list MIN is your min value for your range MAX is your max value for your range其中 iList 是您的初始列表 MIN 是您的范围的最小值 MAX 是您的范围的最大值

Could you figure out the subnet mask from your IP range?你能从你的 IP 范围中找出子网掩码吗?

If so then maybe you could use this IsInSameSubnet method..如果是这样,那么也许你可以使用这个IsInSameSubnet方法..

I want to +1 BuddhiP's answer above which recommends the IPAddressRange package from NuGet: https://www.nuget.org/packages/IPAddressRange/我想 +1 BuddhiP 的回答,上面推荐 NuGet 的 IPAddressRange 包: https ://www.nuget.org/packages/IPAddressRange/

But because code formatting is hard in a comment I'll just add a practical code example here on how to use IPAddressRange.但是因为代码格式在注释中很难,我将在这里添加一个关于如何使用 IPAddressRange 的实用代码示例。

CheckIPWhitelist reads a setting called IPWhitelist and assumes a semi-colon delimited list of IP ranges (such as "192.168.10.10-20;192.168.125.1-150;192.168.123.1-150") that IPAddressRange can parse. CheckIPWhitelist 读取名为 IPWhitelist 的设置,并假定 IPAddressRange 可以解析的 IP 范围(例如“192.168.10.10-20;192.168.125.1-150;192.168.123.1-150”)的分号分隔列表。 The function iterates the ranges and will and return true if present, false if not found.该函数迭代范围和意志,如果存在则返回 true,如果未找到则返回 false。

This function is VB.NET and assumes some ASP.NET dependencies are present (such as the System.Web.HttpRequest namespace)此函数是 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

You can remove dot at the middle of them and convert all IP to long at first, Then check them in an if :您可以删除它们中间的点并首先将所有 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!");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM