From 1a75a2ccc6ef1f5489de96b3b047aa6f0faa4ea2 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Fri, 6 Mar 2026 23:16:17 +0000 Subject: [PATCH] Expanded flow nodex with SNMP --- scripts/lua/flow_details.lua | 113 +++++++++++++++++--------- scripts/lua/modules/flow_utils.lua | 7 ++ scripts/lua/modules/lua_utils_gui.lua | 14 ++-- 3 files changed, 89 insertions(+), 45 deletions(-) diff --git a/scripts/lua/flow_details.lua b/scripts/lua/flow_details.lua index 069b58c537..06797ab993 100644 --- a/scripts/lua/flow_details.lua +++ b/scripts/lua/flow_details.lua @@ -33,6 +33,7 @@ local alert_consts = require("alert_consts") local mitre_utils = require("mitre_utils") local auth = require "auth" local exporter_site_utils = nil +local snmp_cached_dev local page = _GET["page"] @@ -42,6 +43,7 @@ local show_graph = _GET["showGraph"] or false if ntop.isPro() then package.path = dirs.installdir .. "/scripts/lua/pro/modules/?.lua;" .. package.path exporter_site_utils = require "exporter_site_utils" + snmp_cached_dev = require "snmp_cached_dev" end if ntop.isPro() then @@ -66,6 +68,31 @@ function formatIPPort(ip, port) return ip, port end +-- ######## + +local cached_devices = {} + +function getSNMPInterfaceIP(device_ip, port_idx) + if(cached_devices[device_ip] == nil) then + cached_devices[device_ip] = snmp_cached_dev:get_interfaces(device_ip) + end + + port_idx = tostring(port_idx) + if(cached_devices[device_ip] ~= nil) then + local port = cached_devices[device_ip].interfaces[port_idx..""] + + if((port ~= nil) and (port.ip_addr ~= nil) and (table.len(port.ip_addr) > 0)) then + local ip_addr = port.ip_addr + + return(ip_addr[1]) + end + end + + return(nil) -- fallback +end + +-- ######## + function formatASN(v, peer_as, ip, is_client_as) local asn local max_len = 64 @@ -505,7 +532,7 @@ local function displayProc(proc, label) print(label) - print("" .. i18n("flow_details.user_name") .. " + print("" .. i18n("flow_details.user_name") .. "".. proc.user_name .. "\n") print("" .. i18n("flow_details.process_pid_name") .. "" .. @@ -2044,10 +2071,6 @@ if isEmptyString(page) or page == "overview" then next_hop, next_hop_ip, next_hop_name, next_hop_site = formatNextHop(next_hop) nodes_names[next_hop_ip] = { firstDottedElement(next_hop_name), next_hop_site } end - - if(flow_trajectory[exporter_ip] == nil) then - flow_trajectory[exporter_ip] = {} - end end if(flow.exporters ~= nil) then @@ -2060,36 +2083,49 @@ if isEmptyString(page) or page == "overview" then local ret, exp_ip, exp_name, site = formatExporter(v.exporter_ip) local ret1, next_hop_ip, next_hop_name, next_hope_site = formatNextHop(v.next_hop) local source_label = "" - + -- tprint(v) - if(v.source > 0) then - source_label = " " - - if(v.source == 1) then - source_label = source_label .. "NetFlow / IPFIX" - elseif(v.source == 2) then - source_label = source_label .."sFlow" + if(false) then + if(v.source > 0) then + source_label = " " + + if(v.source == 1) then + source_label = source_label .. "NetFlow / IPFIX" + elseif(v.source == 2) then + source_label = source_label .."sFlow" + end + + source_label = source_label .. "" end - - source_label = source_label .. "" end --tprint(source_label) - + print("".. ret .. ' ' .. ret1) if(v.return_path == true) then print(" ".. i18n("dedup_flow_swapped").."") end print(source_label.. "") printFlowSNMPInfo(v.exporter_ip, v.input_idx, v.output_idx, true) print("") - if(flow_trajectory[exp_ip] == nil) then - flow_trajectory[exp_ip] = {} - end + local from_ip = getSNMPInterfaceIP(v.exporter_ip, v.input_idx) + local to_ip = getSNMPInterfaceIP(v.exporter_ip, v.output_idx) - if(next_hop_ip ~= "0.0.0.0") then - table.insert(flow_trajectory[exp_ip], { next_hop = next_hop_ip, return_path = v.return_path }) - nodes_names[next_hop_ip] = { firstDottedElement(next_hop_name), next_hope_site } + if((from_ip ~= nil) and (to_ip ~= nil)) then + if(flow_trajectory[from_ip] == nil) then flow_trajectory[from_ip] = {} end + if(flow_trajectory[to_ip] == nil) then flow_trajectory[to_ip] = {} end + + if(next_hop_ip ~= "0.0.0.0") then + local ret1, exp_ip, exp_name, exp_site = formatNextHop(v.exporter_ip) + + table.insert(flow_trajectory[from_ip], { next_hop = to_ip, return_path = v.return_path }) + table.insert(flow_trajectory[to_ip], { next_hop = next_hop_ip, return_path = v.return_path }) + + nodes_names[from_ip] = { from_ip, exp_site } + nodes_names[to_ip] = { to_ip, exp_site } + + nodes_names[next_hop_ip] = { firstDottedElement(next_hop_name), next_hope_site } + end end nodes_names[exp_ip] = { firstDottedElement(exp_name), site } @@ -2098,23 +2134,26 @@ if isEmptyString(page) or page == "overview" then print("") end + tprint(flow_trajectory) + if(table.len(flow_trajectory) > 0) then local nodes, edges = buildExportersGraph(flow_trajectory, nodes_names, flow["cli.ip"], flow["srv.ip"]) - -- If there are at least 3 nodes -> show the graph - if table.len(nodes) >= 3 then - print('') - if(table.len(flow.exporters) == 0) then print("") end - print('') - - local json_context = json.encode({ nodes = nodes, edges = edges }) - print('
') - template.render("pages/vue_page.template", { - vue_page_name = "PageExportersGraph", - page_context = json_context - }) - print('
') - print('\n') - end + + -- If there are at least 3 nodes -> show the graph + if table.len(nodes) >= 3 then + print('') + if(table.len(flow.exporters) == 0) then print("") end + print('') + + local json_context = json.encode({ nodes = nodes, edges = edges }) + print('
') + template.render("pages/vue_page.template", { + vue_page_name = "PageExportersGraph", + page_context = json_context + }) + print('
') + print('\n') + end end local function format_custom_field(key, value, snmpdevice) diff --git a/scripts/lua/modules/flow_utils.lua b/scripts/lua/modules/flow_utils.lua index 3155334435..a2e4f43e9b 100644 --- a/scripts/lua/modules/flow_utils.lua +++ b/scripts/lua/modules/flow_utils.lua @@ -1828,6 +1828,13 @@ end -- ####################### +function addTrajectory(snmpdevice, input_idx, output_idx) + local inputidx_name = format_portidx_name(snmpdevice, tostring(input_idx), false) + local outputidx_name = format_portidx_name(snmpdevice, tostring(output_idx), false) +end + +-- ####################### + function printFlowSNMPInfo(snmpdevice, input_idx, output_idx, as_row) local inputidx_name = format_portidx_name(snmpdevice, tostring(input_idx), true) local outputidx_name = format_portidx_name(snmpdevice, tostring(output_idx), true) diff --git a/scripts/lua/modules/lua_utils_gui.lua b/scripts/lua/modules/lua_utils_gui.lua index 741260e498..6c8324a4ce 100644 --- a/scripts/lua/modules/lua_utils_gui.lua +++ b/scripts/lua/modules/lua_utils_gui.lua @@ -23,14 +23,14 @@ local format_utils = require "format_utils" local dns_utils = require "dns_utils" local http_utils = require "http_utils" local rest_utils = require "rest_utils" -local snmp_utils +--local snmp_utils local cache_utils = require "cache_utils" local exporter_site_utils if ntop.isPro() then package.path = dirs.installdir .. "/scripts/lua/pro/modules/?.lua;" .. package.path require "flow_exporter_utils" - snmp_utils = require "snmp_utils" + -- snmp_utils = require "snmp_utils" exporter_site_utils = require "exporter_site_utils" end -- For backward compatibility override these functions @@ -996,20 +996,18 @@ function format_portidx_name(device_ip, portidx, short_version) if (cached_val ~= nil) then local num_value = tonumber(cached_val) + if(num_value and (num_value == tonumber(portidx))) then -- With integer it seems there is some problem when caching the value -- returning values like 6.00000 instead of 6 return(portidx) end + if(short_version) then - cached_val = shortenString(cached_val, 26) + cached_val = shortenString(cached_val, 26) end - - -- if(cached_val ~= portidx) then - -- return (cached_val.." ("..portidx..")") - -- else + return (cached_val) - -- end else return(portidx) end