From 04dc238aeaab95b34dda017b2c5f87341e77e912 Mon Sep 17 00:00:00 2001 From: Phillip Tarrant Date: Fri, 21 Nov 2025 13:33:38 -0600 Subject: [PATCH] Add configurable UDP scanning and numeric IP sorting - Add UDP_SCAN_ENABLED and UDP_PORTS environment variables to control UDP scanning - UDP scanning disabled by default for faster scans - Support port ranges (100-200), lists (53,67,68), or mixed formats - Sort IPs numerically by octets in site management modal --- .env.example | 11 +++++++++++ app/src/scanner.py | 20 +++++++++++++++----- app/web/templates/sites.html | 12 ++++++++++++ docker-compose.yml | 3 +++ 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index e2fdf42..c057551 100644 --- a/.env.example +++ b/.env.example @@ -57,6 +57,17 @@ SCHEDULER_EXECUTORS=2 # Recommended: 3 for typical usage SCHEDULER_JOB_DEFAULTS_MAX_INSTANCES=3 +# ================================ +# UDP Scanning Configuration +# ================================ +# Enable UDP port scanning (disabled by default as it's slower) +UDP_SCAN_ENABLED=false + +# UDP ports to scan when enabled +# Supports ranges (e.g., 100-200), lists (e.g., 53,67,68), or mixed (e.g., 53,67-69,123) +# Default: common UDP services +UDP_PORTS=53,67,68,69,123,161,500,514,1900 + # ================================ # Initial Password (First Run) # ================================ diff --git a/app/src/scanner.py b/app/src/scanner.py index 3159fcc..3e7f5eb 100644 --- a/app/src/scanner.py +++ b/app/src/scanner.py @@ -6,6 +6,7 @@ SneakyScanner - Masscan-based network scanner with YAML configuration import argparse import json import logging +import os import subprocess import sys import tempfile @@ -906,11 +907,20 @@ class SneakyScanner: progress_callback('tcp_scan', None, {'status': 'starting'}) tcp_results = self._run_masscan(all_ips, '0-65535', 'tcp') - # Perform UDP scan (all ports) - print(f"\n[3/5] Performing UDP scan on {len(all_ips)} IPs (ports 0-65535)...", flush=True) - if progress_callback: - progress_callback('udp_scan', None, {'status': 'starting'}) - udp_results = self._run_masscan(all_ips, '0-65535', 'udp') + # Perform UDP scan (if enabled) + udp_enabled = os.environ.get('UDP_SCAN_ENABLED', 'false').lower() == 'true' + udp_ports = os.environ.get('UDP_PORTS', '53,67,68,69,123,161,500,514,1900') + + if udp_enabled: + print(f"\n[3/5] Performing UDP scan on {len(all_ips)} IPs (ports {udp_ports})...", flush=True) + if progress_callback: + progress_callback('udp_scan', None, {'status': 'starting'}) + udp_results = self._run_masscan(all_ips, udp_ports, 'udp') + else: + print(f"\n[3/5] Skipping UDP scan (disabled)...", flush=True) + if progress_callback: + progress_callback('udp_scan', None, {'status': 'skipped'}) + udp_results = [] # Organize results by IP results_by_ip = {} diff --git a/app/web/templates/sites.html b/app/web/templates/sites.html index 9fffda7..074ba3b 100644 --- a/app/web/templates/sites.html +++ b/app/web/templates/sites.html @@ -688,6 +688,18 @@ async function loadSiteIps(siteId) { const data = await response.json(); const ips = data.ips || []; + // Sort IPs by numeric octets + ips.sort((a, b) => { + const partsA = a.ip_address.split('.').map(Number); + const partsB = b.ip_address.split('.').map(Number); + for (let i = 0; i < 4; i++) { + if (partsA[i] !== partsB[i]) { + return partsA[i] - partsB[i]; + } + } + return 0; + }); + document.getElementById('ip-count').textContent = data.total || ips.length; // Render flat IP table diff --git a/docker-compose.yml b/docker-compose.yml index 036b2c9..8af5222 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,6 +41,9 @@ services: # Scheduler configuration (APScheduler) - SCHEDULER_EXECUTORS=${SCHEDULER_EXECUTORS:-2} - SCHEDULER_JOB_DEFAULTS_MAX_INSTANCES=${SCHEDULER_JOB_DEFAULTS_MAX_INSTANCES:-3} + # UDP scanning configuration + - UDP_SCAN_ENABLED=${UDP_SCAN_ENABLED:-false} + - UDP_PORTS=${UDP_PORTS:-53,67,68,69,123,161,500,514,1900} # Scanner functionality requires privileged mode and host network for masscan/nmap privileged: true network_mode: host