--
-- (C) 2013-20 - ntop.org
--
dirs = ntop.getDirs()
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
require "lua_utils"
local ts_utils = require("ts_utils")
local callback_utils = require("callback_utils")
local json = require("dkjson")
local page_utils = require("page_utils")
local format_utils = require("format_utils")
local info = ntop.getInfo()
sendHTTPContentTypeHeader('text/html')
page_utils.set_active_menu_entry(page_utils.menu_entries.host_explorer)
dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua")
print("
Host Explorer
")
-- https://www.d3-graph-gallery.com/graph/bubble_template.html
local modes = {
{ mode = 0, label = "All Flows" },
{ mode = 1, label = "Unreacheable Flows" },
{ mode = 2, label = "Misbehaving Flows" },
{ mode = 3, label = "DNS Queries vs Replies" },
{ mode = 4, label = "SYN Distribution" },
{ mode = 5, label = "SYN vs RST" },
{ mode = 6, label = "SYN vs SYNACK" },
{ mode = 7, label = "TCP Packets Sent/Received" },
{ mode = 8, label = "TCP Bytes Sent/Received" }
}
local show_remote = true
local local_hosts = { }
local remote_hosts = { }
local max_r = 0
local local_label = "Local Hosts"
local remote_label = "Remote Hosts"
local x_label
local y_label
local bubble_mode = tonumber(_GET["bubble_mode"]) or 0
if(bubble_mode == 0) then
x_label = 'Flows as Server'
y_label = 'Flows as Client'
elseif(bubble_mode == 1) then
x_label = 'Unreachable Flows as Server'
y_label = 'Unreachable Flows as Client'
elseif(bubble_mode == 2) then
x_label = 'Misbehaving Flows as Server'
y_label = 'Misbehaving Flows as Client'
elseif(bubble_mode == 3) then
x_label = 'Positive DNS Replies Received'
y_label = 'DNS Queries Sent'
elseif(bubble_mode == 4) then
x_label = '# of SYN Sent'
y_label = '# of SYN Received'
elseif(bubble_mode == 5) then
x_label = '# of SYN Sent'
y_label = '# of RST Received'
elseif(bubble_mode == 6) then
x_label = '# of SYN Sent'
y_label = '# of SYNACK Received'
elseif(bubble_mode == 7) then
x_label = 'TCP Packets Sent'
y_label = 'TCP Packets Received'
elseif(bubble_mode == 8) then
x_label = 'TCP Bytes Sent'
y_label = 'TCP Bytes Received'
end
function string.starts(String,Start)
return string.sub(String,1,string.len(Start))==Start
end
function processHost(hostname, host)
local line
--io.write("================================\n")
--io.write(hostname.."\n")
--tprint(host)
local label = hostinfo2hostkey(host)
if((label == nil) or (string.len(label) == 0) or string.starts(label, "@")) then label = hostname end
line = nil
if(bubble_mode == 0) then
line = { link = hostname, label = label, x = host["active_flows.as_server"], y = host["active_flows.as_client"], r = host["bytes.sent"]+host["bytes.rcvd"] }
elseif(bubble_mode == 1) then
if(host["unreachable_flows.as_server"] + host["unreachable_flows.as_client"] > 0) then
line = { link = hostname, label = label, x = host["unreachable_flows.as_server"], y = host["unreachable_flows.as_client"], r = host["bytes.sent"]+host["bytes.rcvd"] }
end
elseif(bubble_mode == 2) then
if((host["misbehaving_flows.as_server"] ~= nil)
and (host["misbehaving_flows.as_client"] ~= nil)
and (host["misbehaving_flows.as_server"] + host["misbehaving_flows.as_client"] > 0)) then
line = { link = hostname, label = label, x = host["misbehaving_flows.as_server"], y = host["misbehaving_flows.as_client"], r = host["misbehaving_flows.as_server"] + host["misbehaving_flows.as_client"] }
-- if(label == "74.125.20.109") then tprint(line) end
end
elseif(bubble_mode == 3) then
if((host["dns"] ~= nil) and ((host["dns"]["sent"]["num_queries"]+host["dns"]["rcvd"]["num_queries"]) > 0)) then
line = { link = hostname, label = label, x = host["dns"]["rcvd"]["num_replies_ok"], y = host["dns"]["sent"]["num_queries"], r = host["dns"]["rcvd"]["num_replies_error"] }
end
elseif(bubble_mode == 4) then
local stats = interface.getHostInfo(host["ip"],host["vlan"])
line = { link = hostname, label = label, x = stats["pktStats.sent"]["tcp_flags"]["syn"], y = stats["pktStats.recv"]["tcp_flags"]["syn"],
r = host["active_flows.as_client"] + host["active_flows.as_server"] }
elseif(bubble_mode == 5) then
local stats = interface.getHostInfo(host["ip"],host["vlan"])
line = { link = hostname, label = label, x = stats["pktStats.sent"]["tcp_flags"]["syn"], y = stats["pktStats.recv"]["tcp_flags"]["rst"],
r = host["active_flows.as_client"] + host["active_flows.as_server"] }
elseif(bubble_mode == 6) then
local stats = interface.getHostInfo(host["ip"],host["vlan"])
line = { link = hostname, label = label, x = stats["pktStats.sent"]["tcp_flags"]["syn"], y = stats["pktStats.recv"]["tcp_flags"]["synack"],
r = host["active_flows.as_client"] + host["active_flows.as_server"] }
elseif(bubble_mode == 7) then
local stats = interface.getHostInfo(host["ip"],host["vlan"])
line = { link = hostname, label = label, x = stats["tcp.packets.sent"], y = stats["tcp.packets.rcvd"],
r = stats["tcp.bytes.sent"]+stats["tcp.bytes.rcvd"] }
elseif(bubble_mode == 8) then
local stats = interface.getHostInfo(host["ip"],host["vlan"])
line = { link = hostname, label = label, x = stats["tcp.bytes.sent"], y = stats["tcp.bytes.rcvd"],
r = stats["tcp.bytes.sent"]+stats["tcp.bytes.rcvd"] }
-- io.write("--------------------------\n")
-- tprint(host)
end
if(line ~= nil) then
if(line.r > max_r) then max_r = line.r end
if(host.localhost) then
table.insert(local_hosts, line)
else
table.insert(remote_hosts, line)
end
end
end
if(show_remote == true) then
callback_utils.foreachHost(ifname, processHost)
else
callback_utils.foreachLocalHost(ifname, processHost)
end
local max_radius_px = 30
local min_radius_px = 3
local ratio = max_r / max_radius_px
for i,v in pairs(local_hosts) do local_hosts[i].r = math.floor(min_radius_px+local_hosts[i].r / ratio) end
if(show_remote == true) then
for i,v in pairs(remote_hosts) do remote_hosts[i].r = math.floor(min_radius_px+remote_hosts[i].r / ratio) end
end
local local_js = json.encode(local_hosts)
local remote_js = json.encode(remote_hosts)
print [[