Reporting: Traffic - use async resolver to reverse lookup addresses. closes https://github.com/opnsense/core/issues/5536

This commit is contained in:
Ad Schellevis 2022-02-20 20:14:46 +01:00
parent 171fd93167
commit 92352ec4fa
2 changed files with 39 additions and 1 deletions

View File

@ -264,7 +264,15 @@ POSSIBILITY OF SUCH DAMAGE.
.data('bps_max_out', 0).data('total_in', 0).data('total_out', 0)
.data('intf', intf);
tr.append($("<td/>").html(intf_label));
tr.append($("<td/>").text(item.address));
if (item.rname) {
tr.append(
$("<td/>").append(
$("<span/>").text(item.rname), $("<small/>").text("("+item.address+")")
)
);
} else {
tr.append($("<td/>").text(item.address));
}
tr.append($("<td class='bps_in'/>").text("0b"));
tr.append($("<td class='bps_out'/>").text("0b"));
tr.append($("<td class='bps_max_in'/>").text("0b"));

View File

@ -27,6 +27,7 @@
"""
import argparse
import asyncio
import decimal
import subprocess
import os
@ -34,6 +35,8 @@ import sys
import math
import ujson
import netaddr
import dns.resolver
from dns.asyncresolver import Resolver
from concurrent.futures import ThreadPoolExecutor
from netaddr import IPNetwork, IPAddress, AddrFormatError
@ -79,6 +82,31 @@ def to_bformat(value):
ndx = math.floor(math.log(value) / math.log(1000)) if value > 0 else 0
return "%s %s" % (round(value / math.pow(1000, ndx), 2), fileSizeTypes[ndx])
class AsyncLookup:
def __init__(self):
self._results = {}
async def request_ittr(self, addresses):
self._results = {}
dnsResolver = Resolver()
dnsResolver.timeout = 2
tasks = []
for adres in addresses:
tasks.append(dnsResolver.resolve_address(adres))
responses = await asyncio.gather(*tasks, return_exceptions=True)
for response in responses:
if type(response) is dns.resolver.Answer:
addr = ".".join(reversed(response.canonical_name.to_text().replace('.in-addr.arpa.', '').split('.')))
for item in response.response.answer:
if type(item) is dns.rrset.RRset and len(item.items) > 0:
self._results[addr] = str(list(item.items)[0])
def collect(self, addresses):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.run(self.request_ittr(addresses))
loop.close()
return self._results
if __name__ == '__main__':
result = dict()
@ -152,7 +180,9 @@ if __name__ == '__main__':
# XXX: sort output, limit output results to max 200 (safety precaution)
top_hosts = sorted(agg_results.values(), key=lambda x: x['rate_bits'], reverse=True)[:200]
reverse_lookup = AsyncLookup().collect([x['address'] for x in top_hosts])
for host in top_hosts:
host['rname'] = reverse_lookup[host['address']] if host['address'] in reverse_lookup else ""
host['rate_in'] = to_bformat(host['rate_bits_in'])
host['rate_out'] = to_bformat(host['rate_bits_out'])
host['rate'] = to_bformat(host['rate_bits'])