Store IP Addresses in MongoDB

/ IPAM, Node.js, JS, MongoDB

Store IP Addresses in MongoDB

Programatically store IPv4 and/or IPv6 IP addresses in MongoDB.

Recently, I wanted to write some IP Address Management tools using server side Javascript (nodejs) and be able to store IP Address data into a MongoDB backend database. Simple! I'll just perform IP-to-Decimal conversions like I always do. Problem solved. End of article? Wait! Not so fast...

That won't work since:

  • Javascript's native Number data type only supports 64-bit integers
  • MongoDB doesn't have a data types that would support BigInts - so, I couldn't use one of the many Number-to-BigInt libraries

The solution to the problem is to store the IP addresses in Binary form. This is a supported MongoDB BSON data type. So the next part of the challenge was to figure out how to do that. I evaluated three (3) different IP Address parsing libraries to help with this task.

I found no one module would do all the things I wanted them to do. I ended up using Fedor Indutny's ip module's ip.toBuffer() method to do my conversion of IPv4 or IPv6 network addresses. I used Beau Gunderson's ipv6 module to perform validation on the network address, and to calculate the string value of the starting and ending IP address. These values would be passed into the ip.toBuffer() method for storage in MongoDB.

Let's put it all together. First I build an instance of a Network, a Mongoose Model that I've defined, like so:

var my_net = new Network({
   network: '192.168.1.0',
   prefix_length: 24,
   comment: 'my test network',
   block: false,
   start_addr: ip.toBuffer('192.168.1.0'),
   end_addr: ip.toBuffer('192.168.1.255')
});

Then I simply save it to the database:

my_net.save(function(err, network)) {
    if(err) return res.send(err);
    return(network);
});

Now that I'm storing IP addresses in MongoDB as Binary, how would I perform comparisons? How would I query it? Example - Suppose I was given a host address, and I needed to find a network in my database that contains that IP Address. No problem! The following query searches the database for ANY network that contains the IP 192.168.1.1:

var mongoose = require('mongoose');
var Network = require('./models/network.js');
/* load ip module */
var ip = require('ip');

mongoose.connect('mongodb://localhost/ddiguru_ddi');

var ip_bin = ip.toBuffer('192.168.1.1');

Network.find({
        $and: [
            { 'start_addr' : {$lt: ip_bin}},
            { 'end_addr'   : {$gt: ip_bin}}
        ]},
        function(err, networks) {
            if(err) return console.error(err);
            console.log(networks);
});

The above code works for IPv6 addresses as well.

Next Post Previous Post