diff --git a/back/pialert.py b/back/pialert.py index 895159b5..11b56279 100755 --- a/back/pialert.py +++ b/back/pialert.py @@ -291,12 +291,13 @@ PHOLUS_RUN = 'once' PHOLUS_RUN_TIMEOUT = 300 PHOLUS_RUN_SCHD = '0 4 * * *' -# Pholus settings +# Nmap settings # ---------------------- NMAP_ACTIVE = False NMAP_TIMEOUT = 120 NMAP_RUN = 'once' NMAP_RUN_SCHD = '0 2 * * *' +NMAP_ARGS = '-p -10000' #=============================================================================== # Initialise user defined values @@ -373,7 +374,7 @@ def importConfig (): # Pholus global PHOLUS_ACTIVE, PHOLUS_TIMEOUT, PHOLUS_FORCE, PHOLUS_DAYS_DATA, PHOLUS_RUN, PHOLUS_RUN_SCHD, PHOLUS_RUN_TIMEOUT # Nmap - global NMAP_ACTIVE, NMAP_TIMEOUT, NMAP_RUN, NMAP_RUN_SCHD + global NMAP_ACTIVE, NMAP_TIMEOUT, NMAP_RUN, NMAP_RUN_SCHD, NMAP_ARGS # get config file @@ -467,6 +468,7 @@ def importConfig (): NMAP_TIMEOUT = check_config_dict('NMAP_TIMEOUT', NMAP_TIMEOUT , config_dict) NMAP_RUN = check_config_dict('NMAP_RUN', NMAP_RUN , config_dict) NMAP_RUN_SCHD = check_config_dict('NMAP_RUN_SCHD', NMAP_RUN_SCHD , config_dict) + NMAP_ARGS = check_config_dict('NMAP_ARGS', NMAP_ARGS , config_dict) # Code_Name, Display_Name, Description, Type, Options, Value, Group @@ -550,7 +552,8 @@ def importConfig (): ('NMAP_ACTIVE', 'Enable Nmap scans', '', 'boolean', '', '' , str(NMAP_ACTIVE) , 'Nmap'), ('NMAP_TIMEOUT', 'Nmap timeout', '', 'integer', '', '' , str(NMAP_TIMEOUT) , 'Nmap'), ('NMAP_RUN', 'Nmap enable schedule', '', 'selecttext', "['none', 'once', 'schedule']", '' , str(NMAP_RUN) , 'Nmap'), - ('NMAP_RUN_SCHD', 'Nmap schedule', '', 'text', '', '' , str(NMAP_RUN_SCHD) , 'Nmap') + ('NMAP_RUN_SCHD', 'Nmap schedule', '', 'text', '', '' , str(NMAP_RUN_SCHD) , 'Nmap'), + ('NMAP_ARGS', 'Nmap custom arguments', '', 'text', '', '' , str(NMAP_ARGS) , 'Nmap') ] @@ -698,17 +701,29 @@ def main (): if run: nmapSchedule.last_run = datetime.datetime.now(tz).replace(microsecond=0) - performNmapScan(NMAP_TIMEOUT) + performNmapScan(get_all_devices()) - # Perform an arp-scan if not disable with a file + # Perform an arp-scan if not disabled with a file if last_network_scan + datetime.timedelta(minutes=SCAN_CYCLE_MINUTES) < time_started and os.path.exists(STOPARPSCAN) == False: last_network_scan = time_started cycle = 1 # network scan scan_network() + + # Check if new devices need to be scanned with Nmap + if NMAP_ACTIVE: + sql.execute ("""SELECT eve_IP as dev_LastIP, eve_MAC as dev_MACq FROM Events_Devices + WHERE eve_PendingAlertEmail = 1 + AND eve_EventType = 'New Device' + ORDER BY eve_DateTime""") + + rows = sql.fetchall() + commitDB() + + performNmapScan(rows) # Reporting if cycle in check_report: - email_reporting() + send_notifications() # clean up the DB once a day if last_cleanup + datetime.timedelta(hours = 24) < time_started: @@ -942,6 +957,17 @@ def cleanup_database (): AND Pholus_Scan.Value = p2.Value AND Pholus_Scan.Record_Type = p2.Record_Type );""") + + # De-Dupe (de-duplicate - remove duplicate entries) from the Nmap_Scan table + file_print(' Nmap_Scan: Delete all duplicates') + sql.execute ("""DELETE FROM Nmap_Scan + WHERE rowid > ( + SELECT MIN(rowid) FROM Nmap_Scan p2 + WHERE Nmap_Scan.MAC = p2.MAC + AND Nmap_Scan.Port = p2.Port + AND Nmap_Scan.State = p2.State + AND Nmap_Scan.Service = p2.Service + );""") # Shrink DB file_print(' Shrink Database') @@ -1737,15 +1763,8 @@ def update_devices_names (): # file_print(sql.rowcount) #------------------------------------------------------------------------------- -def performNmapScan(timeoutSec, ip = ""): - devicesToScan = [] - # Check if we got a specific IP or if we scan all devices - if ip != "": - devicesToScan.append(ip) - else: - # Get all devices - devicesToScan = get_all_devices() - +def performNmapScan(devicesToScan): + timeoutSec = NMAP_TIMEOUT updateState("Scan: Nmap") @@ -1759,7 +1778,10 @@ def performNmapScan(timeoutSec, ip = ""): # nmap -p portFrom-portTo 192.168.1.3 # nmap -p -10000 192.168.1.3 - nmapArgs = ['nmap', '-p', "-10000", device["dev_LastIP"]] + nmapArgs = ['nmap'] + NMAP_ARGS.split() + [device["dev_LastIP"]] + # nmapArgs = nmapArgs.append(NMAP_ARGS.split()) + # nmapArgs = nmapArgs.append(device["dev_LastIP"]) + try: # try runnning a subprocess with a forced (timeout + 30 seconds) in case the subprocess hangs @@ -1802,8 +1824,8 @@ def performNmapScan(timeoutSec, ip = ""): params.append((device["dev_MAC"], timeNow(), line.split()[0], line.split()[1], line.split()[2], '')) elif 'Nmap done' in line: duration = line.split('scanned in ')[1] - else: - file_print('>>>>>', line, 'len', len(line.split())) + # else: + # file_print('>>>>>', line, 'len', len(line.split())) index += 1 if len(params) > 0: @@ -2176,7 +2198,7 @@ def skip_repeated_notifications (): # create a json for webhook and mqtt notifications to provide further integration options json_final = [] -def email_reporting (): +def send_notifications (): global mail_text global mail_html diff --git a/front/deviceDetails.php b/front/deviceDetails.php index 39007705..4530eeda 100755 --- a/front/deviceDetails.php +++ b/front/deviceDetails.php @@ -460,9 +460,9 @@
- +

Online Speedtest

@@ -482,9 +482,9 @@ if ($_REQUEST['mac'] == 'Internet') { }) } - +

Nmap Scans

+ + + + + + + + + + + + + + + + + +
IndexTimePortStateServiceExtra
+ + @@ -1612,9 +1632,57 @@ function initializeTabsNew () { { loadPholus(); } + if(target == "#panNmap") + { + loadNmap(); + } }); } +// ----------------------------------------------------------------------------- + +function loadNmap() +{ + // console.log(mac) + // console.log('php/server/devices.php?action=getPholus&mac='+ mac) + + $(".deviceSpecific").remove(); + + $.get('php/server/devices.php?action=getNmap&mac='+ mac, function(data) { + + data = sanitize(data); + + if(data != "false" && $.trim(data) != []) + { + var listData = JSON.parse(data); + var order = 1; + + // console.log(listData) + + // console.log(listData[0].MAC) + + tableRows = ""; + + // for each item + listData.forEach(function (item, index) { + tableRows += ''+item.Index+''+item.Time+''+item.Port+''+item.State+''+item.Service+''+item.Extra+''; + }); + + $("#tableNmapBody").html($("#tableNmapBody").html()+tableRows); + // $("#tablePholusPlc").attr("style", "display:none"); + $("#tableNmapPlc").hide(); + } + else + { + // console.log("else") + $("#tableNmapPlc").show(); + $(".deviceSpecific").remove(); + } + }); +} + +// ----------------------------------------------------------------------------- + function loadPholus() { // console.log(mac) @@ -1760,10 +1828,6 @@ $("#"+tableId).attr("data-mac", mac) $('#'+tableId).on( 'length.dt', function ( e, settings, len ) { setParameter (parSessionsRows, len); - // Sync Rows in both datatables - // if ( $('#tableEvents').DataTable().page.len() != len) { - // $('#tableEvents').DataTable().page.len( len ).draw(); - // } } ); } @@ -1777,11 +1841,16 @@ window.onload = function async() function reloadTab() { - // load tab data only when needed (tab change) + // tab loaded without switching if(getCache("activeDevicesTab") == "tabPholus") { loadPholus(); } + + if(getCache("activeDevicesTab") == "tabNmap") + { + loadNmap(); + } } diff --git a/front/php/server/devices.php b/front/php/server/devices.php index 22928df0..dc4f8998 100755 --- a/front/php/server/devices.php +++ b/front/php/server/devices.php @@ -56,6 +56,7 @@ case 'getGroups': getGroups(); break; case 'getLocations': getLocations(); break; case 'getPholus': getPholus(); break; + case 'getNmap': getNmap(); break; default: logServerConsole ('Action: '. $action); break; } @@ -900,7 +901,7 @@ function getLocations() { } //------------------------------------------------------------------------------ -// Query the List of locations +// Query the List of Pholus entries //------------------------------------------------------------------------------ function getPholus() { global $db; @@ -947,6 +948,53 @@ function getPholus() { } } +//------------------------------------------------------------------------------ +// Query the List of Nmap entries +//------------------------------------------------------------------------------ +function getNmap() { + global $db; + + // SQL + $mac = $_REQUEST['mac']; + + if ($mac == "Internet") // Not performing data lookup for router (improvement idea for later maybe) + { + echo "false"; + return; + } + + if (false === filter_var($mac , FILTER_VALIDATE_MAC)) { + throw new Exception('Invalid mac address'); + } + else{ + $sql = 'SELECT * from Nmap_Scan where MAC ="'.$mac.'" '; + + // array + $tableData = array(); + + // execute query + $result = $db->query($sql); + while ($row = $result -> fetchArray (SQLITE3_ASSOC)){ + // Push row data + $tableData[] = array( 'Index' => $row['Index'], + 'MAC' => $row['MAC'], + 'Port' => $row['Port'], + 'Time' => $row['Time'], + 'State' => $row['State'], + 'Service' => $row['Service'], + 'Extra' => $row['Extra']); + } + + if(count($tableData) == 0) + { + echo "false"; + } else{ + // Return json + echo (json_encode ($tableData)); + } + } +} + //------------------------------------------------------------------------------ // Status Where conditions //------------------------------------------------------------------------------ diff --git a/front/php/templates/language/en_us.php b/front/php/templates/language/en_us.php index 9ec0d82b..410b9a03 100755 --- a/front/php/templates/language/en_us.php +++ b/front/php/templates/language/en_us.php @@ -155,6 +155,7 @@ $lang['en_us'] = array( 'DevDetail_Tab_Events' => 'Events', 'DevDetail_Tab_Pholus' => 'Pholus', 'DevDetail_Tab_PholusEmpty' => 'Nothing sniffed out with Pholus for this device.', +'DevDetail_Tab_NmapEmpty' => 'No ports detected with Nmap on this device.', 'DevDetail_MainInfo_Title' => 'Main Info', 'DevDetail_MainInfo_mac' => 'MAC', 'DevDetail_MainInfo_Name' => 'Name', @@ -453,7 +454,7 @@ the arp-scan will take hours to complete instead of seconds. 'PIALERT_WEB_PASSWORD_name' => 'Login password', 'PIALERT_WEB_PASSWORD_description' => 'The default password is 123456. To change the password run /home/pi/pialert/back/pialert-cli in the container', 'INCLUDED_SECTIONS_name' => 'Notify on', -'INCLUDED_SECTIONS_description' => 'Specifies which events trigger notifications. Remove the event type(s) you don\'t want to get notified on. This setting overrides device-specific settings in the UI. (CTRL + Click to select / deselect).', +'INCLUDED_SECTIONS_description' => 'Specifies which events trigger notifications. Remove the event type(s) you don\'t want to get notified on. This setting overrides device-specific settings in the UI. (CTRL + Click to select / deselect).', 'SCAN_CYCLE_MINUTES_name' => 'Scan cycle delay', 'SCAN_CYCLE_MINUTES_description' => 'The delay between scans. If using arp-scan, the scan time itself depends on the number of IP addresses to check. This is influenced by the network mask set in the SCAN_SUBNETS setting at the top. Every IP takes a couple seconds to scan.', 'DAYS_TO_KEEP_EVENTS_name' => 'Delete events older than', @@ -564,20 +565,22 @@ the arp-scan will take hours to complete instead of seconds. 'PHOLUS_RUN_TIMEOUT_name' => 'Scheduled run timeout', 'PHOLUS_RUN_TIMEOUT_description' => 'The timeout in seconds for the scheduled Pholus scan. Same notes regarding the duration apply as on the PHOLUS_TIMEOUT setting. A scheduled scan doesn\'t check if there are (unknown) or (name not found) devices, the scan is executed either way.', 'PHOLUS_RUN_SCHD_name' => 'Schedule', -'PHOLUS_RUN_SCHD_description' => 'Only run if you select schedule in the PHOLUS_RUN setting. Make sure you enter the schedule in the correct cron-like format +'PHOLUS_RUN_SCHD_description' => 'Only enabled if you select schedule in the PHOLUS_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 0 4 * * * will run the scan after 4 am in the TIMEZONE you set above. Will be run NEXT time the time passes.', 'PHOLUS_DAYS_DATA_name' => 'Data retention', 'PHOLUS_DAYS_DATA_description' => 'How many days of Pholus scan entries should be kept (globally, not device specific!). The pialert_pholus.log file is not touched. Enter 0 to disable.', // Nmap 'NMAP_ACTIVE_name' => 'Cycle run', -'NMAP_ACTIVE_description' => 'If enabled this will execute the scan before every network scan cycle. For a scheduled or one-off scan, check the NMAP_RUN setting.', +'NMAP_ACTIVE_description' => 'If enabled this will execute the scan every time a new device is found on the network. For a scheduled or one-off scan, check the NMAP_RUN setting.', 'NMAP_TIMEOUT_name' => 'Run timeout', -'NMAP_TIMEOUT_description' => 'Maximum time to wait for an Nmap scan to finish.', +'NMAP_TIMEOUT_description' => 'Maximum time to wait for an Nmap scan to finish on any device.', 'NMAP_RUN_name' => 'Scheduled run', 'NMAP_RUN_description' => 'Enable a regular Nmap scan on your network on all devices. The scheduling settings can be found below. If you select once Nmap is run only once on start for the time specified in NMAP_TIMEOUT setting.', 'NMAP_RUN_SCHD_name' => 'Schedule', -'NMAP_RUN_SCHD_description' => 'Only run if you select schedule in the NMAP_RUN setting. Make sure you enter the schedule in the correct cron-like format.', +'NMAP_RUN_SCHD_description' => 'Only enabled if you select schedule in the NMAP_RUN setting. Make sure you enter the schedule in the correct cron-like format.', +'NMAP_ARGS_name' => 'Arguments', +'NMAP_ARGS_description' => 'Arguments used to run the Nmap scan. Be careful to specify the arguments correctly. For example -p -10000 scans ports from 1 to 10000.', ); diff --git a/front/settings.php b/front/settings.php index dd24d401..41c4cd14 100644 --- a/front/settings.php +++ b/front/settings.php @@ -247,7 +247,7 @@ CommitDB();