From c08b70a38d472f17cba9d766ca9f102bc8671b3f Mon Sep 17 00:00:00 2001 From: Jokob-sk Date: Wed, 20 Sep 2023 21:53:22 +1000 Subject: [PATCH] internet_ip plugin 0.2 --- back/report_template.html | 2 +- back/report_template.txt | 1 - back/report_template_new_version.html | 5 +- front/plugins/README.md | 33 +- front/plugins/arp_scan/config.json | 2 +- front/plugins/arp_scan/script.py | 2 +- front/plugins/internet_ip/config.json | 429 +++++++++++++++++++----- front/plugins/internet_ip/ignore_plugin | 0 front/plugins/internet_ip/script.py | 193 ++++++----- front/plugins/pholus_scan/script.py | 29 +- pialert/README.md | 8 - pialert/__main__.py | 15 +- pialert/conf.py | 3 +- pialert/device.py | 9 +- pialert/helper.py | 20 -- pialert/initialise.py | 5 +- pialert/reporting.py | 22 +- pialert/scanners/internet.py | 156 --------- 18 files changed, 495 insertions(+), 439 deletions(-) delete mode 100644 front/plugins/internet_ip/ignore_plugin delete mode 100755 pialert/scanners/internet.py diff --git a/back/report_template.html b/back/report_template.html index 83809c3b..cf5ae0d7 100755 --- a/back/report_template.html +++ b/back/report_template.html @@ -38,7 +38,7 @@ - + diff --git a/back/report_template.txt b/back/report_template.txt index a155751d..85f8575a 100755 --- a/back/report_template.txt +++ b/back/report_template.txt @@ -4,5 +4,4 @@ Server: - diff --git a/back/report_template_new_version.html b/back/report_template_new_version.html index 216767cb..ad27257d 100755 --- a/back/report_template_new_version.html +++ b/back/report_template_new_version.html @@ -41,9 +41,8 @@ - - - + + diff --git a/front/plugins/README.md b/front/plugins/README.md index 2d95ab58..db266652 100755 --- a/front/plugins/README.md +++ b/front/plugins/README.md @@ -14,23 +14,24 @@ ### 🔌 Plugins & 📚 Docs -| Required | CurrentScan | Unique Prefix | Plugin Type | Link + Docs | +| Required | CurrentScan | Unique Prefix | Plugin Type | Link + Docs | |-------------|-------------|-----------------------|------------------------|----------------------------------------------------------| -| | Yes | ARPSCAN | Script | 📚[arp_scan](/front/plugins/arp_scan/) | -| | | CSVBCKP | Script | 📚[csv_backup](/front/plugins/csv_backup/) | -| Yes* | | DBCLNP | Script | 📚[db_cleanup](/front/plugins/db_cleanup/) | -| | Yes | DHCPLSS | Script | 📚[dhcp_leases](/front/plugins/dhcp_leases/) | -| | | DHCPSRVS | Script | 📚[dhcp_servers](/front/plugins/dhcp_servers/) | -| Yes | | NEWDEV | Template | 📚[newdev_template](/front/plugins/newdev_template/) | -| | | NMAP | Script | 📚[nmap_scan](/front/plugins/nmap_scan/) | -| | Yes | PIHOLE | External SQLite DB | 📚[pihole_scan](/front/plugins/pihole_scan/) | -| | | SETPWD | Script | 📚[set_password](/front/plugins/set_password/) | -| | | SNMPDSC | Script | 📚[snmp_discovery](/front/plugins/snmp_discovery/) | -| | Yes* | UNDIS | Script | 📚[undiscoverables](/front/plugins/undiscoverables/) | -| | Yes | UNFIMP | Script | 📚[unifi_import](/front/plugins/unifi_import/) | -| | | VNDRPDT | Script | 📚[vendor_update](/front/plugins/vendor_update/) | -| | | WEBMON | Script | 📚[website_monitor](/front/plugins/website_monitor/) | -| N/A | | N/A | SQL query | No example available, but the External SQLite based plugins work very similar | +| | Yes | ARPSCAN | Script | 📚[arp_scan](/front/plugins/arp_scan/) | +| | | CSVBCKP | Script | 📚[csv_backup](/front/plugins/csv_backup/) | +| Yes* | | DBCLNP | Script | 📚[db_cleanup](/front/plugins/db_cleanup/) | +| | Yes | DHCPLSS | Script | 📚[dhcp_leases](/front/plugins/dhcp_leases/) | +| | | DHCPSRVS | Script | 📚[dhcp_servers](/front/plugins/dhcp_servers/) | +| | Yes | INTRNT | Script | 📚[internet_ip](/front/plugins/internet_ip/) | +| Yes | | NEWDEV | Template | 📚[newdev_template](/front/plugins/newdev_template/) | +| | | NMAP | Script | 📚[nmap_scan](/front/plugins/nmap_scan/) | +| | Yes | PIHOLE | External SQLite DB | 📚[pihole_scan](/front/plugins/pihole_scan/) | +| | | SETPWD | Script | 📚[set_password](/front/plugins/set_password/) | +| | | SNMPDSC | Script | 📚[snmp_discovery](/front/plugins/snmp_discovery/) | +| | Yes* | UNDIS | Script | 📚[undiscoverables](/front/plugins/undiscoverables/) | +| | Yes | UNFIMP | Script | 📚[unifi_import](/front/plugins/unifi_import/) | +| | | VNDRPDT | Script | 📚[vendor_update](/front/plugins/vendor_update/) | +| | | WEBMON | Script | 📚[website_monitor](/front/plugins/website_monitor/) | +| N/A | | N/A | SQL query | N/A, but the External SQLite DB plugins work similar | > \* The Undiscoverables plugin (`UNDIS`) inserts only user-specified dummy devices. > diff --git a/front/plugins/arp_scan/config.json b/front/plugins/arp_scan/config.json index 939dce1c..eb70b30d 100755 --- a/front/plugins/arp_scan/config.json +++ b/front/plugins/arp_scan/config.json @@ -352,7 +352,7 @@ "language_code":"en_us", "string" : "Status" }, - { + { "language_code":"es_es", "string" : "Estado" }] diff --git a/front/plugins/arp_scan/script.py b/front/plugins/arp_scan/script.py index 44cb3eb7..833315c1 100755 --- a/front/plugins/arp_scan/script.py +++ b/front/plugins/arp_scan/script.py @@ -62,7 +62,7 @@ def main(): subnets_list = userSubnetsParam.split(',') else: subnets_list = [userSubnetsParam] - + # Execute the ARP scanning process on the list of subnets (whether it's one or multiple subnets). # The function 'execute_arpscan' is assumed to be defined elsewhere in the code. unique_devices = execute_arpscan(subnets_list) diff --git a/front/plugins/internet_ip/config.json b/front/plugins/internet_ip/config.json index 8d242dd6..ed112649 100755 --- a/front/plugins/internet_ip/config.json +++ b/front/plugins/internet_ip/config.json @@ -2,10 +2,23 @@ "code_name": "internet_ip", "unique_prefix": "INTRNT", "enabled": true, - "data_source": "script", + "mapped_to_table": "CurrentScan", + "data_filters": [ + { + "compare_column": "Object_PrimaryID", + "compare_operator": "==", + "compare_field_id": "txtMacFilter", + "compare_js_template": "'{value}'.toString()", + "compare_use_quotes": true + } + ], + "data_source": "script", "show_ui": true, - "localized": ["display_name", "description", "icon"], - + "localized": [ + "display_name", + "description", + "icon" + ], "display_name": [ { "language_code": "en_us", @@ -22,60 +35,91 @@ { "language_code": "en_us", "string": "A plugin to check your internet connectivity and IP." - } - ], - "params" : [{ - "name" : "pluginskeephistory", - "type" : "setting", - "value" : "PLUGINS_KEEP_HIST" - }, - { - "name" : "daystokeepevents", - "type" : "setting", - "value" : "DAYS_TO_KEEP_EVENTS" - }, - { - "name" : "hourstokeepnewdevice", - "type" : "setting", - "value" : "HRS_TO_KEEP_NEWDEV" - }, - { - "name" : "pholuskeepdays", - "type" : "setting", - "value" : "PHOLUS_DAYS_DATA" } - ], - + ], + "params": [ + { + "name": "prev_ip", + "type": "sql", + "value": "SELECT dev_LastIP FROM Devices WHERE dev_MAC = 'Internet' " + }, + { + "name": "DDNS_ACTIVE", + "type": "setting", + "value": "DDNS_ACTIVE" + }, + { + "name": "DDNS_UPDATE_URL", + "type": "setting", + "value": "DDNS_UPDATE_URL" + }, + { + "name": "DDNS_USER", + "type": "setting", + "value": "DDNS_USER" + }, + { + "name": "DDNS_PASSWORD", + "type": "setting", + "value": "DDNS_PASSWORD" + }, + { + "name": "DDNS_DOMAIN", + "type": "setting", + "value": "DDNS_DOMAIN" + }, + { + "name": "DIG_GET_IP_ARG", + "type": "setting", + "value": "DIG_GET_IP_ARG", + "base64": true + } + ], "settings": [ { - "function": "RUN", - "type": "text.select", - "default_value":"schedule", - "options": ["disabled", "once", "schedule", "always_after_scan"], - "localized": ["name", "description"], - "name" :[{ - "language_code":"en_us", - "string" : "When to run" - }, - { - "language_code":"es_es", - "string" : "Cuándo ejecutar" - }, - { - "language_code":"de_de", - "string" : "Wann laufen" - }], - "description": [{ - "language_code":"en_us", - "string" : "When the cleanup should be performed. An hourly or daily SCHEDULE is a good option." - }] - }, + "function": "RUN", + "type": "text.select", + "default_value": "schedule", + "options": [ + "disabled", + "once", + "schedule", + "always_after_scan" + ], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "When to run" + }, + { + "language_code": "es_es", + "string": "Cuándo ejecutar" + }, + { + "language_code": "de_de", + "string": "Wann laufen" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "When the cleanup should be performed. An hourly or daily SCHEDULE is a good option." + } + ] + }, { "function": "CMD", "type": "readonly", - "default_value": "python3 /home/pi/pialert/front/plugins/db_cleanup/script.py pluginskeephistory={pluginskeephistory} hourstokeepnewdevice={hourstokeepnewdevice} daystokeepevents={daystokeepevents} pholuskeepdays={pholuskeepdays}", + "default_value": "python3 /home/pi/pialert/front/plugins/internet_ip/script.py prev_ip={prev_ip} DDNS_ACTIVE={DDNS_ACTIVE} DDNS_UPDATE_URL={DDNS_UPDATE_URL} DDNS_USER={DDNS_USER} DDNS_PASSWORD={DDNS_PASSWORD} DDNS_DOMAIN={DDNS_DOMAIN} DIG_GET_IP_ARG={DIG_GET_IP_ARG}", "options": [], - "localized": ["name", "description"], + "localized": [ + "name", + "description" + ], "name": [ { "language_code": "en_us", @@ -88,7 +132,7 @@ { "language_code": "de_de", "string": "Befehl" - } + } ], "description": [ { @@ -102,46 +146,56 @@ { "language_code": "de_de", "string": "Befehl zum Ausführen. Dies kann nicht geändert werden" - } + } ] }, { "function": "RUN_SCHD", "type": "text", - "default_value":"*/30 * * * *", + "default_value": "*/5 * * * *", "options": [], - "localized": ["name", "description"], - "name" : [{ - "language_code":"en_us", - "string" : "Schedule" - }, - { - "language_code":"es_es", - "string" : "Schedule" - }, - { - "language_code":"de_de", - "string" : "Schedule" - }], - "description": [{ - "language_code":"en_us", - "string" : "Only enabled if you select schedule in the DBCLNP_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." - }, - { - "language_code":"es_es", - "string" : "Solo está habilitado si selecciona schedule en la configuración DBCLNP_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo." - }, - { - "language_code":"de_de", - "string" : "Nur aktiviert, wenn Sie schedule in der DBCLNP_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht." - }] - }, + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Schedule" + }, + { + "language_code": "es_es", + "string": "Schedule" + }, + { + "language_code": "de_de", + "string": "Schedule" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Only enabled if you select schedule in the INTRNT_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." + }, + { + "language_code": "es_es", + "string": "Solo está habilitado si selecciona schedule en la configuración INTRNT_RUN. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en crontab.guru). Por ejemplo, ingresar 0 4 * * * ejecutará el escaneo después de las 4 a.m. en el TIMEZONE que configuró arriba. Se ejecutará la PRÓXIMA vez que pase el tiempo." + }, + { + "language_code": "de_de", + "string": "Nur aktiviert, wenn Sie schedule in der INTRNT_RUN-Einstellung auswählen. Stellen Sie sicher, dass Sie den Zeitplan im richtigen Cron-ähnlichen Format eingeben (z. B. validieren unter crontab.guru). Wenn Sie beispielsweise 0 4 * * * eingeben, wird der Scan nach 4 Uhr morgens in der TIMEZONE den Sie oben festgelegt haben. Wird das NÄCHSTE Mal ausgeführt, wenn die Zeit vergeht." + } + ] + }, { "function": "RUN_TIMEOUT", "type": "integer", "default_value": 30, "options": [], - "localized": ["name", "description"], + "localized": [ + "name", + "description" + ], "name": [ { "language_code": "en_us", @@ -154,7 +208,7 @@ { "language_code": "de_de", "string": "Zeitüberschreitung" - } + } ], "description": [ { @@ -168,13 +222,214 @@ { "language_code": "de_de", "string": "Maximale Zeit in Sekunden, die auf den Abschluss des Skripts gewartet werden soll. Bei Überschreitung dieser Zeit wird das Skript abgebrochen." - } + } + ] + }, + { + "function": "WATCH", + "type": "text.multiselect", + "default_value": [ + "Watched_Value1" + ], + "options": [ + "Watched_Value1", + "Watched_Value2", + "Watched_Value3", + "Watched_Value4" + ], + "localized": [ + "name", + "description" + ], + "name": [ + { + "language_code": "en_us", + "string": "Watched" + }, + { + "language_code": "es_es", + "string": "Visto" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Send a notification if selected values change. Use CTRL + Click to select/deselect.
  • Watched_Value1 is response status code (e.g.: 200, 404)
  • Watched_Value2 is Latency (not recommended)
  • Watched_Value3 unused
  • Watched_Value4 unused
" + }, + { + "language_code": "es_es", + "string": "Envíe una notificación si los valores seleccionados cambian. Use CTRL + Click para seleccionar/deseleccionar.
  • Watched_Value1 es un código de estado de respuesta (por ejemplo: 200, 404)
  • Valor_observado2 es Latencia (no recomendado)
  • Valor_observado3 no utilizado
  • Valor_observado4 sin usar
" + } ] } ], - - "database_column_definitions": - [ - + "database_column_definitions": [ + { + "column": "Object_PrimaryID", + "mapped_to_column": "cur_MAC", + "css_classes": "col-sm-2", + "show": true, + "type": "device_name_mac", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "MAC" + }, + { + "language_code": "es_es", + "string": "MAC" + } + ] + }, + { + "column": "Watched_Value1", + "mapped_to_column": "cur_IP", + "css_classes": "col-sm-2", + "show": true, + "type": "device_ip", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "IP" + }, + { + "language_code": "es_es", + "string": "IP" + } + ] + }, + { + "column": "Watched_Value2", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Extra" + } + ] + }, + { + "column": "Dummy", + "mapped_to_column": "cur_ScanMethod", + "mapped_to_column_data": { + "value": "INTRNT" + }, + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Scan method" + }, + { + "language_code": "es_es", + "string": "Método de escaneo" + } + ] + }, + { + "column": "DateTimeCreated", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Created" + }, + { + "language_code": "es_es", + "string": "Creado" + } + ] + }, + { + "column": "DateTimeChanged", + "mapped_to_column": "cur_DateTime", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value": "", + "options": [], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Changed" + }, + { + "language_code": "es_es", + "string": "Cambiado" + } + ] + }, + { + "column": "Status", + "css_classes": "col-sm-1", + "show": true, + "type": "replace", + "default_value": "", + "options": [ + { + "equals": "watched-not-changed", + "replacement": "
" + }, + { + "equals": "watched-changed", + "replacement": "
" + }, + { + "equals": "new", + "replacement": "
" + }, + { + "equals": "missing-in-last-scan", + "replacement": "
" + } + ], + "localized": [ + "name" + ], + "name": [ + { + "language_code": "en_us", + "string": "Status" + }, + { + "language_code": "es_es", + "string": "Estado" + } + ] + } ] -} +} \ No newline at end of file diff --git a/front/plugins/internet_ip/ignore_plugin b/front/plugins/internet_ip/ignore_plugin deleted file mode 100644 index e69de29b..00000000 diff --git a/front/plugins/internet_ip/script.py b/front/plugins/internet_ip/script.py index d69734e9..5abfb858 100755 --- a/front/plugins/internet_ip/script.py +++ b/front/plugins/internet_ip/script.py @@ -19,7 +19,7 @@ sys.path.append('/home/pi/pialert/pialert') from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64 from logger import mylog, append_line_to_file -from helper import timeNowTZ, get_internet_IP +from helper import timeNowTZ, check_IP_format from const import logPath, pialertPath, fullDbPath @@ -32,31 +32,71 @@ def main(): mylog('verbose', ['[INTRNT] In script']) parser = argparse.ArgumentParser(description='Check internet connectivity and IP') - parser.add_argument('pluginskeephistory', action="store", help="TBC") - parser.add_argument('hourstokeepnewdevice', action="store", help="TBC") - parser.add_argument('daystokeepevents', action="store", help="TBC") - parser.add_argument('pholuskeepdays', action="store", help="TBC") - values = parser.parse_args() + parser.add_argument('prev_ip', action="store", help="Previous IP address to compare against the current IP") + parser.add_argument('DDNS_ACTIVE', action="store", help="Indicates if Dynamic DNS (DDNS) is active (True/False)") + parser.add_argument('DDNS_UPDATE_URL', action="store", help="URL for updating Dynamic DNS (DDNS)") + parser.add_argument('DDNS_USER', action="store", help="Username for Dynamic DNS (DDNS) authentication") + parser.add_argument('DDNS_PASSWORD', action="store", help="Password for Dynamic DNS (DDNS) authentication") + parser.add_argument('DDNS_DOMAIN', action="store", help="Dynamic DNS (DDNS) domain name") + parser.add_argument('DIG_GET_IP_ARG', action="store", help="Arguments for the 'dig' command to retrieve the IP address") - DDNS_ACTIVE = values.TBC.split('=')[1] - DDNS_UPDATE_URL = values.TBC.split('=')[1] - DDNS_USER = values.TBC.split('=')[1] - DDNS_PASSWORD = values.TBC.split('=')[1] - DDNS_DOMAIN = values.TBC.split('=')[1] + args = parser.parse_args() + + PREV_IP = values.prev_ip.split('=')[1] + DDNS_ACTIVE = values.DDNS_ACTIVE.split('=')[1] + DDNS_UPDATE_URL = values.DDNS_UPDATE_URL.split('=')[1] + DDNS_USER = values.DDNS_USER.split('=')[1] + DDNS_PASSWORD = values.DDNS_PASSWORD.split('=')[1] + DDNS_DOMAIN = values.DDNS_DOMAIN.split('=')[1] + DIG_GET_IP_ARG = values.DIG_GET_IP_ARG.split('=')[1] + + mylog('verbose', ['[INTRNT] DIG_GET_IP_ARG: ', DIG_GET_IP_ARG]) + + # Decode the base64-encoded value to get the actual value in ASCII format. + DIG_GET_IP_ARG = base64.b64decode(DIG_GET_IP_ARG).decode('ascii') - # Connect to the PiAlert SQLite database - conn = sqlite3.connect(fullDbPath) - cursor = conn.cursor() + mylog('verbose', ['[INTRNT] DIG_GET_IP_ARG resolved: ', DIG_GET_IP_ARG]) + + # if internet_IP != "" : + # sql.execute (f"""INSERT INTO CurrentScan (cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) + # VALUES ( 'Internet', '{internet_IP}', Null, 'queryDNS') """) + + # # Save event + # cursor.execute ("""INSERT INTO Events (eve_MAC, eve_IP, eve_DateTime, + # eve_EventType, eve_AdditionalInfo, + # eve_PendingAlertEmail) + # VALUES ('Internet', ?, ?, 'Internet IP Changed', + # 'Previous Internet IP: '|| ?, 1) """, + # (pNewIP, timeNowTZ(), prevIp) ) + + + # # Save new IP + # cursor.execute ("""UPDATE Devices SET dev_LastIP = ? + # WHERE dev_MAC = 'Internet' """, + # (pNewIP,) ) + + + # Object_PrimaryID - cur_MAC + # Watched_Value1 - cur_IP + # Watched_Value2 - Extra / prev IP + - # do stuff - check_internet_IP(conn, cursor, DDNS_ACTIVE, DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN) + new_internet_IP = check_internet_IP( DDNS_ACTIVE, DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN, PREV_IP, DIG_GET_IP_ARG) - cursor.execute ("""SELECT from Online_History""") # TODO delete + plugin_objects = Plugin_Objects(RESULT_FILE) + + plugin_objects.add_object( + primaryId = 'Internet', # MAC (Device Name) + secondaryId = '', + watched1 = new_internet_IP, # IP Address + watched2 = f'Previous IP: {prev_ip}', + watched3 = '', + watched4 = '', + extra = f'Previous IP: {prev_ip}', + foreignKey = 'Internet') - conn.commit() - # Close the database connection - conn.close() + plugin_objects.write_result_file() mylog('verbose', ['[INTRNT] Finished ']) @@ -67,37 +107,26 @@ def main(): #=============================================================================== # INTERNET IP CHANGE #=============================================================================== -def check_internet_IP (conn, cursor, DDNS_ACTIVE, DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN ): - - # Header - updateState("Scan: Internet IP") - mylog('verbose', ['[INTRNT] Check Internet IP started']) - +def check_internet_IP ( DDNS_ACTIVE, DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN, PREV_IP, DIG_GET_IP_ARG ): + # Get Internet IP mylog('verbose', ['[INTRNT] - Retrieving Internet IP']) - internet_IP = get_internet_IP() - # TESTING - Force IP - # internet_IP = "1.2.3.4" + internet_IP = get_internet_IP(DIG_GET_IP_ARG) # Check result = IP if internet_IP == "" : - mylog('none', ['[INTRNT] Error retrieving Internet IP']) - mylog('none', ['[INTRNT] Exiting...']) - return False - mylog('verbose', ['[INTRNT] IP: ', internet_IP]) + mylog('none', ['[INTRNT] Error retrieving Internet IP']) + + # Get previous stored IP + previous_IP = '0.0.0.0' + + if PREV_IP is not None and len(result) > 0 : + previous_IP = PREV_IP - # Get previous stored IP - mylog('verbose', ['[INTRNT] Retrieving previous IP:']) - previous_IP = get_previous_internet_IP (conn, cursor) mylog('verbose', ['[INTRNT] ', previous_IP]) - # Check IP Change - if internet_IP != previous_IP : - mylog('minimal', ['[INTRNT] New internet IP: ', internet_IP]) - save_new_internet_IP (conn, cursor, internet_IP) - - else : - mylog('verbose', ['[INTRNT] No changes to perform']) + # logging + append_line_to_file (logPath + '/IP_changes.log', '['+str(timeNowTZ()) +']\t'+ pNewIP +'\n') # Get Dynamic DNS IP if DDNS_ACTIVE : @@ -119,49 +148,7 @@ def check_internet_IP (conn, cursor, DDNS_ACTIVE, DDNS_UPDATE_URL, DDNS_USER, DD else : mylog('verbose', ['[DDNS] Skipping Dynamic DNS update']) - - -#------------------------------------------------------------------------------- -def save_new_internet_IP (conn, cursor, pNewIP): - # Log new IP into logfile - append_line_to_file (logPath + '/IP_changes.log', - '['+str(timeNowTZ()) +']\t'+ pNewIP +'\n') - - prevIp = get_previous_internet_IP(conn, cursor) - # Save event - cursor.execute ("""INSERT INTO Events (eve_MAC, eve_IP, eve_DateTime, - eve_EventType, eve_AdditionalInfo, - eve_PendingAlertEmail) - VALUES ('Internet', ?, ?, 'Internet IP Changed', - 'Previous Internet IP: '|| ?, 1) """, - (pNewIP, timeNowTZ(), prevIp) ) - - # Save new IP - cursor.execute ("""UPDATE Devices SET dev_LastIP = ? - WHERE dev_MAC = 'Internet' """, - (pNewIP,) ) - - # commit changes - conn.commit() - -#------------------------------------------------------------------------------- -def get_previous_internet_IP (conn, cursor): - - previous_IP = '0.0.0.0' - - # get previous internet IP stored in DB - cursor.execute ("SELECT dev_LastIP FROM Devices WHERE dev_MAC = 'Internet' ") - result = db.sql.fetchone() - - conn.commit() - - if result is not None and len(result) > 0 : - previous_IP = result[0] - - # return previous IP - return previous_IP - - + return internet_IP #------------------------------------------------------------------------------- @@ -194,12 +181,13 @@ def set_dynamic_DNS_IP (DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN): try: # try runnning a subprocess # Update Dynamic IP - curl_output = subprocess.check_output (['curl', '-s', - DDNS_UPDATE_URL + - 'username=' + DDNS_USER + - '&password=' + DDNS_PASSWORD + - '&hostname=' + DDNS_DOMAIN], - universal_newlines=True) + curl_output = subprocess.check_output (['curl', + '-s', + DDNS_UPDATE_URL + + 'username=' + DDNS_USER + + '&password=' + DDNS_PASSWORD + + '&hostname=' + DDNS_DOMAIN], + universal_newlines=True) except subprocess.CalledProcessError as e: # An error occured, handle it mylog('none', ['[DDNS] ERROR - ',e.output]) @@ -207,6 +195,27 @@ def set_dynamic_DNS_IP (DDNS_UPDATE_URL, DDNS_USER, DDNS_PASSWORD, DDNS_DOMAIN): return curl_output + +#------------------------------------------------------------------------------- +def get_internet_IP (DIG_GET_IP_ARG): + # BUGFIX #46 - curl http://ipv4.icanhazip.com repeatedly is very slow + # Using 'dig' + dig_args = ['dig', '+short'] + DIG_GET_IP_ARG.strip().split() + try: + cmd_output = subprocess.check_output (dig_args, universal_newlines=True) + except subprocess.CalledProcessError as e: + mylog('none', [e.output]) + cmd_output = '' # no internet + + # Check result is an IP + IP = check_IP_format (cmd_output) + + # Handle invalid response + if IP == '': + IP = '0.0.0.0' + + return IP + #=============================================================================== # BEGIN #=============================================================================== diff --git a/front/plugins/pholus_scan/script.py b/front/plugins/pholus_scan/script.py index 32c22f6d..ec696394 100755 --- a/front/plugins/pholus_scan/script.py +++ b/front/plugins/pholus_scan/script.py @@ -54,15 +54,14 @@ def main(): timeoutSec = values.timeoutSec[0].split('=')[1] # Printing the extracted base64-encoded subnet information. - print(userSubnetsParamBase64) - print(timeoutSec) + mylog('verbose', [f'[PHOLUS] { userSubnetsParamBase64 }']) + mylog('verbose', [f'[PHOLUS] { timeoutSec }']) # Decode the base64-encoded subnet information to get the actual subnet information in ASCII format. userSubnetsParam = base64.b64decode(userSubnetsParamBase64).decode('ascii') - # Print the decoded subnet information. - print('userSubnetsParam:') - print(userSubnetsParam) + # Print the decoded subnet information. + mylog('verbose', [f'[PHOLUS] userSubnetsParam { userSubnetsParam } ']) # Check if the decoded subnet information contains multiple subnets separated by commas. # If it does, split the string into a list of individual subnets. @@ -101,7 +100,7 @@ def execute_pholus_scan(userSubnets, timeoutSec): timeoutPerSubnet = float(timeoutSec) / len(userSubnets) - print(timeoutPerSubnet) + mylog('verbose', [f'[PHOLUS] { timeoutPerSubnet } ']) # scan each interface @@ -110,7 +109,7 @@ def execute_pholus_scan(userSubnets, timeoutSec): temp = interface.split("--interface=") if len(temp) != 2: - mylog('none', ["[PholusScan] Skip scan (need interface in format '192.168.1.0/24 --inteface=eth0'), got: ", interface]) + mylog('none', ["[PHOLUS] Skip scan (need interface in format '192.168.1.0/24 --inteface=eth0'), got: ", interface]) return mask = temp[0].strip() @@ -118,7 +117,7 @@ def execute_pholus_scan(userSubnets, timeoutSec): pholus_output_list = execute_pholus_on_interface (interface, timeoutPerSubnet, mask) - print(pholus_output_list) + mylog('verbose', [f'[PHOLUS] { pholus_output_list } ']) result_list += pholus_output_list @@ -134,8 +133,8 @@ def execute_pholus_on_interface(interface, timeoutSec, mask): # logging & updating app state - mylog('verbose', ['[PholusScan] Scan: Pholus for ', str(timeoutSec), 's ('+ str(round(int(timeoutSec) / 60, 1)) +'min)']) - mylog('verbose', ["[PholusScan] Pholus scan on [interface] ", interface, " [mask] " , mask]) + mylog('verbose', ['[PHOLUS] Scan: Pholus for ', str(timeoutSec), 's ('+ str(round(int(timeoutSec) / 60, 1)) +'min)']) + mylog('verbose', ["[PHOLUS] Pholus scan on [interface] ", interface, " [mask] " , mask]) # 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)) @@ -151,15 +150,15 @@ def execute_pholus_on_interface(interface, timeoutSec, mask): 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 - mylog('none', ['[PholusScan]', e.output]) - mylog('none', ["[PholusScan] Error - Pholus Scan - check logs"]) + mylog('none', ['[PHOLUS]', e.output]) + mylog('none', ["[PHOLUS] Error - Pholus Scan - check logs"]) except subprocess.TimeoutExpired as timeErr: - mylog('none', ['[PholusScan] Pholus TIMEOUT - the process forcefully terminated as timeout reached']) + mylog('none', ['[PHOLUS] Pholus TIMEOUT - the process forcefully terminated as timeout reached']) if output == "": # check if the subprocess failed - mylog('none', ['[PholusScan] Scan: Pholus FAIL - check logs']) + mylog('none', ['[PHOLUS] Scan: Pholus FAIL - check logs']) else: - mylog('verbose', ['[PholusScan] Scan: Pholus SUCCESS']) + mylog('verbose', ['[PHOLUS] Scan: Pholus SUCCESS']) # check the last run output f = open(logPath + '/pialert_pholus_lastrun.log', 'r+') diff --git a/pialert/README.md b/pialert/README.md index 5d6ff197..2b0a3858 100755 --- a/pialert/README.md +++ b/pialert/README.md @@ -8,7 +8,6 @@ The original pilaert.py code is now moved to this new folder and split into diff |```__init__.py```| an empty init file| |```README.md```| this readme file| |**publishers**| a folder containing all modules used to publish the results| -|**scanners**| a folder containing all modules used to scan for devices | |```api.py```| updating the API endpoints with the relevant data. (Should move to publishers)| |```const.py```| A place to define the constants for Pi.Alert like log path or config path.| |```conf.py```| conf.py holds the configuration variables and makes them available for all modules. It is also the workaround for global variables that need to be resolved at some point| @@ -35,12 +34,5 @@ publishers generally have a check_config method as well as a send method. |```pushsafer.py```| integrate with pushsafer | |```webhook.py```| integrate via webhook | -## scanners -different methods to scan the network for devices or to find more details about the discovered devices -| Module | Description | -|--------|-----------| -|```__init__.py```| an empty init file (oops missing in the repo)| -|```internet.py```| discover the internet interface and check the external IP also manage Dynamic DNS | -|```nmapscan.py```| use Nmap to discover more about devices | diff --git a/pialert/__main__.py b/pialert/__main__.py index a1b926b8..ab90f581 100755 --- a/pialert/__main__.py +++ b/pialert/__main__.py @@ -32,10 +32,6 @@ from database import DB, get_all_devices from reporting import check_and_run_event, send_notifications from plugin import run_plugin_scripts -# different scanners -from scanners.internet import check_internet_IP - - #=============================================================================== #=============================================================================== @@ -54,8 +50,6 @@ main structure of Pi Alert run frontend events update API run plugins (scheduled) - check internet IP - check vendor processing scan results run plugins (after Scan) reporting @@ -123,8 +117,7 @@ def main (): if conf.last_scan_run + datetime.timedelta(minutes=1) < conf.loop_start_time : # last time any scan or maintenance/upkeep was run - conf.last_scan_run = loop_start_time - last_internet_IP_scan = conf.last_internet_IP_scan + conf.last_scan_run = loop_start_time # Header updateState("Process: Start") @@ -138,12 +131,6 @@ def main (): # determine run/scan type based on passed time # -------------------------------------------- - - # check for changes in Internet IP - if last_internet_IP_scan + datetime.timedelta(minutes=3) < loop_start_time: - conf.cycle = 'internet_IP' - last_internet_IP_scan = loop_start_time - check_internet_IP(db) # Run splugin scripts which are set to run every timne after a scans finished pluginsState = run_plugin_scripts(db,'always_after_scan', pluginsState) diff --git a/pialert/conf.py b/pialert/conf.py index 90365b0f..77b30c25 100755 --- a/pialert/conf.py +++ b/pialert/conf.py @@ -20,7 +20,6 @@ plugins_once_run = False newVersionAvailable = False time_started = '' startTime = '' -last_internet_IP_scan = '' last_scan_run = '' last_version_check = '' arpscan_devices = [] @@ -44,7 +43,7 @@ UI_LANG = 'English' UI_PRESENCE = ['online', 'offline', 'archived'] PIALERT_WEB_PROTECTION = False PIALERT_WEB_PASSWORD = '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92' -INCLUDED_SECTIONS = ['internet', 'new_devices', 'down_devices', 'events'] +INCLUDED_SECTIONS = ['new_devices', 'down_devices', 'events'] DAYS_TO_KEEP_EVENTS = 90 REPORT_DASHBOARD_URL = 'http://pi.alert/' diff --git a/pialert/device.py b/pialert/device.py index eeb53f33..580e52fa 100755 --- a/pialert/device.py +++ b/pialert/device.py @@ -3,7 +3,7 @@ import subprocess import conf import re -from helper import timeNowTZ, get_setting, get_setting_value,resolve_device_name_dig, resolve_device_name_pholus, check_IP_format, get_internet_IP +from helper import timeNowTZ, get_setting, get_setting_value,resolve_device_name_dig, resolve_device_name_pholus, check_IP_format from logger import mylog, print_log from const import vendorsPath6, vendorsPath9 @@ -13,13 +13,6 @@ from const import vendorsPath6, vendorsPath9 def save_scanned_devices (db): sql = db.sql #TO-DO - # Check Internet connectivity - internet_IP = get_internet_IP() - # TESTING - Force IP - # internet_IP = "" - if internet_IP != "" : - sql.execute (f"""INSERT INTO CurrentScan (cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) - VALUES ( 'Internet', '{internet_IP}', Null, 'queryDNS') """) # #76 Add Local MAC of default local interface # BUGFIX #106 - Device that pialert is running diff --git a/pialert/helper.py b/pialert/helper.py index c48ded38..175071bb 100755 --- a/pialert/helper.py +++ b/pialert/helper.py @@ -291,26 +291,6 @@ def check_IP_format (pIP): -#------------------------------------------------------------------------------- -def get_internet_IP (): - # BUGFIX #46 - curl http://ipv4.icanhazip.com repeatedly is very slow - # Using 'dig' - dig_args = ['dig', '+short'] + conf.DIG_GET_IP_ARG.strip().split() - try: - cmd_output = subprocess.check_output (dig_args, universal_newlines=True) - except subprocess.CalledProcessError as e: - mylog('none', [e.output]) - cmd_output = '' # no internet - - # Check result is an IP - IP = check_IP_format (cmd_output) - - # Handle invalid response - if IP == '': - IP = '0.0.0.0' - - return IP - #------------------------------------------------------------------------------- def resolve_device_name_dig (pMAC, pIP): diff --git a/pialert/initialise.py b/pialert/initialise.py index 27d45e20..a90f1b10 100755 --- a/pialert/initialise.py +++ b/pialert/initialise.py @@ -96,7 +96,7 @@ def importConfigs (db): conf.PLUGINS_KEEP_HIST = ccd('PLUGINS_KEEP_HIST', 250 , c_d, 'Keep history entries', 'integer', '', 'General') conf.PIALERT_WEB_PROTECTION = ccd('PIALERT_WEB_PROTECTION', False , c_d, 'Enable logon', 'boolean', '', 'General') conf.PIALERT_WEB_PASSWORD = ccd('PIALERT_WEB_PASSWORD', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92' , c_d, 'Logon password', 'readonly', '', 'General') - conf.INCLUDED_SECTIONS = ccd('INCLUDED_SECTIONS', ['internet', 'new_devices', 'down_devices', 'events'] , c_d, 'Notify on', 'text.multiselect', "['internet', 'new_devices', 'down_devices', 'events', 'plugins']", 'General') + conf.INCLUDED_SECTIONS = ccd('INCLUDED_SECTIONS', ['new_devices', 'down_devices', 'events'] , c_d, 'Notify on', 'text.multiselect', "['new_devices', 'down_devices', 'events', 'plugins']", 'General') conf.REPORT_DASHBOARD_URL = ccd('REPORT_DASHBOARD_URL', 'http://pi.alert/' , c_d, 'PiAlert URL', 'text', '', 'General') conf.DIG_GET_IP_ARG = ccd('DIG_GET_IP_ARG', '-4 myip.opendns.com @resolver1.opendns.com' , c_d, 'DIG arguments', 'text', '', 'General') conf.UI_LANG = ccd('UI_LANG', 'English' , c_d, 'Language Interface', 'text.select', "['English', 'German', 'Spanish']", 'General') @@ -175,8 +175,7 @@ def importConfigs (db): conf.startTime = conf.time_started now_minus_24h = conf.time_started - datetime.timedelta(hours = 24) - # set these times to the past to force the first run - conf.last_internet_IP_scan = now_minus_24h + # set these times to the past to force the first run conf.last_scan_run = now_minus_24h conf.last_version_check = now_minus_24h diff --git a/pialert/reporting.py b/pialert/reporting.py index 488dc987..4b25ebfd 100755 --- a/pialert/reporting.py +++ b/pialert/reporting.py @@ -183,20 +183,20 @@ def send_notifications (db): mylog('verbose', ['[Notification] included sections: ', conf.INCLUDED_SECTIONS ]) - if 'internet' in conf.INCLUDED_SECTIONS : - # Compose Internet Section - sqlQuery = """SELECT eve_MAC as MAC, eve_IP as IP, eve_DateTime as Datetime, eve_EventType as "Event Type", eve_AdditionalInfo as "More info" FROM Events - WHERE eve_PendingAlertEmail = 1 AND eve_MAC = 'Internet' - ORDER BY eve_DateTime""" + # if 'internet' in conf.INCLUDED_SECTIONS : + # # Compose Internet Section + # sqlQuery = """SELECT eve_MAC as MAC, eve_IP as IP, eve_DateTime as Datetime, eve_EventType as "Event Type", eve_AdditionalInfo as "More info" FROM Events + # WHERE eve_PendingAlertEmail = 1 AND eve_MAC = 'Internet' + # ORDER BY eve_DateTime""" - notiStruc = construct_notifications(db, sqlQuery, "Internet IP change") + # notiStruc = construct_notifications(db, sqlQuery, "Internet IP change") - # collect "internet" (IP changes) for the webhook json - json_internet = notiStruc.json["data"] + # # collect "internet" (IP changes) for the webhook json + # json_internet = notiStruc.json["data"] - mail_text = mail_text.replace ('', notiStruc.text + '\n') - mail_html = mail_html.replace ('', notiStruc.html) - mylog('verbose', ['[Notification] Internet sections done.']) + # mail_text = mail_text.replace ('', notiStruc.text + '\n') + # mail_html = mail_html.replace ('', notiStruc.html) + # mylog('verbose', ['[Notification] Internet sections done.']) if 'new_devices' in conf.INCLUDED_SECTIONS : # Compose New Devices Section diff --git a/pialert/scanners/internet.py b/pialert/scanners/internet.py deleted file mode 100755 index 6e85e4d2..00000000 --- a/pialert/scanners/internet.py +++ /dev/null @@ -1,156 +0,0 @@ -""" internet related functions to support Pi.Alert """ - -import subprocess -import re - -# pialert modules - -import conf -from helper import timeNowTZ, updateState, check_IP_format, get_internet_IP -from logger import append_line_to_file, mylog -from const import logPath - - -#=============================================================================== -# INTERNET IP CHANGE -#=============================================================================== -def check_internet_IP ( db ): - - # Header - updateState("Scan: Internet IP") - mylog('verbose', ['[Internet IP] Check Internet IP started']) - - # Get Internet IP - mylog('verbose', ['[Internet IP] - Retrieving Internet IP']) - internet_IP = get_internet_IP() - # TESTING - Force IP - # internet_IP = "1.2.3.4" - - # Check result = IP - if internet_IP == "" : - mylog('none', ['[Internet IP] Error retrieving Internet IP']) - mylog('none', ['[Internet IP] Exiting...']) - return False - mylog('verbose', ['[Internet IP] IP: ', internet_IP]) - - # Get previous stored IP - mylog('verbose', ['[Internet IP] Retrieving previous IP:']) - previous_IP = get_previous_internet_IP (db) - mylog('verbose', ['[Internet IP] ', previous_IP]) - - # Check IP Change - if internet_IP != previous_IP : - mylog('minimal', ['[Internet IP] New internet IP: ', internet_IP]) - save_new_internet_IP (db, internet_IP) - - else : - mylog('verbose', ['[Internet IP] No changes to perform']) - - # Get Dynamic DNS IP - if conf.DDNS_ACTIVE : - mylog('verbose', ['[DDNS] Retrieving Dynamic DNS IP']) - dns_IP = get_dynamic_DNS_IP() - - # Check Dynamic DNS IP - if dns_IP == "" or dns_IP == "0.0.0.0" : - mylog('none', ['[DDNS] Error retrieving Dynamic DNS IP']) - mylog('none', ['[DDNS] ', dns_IP]) - - # Check DNS Change - if dns_IP != internet_IP : - mylog('none', ['[DDNS] Updating Dynamic DNS IP']) - message = set_dynamic_DNS_IP () - mylog('none', ['[DDNS] ', message]) - else : - mylog('verbose', ['[DDNS] No changes to perform']) - else : - mylog('verbose', ['[DDNS] Skipping Dynamic DNS update']) - - - - -#------------------------------------------------------------------------------- -def get_previous_internet_IP (db): - - previous_IP = '0.0.0.0' - - # get previous internet IP stored in DB - db.sql.execute ("SELECT dev_LastIP FROM Devices WHERE dev_MAC = 'Internet' ") - result = db.sql.fetchone() - - db.commitDB() - - if result is not None and len(result) > 0 : - previous_IP = result[0] - - # return previous IP - return previous_IP - - - -#------------------------------------------------------------------------------- -def save_new_internet_IP (db, pNewIP): - # Log new IP into logfile - append_line_to_file (logPath + '/IP_changes.log', - '['+str(timeNowTZ()) +']\t'+ pNewIP +'\n') - - prevIp = get_previous_internet_IP(db) - # Save event - db.sql.execute ("""INSERT INTO Events (eve_MAC, eve_IP, eve_DateTime, - eve_EventType, eve_AdditionalInfo, - eve_PendingAlertEmail) - VALUES ('Internet', ?, ?, 'Internet IP Changed', - 'Previous Internet IP: '|| ?, 1) """, - (pNewIP, timeNowTZ(), prevIp) ) - - # Save new IP - db.sql.execute ("""UPDATE Devices SET dev_LastIP = ? - WHERE dev_MAC = 'Internet' """, - (pNewIP,) ) - - # commit changes - db.commitDB() - - -#------------------------------------------------------------------------------- -def get_dynamic_DNS_IP (): - # Using OpenDNS server - # dig_args = ['dig', '+short', DDNS_DOMAIN, '@resolver1.opendns.com'] - - # Using default DNS server - dig_args = ['dig', '+short', conf.DDNS_DOMAIN] - - try: - # try runnning a subprocess - dig_output = subprocess.check_output (dig_args, universal_newlines=True) - except subprocess.CalledProcessError as e: - # An error occured, handle it - mylog('none', ['[DDNS] ERROR - ', e.output]) - dig_output = '' # probably no internet - - # Check result is an IP - IP = check_IP_format (dig_output) - - # Handle invalid response - if IP == '': - IP = '0.0.0.0' - - return IP - -#------------------------------------------------------------------------------- -def set_dynamic_DNS_IP (): - try: - # try runnning a subprocess - # Update Dynamic IP - curl_output = subprocess.check_output (['curl', '-s', - conf.DDNS_UPDATE_URL + - 'username=' + conf.DDNS_USER + - '&password=' + conf.DDNS_PASSWORD + - '&hostname=' + conf.DDNS_DOMAIN], - universal_newlines=True) - except subprocess.CalledProcessError as e: - # An error occured, handle it - mylog('none', ['[DDNS] ERROR - ',e.output]) - curl_output = "" - - return curl_output