All colors are beautiful for py-flow-info.

* instance alias is now mandatory (will be required for future use-cases)

Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
This commit is contained in:
Toni Uhlig
2021-01-26 19:07:16 +01:00
parent 25c23e3d23
commit 102b61175c
3 changed files with 83 additions and 11 deletions

View File

@@ -8,6 +8,12 @@ import os
import scapy.all
import stat
import socket
try:
from colorama import Back, Fore, Style
USE_COLORAMA=True
except ModuleNotFoundError:
print('Python module colorama not found, using fallback.')
USE_COLORAMA=False
DEFAULT_HOST = '127.0.0.1'
DEFAULT_PORT = 7000
@@ -34,11 +40,52 @@ FLOW_EVENTS = [ ('Invalid','invalid'), ('New','new'), ('End','end'), ('Idle','id
('Detected','detected'), ('Detection-Update','detection-update'), ('Not-Detected','not-detected') ]
class TermColor:
HINT = '\033[33m'
WARNING = '\033[93m'
FAIL = '\033[91m'
BOLD = '\033[1m'
END = '\033[0m'
BLINK = "\x1b[5m"
BLINK = '\x1b[5m'
if USE_COLORAMA is True:
COLOR_TUPLES = [ (Fore.BLUE, [Back.RED, Back.MAGENTA, Back.WHITE]),
(Fore.CYAN, [Back.MAGENTA, Back.RED, Back.WHITE]),
(Fore.GREEN, [Back.YELLOW, Back.RED, Back.MAGENTA, Back.WHITE]),
(Fore.MAGENTA, [Back.CYAN, Back.BLUE, Back.WHITE]),
(Fore.RED, [Back.GREEN, Back.BLUE, Back.WHITE]),
(Fore.WHITE, [Back.BLACK, Back.MAGENTA, Back.RED, Back.BLUE]),
(Fore.YELLOW, [Back.RED, Back.CYAN, Back.BLUE, Back.WHITE]),
(Fore.LIGHTBLUE_EX, [Back.LIGHTRED_EX, Back.RED]),
(Fore.LIGHTCYAN_EX, [Back.LIGHTMAGENTA_EX, Back.MAGENTA]),
(Fore.LIGHTGREEN_EX, [Back.LIGHTYELLOW_EX, Back.YELLOW]),
(Fore.LIGHTMAGENTA_EX, [Back.LIGHTCYAN_EX, Back.CYAN]),
(Fore.LIGHTRED_EX, [Back.LIGHTGREEN_EX, Back.GREEN]),
(Fore.LIGHTWHITE_EX, [Back.LIGHTBLACK_EX, Back.BLACK]),
(Fore.LIGHTYELLOW_EX, [Back.LIGHTRED_EX, Back.RED]) ]
@staticmethod
def calcColorHash(string):
h = 0
for char in string:
h += ord(char)
return h
@staticmethod
def getColorsByHash(string):
h = TermColor.calcColorHash(string)
tuple_index = h % len(TermColor.COLOR_TUPLES)
bg_tuple_index = h % len(TermColor.COLOR_TUPLES[tuple_index][1])
return (TermColor.COLOR_TUPLES[tuple_index][0],
TermColor.COLOR_TUPLES[tuple_index][1][bg_tuple_index])
@staticmethod
def setColorByString(string):
if USE_COLORAMA is True:
fg_color, bg_color = TermColor.getColorsByHash(string)
color_hash = TermColor.calcColorHash(string)
return '{}{}{}{}{}'.format(Style.BRIGHT, fg_color, bg_color, string, Style.RESET_ALL)
else:
return '{}{}{}'.format(TermColor.BOLD, string, TermColor.END)
class nDPIsrvdSocket:
def __init__(self):

View File

@@ -41,9 +41,19 @@ def parse_json_str(json_str):
else TermColor.FAIL + TermColor.BOLD + TermColor.BLINK + 'RISK' + TermColor.END,
ndpi_frisk[:-2])
instance_and_source = ''
instance_and_source += '[{}]'.format(TermColor.setColorByString(j['alias']))
instance_and_source += '[{}]'.format(TermColor.setColorByString(j['source']))
flow_event_name = ''
if nDPIdEvent.FlowEventName == 'guessed' or nDPIdEvent.FlowEventName == 'undetected':
flow_event_name += '{}{:>16}{}'.format(TermColor.HINT, nDPIdEvent.FlowEventPrettyName, TermColor.END)
else:
flow_event_name += '{:>16}'.format(nDPIdEvent.FlowEventPrettyName)
if j['l3_proto'] == 'ip4':
print('{:>16}: [{:.>6}] [{}][{:.>5}] [{:.>15}]{} -> [{:.>15}]{} {}' \
''.format(nDPIdEvent.FlowEventPrettyName,
print('{} {}: [{:.>6}] [{}][{:.>5}] [{:.>15}]{} -> [{:.>15}]{} {}' \
''.format(instance_and_source, flow_event_name,
j['flow_id'], j['l3_proto'], j['l4_proto'],
j['src_ip'].lower(),
'[{:.>5}]'.format(j['src_port']) if 'src_port' in j else '',
@@ -51,8 +61,8 @@ def parse_json_str(json_str):
'[{:.>5}]'.format(j['dst_port']) if 'dst_port' in j else '',
ndpi_proto_categ))
elif j['l3_proto'] == 'ip6':
print('{:>16}: [{:.>6}] [{}][{:.>5}] [{:.>39}]{} -> [{:.>39}]{} {}' \
''.format(nDPIdEvent.FlowEventPrettyName,
print('{} {}: [{:.>6}] [{}][{:.>5}] [{:.>39}]{} -> [{:.>39}]{} {}' \
''.format(instance_and_source, flow_event_name,
j['flow_id'], j['l3_proto'], j['l4_proto'],
j['src_ip'].lower(),
'[{:.>5}]'.format(j['src_port']) if 'src_port' in j else '',
@@ -63,7 +73,7 @@ def parse_json_str(json_str):
raise RuntimeError('unsupported l3 protocol: {}'.format(j['l3_proto']))
if len(ndpi_frisk) > 0:
print('{:>18}{}'.format('', ndpi_frisk))
print('{} {:>18}{}'.format(instance_and_source, '', ndpi_frisk))
if __name__ == '__main__':

25
nDPId.c
View File

@@ -940,10 +940,7 @@ static void jsonize_basic(struct nDPId_reader_thread * const reader_thread)
ndpi_serialize_string_int32(&workflow->ndpi_serializer, "thread_id", reader_thread->array_index);
ndpi_serialize_string_uint32(&workflow->ndpi_serializer, "packet_id", workflow->packets_captured);
ndpi_serialize_string_string(&workflow->ndpi_serializer, "source", pcap_file_or_interface);
if (instance_alias != NULL)
{
ndpi_serialize_string_string(&workflow->ndpi_serializer, "alias", instance_alias);
}
ndpi_serialize_string_string(&workflow->ndpi_serializer, "alias", instance_alias);
}
static void jsonize_daemon(struct nDPId_reader_thread * const reader_thread, enum daemon_event event)
@@ -2554,7 +2551,9 @@ static int parse_options(int argc, char ** argv)
"\t-p\tWrite the daemon PID to the given file path.\n"
"\t-u\tChange UID to the numeric value of user.\n"
"\t-g\tChange GID to the numeric value of group.\n"
"\t-a\tSet an optional name of this daemon instance which will be part of every JSON message.\n"
"\t-a\tSet an alias name of this daemon instance which will be part of every JSON message.\n"
"\t \tThis value is required for correct flow handling of multiple instances and should be unique.\n"
"\t \tDefaults to your hostname.\n"
"\t-o\t(Carefully) Tune some daemon options. See subopts below.\n\n";
while ((opt = getopt(argc, argv, "hi:IEP:lc:dp:u:g:a:o:")) != -1)
@@ -2688,6 +2687,22 @@ static int validate_options(char const * const arg0)
{
int retval = 0;
if (instance_alias == NULL) {
char hname[256];
errno = 0;
if (gethostname(hname, sizeof(hname)) != 0) {
fprintf(stderr, "%s: Could not retrieve your hostname: %s\n", arg0, strerror(errno));
retval = 1;
} else {
instance_alias = strdup(hname);
fprintf(stderr,
"%s: No instance alias given, using your hostname '%s'\n", arg0, instance_alias);
if (instance_alias == NULL) {
retval = 1;
}
}
}
if (max_flows_per_thread < 128 || max_flows_per_thread > nDPId_MAX_FLOWS_PER_THREAD)
{
fprintf(stderr,