1
\$\begingroup\$

Background and assumptions:

  1. A flow corresponds to a netflow record that is written into mongodb.
  2. Each flow record has a client_addr and server_addr amongst many other fields.
  3. orgLevelIPSubnet refers to an array of IP addresses and / or CIDR ranges. They correspond to devices within an organization.
  4. orgLevelBlacklistedServers refers to an array of IP addresses and / or CIDR range. They correspond to device that should not be interacted with (blacklist)
  5. rangeCheck is used only for the purpose of determining if the IP address is of type IPV4
  6. Addr is used to check if an IP address falls in range of a subnet.
  7. If a client inside the network is initiating a connection to a blacklisted entity or vice-versa, raise a new alert or update an existing open alert by writing to the alerts db (MongoDB).

The below function gets executed each time a new flow is received. Given the nature of duplicity of the if blocks and nested for loops, would like some guidance over how best they can be optimized while redundancy be minimized.

orgLevelFlow_blacklistedServers_check: function(orgLevelPolicy, flow) {


        var Addr = require('netaddr').Addr;
        var rangeCheck = require('range_check');

        // General rules to check for blacklisted server activity:
        // 1: if client is in org's IP subnets && server is in org's blacklisted IP
        //    ==> raise alert as this means that an org's entiry is trying to talk to a blacklisted entitiy
        // 2: if server is in org's IP subnets && client is in org's blacklisted IP
        //    ==> raise alert as this means that an outside blacklisted entitiy is trying to talk to an org's entitiy
        //
        //get orgLevelPolicy's IP subnets & convert it to array
        var orgLevelIpSubnets = orgLevelPolicy.ipSubnets.split(",");
        //get orgLevelPolicy's blacklistedServers & convert it to array
        var orgLevelBlacklistedServers = orgLevelPolicy.blacklistedServers.split(",");

        // only check for ipv4 addresses for now.
        // @TODO: Implement ipv6 range check also. Note: netAddr does not support ipv6 range owing to JS int 64bit / 128bit not existing
        if (rangeCheck.isV4(flow.netflow.client_addr) && rangeCheck.isV4(flow.netflow.server_addr)) {

            for (var i = 0; i < orgLevelIpSubnets.length; i++) {

                // if client_addr is part of ipSubnet:
                if (Addr(orgLevelIpSubnets[i]).contains(Addr(flow.netflow.client_addr))) {

                    for (var j = 0; j < orgLevelBlacklistedServers.length; j++) {
                        if (Addr(orgLevelBlacklistedServers[j]).contains(Addr(flow.netflow.server_addr))) {
                            // console.log("client: " + flow.netflow.client_addr + " Server: " + flow.netflow.server_addr);
                            // if there exists an open alert, then append to that alert.

                            if (alerts.findOne({
                                    alertLevel: "orgLevelAlert",
                                    alertCategory: "blacklistedServersViolationAlert",
                                    alertState: "open"
                                })) {
                                // append
                                // console.log("Appending to existing open alert");
                                alerts.update({
                                    alertLevel: "orgLevelAlert",
                                    alertCategory: "blacklistedServersViolationAlert",
                                    alertState: "open"
                                }, {
                                    $set: {
                                        "misc.updatedTime": new Date()
                                    },
                                    $inc: {
                                        flowCount: 1
                                    },
                                    $addToSet: {
                                        blacklistedCommunication: {
                                            client: flow.netflow.client_addr,
                                            server: flow.netflow.server_addr
                                        }
                                    }
                                });
                            }
                            // if there is a closed alert, then open a new alert.
                            // if there is no alert, create a new one. (No need to check this condition)
                            else {
                                console.log("Creating new alert");
                                alerts.insert({
                                    alertLevel: "orgLevelAlert",
                                    alertCategory: "blacklistedServersViolationAlert",
                                    alertState: "open",
                                    flowCount: 1,
                                    blacklistedCommunication: [{
                                        client: flow.netflow.client_addr,
                                        server: flow.netflow.server_addr,
                                    }],
                                    misc: {
                                        createdBy: "system",
                                        updatedBy: "system",
                                        createdTime: new Date(),
                                        updatedTime: new Date()
                                    }
                                });
                            }
                        }

                    }

                } // client server pair 1


                //if server_addr is part of the ipSubnet:
                else if (Addr(orgLevelIpSubnets[i]).contains(Addr(flow.netflow.server_addr))) {
                    for (var j = 0; j < orgLevelBlacklistedServers.length; j++) {
                        if (Addr(orgLevelBlacklistedServers[j]).contains(Addr(flow.netflow.client_addr))) {
                            // console.log("client: " + flow.netflow.client_addr + " Server: " + flow.netflow.server_addr);
                            // if there exists an open alert, then append to that alert.

                            if (alerts.findOne({
                                    alertLevel: "orgLevelAlert",
                                    alertCategory: "blacklistedServersViolationAlert",
                                    alertState: "open"
                                })) {
                                // append
                                // console.log("Appending to existing open alert");
                                alerts.update({
                                    alertLevel: "orgLevelAlert",
                                    alertCategory: "blacklistedServersViolationAlert",
                                    alertState: "open"
                                }, {
                                    $set: {
                                        "misc.updatedTime": new Date()
                                    },
                                    $inc: {
                                        flowCount: 1
                                    },
                                    $addToSet: {
                                        blacklistedCommunication: {
                                            client: flow.netflow.client_addr,
                                            server: flow.netflow.server_addr
                                        }
                                    }
                                });
                            }
                            // if there is a closed alert, then open a new alert.
                            // if there is no alert, create a new one. (No need to check this condition)
                            else {
                                console.log("Creating new alert");
                                alerts.insert({
                                    alertLevel: "orgLevelAlert",
                                    alertCategory: "blacklistedServersViolationAlert",
                                    alertState: "open",
                                    flowCount: 1,
                                    blacklistedCommunication: [{
                                        client: flow.netflow.client_addr,
                                        server: flow.netflow.server_addr
                                    }],
                                    misc: {
                                        createdBy: "system",
                                        updatedBy: "system",
                                        createdTime: new Date(),
                                        updatedTime: new Date()
                                    }
                                });
                            }
                        }
                    }
                } //client server pair 2
            }
        } //end of if it's an ipv4
    }
\$\endgroup\$
  • 1
    \$\begingroup\$ Yo should use a Set to store each of the IP lists. Set uses hash tables for looking up entries and is the fastest way to handle the type of filtering. Very easy to use and fast. See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… \$\endgroup\$ – Blindman67 Nov 22 '17 at 14:01
  • \$\begingroup\$ @200_success - I have put in more detailing to the code and goal. Please review and have the question reopened if you feel it to be fit. Thanks. \$\endgroup\$ – blueren Nov 22 '17 at 15:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.