5

I am developing an IP authentication service and I am looking for a proper way to store ip range in mongoDB for later checking if an ip falls in a range. Basically I have 3 ideas:

  • Store as string {from;to} and then create a js function that will perform the check for a ip, and then use it inside find;
  • Store as byte and then create a js function will do the checking.
  • Store as string, and use it inside C# a perform ip matching there not in Mongo.

Are there any other solutions that will be far more performant than the ones I mention?

Markus W Mahlberg
  • 19,711
  • 6
  • 65
  • 89
  • 2
    Why not store it as numbers (removed dots)? it's practically what it is. You can then query by $gt and $lt operators. – Sagish Aug 10 '15 at 09:36
  • 2
    @Sagish you wouldn't even have to do this. `10.0.0.2` is between `10.0.0.1` and `10.0.0.3` in a lexicographic comparison. So `db.ranges.find({$and: [ { "ip": { $gte: "10.0.0.1"}},{ "ip": { $lte: "10.0.0.3"}}]},{_id:0,ip:1})` should return 10.0.0.2, hence not null and you are done. Although, I'd add an index over the `ip` field. – Markus W Mahlberg Aug 10 '15 at 09:52
  • @MarkusWMahlberg That's not actually correct because, for example, IP 30.1.2.3 is lexicographically between 1.0.0.0 and 8.255.255.255. So, to handle IP range comparisons correctly, storing the IPs as numbers would indeed be more appropriate. It won't cause unexpected situations. – Jan Švábík Aug 03 '23 at 07:48

1 Answers1

0

Because this question still lacks a complete answer, I decided to post it here.

Store the range's start and end IP address as an integer and when querying, use $lte and $gte MongoDB operators to find the match. Also, create indexes on the start and end fields so the performance is good even with a bigger amount of documents to search through.

Let's perform one example with an IP range starting with 2.0.0.0 and ending with 8.255.255.255. Two IP addresses are going to be tested: a) 4.5.6.7, b) 60.70.80.90:

You need to convert all IPs to integers.

  • Range start 2.0.0.0 = 33554432
  • Range end 8.255.255.255 = 150994943
  • Testing IP a 4.5.6.7 = 67438087
  • Testing IP b 60.70.80.90 = 1011241050

For storing the IP range in the database you can create a MongoDB document like the one below this paragraph. If you'd like to enlist just one IP, both the start and the end fields will need to have the same value.

{ "start": 33554432, "end": 150994943 }

Then perform a find query using $lte and $gte operators which will get the integer value of the IP to be tested.

// this will result in one match because 67438087 = 4.5.6.7
db.collection.find({
    start: { $lte: 67438087 },
    end: { $gte: 67438087 },
})
// this will end up with no result because 1011241050 = 60.70.80.90
db.collection.find({
    start: { $lte: 1011241050 },
    end: { $gte: 1011241050 },
})
Jan Švábík
  • 314
  • 2
  • 13