我有以下实现来将一堆ips解析为多个范围的cidrs。我被最多50个cidrs限制。我需要以某种方式添加该限制。我正在考虑计算每个cidr之间的距离以将它们分组,直到我在一种递归算法中达到50限制。
有什么建议吗?
public static IEnumerable<string> Parse(IEnumerable<string> ipCollection)
{
var ips = ipCollection as IList<string> ?? ipCollection.ToList();
if (!ips.Any()) return Enumerable.Empty<string>();
var parsedIps = new List<IPNetwork>();
foreach (var ip in ips)
{
IPNetwork ipNetwork;
if (IPNetwork.TryParse(ip, out ipNetwork)) parsedIps.Add(ipNetwork);
}
// unable to parse any ips
if (!parsedIps.Any()) return Enumerable.Empty<string>();
return parsedIps.Count == 1
? ips.Select(ip => $"{ip}/32")
: IPNetwork.Supernet(parsedIps.ToArray()).Select(x => x.ToString());
}
答案 0 :(得分:0)
我找到了一种更好的方法来生成我的cidrs。我使用的方法是提供ips的前两个八位字节,这主要是因为提供者总是有这些ips的范围。
public static IEnumerable<string> Parse(IEnumerable<string> ipCollection)
{
var parsedIpAddresses = new List<IPAddress>();
ipCollection.ForEach(ip =>
{
IPAddress validIp;
if (IPAddress.TryParse(ip, out validIp)) parsedIpAddresses.Add(validIp);
});
return SplitCidrs(parsedIpAddresses);
}
private static IEnumerable<string> SplitCidrs(List<IPAddress> ips)
{
var cidrs = new List<IPNetwork>();
foreach (var mask in GetOrderedMasks(ips))
{
var filterIps = ips.Where(
x => x.ToString().StartsWith(mask)
)
.OrderBy(x => x.Address)
.Select(x => x.ToString())
.ToList();
var newCidr = IPNetwork.WideSubnet(filterIps.First(), filterIps.Last());
if (!cidrs.Contains(newCidr))
{
cidrs.Add(newCidr);
}
if (cidrs.Count >= AwsSgLimit - 1)
{
throw new AmazonSgLimitReached();
}
}
return cidrs.Select(x => x.ToString());
}
private static IEnumerable<string> GetOrderedMasks(IEnumerable<IPAddress> ips)
{
return ips
.Where(x => !x.ToString().StartsWith("10."))
.GroupBy(
x => string.Join(".", x.GetAddressBytes().Take(2))
)
.OrderByDescending(x => x.Count())
.Select(group => group.Key.ToString() + ".");
}
在下面的算法中,我使用了一种完全不同的方法,我使用不同的IP群体进行了测试。在其中一个测试中,我传入函数55不一致的ips(记住我的限制是50个cidrs),使用上面的原始代码最终返回非常宽的cidrs(/ 8,/ 16)。使用新算法,我只得到/ 32,这是100%优化更新。我知道有5个被浪费了,但这种情况在互联网提供商子网环境下并不真实。
在第二次测试中,我再次传递了真实的生产数据。结果非常好,因为我摆脱了所有的“/ 7”和九个“/ 8”( 161百万ips )现在我只得一个“/ 16”( 65k ips )作为最差的cidr。考虑到这是真实的数据,这也是一个巨大的改进,我基本上得到了相同的结果。
其余的是实际范围,但仍然很小(21,24,28)和孤儿ips(32)。仍然有待改进,因为我们没有达到50个28个空闲插槽的AWS限制。
我绝对建议使用此算法根据特定提供商分配的ips生成cidrs,因为这些提供商通常会在特定范围内移动。