Hi Guys,
I would like to share an issue and possible solutions for the issue related to store and compare IP address in MongoDB.
The RequirementClient have its own master IP Address list marked as GOOD and BAD ip address, in master list it may have plain IP address (i.e. 192.168.1.1) or in CIDR notation (i.e. 192.168.1.1/24). The actual task is to store the master data and compare it with user specific data.
User Specific Data: Here we are using netstat command to get network connections (foreign address: both incoming and outgoing) on which the computer is connected.
CIDR Notation: CIDR means Classless Inter-Domain Routing. It used for subnetting and in simple term it used to define range. For example if we use 192.168.1.1/24 so it contains 256 ip addresses starting from 192.168.1.0 to 192.168.1.255 .
Initially i have decided to generate range of CIDR and store it into MongoDB, the hurdle not came is client have choice to add many ip address with cidr so we ends up with billions of ip address(It returns 2147483648 ip addresses if our ip is 128.0.0.0/1 ) and it take time to compare multiple address.
SolutionThe one solution which i applied here to compare user’s ip address with master list is i have converted a first address and last address which i got from CIDR notation to long and did mathematical operation to check whether particular ip address lies between range or not.
I have used below mongo structure and java code to convert ip to long.
Mongo Structure: { "_id" : ObjectId("582d85fe9db5adcbfcafc8c8"), "name" : "31.11.43.0/24", "ipType" : "CIDR", "first" : "31.11.43.0", "last" : "31.11.43.255", "start" : NumberLong(520825600), "end" : NumberLong(520825855), "count" : NumberLong(256) "Status": "GOOD" } Java Code to convert ip address to Long: public class IpUtil { public static long ipToLong(String ipAddress) { String[] ipAddressInArray = ipAddress.split("\\."); long result = 0; for (int i = 0; i < ipAddressInArray.length; i++) { int power = 3 - i; int ip = Integer.parseInt(ipAddressInArray[i]); result += ip * Math.pow(256, power); } return result; } public static String longToIp(long ip) { StringBuilderresult = new StringBuilder(15); for (int i = 0; i < 4; i++) { result.insert(0, Long.toString(ip & 0xff)); if (i < 3) { result.insert(0, '.'); } ip = ip >> 8; } return result.toString(); } }Now we can easily execute a query to check whether particular ip is in range or not using code below.
public boolean isGood(String ip) { long ipLong = IpUtil.ipToLong(ip); if (mongoTemplate.count(new Query(Criteria.where("status").is(MongoNetworkStatus.GOOD).and("start") .lte(ipLong).and("end").gte(ipLong)), CustomNetwork.class) > 0) { return true; } return false; }Where mongoTemplate is instance of org.springframework.data.MongoDB.core.MongoTemplate
CustomNetworkis class having fields status, start and end.
Share current post by copy: https://goo.gl/tWuc8M
Hope it may help somewhere.
Thanks, Yogesh P