diff --git a/docs/LUA_SUPPORT.md b/docs/LUA_SUPPORT.md new file mode 100644 index 00000000..27383c78 --- /dev/null +++ b/docs/LUA_SUPPORT.md @@ -0,0 +1,16 @@ +### We have LUA support for processing NetFlow flows + +It supported only for NetFlow v5 at this moment. + +It's not compiled by default and you need build it explicitly. + +Install dependency list (Debian 8 and Ubuntu 14.04 has it): +```bash +apt-get install -y libluajit-5.1-dev luajit +``` + +Build it: +``` +cmake -DENABLE_LUA_SUPPORT=ON .. +make +``` diff --git a/src/fastnetmon.conf b/src/fastnetmon.conf index f2e1638d..72e7fee1 100644 --- a/src/fastnetmon.conf +++ b/src/fastnetmon.conf @@ -92,6 +92,10 @@ netflow_sampling_ratio = 1 # We could try to get smoother data with this option, i.e. we will divide counters on collection interval time netflow_divide_counters_on_interval_length = off +# With this option we could process each netflow packet with LUA +# This option is not default and you need build it additionally +netflow_lua_hooks_path = /usr/src/fastnetmon/src/netflow_hooks.lua + # sFLOW configuration sflow_port = 6343 sflow_host = 0.0.0.0 diff --git a/src/netflow_hooks.lua b/src/netflow_hooks.lua index fe37620f..2b9f3fcc 100644 --- a/src/netflow_hooks.lua +++ b/src/netflow_hooks.lua @@ -22,22 +22,35 @@ ffi.cdef([[typedef struct __attribute__((packed)) NF5_FLOW { uint16_t pad2; } NF5_FLOW_t;]]) -function process_netflow(flow) +-- Load json file once +local json_file = io.open("/usr/src/fastnetmon/src/tests/netflow_exclude.json", "r") +local decoded = json.decode(json_file:read("*all")) + +function process_netflow(flow_agent_ip, flow) local netlflow5_t = ffi.typeof('NF5_FLOW_t*') local lua_flow = ffi.cast(netlflow5_t, flow) + --print ("We got this packets from: ", flow_agent_ip) -- TODO: PLEASE BE AWARE! Thid code will read json file for every netflow packet - print ("Flow packets and bytes: ", lua_flow.flow_packets, lua_flow.flow_octets) - print ("In interface :", lua_flow.if_index_in, " out interface: ", lua_flow.if_index_out) - local json_file = io.open("/usr/src/fastnetmon/src/tests/netflow_exclude.json", "r") - - local decoded = json.decode(json_file:read("*all")) + --print ("Flow packets and bytes: ", lua_flow.flow_packets, lua_flow.flow_octets) + --print ("In interface :", lua_flow.if_index_in, " out interface: ", lua_flow.if_index_out) - for k,v in pairs(decoded) do - for kk, vv in pairs(v) do - --print(k, kk, vv) + for agent_ip, ports_table in pairs(decoded) do + if agent_ip == flow_agent_ip then + for port_number, port_description in pairs(ports_table) do + if lua_flow.if_index_in == port_number then + -- We found this port in ignore list + return false + end + end end end + --for k,v in pairs(decoded) do + -- for kk, vv in pairs(v) do + -- --print(k, kk, vv) + -- end + --end + return true end diff --git a/src/netflow_plugin/netflow_collector.cpp b/src/netflow_plugin/netflow_collector.cpp index 44c06b3d..03bd5049 100644 --- a/src/netflow_plugin/netflow_collector.cpp +++ b/src/netflow_plugin/netflow_collector.cpp @@ -37,7 +37,7 @@ lua_State* lua_state = NULL; bool lua_hooks_enabled = true; std::string lua_hooks_path = "/usr/src/fastnetmon/src/netflow_hooks.lua"; -bool call_netflow_process_lua_hook(lua_State* lua_state_param, struct NF5_FLOW* flow); +bool call_netflow_process_lua_hook(lua_State* lua_state_param, std::string client_addres_in_string_format, struct NF5_FLOW* flow); void init_lua_jit(); #endif @@ -989,12 +989,12 @@ void process_netflow_packet_v5(u_int8_t* packet, u_int len, std::string client_a #ifdef ENABLE_LUA_HOOKS if (lua_hooks_enabled) { - // TODO: remove it!!! - if (lua_state == NULL) { - init_lua_jit(); - } + // This code could be used only for tests with pcap_reader + //if (lua_state == NULL) { + // init_lua_jit(); + //} - if (call_netflow_process_lua_hook(lua_state, nf5_flow)) { + if (call_netflow_process_lua_hook(lua_state, client_addres_in_string_format, nf5_flow)) { // We will process this packet } else { logger << log4cpp::Priority::INFO << "We will drop this packets because LUA script decided to do it"; @@ -1047,12 +1047,16 @@ void init_lua_jit() { } } -bool call_netflow_process_lua_hook(lua_State* lua_state_param, struct NF5_FLOW* flow) { +bool call_netflow_process_lua_hook(lua_State* lua_state_param, std::string client_addres_in_string_format, struct NF5_FLOW* flow) { + /* Function name */ lua_getfield(lua_state_param, LUA_GLOBALSINDEX, "process_netflow"); + + /* Function params */ + lua_pushstring(lua_state_param, client_addres_in_string_format.c_str()); lua_pushlightuserdata(lua_state_param, (void*)flow); - + // Call with 1 argumnents and 1 result - lua_call(lua_state_param, 1, 1); + lua_call(lua_state_param, 2, 1); if (lua_gettop(lua_state_param) == 1) { bool result = lua_toboolean(lua_state_param, -1) == 1 ? true : false; @@ -1104,6 +1108,10 @@ void start_netflow_collection(process_packet_pointer func_ptr) { configuration_map["netflow_divide_counters_on_interval_length"] == "on" ? true : false; } + if (configuration_map.count("netflow_lua_hooks_path") != 0) { + lua_hooks_path = configuration_map["netflow_lua_hooks_path"]; + } + logger << log4cpp::Priority::INFO << "netflow plugin will listen on " << netflow_host << ":" << netflow_port << " udp port"; diff --git a/src/tests/netflow_exclude.json b/src/tests/netflow_exclude.json index 97243ee4..13b310aa 100644 --- a/src/tests/netflow_exclude.json +++ b/src/tests/netflow_exclude.json @@ -1 +1 @@ -{"22.11.22.33" : { 33 : "BB", 4 : "BB", 3 : "BB" },"88.99.11.22" : { 559 : "BB", 572 : "BB", 613 : "BB", 542 : "BB", 565 : "BB", 558 : "BB", 561 : "BB", 543 : "BB", 555 : "BB", 545 : "BB", 568 : "BB", 551 : "BB", 574 : "BB" } } +{"22.11.22.33" : { 33 : "BB", 4 : "BB", 3 : "BB" },"88.99.11.22" : { 559 : "BB", 572 : "BB", 613 : "BB", 542 : "BB", 565 : "BB", 558 : "BB", 561 : "BB", 543 : "BB", 555 : "BB", 545 : "BB", 568 : "BB", 551 : "BB", 574 : "BB" }, "10.0.1.2" : { 916 : "BB" } }