C# 如何使用CIDR表示法查看IP地址是否属于IP范围内?

C# 如何使用CIDR表示法查看IP地址是否属于IP范围内?,c#,ip,cidr,C#,Ip,Cidr,这里我有一个静态参考,需要检查范围: private static List<string> Ip_Range = new List<string>() { "12.144.86.0/23", "31.201.1.176/30", "46.36.198.101/32", "46.36.198.102/31", "46.36.198.104/31", "46.136.172.0/24", "63.65.11.0/24"

这里我有一个静态参考,需要检查范围:

private static List<string> Ip_Range = new List<string>()
{
    "12.144.86.0/23",
    "31.201.1.176/30",
    "46.36.198.101/32",
    "46.36.198.102/31",
    "46.36.198.104/31",
    "46.136.172.0/24",
    "63.65.11.0/24",
    "63.65.12.0/25",
    "63.65.12.128/26",
    "63.65.12.192/27",
    "63.65.12.224/28",
    "63.65.12.240/29",
    "63.65.12.248/30",
    "63.65.12.252/31",
    "63.65.12.254/32",
    "65.173.56.0/21",
    "67.23.241.179/32",
    "67.23.241.180/30",
    "67.23.241.184/29",
    "67.23.241.192/30",
    "67.23.241.196/31",
    "67.23.241.198/32",
    "72.32.164.56/29",
    "72.46.244.32/28",
    "74.91.16.48/29",
    "74.91.16.208/29",
    "74.91.20.48/28",
    "74.91.20.64/29",
    "74.112.134.120/29",
    "74.112.135.104/29",
    "74.205.37.16/29",
    "78.24.205.32/28",
    "98.129.27.88/29",
    "98.129.91.40/29",
    "166.114.0.0/16",
    "167.157.0.0/16",
    "174.143.165.80/29",
    "186.0.156.0/22",
    "186.2.0.0/17",
    "186.27.0.0/17",
    "190.0.248.0/21",
    "190.3.184.0/21"
};

关于如何编写此功能的任何建议?

如果您理解CIDR符号,您可以轻松地在解析方法中进行计算

您基本上知道IPv4地址的长度为32位,CIDR表示法意味着“/”后面的位数是网络地址位数(即屏蔽位),因此剩余位数表示子网中的主机数

来自维基百科:

由掩码或前缀定义的子网的地址数可以是 计算为2地址大小-前缀大小,其中地址 IPv6的大小为128,IPv4的大小为32。例如,在IPv4中,前缀 /29的大小给出:232-29=23=8个地址


因此,您可以(不,我不打算为您计算细节)将您的地址转换为二进制,并使用给定的掩码(也是二进制形式)执行二进制和,然后您就剩下了IP地址的网络地址部分,它应该与您要检查的任何地址相匹配,以查看它是否在特定子网中。

幸运的是,大部分工作已经为您完成(因此我们不必这样做)。看看这个项目。您将使用
IPNetwork.parse
解析所有CIDR地址。然后,要查看特定的
IPAddress
是否在范围内,只需使用
IPNetwork.Contains
方法即可


我觉得很无聊,所以这里有一种方法可以用来测试IP地址是否在范围内:

private Dictionary<string, IPNetwork> netCache = null;
public bool IsInRange(string ipAddress)
{
    if (netCache == null)
        netCache = Ip_Range.ToDictionary((keyItem) => keyItem, (valueItem) => IPNetwork.Parse(valueItem));

    return netCache.Values.Any(net => IPNetwork.Contains(net, IPAddress.Parse(ipAddress)));
}
测试输出:

12.144.86.1: True
10.254.6.172: False

当然,仍然有很多事情可以(也可能应该)用它来完成,但这证明了这个概念。

对于start,您应该使用它:

IPNetwork ipnetwork = IPNetwork.Parse("192.168.168.100/29");
Console.WriteLine("CIDR: {0}", ipnetwork.Cidr);
输出

CIDR: 29

决定回答我自己的问题,让人们受益。如果可以改进,请做

我用了这个方法,结果非常棒!下面是我使用的代码:

using System.Net;

public static class RedirectHelpers
{
    public static bool IpIsWithinBoliviaRange(string ip)
    {
        IPAddress incomingIp = IPAddress.Parse(ip);
        foreach (var subnet in Bolivia_Ip_Range)
        {
            IPNetwork network = IPNetwork.Parse(subnet);

            if (IPNetwork.Contains(network, incomingIp))
                return true;
        }
        return false;
    }

    private static List<string> Bolivia_Ip_Range = new List<string>()
    {
        "12.144.86.0/23",
        "31.201.1.176/30",
        "46.36.198.101/32",
        "46.36.198.102/31",
        "46.36.198.104/31",
        "46.136.172.0/24",
        "63.65.11.0/24",
        "63.65.12.0/25",
        "63.65.12.128/26",
        "63.65.12.192/27",
        "63.65.12.224/28",
        "63.65.12.240/29",
        "63.65.12.248/30",
        "63.65.12.252/31",
        "63.65.12.254/32",
        "65.173.56.0/21",
        "67.23.241.179/32",
        "67.23.241.180/30",
        "67.23.241.184/29",
        "67.23.241.192/30",
        "67.23.241.196/31",
        "67.23.241.198/32",
        "72.32.164.56/29",
        "72.46.244.32/28",
        "74.91.16.48/29",
        "74.91.16.208/29",
        "74.91.20.48/28",
        "74.91.20.64/29",
        "74.112.134.120/29",
        "74.112.135.104/29",
        "74.205.37.16/29",
        "78.24.205.32/28",
        "98.129.27.88/29",
        "98.129.91.40/29",
        "166.114.0.0/16",
        "167.157.0.0/16",
        "174.143.165.80/29",
        "186.0.156.0/22",
        "186.2.0.0/17",
        "186.27.0.0/17",
        "190.0.248.0/21",
        "190.3.184.0/21",
        "166.114.0.0/16",
        "167.157.0.0/16",
        "186.2.0.0/18",
        "190.11.64.0/20",
        "190.11.80.0/20",
        "190.103.64.0/20",
        "190.104.0.0/19",
        "190.107.32.0/20",
        "190.129.0.0/17",
        "190.181.0.0/18",
        "190.186.0.0/18",
        "190.186.64.0/18",
        "190.186.128.0/18",
        "200.7.160.0/20",
        "200.58.64.0/20",
        "200.58.80.0/20",
        "200.58.160.0/20",
        "200.58.176.0/20",
        "200.75.160.0/20",
        "200.85.128.0/20",
        "200.87.0.0/17",
        "200.87.128.0/17",
        "200.105.128.0/19",
        "200.105.160.0/19",
        "200.105.192.0/19",
        "200.112.192.0/20",
        "200.119.192.0/20",
        "200.119.208.0/20",
        "201.222.64.0/19",
        "201.222.96.0/19"
    };
}
使用System.Net;
公共静态类重定向帮助程序
{
公共静态布尔IPISWITHINBRIVIARANGE(字符串ip)
{
IPAddress incomingIp=IPAddress.Parse(ip);
foreach(玻利维亚Ip范围内的var子网)
{
IPNetwork=IPNetwork.Parse(子网);
if(IPNetwork.Contains(network,incomingIp))
返回true;
}
返回false;
}
私有静态列表玻利维亚_Ip_范围=新列表()
{
"12.144.86.0/23",
"31.201.1.176/30",
"46.36.198.101/32",
"46.36.198.102/31",
"46.36.198.104/31",
"46.136.172.0/24",
"63.65.11.0/24",
"63.65.12.0/25",
"63.65.12.128/26",
"63.65.12.192/27",
"63.65.12.224/28",
"63.65.12.240/29",
"63.65.12.248/30",
"63.65.12.252/31",
"63.65.12.254/32",
"65.173.56.0/21",
"67.23.241.179/32",
"67.23.241.180/30",
"67.23.241.184/29",
"67.23.241.192/30",
"67.23.241.196/31",
"67.23.241.198/32",
"72.32.164.56/29",
"72.46.244.32/28",
"74.91.16.48/29",
"74.91.16.208/29",
"74.91.20.48/28",
"74.91.20.64/29",
"74.112.134.120/29",
"74.112.135.104/29",
"74.205.37.16/29",
"78.24.205.32/28",
"98.129.27.88/29",
"98.129.91.40/29",
"166.114.0.0/16",
"167.157.0.0/16",
"174.143.165.80/29",
"186.0.156.0/22",
"186.2.0.0/17",
"186.27.0.0/17",
"190.0.248.0/21",
"190.3.184.0/21",
"166.114.0.0/16",
"167.157.0.0/16",
"186.2.0.0/18",
"190.11.64.0/20",
"190.11.80.0/20",
"190.103.64.0/20",
"190.104.0.0/19",
"190.107.32.0/20",
"190.129.0.0/17",
"190.181.0.0/18",
"190.186.0.0/18",
"190.186.64.0/18",
"190.186.128.0/18",
"200.7.160.0/20",
"200.58.64.0/20",
"200.58.80.0/20",
"200.58.160.0/20",
"200.58.176.0/20",
"200.75.160.0/20",
"200.85.128.0/20",
"200.87.0.0/17",
"200.87.128.0/17",
"200.105.128.0/19",
"200.105.160.0/19",
"200.105.192.0/19",
"200.112.192.0/20",
"200.119.192.0/20",
"200.119.208.0/20",
"201.222.64.0/19",
"201.222.96.0/19"
};
}

如果您不想/无法将另一个库(如IPnetwork库)添加到您的项目中,并且只需要处理IPv4 CIDR范围,这里有一个快速解决方案

// true if ipAddress falls inside the CIDR range, example
// bool result = IsInRange("10.50.30.7", "10.0.0.0/8");
private bool IsInRange(string ipAddress, string CIDRmask)
{
    string[] parts = CIDRmask.Split('/');

    int IP_addr = BitConverter.ToInt32(IPAddress.Parse(parts[0]).GetAddressBytes(), 0);
    int CIDR_addr = BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0);
    int CIDR_mask = IPAddress.HostToNetworkOrder(-1 << (32 - int.Parse(parts[1])));

    return ((IP_addr & CIDR_mask) == (CIDR_addr & CIDR_mask));
}
//如果ipAddress在CIDR范围内,则为true,例如
//布尔结果=IsInRange(“10.50.30.7”、“10.0.0.0/8”);
私有布尔IsInRange(字符串ipAddress、字符串CIDRmask)
{
string[]parts=CIDRmask.Split('/');
int IP_addr=BitConverter.ToInt32(IPAddress.Parse(parts[0]).GetAddressBytes(),0);
int CIDR_addr=BitConverter.ToInt32(IPAddress.Parse(IPAddress.GetAddressBytes(),0);

int CIDR_mask=IPAddress.HostToNetworkOrder(-1I使用以下方法确定给定IP地址是公共地址还是私有/内部地址:

private bool IsInternalIpAddress(string ipAddress)
    {
        // notes: http://whatismyipaddress.com/private-ip

        var internalIpRanges = Enumerable
            .Range(16, 31)
            .Select(i => "172.{0}.".FormatWith(i))
            .Concat(new[] {"192.168.", "10.", "127."})
            .ToArray();

        return ipAddress.StartsWith(internalIpRanges);
    }
publicstaticboolipsinRange(字符串子网,字符串ip)
{
var splitSubnet=subnet.Split('/');
var maskBits=32-int.Parse(splitSubnet[1]);
if(maskBits==32)
{
返回true;
}

var subnetIp=BitConverter.ToInt32(IPAddress.Parse(splitSubnet[0]).GetAddressBytes().Reverse().ToArray(),0)>>maskBits>maskBits你是在要求我们完成这项工作吗?这个项目应该能够处理你要做的大部分工作。@Tony:朝着正确的方向轻推同样好。这就是这个网站的重点。:)我在Ruby中做过,但我不太熟悉如何在C#中完成。那么,你是如何在Ruby中解决这个问题的?你在翻译成C#?@m.Babcock IPNetwork项目时遇到了问题。我想
// true if ipAddress falls inside the CIDR range, example
// bool result = IsInRange("10.50.30.7", "10.0.0.0/8");
private bool IsInRange(string ipAddress, string CIDRmask)
{
    string[] parts = CIDRmask.Split('/');

    int IP_addr = BitConverter.ToInt32(IPAddress.Parse(parts[0]).GetAddressBytes(), 0);
    int CIDR_addr = BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0);
    int CIDR_mask = IPAddress.HostToNetworkOrder(-1 << (32 - int.Parse(parts[1])));

    return ((IP_addr & CIDR_mask) == (CIDR_addr & CIDR_mask));
}
private bool IsInternalIpAddress(string ipAddress)
    {
        // notes: http://whatismyipaddress.com/private-ip

        var internalIpRanges = Enumerable
            .Range(16, 31)
            .Select(i => "172.{0}.".FormatWith(i))
            .Concat(new[] {"192.168.", "10.", "127."})
            .ToArray();

        return ipAddress.StartsWith(internalIpRanges);
    }
    public static bool IpIsInRange(string subnet, string ip)
    {
        var splitSubnet = subnet.Split('/');
        var maskBits = 32 - int.Parse(splitSubnet[1]);
        if (maskBits == 32)
        {
            return true;
        }
        var subnetIp = BitConverter.ToInt32(IPAddress.Parse(splitSubnet[0]).GetAddressBytes().Reverse().ToArray(), 0) >> maskBits << maskBits;
        var clientIp = BitConverter.ToInt32(IPAddress.Parse(ip).GetAddressBytes().Reverse().ToArray(), 0) >> maskBits << maskBits;
        return subnetIp == clientIp;
    }