#!/usr/bin/env python # -*- coding: utf-8 -*- from flask import Flask, render_template, jsonify import socket import platform import os import subprocess import json import datetime import psutil import netifaces app = Flask(__name__) DEBUG_PORT = 5555 # Port für den Debug-Server @app.route('/') def index(): """Rendert die Hauptseite des Debug-Servers.""" return render_template('index.html', hostname=socket.gethostname(), ip_address=get_ip_address(), timestamp=datetime.datetime.now().strftime("%d.%m.%Y %H:%M:%S")) @app.route('/systeminfo') def systeminfo(): """Gibt Systeminformationen zurück.""" info = { "hostname": socket.gethostname(), "platform": platform.platform(), "architecture": platform.machine(), "processor": platform.processor(), "python_version": platform.python_version(), "uptime": get_uptime(), "memory": get_memory_info(), "disk": get_disk_info(), } return jsonify(info) @app.route('/network') def network(): """Gibt Netzwerkinformationen zurück.""" info = { "interfaces": get_network_interfaces(), "connections": get_active_connections(), "dns_servers": get_dns_servers(), "gateway": get_default_gateway(), } return jsonify(info) @app.route('/docker') def docker(): """Gibt Docker-Informationen zurück.""" return jsonify(get_docker_info()) @app.route('/ping/') def ping_host(host): """Pingt einen Zielhost an und gibt das Ergebnis zurück.""" if is_valid_hostname(host): try: result = subprocess.run(['ping', '-n', '4', host], capture_output=True, text=True, timeout=10) return jsonify({ "success": result.returncode == 0, "output": result.stdout, "error": result.stderr, "return_code": result.returncode }) except subprocess.TimeoutExpired: return jsonify({"success": False, "error": "Zeitüberschreitung beim Ping-Befehl"}) except Exception as e: return jsonify({"success": False, "error": str(e)}) else: return jsonify({"success": False, "error": "Ungültiger Hostname oder IP-Adresse"}) @app.route('/traceroute/') def traceroute_host(host): """Führt einen Traceroute zum Zielhost durch und gibt das Ergebnis zurück.""" if is_valid_hostname(host): try: result = subprocess.run(['tracert', host], capture_output=True, text=True, timeout=30) return jsonify({ "success": True, "output": result.stdout, "error": result.stderr, "return_code": result.returncode }) except subprocess.TimeoutExpired: return jsonify({"success": False, "error": "Zeitüberschreitung beim Traceroute-Befehl"}) except Exception as e: return jsonify({"success": False, "error": str(e)}) else: return jsonify({"success": False, "error": "Ungültiger Hostname oder IP-Adresse"}) @app.route('/nslookup/') def nslookup_host(host): """Führt eine DNS-Abfrage für den angegebenen Host durch.""" if is_valid_hostname(host): try: result = subprocess.run(['nslookup', host], capture_output=True, text=True, timeout=10) return jsonify({ "success": result.returncode == 0, "output": result.stdout, "error": result.stderr, "return_code": result.returncode }) except subprocess.TimeoutExpired: return jsonify({"success": False, "error": "Zeitüberschreitung beim NSLookup-Befehl"}) except Exception as e: return jsonify({"success": False, "error": str(e)}) else: return jsonify({"success": False, "error": "Ungültiger Hostname oder IP-Adresse"}) @app.route('/backend-status') def backend_status(): """Überprüft den Status des Haupt-Backend-Servers.""" try: # Benutze den Localhost und den Port des Haupt-Backends (Standard: 5000) backend_port = 5000 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(2) result = s.connect_ex(('localhost', backend_port)) s.close() return jsonify({ "status": "online" if result == 0 else "offline", "port": backend_port, "error_code": result }) except Exception as e: return jsonify({ "status": "error", "message": str(e) }) # Hilfsfunktionen def get_ip_address(): """Ermittelt die primäre IP-Adresse des Servers.""" try: # Für die lokale Netzwerk-IP s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) return s.getsockname()[0] except: return "127.0.0.1" # Fallback auf localhost finally: s.close() def get_uptime(): """Ermittelt die Systemlaufzeit.""" return str(datetime.timedelta(seconds=int(psutil.boot_time()))) def get_memory_info(): """Gibt Informationen über den Speicherverbrauch zurück.""" mem = psutil.virtual_memory() return { "total": format_bytes(mem.total), "used": format_bytes(mem.used), "free": format_bytes(mem.available), "percent": mem.percent } def get_disk_info(): """Gibt Informationen über den Festplattenspeicher zurück.""" disk = psutil.disk_usage('/') return { "total": format_bytes(disk.total), "used": format_bytes(disk.used), "free": format_bytes(disk.free), "percent": disk.percent } def get_network_interfaces(): """Gibt Informationen über die Netzwerkschnittstellen zurück.""" interfaces = {} for iface in netifaces.interfaces(): addrs = netifaces.ifaddresses(iface) if netifaces.AF_INET in addrs: ipv4 = addrs[netifaces.AF_INET][0] interfaces[iface] = { "ip": ipv4.get('addr', ''), "netmask": ipv4.get('netmask', ''), "broadcast": ipv4.get('broadcast', '') } else: interfaces[iface] = {"ip": "Keine IPv4-Adresse", "netmask": "", "broadcast": ""} return interfaces def get_active_connections(): """Gibt Informationen über aktive Netzwerkverbindungen zurück.""" connections = [] for conn in psutil.net_connections(kind='inet'): if conn.status == 'ESTABLISHED': connections.append({ "local_address": f"{conn.laddr.ip}:{conn.laddr.port}", "remote_address": f"{conn.raddr.ip}:{conn.raddr.port}", "status": conn.status, "pid": conn.pid }) return connections[:20] # Begrenze auf 20 Verbindungen def get_dns_servers(): """Ermittelt die DNS-Server-Konfiguration.""" dns_servers = [] try: if os.name == 'nt': # Windows output = subprocess.check_output( ['powershell', '-Command', "Get-DnsClientServerAddress -AddressFamily IPv4 | Select-Object -ExpandProperty ServerAddresses"], text=True) for line in output.strip().split('\n'): line = line.strip() if line: dns_servers.append(line) else: # Linux/Unix with open('/etc/resolv.conf', 'r') as f: for line in f: if line.startswith('nameserver'): dns_servers.append(line.split()[1]) except Exception as e: dns_servers.append(f"Fehler: {str(e)}") return dns_servers def get_default_gateway(): """Ermittelt das Standard-Gateway.""" gateways = netifaces.gateways() if 'default' in gateways and netifaces.AF_INET in gateways['default']: return gateways['default'][netifaces.AF_INET][0] return "Kein Standard-Gateway gefunden" def get_docker_info(): """Gibt Informationen über Docker und laufende Container zurück.""" docker_info = {"installed": False, "version": "", "containers": []} try: # Prüfe, ob Docker installiert ist version_result = subprocess.run(['docker', '--version'], capture_output=True, text=True, timeout=5) if version_result.returncode == 0: docker_info["installed"] = True docker_info["version"] = version_result.stdout.strip() # Hole Informationen über laufende Container container_result = subprocess.run( ['docker', 'ps', '--format', '{{.ID}},{{.Image}},{{.Status}},{{.Ports}},{{.Names}}'], capture_output=True, text=True, timeout=5) if container_result.returncode == 0: for line in container_result.stdout.strip().split('\n'): if line: parts = line.split(',') if len(parts) >= 5: docker_info["containers"].append({ "id": parts[0], "image": parts[1], "status": parts[2], "ports": parts[3], "name": parts[4] }) except (subprocess.SubprocessError, FileNotFoundError): pass # Docker ist nicht installiert oder nicht zugänglich return docker_info def is_valid_hostname(hostname): """Überprüft, ob ein Hostname oder eine IP-Adresse gültig ist.""" if len(hostname) > 255: return False if hostname == "localhost" or hostname == "127.0.0.1": return True # Prüfe auf IP-Format try: socket.inet_pton(socket.AF_INET, hostname) return True except socket.error: pass try: socket.inet_pton(socket.AF_INET6, hostname) return True except socket.error: pass # Prüfe auf Hostname-Format allowed = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.") return all(c in allowed for c in hostname) and not hostname.startswith(".") def format_bytes(size): """Formatiert Bytes in eine lesbare Größe.""" power = 2**10 # 1024 n = 0 power_labels = {0: 'B', 1: 'KB', 2: 'MB', 3: 'GB', 4: 'TB'} while size > power and n < 4: size /= power n += 1 return f"{size:.2f} {power_labels[n]}" if __name__ == "__main__": print(f"MYP Backend Debug-Server wird gestartet auf Port {DEBUG_PORT}...") app.run(host='0.0.0.0', port=DEBUG_PORT, debug=True)