EVOLUTION-MANAGER
Edit File: flowSearch.lua
-- ################################################## -- -- Available commands -- -- <field> eq <value> -- <field> not <value> -- <field> is null|notnull -- <field> contains <value> -- -- ################################################## package.path = "./lua/?.lua;/usr/local/lib/nprobe/lua/?.lua;" .. package.path require "template" local j = require("dkjson") -- Enable debug here local debug = false -- <====== DEBUG HERE -- ################################################## function tprint (tbl, indent) if not indent then indent = 0 end if tbl == nil then tbl = {} elseif type(tbl) == 'string' then tbl = {tbl} end for k, v in pairs(tbl) do formatting = string.rep(" ", indent) .. k .. ": " if type(v) == "table" then print(formatting) tprint(v, indent+1) elseif type(v) == 'boolean' then print(formatting .. tostring(v)) else print(formatting .. v) end end end -- ################################################## -- set rules.lastchange <epoch> -- Defaults protoRules = { } function refreshProtoRules(proto) local rule = redis.hget("nprobe.rules", proto) if((rule == "") or (rule == nil)) then rule = "[ ]" else rule = string.gsub(rule, "\n", "") end if(debug) then print("Loading "..proto) io.write(rule.."\n") end local obj, pos, err = j.decode(rule, 1, nil) if err then print ("Error:", err) protoRules[proto] = { } else if(debug) then for i = 1,#obj do local filter = obj[i].filter print(proto.." rule "..obj[i].id) for j = 1,#filter do print (filter[j].key.." "..filter[j].op.." "..filter[j].val) end end end protoRules[proto] = obj end end -- ################################################## function refreshRules(when) refreshProtoRules("http") refreshProtoRules("dns") refreshProtoRules("dhcp") refreshProtoRules("ftp") refreshProtoRules("radius") refreshProtoRules("sip") refreshProtoRules("pop") refreshProtoRules("smtp") refreshProtoRules("imap") refreshProtoRules("gtpv1") end -- ################################################## function updateRules() if rules.haveChanged() then refreshRules(os.time()) rules.updated() end end -- ################################################## function dumpTable(label, what) for k,v in pairs(what) do print(label.."\t"..k.."="..v.."\n") end end -- ################################################## function dumpRule(label, rule) for k,v in pairs(rule) do print(label.."\t"..k.." "..v[1].." "..v[2].."\n") end end -- ################################################## function dumpRules(label, rule) for id,r in pairs(rule) do for k,v in pairs(r) do print(label.."\t["..id.."] "..k.." "..v[1].." "..v[2].."\n") end end end -- ################################################## function checkFlowMatch(label, flow, rule) if(debug == true) then io.write("\n\n ===>> Checking flow "..j.encode(flow).."\n") end -- if(debug == true) then io.write("\n\n ===>> Checking flow ["..label.."]\n") end for i = 1,#rule do local id = rule[i].id local filter = rule[i].filter local rsp = true -- be optimistic if(debug == true) then io.write("Checking rule "..id.."\n") end for j = 1,#filter do if(rsp == true) then if(flow[filter[j].key] ~= nil) then value = flow[filter[j].key] else value = "???" end if(debug == true) then io.write(filter[j].op.." | "..filter[j].val.." | "..value.."\n") end if(filter[j].op == "eq") then if(not(value == filter[j].val)) then rsp = false break end elseif(filter[j].op == "not") then if(not(value ~= filter[j].val)) then rsp = false break end elseif(filter[j].op == "is") then if(((flow[filter[j].key] ~= nil) and (filter[j].val == "null")) or ((flow[filter[j].key] == nil) and (filter[j].val == "notnull"))) then rsp = false break end elseif(filter[j].op == "contains") then if(not(string.find(value, filter[j].val, 1, true)) and not(value == filter[j].val)) then rsp = false break end else print("Invalid operator '"..filter[j].op.."' on rule id "..id.."\n") rsp = false break end end end if(debug == true) then io.write("Result for rule "..id.."="..tostring(rsp).."\n") end if(rsp == true) then execMatchCommand(label, flow, id, r) end end end -- ################################################## function execMatchCommand(label, flow, id, rule) local message = { ['plugin'] = label, ['flow'] = flow, ['id'] = id, ['rule'] = rule } local message = j.encode(message) redis.rpush("nprobe.alerts", message) if(debug) then io.write("\nMATCHED "..message.."\n") end end -- ################################################## function checkFlow(label, flow, rule) updateRules() checkFlowMatch(label, flow, rule) end -- ################################################## function checkHTTPFlow() checkFlow("http", http, protoRules["http"]) end function checkDNSFlow() checkFlow("dns", dns, protoRules["dns"]) end function checkDHCPFlow() checkFlow("dhcp", dhcp, protoRules["dhcp"]) end function checkFTPFlow() checkFlow("ftp", ftp, protoRules["ftp"]) end function checkRADIUSFlow() checkFlow("radius", radius, protoRules["radius"]) end function checkSIPFlow() checkFlow("sip", sip, protoRules["sip"]) end function checkPOPFlow() checkFlow("pop", pop, protoRules["pop"]) end function checkSMTPFlow() checkFlow("smtp", smtp, protoRules["smtp"]) end function checkIMAPFlow() checkFlow("imap", imap, protoRules["imap"]) end function checkGTPV1Flow() checkFlow("gtpv1", gtpv1, protoRules["gtpv1"]) end -- ################################################## function exportFlow() if(false) then src = flow.getIE(template['IPV4_SRC_ADDR']) dst = flow.getIE(template['IPV4_DST_ADDR']) sport = flow.getIE(template['L4_SRC_PORT']) dport = flow.getIE(template['L4_DST_PORT']) protocol = flow.getIE(template['PROTOCOL']) print(src..":"..sport.." <-> "..dst..":"..dport.."\n") end end -- ################################################## -- ################################################## print("[LUA] Welcome to nProbe Lua!\n") refreshRules(os.time()) print("[LUA] Rules loaded successfully")