2009-02-02 19 views
14

Vì vậy, tôi có ~ 12600 mạng con:JavaScript: IP có thuộc một trong các mạng con này không?

ví dụ: 123.123.208.0/20

và IP.

tôi có thể sử dụng một cơ sở dữ liệu SQLite hoặc một mảng hoặc bất cứ điều gì

Có một câu hỏi tương tự được hỏi về cách đây một tháng, tuy nhiên tôi không tìm kiếm kiểm tra một IP đối với một subnet nhưng một loạt các mạng con (rõ ràng cách hiệu quả nhất, hy vọng không phải O (tổng số mạng con))

Làm thế nào tôi có thể kiểm tra IP là một trong những mạng con này, tôi cần đúng hay sai chứ không phải mạng con nếu giúp tối ưu hóa.

Có mạng con tương tự trong danh sách như hiện nay .: (thực tế chiết xuất)

123.123.48.0/22 <-- not a typo 
123.123.48.0/24 <-- not a typo 
123.123.90.0/24 
123.123.91.0/24 
123.123.217.0/24 

Trong tổng số họ dao động từ 4.xyz để 222.xyz

Trả lời

2

Chuyển đổi ip thấp hơn và phía trên ip trong phạm vi đến số nguyên và lưu trữ phạm vi trong db sau đó đảm bảo cả hai cột được lập chỉ mục.

Off đỉnh đầu của tôi (pseudo code):

function ipmap(w,x,y,z) { 
    return 16777216*w + 65536*x + 256*y + z; 
} 

var masks = array[ipmap(128,0,0,0), ipmap(196,0,0,0), ..., ipmap(255,255,255,255)] 

function lowrange(w, x, y, z, rangelength) { 
    return ipmap(w, x, y, z) & masks[rangelength] 
} 

function hirange(w, x, y, z, rangelength) { 
    return lowrange(w, x, y, z, ,rangelength) + ipmap(255,255,255,255) - masks[rangelength]; 
} 

Đó phải làm điều đó.

Để tìm xem một ip nói riêng rơi vào bất kỳ phạm vi, chuyển nó sang một số nguyên và làm:

SELECT COUNT(*) FROM ipranges WHERE lowrange <= 1234567 AND 1234567 <= highrange 

Các truy vấn tối ưu sẽ có thể tăng tốc độ này lên rất nhiều.

+0

Cảm ơn bạn đã trả lời, làm thế nào tôi có thể chuyển đổi mạng con thành một phạm vi sử dụng JavaScript? Còn về: 123.123.48.0/22 ​​ 123.123.48.0/24 Chúng trùng nhau. – Steve

+0

Ips bắt đầu và kết thúc của phạm vi sẽ khác nhau. do đó, sự chồng chéo không phải là một vấn đề. –

+0

Không phải: 123.123.48.0/22: 123.123.48.1 - 123.123.51.254 & 123.123.48.0/24: 123.123.48.1 - 123.123.48.254 – Steve

20

Cách tiếp cận tốt nhất là IMO sử dụng các toán tử bitwise. Ví dụ: 123.123.48.0/22 đại diện cho (123<<24)+(123<<16)+(48<<8)+0 (= 2071670784; đây có thể là số âm) dưới dạng địa chỉ IP số 32 bit và -1<<(32-22) = -1024 làm mặt nạ. Với điều này, và tương tự, địa chỉ kiểm tra IP của bạn chuyển đổi thành số, bạn có thể làm:

(inputIP & testMask) == testIP 

Ví dụ, 123.123.49.123 là trong phạm vi đó, như 2071671163 & -1024 là 2071670784

Vì vậy, đây là một số chức năng công cụ:

function IPnumber(IPaddress) { 
    var ip = IPaddress.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); 
    if(ip) { 
     return (+ip[1]<<24) + (+ip[2]<<16) + (+ip[3]<<8) + (+ip[4]); 
    } 
    // else ... ? 
    return null; 
} 

function IPmask(maskSize) { 
    return -1<<(32-maskSize) 
} 

kiểm tra:

(IPnumber('123.123.49.123') & IPmask('22')) == IPnumber('123.123.48.0') 

mang true.

Trong trường hợp mặt nạ của bạn ở định dạng '255.255.252.0', thì bạn cũng có thể sử dụng chức năng IPnumber cho mặt nạ.

+0

Tôi thích việc bạn sử dụng các toán tử bitwise, nhưng JavaScript có đảm bảo mã hóa Ấn Độ của bạn không? Tôi đã phá vỡ phạm vi ip thành thấp và cao để cho phép hành vi O (logN) khi các cột được lập chỉ mục như trái ngược với O (N) bằng cách sử dụng phương pháp này. Nhưng nó có thể phụ thuộc vào việc thực hiện sqlite. Không chắc. –

+0

"đảm bảo mã hóa cuối cùng"? Tôi không hiểu tại sao nó phải thế. Nó chỉ là số. Dù sao, bạn thực sự có thể tìm thấy cả hai giới hạn trên và dưới của phạm vi với IP & mask và với IP | ~ mask (~ -1024 == 1023) tương ứng, vì vậy bạn có thể sử dụng GIỮA để tìm kiếm các kết quả phù hợp cho phạm vi. – bart

+0

@bart Tôi chỉ nhập IP và mặt nạ, tôi muốn kiểm tra xem IP đầu vào nằm trong phạm vi mặt nạ hay không (mặt nạ ở định dạng 255.255.252.0) Làm cách nào để kiểm tra? – Sagar

6

Hãy thử điều này:

var ip2long = function(ip){ 
    var components; 

    if(components = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) 
    { 
     var iplong = 0; 
     var power = 1; 
     for(var i=4; i>=1; i-=1) 
     { 
      iplong += power * parseInt(components[i]); 
      power *= 256; 
     } 
     return iplong; 
    } 
    else return -1; 
}; 

var inSubNet = function(ip, subnet) 
{ 
    var mask, base_ip, long_ip = ip2long(ip); 
    if((mask = subnet.match(/^(.*?)\/(\d{1,2})$/)) && ((base_ip=ip2long(mask[1])) >= 0)) 
    { 
     var freedom = Math.pow(2, 32 - parseInt(mask[2])); 
     return (long_ip > base_ip) && (long_ip < base_ip + freedom - 1); 
    } 
    else return false; 
}; 

Cách sử dụng:

inSubNet('192.30.252.63', '192.30.252.0/22') => true 
inSubNet('192.31.252.63', '192.30.252.0/22') => false 
+0

Nhưng mã của bạn không bao gồm IP đầu tiên và IP cuối cùng. Tôi đã thêm một lần kiểm tra nữa và hiện tại nó có 'return (long_ip> base_ip || long_ip === base_ip) && ((long_ip

2

tôi quản lý để giải quyết việc này bằng cách sử dụng các mô-đun node netmask. Bạn có thể kiểm tra nếu một IP thuộc về một subnet bằng cách làm một cái gì đó như thế này:

import { Netmask } from 'netmask' 

const block = new Netmask('123.123.208.0/20') 
const ip = '123.123.208.0' 
console.log(block.contains(ip)) 

sẽ ở đây in true.

Bạn có thể cài đặt nó bằng cách sử dụng:

npm i --save netmask 
1

Chức năng IPnumberIPmask là tốt đẹp, tuy nhiên tôi thà kiểm tra như:

(IPnumber('123.123.49.123') & IPmask('22')) == (IPnumber('123.123.48.0') & IPmask('22')) 

Bởi vì đối với mỗi địa chỉ, bạn chỉ cần đưa vào chiếm phần mạng của địa chỉ. Do đó, việc thực hiện IPmask('22') sẽ không làm mất phần máy tính của địa chỉ và bạn cũng nên làm như vậy với địa chỉ mạng.

Các vấn đề liên quan