2009-02-02 11 views
14

So habe ich ~ 12600 Subnetze:JavaScript: Ist IP in einem dieser Subnetze?

eg. 123.123.208.0/20

und ein IP.

kann ich eine SQLite-Datenbank oder ein Array verwenden, oder was auch immer

Es gab eine ähnliche Frage vor etwa einem Monat gefragt, aber ich suche nicht eine IP gegen ein Subnetz für die Überprüfung aber eine Reihe von Subnetzen (offensichtlich der am effizientesten Weg, hoffentlich nicht O (insgesamt Subnetze)) :)

Wie kann ich überprüfen, ob die IP-Adresse ist eines dieser Subnetze, ich brauche wahr oder falsch nicht das Subnetz, wenn das hilft die Optimierung.

Es gibt Ähnliche Subnetze in der aktuellen Liste zB .: (Ist-Extrakt)

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 

Insgesamt sie von 4.xyz reichen

Antwort

2

umrechnen untere ip und die oberen auf 222.xyz ip im Bereich zu Integer und speichern Sie den Bereich in der db dann stellen Sie sicher, dass beide Spalten indiziert sind.

Aus der Spitze von meinem Kopf (Pseudocode):

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]; 
} 

Das sollte es tun.

Um herauszufinden, ob eine bestimmte IP in einem der Bereiche fällt, wandelt es in eine ganze Zahl und zu tun:

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

Der Abfrageoptimierer sollte dies erheblich beschleunigen können.

+0

Vielen Dank für Ihre Antwort, wie kann ich ein Subnetz in einen Bereich mit JavaScript konvertieren? Und was ist mit: 123.123.48.0/22 ​​ 123.123.48.0/24 Sie überlappen. – Steve

+0

Die Start- und End-IPs des Bereichs unterscheiden sich. also sollte die Überlappung kein Problem sein. –

+0

Ist nicht: 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

Der beste Ansatz ist die Verwendung von bitweisen Operatoren durch IMO. Beispiel: 123.123.48.0/22 steht für (123<<24)+(123<<16)+(48<<8)+0 (= 2071670784; dies könnte eine negative Zahl sein) als numerische 32-Bit-IP-Adresse und -1<<(32-22) = -1024 als Maske. Damit und ebenso Adresse Ihre IP-Test in eine Zahl umgewandelt, können Sie tun:

(inputIP & testMask) == testIP 

Zum Beispiel ist 123.123.49.123 in diesem Bereich, wie 2071671163 & -1024 ist 2071670784

So, hier sind einige Werkzeugfunktionen:

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) 
} 

Test:

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

ergibt true.

Falls Ihre Maske das Format '255.255.252.0' hat, können Sie auch die IP-Funktion für die Maske verwenden.

+0

Ich mag Ihre Verwendung der bitweisen Operatoren, aber garantiert JavaScript Ihre indische Kodierung? Ich habe den IP-Bereich in Low und High aufgeteilt, um das O (logN) -Verhalten zu ermöglichen, wenn die Spalten indiziert werden, im Gegensatz zu O (N), wenn dieser Ansatz verwendet wird. Aber es kann von der Implementierung von SQLite abhängen. Nicht sicher. –

+0

"garantie endian codierung"? Ich verstehe nicht, warum es so ist. Es sind nur Zahlen. Wie dem auch sei, Sie können sowohl die untere als auch die obere Grenze des Bereichs mit IP & Maske und mit IP | ~ Maske (~ -1024 == 1023) finden, so dass Sie BETWEEN verwenden können, um nach Übereinstimmungen für den Bereich zu suchen. – bart

+0

@bart Ich habe nur IP und Maske eingegeben, ich möchte überprüfen, dass Eingabe-IP im Bereich der Maske liegt oder nicht (Maske im Format 255.255.252.0) Wie überprüft man das? – Sagar

6

Try this:

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; 
}; 

Verbrauch:

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

Aber Ihr Code nicht schließe die erste und die letzte IP ein. Ich habe eine weitere Überprüfung hinzugefügt und jetzt tut es 'zurück (long_ip> base_ip || long_ip === base_ip) && ((long_ip

2

ich es geschafft, dieses Problem zu lösen, indem die node netmask Modul. Sie können überprüfen, ob eine IP zu einem Subnetz gehört von so etwas wie dies zu machen:

import { Netmask } from 'netmask' 

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

Wird true hier Drücken.

Sie können es installieren, indem Sie mit:

npm i --save netmask 
1

Funktionen IPnumber und IPmask sind nett, aber ich würde eher wie testen:

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

Da für jede Adresse, die Sie brauchen nur in nehmen Konto den Netzwerkteil der Adresse. Daher macht IPmask('22') den Computer Teil der Adresse aus, und Sie sollten das gleiche mit der Netzwerkadresse tun.