JS: futoin-ipset

In absence of anything else up-to-date, pure JS and decent for efficient processing of large IP set matching with associative value outcome.

Key features:

  • IPv4 and IPv6 support on top of ip-address module.
  • Efficient prefix matching relying on JS Map implementation performance.
  • Dynamic ipset manipulation.
  • Associate any value for classification of match

Examples

const { IPSet, Address4, Address6 } = require( 'futoin-ipset' );

// universal IPv4/IPv6 set
const ipset = new IPSet();

const Region2 = {}; // any ref can be associated

// cheap operations
ipset.add( '1.2.2.0/23', 'Region 1' );
ipset.add( new Address4('2.3.4.0/24'), Region2 ); // instance of ip-address.Address4 can be also passed
ipset.add( 'abcd::/48', 'Region 1' );
ipset.add( new Address6('bcda::/56'), Region2 ); // ... or instance of ip-address.Address6
ipset.add( '2.3.4.5/32', 'blacklist' );
ipset.add( 'abcd:1234:5678:9abc::/64', 'blacklist' );

ipset.remove( 'bcda::/56' );

// matching
console.log(
    ipset.match( '1.2.3.4' ), // 'Region 1',
    ipset.match( '2.3.4.1' ), // Region2 ref
    ipset.match( new Address4('2.3.4.5') ), // 'blacklist'
    ipset.match( 'abcd:1234:5678:9abc::123' ), // 'blacklist'
    ipset.match( 'bcda::/56' ), // undefined
);

// just a handy helper
ipset.convertAddress('1.2.3.4') -> instance of Address4
ipset.convertAddress('1.2.3.4/23') -> instance of Address4
ipset.convertAddress('::1') -> instance of Address6

Matching logic

Internally, ipset is a map of prefix lengths to map of network address to referenced value, like:

IP version map of
    /23 -> map of
        1.2.2.0 -> ref
        1.1.0.0 -> ref
    /32 -> map of
        1.2.3.4 -> ref

Trivial and fast enough pure JS algo:

  1. Determine IPv4 or IPv6 set to use
  2. Go from longest to smallest registered prefix length

    • get net address with specified prefix length based on address in question
    • if known net then return associated value
  3. Otherwise, return undefined