From 66e6f9b3f76d7bf2f6824f5e1ae22e4f0e448dc3 Mon Sep 17 00:00:00 2001 From: Jokob-sk Date: Mon, 2 Jan 2023 10:01:59 +1100 Subject: [PATCH] Pholus hanging workaround --- back/pialert.py | 71 ++++++++++++++++---------- front/maintenance.php | 10 ++-- front/php/templates/language/en_us.php | 2 +- pholus/pholus3.py | 20 ++++++-- 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/back/pialert.py b/back/pialert.py index cdf3f3a4..a32b4794 100755 --- a/back/pialert.py +++ b/back/pialert.py @@ -1741,7 +1741,7 @@ def update_devices_names (): # file_print(sql.rowcount) #------------------------------------------------------------------------------- -def performPholusScan (timeout): +def performPholusScan (timeoutSec): # scan every interface for subnet in userSubnets: @@ -1755,44 +1755,59 @@ def performPholusScan (timeout): mask = temp[0].strip() interface = temp[1].strip() - file_print(" Pholus scan on [interface] ", interface, " [mask] " , mask) - + # logging & updating app state updateState("Scan: Pholus") - file_print('[', timeNow(), '] Scan: Pholus for ', str(timeout), 's ('+ str(round(int(timeout) / 60, 1)) +'min)') + file_print('[', timeNow(), '] Scan: Pholus for ', str(timeoutSec), 's ('+ str(round(int(timeoutSec) / 60, 1)) +'min)') + file_print(" Pholus scan on [interface] ", interface, " [mask] " , mask) - adjustedTimeout = str(round(int(timeout) / 2, 0)) # the scan alwasy lasts 2x as long, so the desired user time from settings needs to be halved + # the scan always lasts 2x as long, so the desired user time from settings needs to be halved + adjustedTimeout = str(round(int(timeoutSec) / 2, 0)) + pholus_args = ['python3', '/home/pi/pialert/pholus/pholus3.py', interface, "-rdns_scanning", mask, "-stimeout", adjustedTimeout] # Execute command + output = "" + try: - # try runnning a subprocess - output = subprocess.check_output (pholus_args, universal_newlines=True) + # try runnning a subprocess with a forced (timeout + 30 seconds) in case the subprocess hangs + output = subprocess.check_output (pholus_args, universal_newlines=True, stderr=subprocess.STDOUT, timeout=(timeoutSec + 30)) except subprocess.CalledProcessError as e: # An error occured, handle it file_print(e.output) - file_print("Error - PholusScan - check logs") - output = "" + file_print(" Error - PholusScan - check logs") + except subprocess.TimeoutExpired as timeErr: + file_print(' Pholus TIMEOUT - the process forcefully terminated as timeout reached') - if output != "": - file_print('[', timeNow(), '] Scan: Pholus SUCCESS') - write_file (logPath + '/pialert_pholus_lastrun.log', output) - for line in output.split("\n"): - append_line_to_file (logPath + '/pialert_pholus.log', line +'\n') - - # build SQL query parameters to insert into the DB - params = [] - - for line in output.split("\n"): - columns = line.split("|") - if len(columns) == 4: - params.append(( interface + " " + mask, timeNow() , columns[0].replace(" ", ""), columns[1].replace(" ", ""), columns[2].replace(" ", ""), columns[3], '')) - - if len(params) > 0: - sql.executemany ("""INSERT INTO Pholus_Scan ("Info", "Time", "MAC", "IP_v4_or_v6", "Record_Type", "Value", "Extra") VALUES (?, ?, ?, ?, ?, ?, ?)""", params) - commitDB () - - else: + if output == "": # check if the subprocess failed file_print('[', timeNow(), '] Scan: Pholus FAIL - check logs') + else: + file_print('[', timeNow(), '] Scan: Pholus SUCCESS') + + # check the last run output + f = open(logPath + '/pialert_pholus_lastrun.log', 'r+') + newLines = f.read().split('\n') + f.close() + + # cleanup - select only lines containing a separator to filter out unnecessary data + newLines = list(filter(lambda x: '|' in x, newLines)) + + # regular logging + for line in newLines: + append_line_to_file (logPath + '/pialert_pholus.log', line +'\n') + + # build SQL query parameters to insert into the DB + params = [] + + for line in newLines: + columns = line.split("|") + if len(columns) == 4: + params.append(( interface + " " + mask, timeNow() , columns[0].replace(" ", ""), columns[1].replace(" ", ""), columns[2].replace(" ", ""), columns[3], '')) + + if len(params) > 0: + sql.executemany ("""INSERT INTO Pholus_Scan ("Info", "Time", "MAC", "IP_v4_or_v6", "Record_Type", "Value", "Extra") VALUES (?, ?, ?, ?, ?, ?, ?)""", params) + commitDB () + + #------------------------------------------------------------------------------- diff --git a/front/maintenance.php b/front/maintenance.php index bb4b2744..ea1f5632 100755 --- a/front/maintenance.php +++ b/front/maintenance.php @@ -397,16 +397,16 @@ if (isset($_POST['submit']) && submit && isset($_POST['skinselector_set'])) {
-
-
pialert_pholus_subp.log
- +
pialert_pholus_lastrun.log
+
- +
@@ -732,7 +732,7 @@ function scrollDown() tempArea = $('#pialert_pholus_log'); $(tempArea[0]).scrollTop(tempArea[0].scrollHeight); - tempArea = $('#pialert_pholus_subp_log'); + tempArea = $('#pialert_pholus_lastrun_log'); $(tempArea[0]).scrollTop(tempArea[0].scrollHeight); } diff --git a/front/php/templates/language/en_us.php b/front/php/templates/language/en_us.php index 8c0a0e1d..4f109d99 100755 --- a/front/php/templates/language/en_us.php +++ b/front/php/templates/language/en_us.php @@ -427,7 +427,7 @@ $lang['en_us'] = array( 'settings_missing' => 'Not all settings loaded, refresh the page! This is probably caused by a high load on the database.', 'settings_missing_block' => 'You can\'t save your settings without specifying all setting keys. Refresh the page. This is probably caused by a high load on the database.', -'settings_old' => 'The settings in the DB (shown on this page) are outdated. This is probably caused by a running scan. The settings were saved, but the background process didn\'t have time to import it yet. You can wait until the settings get refreshed so you don\'t overwrite your old values. Feel free to save your settings either way if you don\'t mind losing the settings between the last save and now. There are also backup files created if you need to compare your settings later.', +'settings_old' => 'The settings in the DB (shown on this page) are outdated. This is probably caused by a running scan. The settings were saved in the pialert.conf file, but the background process didn\'t have time to import it yet to the DB. You can wait until the settings get refreshed so you don\'t overwrite your old values. Feel free to save your settings either way if you don\'t mind losing the settings between the last save and now. There are also backup files created if you need to compare your settings later.', //General 'SCAN_SUBNETS_name' => 'Subnets to scan', diff --git a/pholus/pholus3.py b/pholus/pholus3.py index 735e7a42..c4deba64 100644 --- a/pholus/pholus3.py +++ b/pholus/pholus3.py @@ -31,7 +31,6 @@ logPath = runPathTmp + '/front/log' def timeNow(): return datetime.datetime.now().replace(microsecond=0) - def write_file (pPath, pText): # Write the text depending using the correct python version if sys.version_info < (3, 0): @@ -43,18 +42,24 @@ def write_file (pPath, pText): file.write (pText) file.close() +# Empty the last run log file +write_file(logPath + "/pialert_pholus_lastrun.log", "") + def file_print(*args): result = '' - file = open(logPath + "/pialert_pholus_subp.log", "a") + file = open(logPath + "/pialert_pholus_lastrun.log", "a") for arg in args: result += str(arg) print(result) file.write(result + '\n') file.close() +# Empty the last run log file +write_file(logPath + "/pialert_pholus_subp_pr.log", "") +# For separate logging of the multiprocess subprocess def file_print_pr(*args): result = '' @@ -134,6 +139,7 @@ def get_my_ipv4_addr(interface): ########################## class Sniffer(): def __init__ (self,filter,interface,sniffer_timeout,queue,dns,show_ttl,dos_ttl, conflict, ttl,d4, d6, target_mac, auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,hlimit,workstation,printer,googlecast,airtv,flood,flooding_timeout,flooding_interval, v4, v6): + file_print(">>>>>>> sniffer_args: ", filter," ",interface," ",sniffer_timeout," ",queue," ",dns," ",show_ttl," ",dos_ttl," ", conflict," ", ttl," ",d4," ", d6," ", target_mac," ", auto_fake_responses," ",source_IPv6," ", source_IPv4," ", target_mac1," ", target_mac2," ",source_mac," ",hlimit," ",workstation," ",printer," ",googlecast," ",airtv," ",flood," ",flooding_timeout," ",flooding_interval," ", v4," ", v6) self.filter = filter self.interface = interface file_print(">>>>>>> sniffer_timeout: ", sniffer_timeout) @@ -172,6 +178,7 @@ class Sniffer(): ################################## class Sniffer_Offline(): def __init__ (self,interface,queue,show_ttl,d4, d6, target_mac,auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,hlimit): + file_print(">>>>>>> Timestamp 0.0210aa: ", timeNow()) self.interface = interface self.queue=queue self.show_ttl=show_ttl @@ -194,7 +201,7 @@ class Sniffer_Offline(): ######################################################################## def ext_handler(packets,queue,unidns,show_ttl,print_res,dos_ttl,conflict,ttl,interface,d4,d6,target_mac,auto_fake_responses,source_IPv6,source_IPv4,target_mac1,target_mac2,source_mac,hlimit,workstation,printer,googlecast,airtv,flood,flooding_timeout,flodding_interval,v4,v6): - file_print(">>>>>>> Timestamp 0.0210: ", timeNow()) + # file_print(">>>>>>> Timestamp 0.0210: ", timeNow()) file_print_pr(">>>>>>> Timestamp 0.0210: ", timeNow()) file_print_pr(">>>>>>> Test ") @@ -270,6 +277,7 @@ def ext_handler(packets,queue,unidns,show_ttl,print_res,dos_ttl,conflict,ttl,int file_print_pr(">>>>>>> Test 6") sendp(new_packet,iface=interface) file_print_pr(">>>>>>> Test 6.1") + elif auto_fake_responses or (not (dos_ttl or conflict)): ## IF THIS IS A QUERY ## file_print_pr(">>>>>>> Test 6.2") @@ -668,6 +676,8 @@ def ext_handler(packets,queue,unidns,show_ttl,print_res,dos_ttl,conflict,ttl,int file_print_pr(">>>>>>> Test 6.2720055") else: file_print_pr(">>>>>>> Test 3") + + file_print_pr(">>>>>>> Test 6.272005599") ######################################## @@ -918,7 +928,9 @@ def main(): file_print("I will sniff for ",values.sniffer_timeout," seconds, unless interrupted by Ctrl-C") file_print("Press Ctrl-C to exit") try: + file_print(">>>>>>> Timestamp 0.0210ab: ", timeNow()) Sniffer(myfilter, values.interface, float(values.sniffer_timeout),q,values.dns,values.show_ttl, values.dos_ttl, values.conflict, values.ttl,values.d4, values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6) + file_print(">>>>>>> Timestamp 0.0210abc: ", timeNow()) except KeyboardInterrupt: file_print("Exiting on user's request 1") exit(0) @@ -1057,7 +1069,7 @@ def main(): ############################################################################################ if pr: try: - file_print(">>>>>>> Timestamp 6.1: ", timeNow()) + file_print(">>>>>>> Timestamp 6.1000: ", timeNow()) pr.join() file_print(">>>>>>> Timestamp 6.2: ", timeNow()) except KeyboardInterrupt: