homelab_scanner.py
scans my local vlan for web interfaces open. exports them to an excel sheet.
This commit is contained in:
commit
ae973dec45
1 changed files with 112 additions and 0 deletions
112
homelab_scanner.py
Normal file
112
homelab_scanner.py
Normal 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)
|
||||
Loading…
Reference in a new issue