JavaScript: è IP in una di queste sottoreti?

Quindi ho ~ 12600 sottoreti:

per esempio. 123.123.208.0/20

e un IP.

Posso utilizzare un database SQLite o un arrays o qualsiasi altra cosa

C'era una domanda simile circa un mese fa, ma non sto cercando di controllare un IP contro una substring, ma un sacco di sottoreti (ovviamente il modo più efficiente, forse non O (sottoreti totali) 🙂

Come posso verificare che l'IP sia una di queste sottoreti, ho bisogno di vero o falso non la substring se aiuta l'ottimizzazione.

Esistono sottoreti simili nell'elenco corrente ad esempio: (estratto effettivo)

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 

In totale essi vanno da 4.xyz a 222.xyz

L'approccio migliore è l'IMO che utilizza operatori a bit. Ad esempio, 123.123.48.0/22 rappresenta (123<<24)+(123<<16)+(48<<8)+0 (= 2071670784; questo potrebbe essere un numero negativo) come un indirizzo IP numbersco a 32 bit, e -1<<(32-22) = -1024 come maschera. Con questo, e allo stesso modo, l'indirizzo IP di prova convertito in un numero, è ansible:

 (inputIP & testMask) == testIP 

Ad esempio, 123.123.49.123 è in tale intervallo, come 2071671163 & -1024 è 2071670784

Quindi, ecco alcune funzioni degli strumenti:

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

resa true .

Nel caso in cui la maschera sia nel formato '255.255.252.0', è ansible utilizzare anche la function IPnumber per la maschera.

Prova questo:

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

Uso:

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

Convertire il ip inferiore e il ip superiore nella gamma di interi e memorizzare l'intervallo nel db, quindi assicurarsi che entrambe le colonne siano indicizzate.

Fuori dalla testa (pseudo codice):

 function ipmap(w,x,y,z) { return 16777216*w + 65536*x + 256*y + z; } var masks = arrays[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]; } 

Quello whereva farlo.

Per verificare se un particolare IP cada in uno qualsiasi degli intervalli, convertirlo in un integer e fare:

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

L'ottimizzatore di query dovrebbe essere in grado di accelerare notevolmente questo.

Sono riuscito a risolvere questo problema utilizzando il nodo netmask module. È ansible verificare se un IP appartiene ad una substring facendo qualcosa di simile:

 import { Netmask } from 'netmask' const block = new Netmask('123.123.208.0/20') const ip = '123.123.208.0' console.log(block.contains(ip)) 

Verrà qui printingto true .

Puoi installarlo utilizzando:

 npm i --save netmask 

Funzioni IPnumber e IPmask sono belle, tuttavia preferirei testare come:

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

Poiché per each indirizzo, è sufficiente prendere in considerazione la parte di networking dell'indirizzo. Di conseguenza, l' IPmask('22') la parte del computer dell'indirizzo e devi fare altrettanto con l'indirizzo di networking.