batman (working version kinda)
This commit is contained in:
commit
6dd38036e7
65 changed files with 3950 additions and 0 deletions
BIN
app/scripts/__pycache__/db_seed.cpython-313.pyc
Normal file
BIN
app/scripts/__pycache__/db_seed.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/scripts/__pycache__/ip_scanner.cpython-313.pyc
Normal file
BIN
app/scripts/__pycache__/ip_scanner.cpython-313.pyc
Normal file
Binary file not shown.
27
app/scripts/db_seed.py
Normal file
27
app/scripts/db_seed.py
Normal 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
178
app/scripts/ip_scanner.py
Normal 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}")
|
Loading…
Add table
Add a link
Reference in a new issue