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?
Is there any existing library in .NET to leverage?
There's nothing built into the framework, but it wouldn't take much effort to create an IPAddressRange
class.
You'd compare the ranges by calling IPAddress.GetAddressBytes on 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.
This method works for both IPv4 and IPv6 addresses.
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)
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. This library supports both IPv4 and IPv6.
https://github.com/jsakamoto/ipaddressrange
It can also be installed via 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
The best is to convert these addresses to an integer and then perform comparisons.
Example from here: IP to Integer
To convert an IP address to integer, break it into four octets. For example, the ip address you provided can be broken into:
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. Have a look at this question: Formatting IPv6 as an int in C# and storing it in SQL Server
The simplest route is to get the framework to do this for you. Use
IPAddress.Parse
to parse the address, thenIPAddress.GetAddressBytes
to get the "number" asbyte[]
.
I used this code on codeproject before, which may be of use to you.
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. 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.
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.
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
.
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).
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).
So your linq query would be
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
Could you figure out the subnet mask from your IP range?
If so then maybe you could use this IsInSameSubnet method..
I want to +1 BuddhiP's answer above which recommends the IPAddressRange package from NuGet: 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.
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.
This function is VB.NET and assumes some ASP.NET dependencies are present (such as the System.Web.HttpRequest namespace)
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 :
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!");
}
精彩评论