batman (working version kinda)

This commit is contained in:
pika 2025-03-30 19:20:13 +02:00
commit 6dd38036e7
65 changed files with 3950 additions and 0 deletions

Binary file not shown.

Binary file not shown.

27
app/scripts/db_seed.py Normal file
View file

@ -0,0 +1,27 @@
from app.core.extensions import db
from app.core.models import Subnet, Server, App
from app.core.auth import User
def seed_database():
# Example seed data for network objects
subnet = Subnet(cidr='192.168.1.0/24', location='Office', auto_scan=True)
server = Server(hostname='server1', ip_address='192.168.1.10', subnet=subnet)
app = App(name='Web App', server=server, documentation='# Welcome to Web App',
_ports='[{"port": 80, "type": "tcp", "desc": "Web"}]')
# Create a default user if none exists
if User.query.count() == 0:
admin = User(email="admin@example.com", is_admin=True)
admin.set_password("admin")
db.session.add(admin)
db.session.add(subnet)
db.session.add(server)
db.session.add(app)
try:
db.session.commit()
print("Database seeded successfully")
except Exception as e:
db.session.rollback()
print(f"Error seeding database: {e}")

178
app/scripts/ip_scanner.py Normal file
View file

@ -0,0 +1,178 @@
import socket
import threading
import ipaddress
import time
from concurrent.futures import ThreadPoolExecutor
from app.core.extensions import db
from app.core.models import Subnet, Server
import json
import subprocess
def scan(cidr, max_threads=10, save_results=False):
"""
Scan a subnet for active hosts
Args:
cidr: The subnet in CIDR notation (e.g. "192.168.1.0/24")
max_threads: Maximum number of threads to use
save_results: Whether to save results to the database
Returns:
A list of dictionaries with IP, hostname, and status
"""
print(f"Starting scan of {cidr}")
network = ipaddress.ip_network(cidr)
# Skip network and broadcast addresses for IPv4
if network.version == 4:
hosts = list(network.hosts())
else:
# For IPv6, just take the first 100 addresses to avoid scanning too many
hosts = list(network.hosts())[:100]
# Split the hosts into chunks for multithreading
chunks = [[] for _ in range(max_threads)]
for i, host in enumerate(hosts):
chunks[i % max_threads].append(host)
# Initialize results
results = [[] for _ in range(max_threads)]
# Create and start threads
threads = []
for i in range(max_threads):
if chunks[i]: # Only start a thread if there are IPs to scan
t = threading.Thread(target=scan_worker, args=(chunks[i], results, i))
threads.append(t)
t.start()
# Wait for all threads to complete
for t in threads:
t.join()
# Combine results
all_results = []
for r in results:
all_results.extend(r)
# Save results to database if requested
if save_results:
try:
save_scan_results(cidr, all_results)
except Exception as e:
print(f"Error saving scan results: {e}")
print(f"Scan completed. Found {len(all_results)} active hosts.")
return all_results
def scan_worker(ip_list, results, index):
"""Worker function for threading"""
for ip in ip_list:
if ping(ip):
hostname = get_hostname(ip)
results[index].append({
'ip': str(ip),
'hostname': hostname if hostname else str(ip),
'status': 'up'
})
def ping(ip):
"""Ping an IP address and return True if it responds"""
try:
# Faster timeout (1 second)
subprocess.check_output(['ping', '-c', '1', '-W', '1', str(ip)], stderr=subprocess.STDOUT)
return True
except subprocess.CalledProcessError:
return False
def get_hostname(ip):
"""Try to get the hostname for an IP address"""
try:
hostname = socket.gethostbyaddr(str(ip))[0]
return hostname
except (socket.herror, socket.gaierror):
return None
def is_host_active_ping(ip):
"""Simple ICMP ping test (platform dependent)"""
import platform
import subprocess
param = '-n' if platform.system().lower() == 'windows' else '-c'
command = ['ping', param, '1', '-w', '1', ip]
try:
return subprocess.call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0
except:
return False
def save_scan_results(cidr, results):
"""Save scan results to the database"""
from flask import current_app
# Need to be in application context
if not hasattr(current_app, 'app_context'):
print("Not in Flask application context, cannot save results")
return
try:
# Find subnet by CIDR
subnet = Subnet.query.filter_by(cidr=cidr).first()
if not subnet:
print(f"Subnet {cidr} not found in database")
return
# Get existing servers in this subnet
existing_servers = {server.ip_address: server for server in Server.query.filter_by(subnet_id=subnet.id).all()}
# Process scan results
for host in results:
ip = host['ip']
hostname = host['hostname']
# Check if server already exists
if ip in existing_servers:
# Update hostname if it was previously unknown
if existing_servers[ip].hostname == ip and hostname != ip:
existing_servers[ip].hostname = hostname
db.session.add(existing_servers[ip])
else:
# Create new server
server = Server(
hostname=hostname,
ip_address=ip,
subnet_id=subnet.id,
documentation=f"# {hostname}\n\nAutomatically discovered by network scan on {time.strftime('%Y-%m-%d %H:%M:%S')}"
)
db.session.add(server)
db.session.commit()
print(f"Saved scan results for {cidr}")
except Exception as e:
db.session.rollback()
print(f"Error saving scan results: {e}")
def schedule_subnet_scans():
"""Schedule automatic scans for subnets marked as auto_scan"""
from flask import current_app
with current_app.app_context():
try:
# Find all subnets with auto_scan enabled
subnets = Subnet.query.filter_by(auto_scan=True).all()
for subnet in subnets:
# Start a thread for each subnet
thread = threading.Thread(
target=scan,
args=(subnet.cidr,),
daemon=True
)
thread.start()
# Sleep briefly to avoid overloading
time.sleep(1)
except Exception as e:
print(f"Error scheduling subnet scans: {e}")