如果我们让用户输入几个IP范围,例如172.16.11.5-100,我该如何编写一个函数来检查IP(172.16.11.50)是否在该范围内?
.NET中是否有任何现有库可利用?
如果我们让用户输入几个IP范围,例如172.16.11.5-100,我该如何编写一个函数来检查IP(172.16.11.50)是否在该范围内?
.NET中是否有任何现有库可利用?
Answers:
框架中没有内置任何东西,但是创建一个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)
&=
确保一旦为假,它就保持为假。如果是的话=
,它可能会true
再次变成。
您可能要考虑使用@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.
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
UInt32
而不是long
或Int32
吗?这不会在任何桥接或高于128.0.0.0的地址范围上失败吗?
最好是将这些地址转换为整数,然后执行比较。
这里的示例: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[]
。
IPAddress
该类支持的IPv6地址。
我以前在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掩码的验证。在生产环境中使用之前,应先修复此问题。
从这里重新发布我的答案
前一段时间,我必须找到给定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上面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