C# 如何检查输入 IP 在特定 IP 范围内

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2138706/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 23:49:32  来源:igfitidea点击:

How to check a input IP fall in a specific IP range

c#asp.net

提问by Ricky

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

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

Is there any existing library in .NET to leverage?

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

采纳答案by Richard Szalay

There's nothing built into the framework, but it wouldn't take much effort to create an IPAddressRangeclass.

框架中没有内置任何东西,但创建一个IPAddressRange类不需要太多努力。

You'd compare the ranges by calling IPAddress.GetAddressByteson the lower address, upper address and comparison address. Starting at the first byte, check if the comparison address is in the range of the upper/lower address.

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

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)

回答by Ricky

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. For example, the ip address you provided can be broken into:

要将 IP 地址转换为整数,请将其分成四个八位字节。比如你提供的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 * 2563) + (second octet * 2562) + (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. Have a look at this question: Formatting IPv6 as an int in C# and storing it in SQL Server

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

The simplest route is to get the framework to do this for you. Use IPAddress.Parseto parse the address, then IPAddress.GetAddressBytesto get the "number" as byte[].

最简单的方法是让框架为你做这件事。使用 IPAddress.Parse解析地址,然后IPAddress.GetAddressBytes获得“数字”作为byte[]

回答by Ian

Could you figure out the subnet maskfrom your IP range?

你能从你的 IP 范围中找出子网掩码吗?

If so then maybe you could use this IsInSameSubnetmethod..

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

回答by Aim Kai

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 IPLista range of IP numbers defined by a From IP and a To IP number. The method breaks up the range into standard IP ranges and finds their masks. 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.

您可以添加到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,您将有可能对此进行检查。

Disclaimer: The Class is only tested with simple data sets, and the Class lacks validation of the IP numbers and IP masks provided. This should be fixed before it is used in production environments.

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

回答by ram

reposting my answer from here

这里重新发布我的答案

A while ago, I had to find the location of a given IP. We got the IP from the request. There are free databases which gave us this mapping. In IPv4, when we say the IP as "a.b.c.d" it is essentially a * (256^3) + b * (256^2) + c * (256) + d.

不久前,我必须找到给定 IP 的位置。我们从请求中获得了 IP。有免费的数据库为我们提供了这种映射。在 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) 之间的 IP ) (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 是本地主机,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 是您的范围的最大值

回答by artwl

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

回答by BuddhiP

You might want to consider this library by @jsakamoto, which allows you to parse range of IP address string 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 conatins check. This library supports both IPv4 and IPv6.

您可能需要考虑@jsakamoto 的这个库,它允许您解析 IP 地址字符串的范围,例如“192.168.0.0/24”和“192.168.0.0/255.255.255.0”和“192.168.0.0-192.168.0.255” , 并且可以进行 conatins 检查。该库支持 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.

回答by Jeff Mergler

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. The function iterates the ranges and will and return true if present, false if not found.

CheckIPWhitelist 读取名为 IPWhitelist 的设置,并假定 IPAddressRange 可以解析的 IP 范围列表(例如“192.168.10.10-20;192.168.125.1-150;192.168.123.1-150”)以分号分隔。该函数对范围进行迭代,如果存在则返回 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