Add ability to process flow with LUA. So much magic there!

This commit is contained in:
Pavel Odintsov 2015-06-22 04:52:56 -04:00
parent 4eb385f21c
commit 318f59c21f
5 changed files with 60 additions and 19 deletions

16
docs/LUA_SUPPORT.md Normal file

@ -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
```

@ -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

@ -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

@ -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";

@ -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" } }