Javascript 通过IPv6地址进行二进制搜索?

Javascript 通过IPv6地址进行二进制搜索?,javascript,node.js,ipv6,Javascript,Node.js,Ipv6,一年前,我必须在IPv4地址范围内实施二进制搜索,以作为优化的HTTP请求过滤器,以应对可能的DOS攻击 今天,我需要重新实现这一点来使用IPv6,但由于在如何转换和比较地址方面存在许多差异,这似乎是一个相当大的挑战。我试图找到一个现有的解决方案,但运气不好。充其量,我可以找到简单的IPv6实用程序来解析地址并进行非常基本的操作,而无需为优化搜索做太多准备。例如,此库: 我以前的解决方案中的关键方法是使用以下转换依赖于地址的整数表示: function intFromIPv4(ip){

一年前,我必须在IPv4地址范围内实施二进制搜索,以作为优化的HTTP请求过滤器,以应对可能的DOS攻击

今天,我需要重新实现这一点来使用IPv6,但由于在如何转换和比较地址方面存在许多差异,这似乎是一个相当大的挑战。我试图找到一个现有的解决方案,但运气不好。充其量,我可以找到简单的IPv6实用程序来解析地址并进行非常基本的操作,而无需为优化搜索做太多准备。例如,此库:

我以前的解决方案中的关键方法是使用以下转换依赖于地址的整数表示:

function intFromIPv4(ip){
    var octets = ip.split(".");
     return octets[0] * 16777216 + octets[1] * 65536 + octets[2] * 256 + octets[3] * 1;
}
然后我可以合并/对齐IP范围,这样就可以进行简单的二进制搜索

这是我写的课程,就是为了做到这一点:

function IPv4Checker() {

    this.ipList = [];

    // takes array of [{f,l}] integers and returns its merged-range version as [{first, last}];
    // works only if:
    // a) the array is ordered by 'f' in ascending order.
    // b) 'f' is always defined, while 'l' is either undefined or not less than 'f'.
    this.mergeRanges = function (data) {
        var ips = [];
        if (data.length > 0) {
            var start = data[0].f;
            var end = data[0].l || start;
            for (var i = 1; i < data.length; i++) {
                if (data[i].f > end + 1) {
                    var d = {first: start};
                    if (end > start) {
                        d.last = end;
                    }
                    ips.push(d);
                    start = data[i].f;
                }
                var v = data[i].l || data[i].f;
                end = v > end ? v : end;
            }
            var d = {first: start};
            if (end > start) {
                d.last = end;
            }
            ips.push(d);
        }
        return ips;
    };

    // Calculates IP address against the current list,
    // using binary / logarithmic search algorithm.
    // It relies on the list of IP-s that is ordered by
    // 'first' in ascending order, and then with all the
    // range overlaps merged.
    this.isValid = function (ip) {
        if (ip === '127.0.0.1') {
            return true; // no checks for the local IP;
        }
        var addr = intFromIPv4(ip);
        var low = 0;
        var high = this.ipList.length - 1;
        var mid;
        while (low <= high) {
            mid = Math.round((low + high) / 2);
            var a = this.ipList[mid];
            if (addr > a.first) {
                if (a.last && addr <= a.last) {
                    return true;
                }
                low = mid + 1;
            } else {
                if (addr < a.first) {
                    high = mid - 1;
                } else {
                    return true;
                }
            }
        }
        return false;
    };
}
函数IPv4Checker(){
this.ipList=[];
//获取[{f,l}]整数数组,并将其合并范围版本返回为[{first,last}];
//仅在以下情况下有效:
//a)数组由“f”按升序排列。
//b)“f”始终是定义的,而“l”要么是未定义的,要么不小于“f”。
this.mergeRanges=函数(数据){
var-ips=[];
如果(data.length>0){
var start=data[0].f;
var end=数据[0]。l | | start;
对于(变量i=1;iend+1){
var d={first:start};
如果(结束>开始){
d、 最后=结束;
}
ips.push(d);
开始=数据[i].f;
}
var v=数据[i].l | |数据[i].f;
结束=v>结束?v:结束;
}
var d={first:start};
如果(结束>开始){
d、 最后=结束;
}
ips.push(d);
}
返回IP;
};
//根据当前列表计算IP地址,
//使用二进制/对数搜索算法。
//它依赖于由订购的IP-s列表
//“首先”按升序排列,然后按所有
//范围重叠合并。
this.isValid=函数(ip){
如果(ip=='127.0.0.1'){
返回true;//不检查本地IP;
}
var addr=intFromIPv4(ip);
var-low=0;
var high=this.ipList.length-1;
var-mid;
while(低a.first){

如果(a.last&&addr因为您可以将任何IPv6地址表示为128位数字,那么您的问题将归结为对128位数字执行二进制搜索

现在JS不具备本地处理128位数字的能力。因此,您可以使用BigInteger JS库;例如,一个快速的谷歌搜索


但是,这对您的应用程序来说可能有些过分。您可以简单地将数字表示为四个32位数字的元组。对于二进制搜索算法,您只需要实现一个函数来比较以这种格式编写的两个数字。这可以通过简单的字典比较来完成。

如果范围不相交,则y您可以存储(索引)某个范围的第一个IP地址,并搜索“小于给定值的最大地址”不是IPv6地址,而是128位数字(与IPv4中的32位数字相反)?为什么你不能简单地通过使用更大的数据类型来扩展你的IPv4算法?@cfh,你认为在JavaScript中使用128位整数是可行的吗?另外,即使是这样,IPv6中定义范围的方式与IPv4中定义范围的方式也大不相同,我甚至不知道如何正确地进行转换。我重新发布了这个问题:这不是简单的不要考虑IPv6地址范围呈现的复杂性以及如何正确地转换成相应的128位整数。它不像IPv4那么微不足道。@ VITALY-T可以将它表示为4个32位整数的四倍并比较它们。一个数字的长度不会改变任何东西。@ VITAYAL-T从一开始就不明显了。这就是您的问题所在。对任何类型的数据(128位或32位)执行二进制搜索应该没有区别。对32位或128位整数数组进行搜索实际上没有区别。@vitaly-t这就是您需要提供更多详细信息的地方。范围可以是CIDR表示法,也可以是不需要的数学(但很少有位运算)或者它是一个
(int,int)
tuple,然后就不清楚它的大小为什么重要了。@vitaly-t在IPv6中,八位字节的最大值是255。但这并不意味着
2001:500:3::42
是无效的IPv6地址。大于255的数字可以使用多个八位字节写入。如果您想支持rt所有有效格式这两种协议都需要做大量的工作。如果您只需要解析由您知道如何工作的特定代码段呈现的地址,那么它会简单得多。但无论哪种情况,使用标准库函数都比使用自己的库函数要好。