homelab_scanner.py

scans my local vlan for web interfaces open.  exports them to an excel sheet.
This commit is contained in:
bkentopp 2026-04-09 17:03:10 +00:00
commit ae973dec45

112
homelab_scanner.py Normal file
View file

@ -0,0 +1,112 @@
import nmap
import pandas as pd
import os
import sys
import requests
from bs4 import BeautifulSoup
import urllib3
from datetime import datetime
# Suppress SSL warnings for self-signed certificates
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def probe_for_web_interface(host, port):
"""
Zero-trust probe: Manually tries HTTPS and HTTP on EVERY open port.
Captures webpage title and software version banners.
"""
for protocol in ["https", "http"]:
url = f"{protocol}://{host}:{port}"
try:
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
response = requests.get(url, timeout=3, verify=False, allow_redirects=True, headers=headers)
# We accept any response < 500 (200, 302, 401, 403)
if response.status_code < 500:
soup = BeautifulSoup(response.text, 'html.parser')
title = soup.title.string.strip() if soup.title else "Web Page (No Title)"
# Grab the 'Server' header to identify the software stack
server_banner = response.headers.get('Server', 'Hidden/Unknown')
return True, url, title, server_banner
except:
continue
return False, None, None, None
def run_exhaustive_scan(target_range):
nm = nmap.PortScanner()
# PHASE 1: Rapid Discovery
print(f"[*] PHASE 1: Discovering live hosts on {target_range}...")
nm.scan(hosts=target_range, arguments='-sn')
live_hosts = nm.all_hosts()
if not live_hosts:
print("[!] No devices found. Check your connection to the 192.168.12.x VLAN.")
return []
print(f"[+] Found {len(live_hosts)} active devices.")
print("[*] PHASE 2: Deep Scanning top 10,000 ports (this will take a few minutes)...")
# Using synchronous scan for Windows stability
target_list = " ".join(live_hosts)
# -sV: Service version detection for hostnames and initial banners
nm_args = '-sV --open -T4 --top-ports 10000'
nm.scan(hosts=target_list, arguments=nm_args)
# PHASE 3: Zero-Trust Web Verification & Banner Grabbing
scan_results = []
print("\n[*] PHASE 3: Verifying web interfaces and grabbing software banners...")
for host in nm.all_hosts():
hostname = nm[host].hostname()
print(f"\n[+] Analyzing host: {host} ({hostname if hostname else 'No DNS Name'})")
for proto in nm[host].all_protocols():
lport = nm[host][proto].keys()
for port in lport:
print(f" - Probing port {port}...")
is_web, verified_url, web_title, banner = probe_for_web_interface(host, port)
if is_web:
scan_results.append({
'IP Address': host,
'Hostname': hostname,
'Port': port,
'Service Identity': web_title,
'Software Banner': banner,
'Verified Login URL': verified_url,
'Discovery Date': datetime.now().strftime("%Y-%m-%d %H:%M")
})
return scan_results
def save_to_excel(data, output_path):
if not data:
print("\n[!] No web services detected on the identified hosts.")
return
df = pd.DataFrame(data)
# XlsxWriter is used to ensure URLs are formatted as clickable blue links
writer = pd.ExcelWriter(output_path, engine='xlsxwriter')
df.to_excel(writer, index=False, sheet_name='Homelab_Inventory')
workbook = writer.book
worksheet = writer.sheets['Homelab_Inventory']
# Formatting for better readability
for i, col in enumerate(df.columns):
width = max(df[col].astype(str).map(len).max(), len(col)) + 2
worksheet.set_column(i, i, width)
writer.close()
print(f"\n[SUCCESS] Discovery Finished! Your documentation is at: {output_path}")
if __name__ == "__main__":
# Settings
TARGET_VLAN = "192.168.12.0/24"
# Storing in your requested directory
OUTPUT_FILE = r"D:\hackerstuff\scripts\my_scripts\ai-code\Full_Homelab_Recovery.xlsx"
os.makedirs(os.path.dirname(OUTPUT_FILE), exist_ok=True)
results = run_exhaustive_scan(TARGET_VLAN)
save_to_excel(results, OUTPUT_FILE)