This commit is contained in:
Jokob-sk
2023-01-02 16:06:13 +11:00
parent 8878853319
commit 86d2e6258d
4 changed files with 173 additions and 13 deletions

View File

@@ -291,6 +291,12 @@ PHOLUS_RUN = 'once'
PHOLUS_RUN_TIMEOUT = 300
PHOLUS_RUN_SCHD = '0 4 * * *'
# Pholus settings
# ----------------------
NMAP_ACTIVE = False
NMAP_TIMEOUT = 120
NMAP_RUN = 'once'
NMAP_RUN_SCHD = '0 2 * * *'
#===============================================================================
# Initialise user defined values
@@ -366,6 +372,9 @@ def importConfig ():
global PIHOLE_ACTIVE, DHCP_ACTIVE
# 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
# get config file
config_file = Path(fullConfPath)
@@ -453,6 +462,12 @@ def importConfig ():
PHOLUS_RUN_SCHD = check_config_dict('PHOLUS_RUN_SCHD', PHOLUS_RUN_SCHD , config_dict)
PHOLUS_DAYS_DATA = check_config_dict('PHOLUS_DAYS_DATA', PHOLUS_DAYS_DATA , config_dict)
# Nmap
NMAP_ACTIVE = check_config_dict('NMAP_ACTIVE', NMAP_ACTIVE , config_dict)
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)
# Code_Name, Display_Name, Description, Type, Options, Value, Group
settings = [
@@ -529,7 +544,14 @@ def importConfig ():
('PHOLUS_RUN', 'Pholus enable schedule', '', 'selecttext', "['none', 'once', 'schedule']", '' , str(PHOLUS_RUN) , 'Pholus'),
('PHOLUS_RUN_TIMEOUT', 'Pholus timeout schedule', '', 'integer', '', '' , str(PHOLUS_RUN_TIMEOUT) , 'Pholus'),
('PHOLUS_RUN_SCHD', 'Pholus schedule', '', 'text', '', '' , str(PHOLUS_RUN_SCHD) , 'Pholus'),
('PHOLUS_DAYS_DATA', 'Pholus keep days', '', 'integer', '', '' , str(PHOLUS_DAYS_DATA) , 'Pholus')
('PHOLUS_DAYS_DATA', 'Pholus keep days', '', 'integer', '', '' , str(PHOLUS_DAYS_DATA) , 'Pholus'),
# Nmap
('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')
]
# Insert into DB
@@ -550,12 +572,20 @@ def importConfig ():
# Update scheduler
global tz, mySchedules
tz = timezone(TIMEZONE)
pholusSchedule = Cron(PHOLUS_RUN_SCHD).schedule(start_date=datetime.datetime.now(tz))
# Init timezone in case it changed
tz = timezone(TIMEZONE)
# reset schedules
mySchedules = []
# init pholus schedule
pholusSchedule = Cron(PHOLUS_RUN_SCHD).schedule(start_date=datetime.datetime.now(tz))
mySchedules.append(serviceSchedule("pholus", pholusSchedule, pholusSchedule.next(), False))
# init nmap schedule
nmapSchedule = Cron(NMAP_RUN_SCHD).schedule(start_date=datetime.datetime.now(tz))
mySchedules.append(serviceSchedule("nmap", nmapSchedule, nmapSchedule.next(), False))
# Format and prepare the list of subnets
updateSubnets()
@@ -638,20 +668,38 @@ def main ():
if PHOLUS_RUN == "schedule" or PHOLUS_RUN == "once":
pholusSchedule = [sch for sch in mySchedules if sch.service == "pholus"][0]
runPholus = False
run = False
# run once after application starts
if PHOLUS_RUN == "once" and pholusSchedule.last_run == 0:
runPholus = True
run = True
# run if overdue scheduled time
if PHOLUS_RUN == "schedule":
runPholus = pholusSchedule.runScheduleCheck()
run = pholusSchedule.runScheduleCheck()
if runPholus:
if run:
pholusSchedule.last_run = datetime.datetime.now(tz).replace(microsecond=0)
performPholusScan(PHOLUS_RUN_TIMEOUT)
# Execute Nmap scheduled or one-off scan if enabled and run conditions fulfilled
if NMAP_RUN == "schedule" or NMAP_RUN == "once":
nmapSchedule = [sch for sch in mySchedules if sch.service == "nmap"][0]
run = False
# run once after application starts
if NMAP_RUN == "once" and nmapSchedule.last_run == 0:
run = True
# run if overdue scheduled time
if NMAP_RUN == "schedule":
run = nmapSchedule.runScheduleCheck()
if run:
nmapSchedule.last_run = datetime.datetime.now(tz).replace(microsecond=0)
performNmapScan(NMAP_TIMEOUT)
# Perform an arp-scan if not disable 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
@@ -1688,6 +1736,81 @@ def update_devices_names ():
# DEBUG - print number of rows updated
# 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()
updateState("Scan: Nmap")
file_print('[', timeNow(), '] Scan: Nmap for max ', str(timeoutSec), 's ('+ str(round(int(timeoutSec) / 60, 1)) +'min) per device')
file_print(" Estimated max delay: ", (len(devicesToScan) * int(timeoutSec)), 's ', '(', round((len(devicesToScan) * int(timeoutSec))/60,1) , 'min)' )
for device in devicesToScan:
# Execute command
output = ""
# nmap -p portFrom-portTo 192.168.1.3
# nmap -p -10000 192.168.1.3
nmapArgs = ['nmap', '-p', "-10000", device["dev_LastIP"]]
try:
# try runnning a subprocess with a forced (timeout + 30 seconds) in case the subprocess hangs
output = subprocess.check_output (nmapArgs, 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 - Nmap Scan - check logs")
except subprocess.TimeoutExpired as timeErr:
file_print(' Nmap TIMEOUT - the process forcefully terminated as timeout reached')
if output == "": # check if the subprocess failed
file_print('[', timeNow(), '] Scan: Nmap FAIL - check logs')
else:
file_print('[', timeNow(), '] Scan: Nmap SUCCESS')
# check the last run output
newLines = output.split('\n')
# regular logging
for line in newLines:
append_line_to_file (logPath + '/pialert_nmap.log', line +'\n')
# collect ports
params = []
index = 0
startCollecting = False
duration = ""
for line in newLines:
if 'Starting Nmap' in line:
if len(newLines) > index+1 and 'Note: Host seems down' in newLines[index+1]:
break # this entry is empty
elif 'PORT' in line and 'STATE' in line and 'SERVICE' in line:
startCollecting = True
elif 'PORT' in line and 'STATE' in line and 'SERVICE' in line:
startCollecting = False # end reached
elif startCollecting and len(line.split()) == 3:
# file_print('>>>>>', line, 'len', len(line.split()))
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()))
index += 1
if len(params) > 0:
sql.executemany ("""INSERT INTO Nmap_Scan ("MAC", "Time", "Port", "State", "Service", "Extra") VALUES (?, ?, ?, ?, ?, ?)""", params)
commitDB ()
#-------------------------------------------------------------------------------
def performPholusScan (timeoutSec):
@@ -1722,7 +1845,7 @@ def performPholusScan (timeoutSec):
except subprocess.CalledProcessError as e:
# An error occured, handle it
file_print(e.output)
file_print(" Error - PholusScan - check logs")
file_print(" Error - Pholus Scan - check logs")
except subprocess.TimeoutExpired as timeErr:
file_print(' Pholus TIMEOUT - the process forcefully terminated as timeout reached')
@@ -2865,11 +2988,11 @@ def upgradeDB ():
# if pholusScanMissing == False:
# # Re-creating Pholus_Scan table
# file_print("[upgradeDB] Re-creating Pholus_Scan table")
# sql.execute("DROP TABLE Pholus_Scan;")
# pholusScanMissing = True
if pholusScanMissing:
file_print("[upgradeDB] Re-creating Pholus_Scan table")
sql.execute("""
CREATE TABLE "Pholus_Scan" (
"Index" INTEGER,
@@ -2884,6 +3007,32 @@ def upgradeDB ():
);
""")
# indicates, if Nmap_Scan table is available
nmapScanMissing = sql.execute("""
SELECT name FROM sqlite_master WHERE type='table'
AND name='Nmap_Scan';
""").fetchone() == None
# if nmapScanMissing == False:
# # Re-creating Nmap_Scan table
# sql.execute("DROP TABLE Nmap_Scan;")
# nmapScanMissing = True
if nmapScanMissing:
file_print("[upgradeDB] Re-creating Nmap_Scan table")
sql.execute("""
CREATE TABLE "Nmap_Scan" (
"Index" INTEGER,
"MAC" TEXT,
"Port" TEXT,
"Time" TEXT,
"State" TEXT,
"Service" TEXT,
"Extra" TEXT,
PRIMARY KEY("Index" AUTOINCREMENT)
);
""")
# don't hog DB access
commitDB ()

View File

@@ -597,7 +597,7 @@ if ($_REQUEST['mac'] == 'Internet') {
<!-- Comment out tbody when trying to implement better table with datatables here -->
<!-- IDEA: Show unmatched pholus entries? -->
<tbody id="tablePholusBody">
<tr id="tablePholusPlc" class="text-center"><td colspan='7'><span>Nothing sniffed out with Polus for this device.</span></td></tr>
<tr id="tablePholusPlc" class="text-center"><td colspan='7'><span><?php echo lang("DevDetail_Tab_PholusEmpty"); ?></span></td></tr>
</tbody>
</table>
</div>

View File

@@ -154,6 +154,7 @@ $lang['en_us'] = array(
'DevDetail_Tab_Presence' => 'Presence',
'DevDetail_Tab_Events' => 'Events',
'DevDetail_Tab_Pholus' => 'Pholus',
'DevDetail_Tab_PholusEmpty' => 'Nothing sniffed out with Pholus for this device.',
'DevDetail_MainInfo_Title' => 'Main Info',
'DevDetail_MainInfo_mac' => 'MAC',
'DevDetail_MainInfo_Name' => 'Name',
@@ -568,6 +569,16 @@ the arp-scan will take hours to complete instead of seconds.
'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 <a href="/maintenance.php#tab_Logging">pialert_pholus.log</a> file is not touched. Enter <code>0</code> 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 <a href="#NMAP_RUN"><code>NMAP_RUN</code> setting</a>.',
'NMAP_TIMEOUT_name' => 'Run timeout',
'NMAP_TIMEOUT_description' => 'Maximum time to wait for an Nmap scan to finish.',
'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 <code>once</code> Nmap is run only once on start for the time specified in <a href="#NMAP_TIMEOUT"><code>NMAP_TIMEOUT</code> setting</a>.',
'NMAP_RUN_SCHD_name' => 'Schedule',
'NMAP_RUN_SCHD_description' => 'Only run if you select <code>schedule</code> in the <a href="#NMAP_RUN"><code>NMAP_RUN</code> setting</a>. Make sure you enter the schedule in the correct cron-like format.',
);
?>

View File

@@ -247,7 +247,7 @@ CommitDB();
<script>
// number of settings has to be equal to
var settingsNumber = 53;
var settingsNumber = 57;
// Wrong number of settings processing
if(<?php echo count($settings)?> != settingsNumber)