1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
--
-- (C) 2021 - ntop.org
--
-- This is going to be an example of a lua script that can be written for cybersecurity reasons.
-- DNS Request/Reply Ratio:
local f_dns = Field.new("dns")
local f_dns_response_flag = Field.new("dns.flags.response")
local f_ip_src = Field.new("ip.src")
local f_ip_dst = Field.new("ip.dst")
--############################################
local function getstring(finfo)
local ok, val = pcall(tostring, finfo)
if not ok then val = "(unknown)" end
return val
end
--############################################
local function processResponse(dns_table, req_or_rep, src, dst)
local key = src .. " -> " .. dst
-- Create the table entry if needed
if not dns_table[key] then
dns_table[key] = {
requests = 0,
replies = 0,
}
end
-- Increase the stats
dns_table[key][req_or_rep] = dns_table[key][req_or_rep] + 1
return dns_table
end
--############################################
local function processPackets(pinfo,tvb, dns_table)
-- Call the function that extracts the field
local dns_traffic = f_dns()
local dns_flag = f_dns_response_flag()
--Check if there is an DNS request or reply
if dns_traffic then
if dns_flag.value == false then
local src = getstring(f_ip_src().value)
local dst = getstring(f_ip_dst().value)
dns_table = processResponse(dns_table, "requests", src, dst)
else
local dst = getstring(f_ip_src().value)
local src = getstring(f_ip_dst().value)
dns_table = processResponse(dns_table, "replies", src, dst)
end
end
return dns_table
end
--############################################
local function dnsReqRepRatio()
-- Declare the window we will use
local tw = TextWindow.new("DNS Request/Reply Ratio")
local dns_table = {}
local tap = Listener.new();
local function removeListener()
-- This way we remove the listener that otherwise will remain running indefinitely
tap:remove();
end
-- We tell the window to call the remove() function when closed
tw:set_atclose(removeListener)
-- This function will be called once for each packet
function tap.packet(pinfo,tvb)
dns_table = processPackets(pinfo,tvb, dns_table)
end
-- This function will be called once every few seconds to update our window
function tap.draw(t)
tw:clear()
local dangerous_flows = {}
local ok_flows = {}
for flow, data in pairs(dns_table) do
local requests = dns_table[flow]["requests"]
local replies = dns_table[flow]["replies"]
local ratio = 0
if replies == 0 then
ratio = 0
else
ratio = requests/replies
end
if ratio ~= 1 then
dangerous_flows[#dangerous_flows + 1] = data
dangerous_flows[#dangerous_flows]["flow"] = flow
dangerous_flows[#dangerous_flows]["ratio"] = ratio
else
ok_flows[#ok_flows + 1] = data
ok_flows[#ok_flows]["flow"] = flow
ok_flows[#ok_flows]["ratio"] = ratio
end
end
if #dangerous_flows > 0 then
tw:append("------------- DETECTED DNS REQUEST/REPLY RATIO -------------\n")
tw:append("TOT SUSPICIOUS FLOWS DETECTED:\t" .. #dangerous_flows .. " -------------\n")
else
tw:append("------------- DNS REQUEST/REPLY RATIO SEEMS FINE -------------\n\n")
end
tw:append("TOTAL DNS FLOWS DETECTED:\t\t" .. #dangerous_flows + #ok_flows .. " -------------\n\n")
for _, data in pairs(dangerous_flows) do
local flow = data["flow"]
local requests = data["requests"]
local replies = data["replies"]
local ratio = data["ratio"]
tw:append(flow .. ":\n\tRatio:\t\t" .. (ratio) .. "\n\tRequests:\t\t" .. requests .. "\n\tReplies:\t\t" .. replies .. "\n\n");
end
end
-- This function will be called whenever a reset is needed
-- e.g. when reloading the capture file
function tap.reset()
tw:clear()
dns_table = {}
end
-- Ensure that all existing packets are processed.
retap_packets()
end
-- Register the menu Entry
register_menu("Sharkfest/DNS Request-Reply Ratio", dnsReqRepRatio, MENU_TOOLS_UNSORTED)
|