#!/usr/bin/env python3 """ UnaysNET Agent - Cross-Platform System Monitor Monitors your computer with real system data and sends it to UnaysNET. Works on Windows, Linux, and macOS. Usage: python agent.py # Run normally (auto-detect OS) python agent.py --server http://... # Custom server URL python agent.py --interval 5 # Custom interval (seconds) python agent.py --debug # Verbose debug output python agent.py --test # Send one report then exit """ import sys import os import time import platform import subprocess from datetime import datetime # ============================================================================= # Cross-Platform Detection # ============================================================================= IS_WINDOWS = platform.system() == "Windows" IS_LINUX = platform.system() == "Linux" IS_MAC = platform.system() == "Darwin" IS_ROOT = False def check_privileges(): """Check if we have admin/root privileges""" global IS_ROOT if IS_WINDOWS: try: import ctypes IS_ROOT = ctypes.windll.shell32.IsUserAnAdmin() != 0 except: IS_ROOT = False else: IS_ROOT = os.geteuid() == 0 return IS_ROOT def request_elevation(): """Request admin/root privileges per platform""" if check_privileges(): print(" [\u2713] Running with elevated privileges") return True print("=" * 55) print(" PRIVILEGE ESCALATION REQUIRED") print("=" * 55) print("") if IS_WINDOWS: print(" Administrator access needed for:") print(" \u2022 Full network connection details") print(" \u2022 All running process information") print(" \u2022 Complete disk and system data") print("") print(" A UAC dialog will appear. Click 'Yes' to continue.") print("") try: import ctypes script = os.path.abspath(sys.argv[0]) ctypes.windll.shell32.ShellExecuteW( None, "runas", sys.executable, f'"{script}"', None, 1 ) print(" [\u2191] Elevation requested in new window.") print(" [\u2139] Close this window and use the new one.") sys.exit(0) except Exception as e: print(f" [!] Elevation failed: {e}") print(" [!] Right-click and select 'Run as Administrator'") return False else: print(" Root privileges needed for:") print(" \u2022 Full network connection details") print(" \u2022 All running process information") print(" \u2022 System log access") print("") print(f" Run: sudo python3 {os.path.basename(sys.argv[0])}") print("") return False # ============================================================================= # System Monitor - Cross-Platform Real Data Collection # ============================================================================= class SystemMonitor: def __init__(self): self.hostname = platform.node() self.os_name = f"{platform.system()} {platform.release()} ({platform.version()})" self.architecture = platform.machine() self.processor = platform.processor() or self._get_proc_name() def _get_proc_name(self): """Get CPU name on Linux where platform.processor() returns empty""" try: if IS_LINUX: with open("/proc/cpuinfo") as f: for line in f: if "model name" in line: return line.split(":")[1].strip() except: pass return "Unknown" def _import_psutil(self): """Import psutil with helpful error""" try: import psutil return psutil except ImportError: print(f"\n [!] {'='*40}") print(f" [!] MISSING DEPENDENCY: psutil") print(f" [!] {'='*40}") print(f" [!] Install it:") print(f" [!") if IS_WINDOWS: print(f" [!] pip install psutil requests") else: print(f" [!] pip3 install psutil requests") print(f" [!] (or: sudo apt install python3-psutil python3-requests)") print(f" [!] {'='*40}\n") return None def get_cpu_info(self, psutil): return { "percent": psutil.cpu_percent(interval=0.5), "count": psutil.cpu_count(), "count_logical": psutil.cpu_count(logical=True), "frequency": dict(psutil.cpu_freq()._asdict()) if psutil.cpu_freq() else {}, "processor": self.processor, } def get_memory_info(self, psutil): mem = psutil.virtual_memory() swap = psutil.swap_memory() return { "total": mem.total, "available": mem.available, "percent": mem.percent, "used": mem.used, "free": mem.free, "swap_total": swap.total, "swap_used": swap.used, "swap_percent": swap.percent, } def get_disk_info(self, psutil): disks = [] for partition in psutil.disk_partitions(): try: usage = psutil.disk_usage(partition.mountpoint) disks.append({ "device": partition.device, "mountpoint": partition.mountpoint, "fstype": partition.fstype, "total": usage.total, "used": usage.used, "free": usage.free, "percent": usage.percent, }) except (PermissionError, OSError): pass return disks def get_network_info(self, psutil): connections = [] try: for conn in psutil.net_connections(kind='inet'): connections.append({ "local": f"{conn.laddr.ip}:{conn.laddr.port}" if conn.laddr else "", "remote": f"{conn.raddr.ip}:{conn.raddr.port}" if conn.raddr else "", "status": conn.status, "pid": conn.pid, }) except (psutil.AccessDenied, PermissionError): connections = [{"error": "Access denied - run as admin/root"}] except Exception: connections = [{"error": "Failed to read connections"}] try: net_io = psutil.net_io_counters() io_data = { "bytes_sent": net_io.bytes_sent, "bytes_recv": net_io.bytes_recv, "packets_sent": net_io.packets_sent, "packets_recv": net_io.packets_recv, } except: io_data = {} return {"connections": connections[:100], **io_data} def get_process_info(self, psutil): processes = [] try: for proc in sorted( psutil.process_iter(["pid", "name", "cpu_percent", "memory_percent", "status"]), key=lambda p: p.info.get("cpu_percent", 0) or 0, reverse=True )[:30]: try: processes.append({ "pid": proc.info["pid"], "name": proc.info["name"], "cpu": round(proc.info["cpu_percent"] or 0, 1), "memory": round(proc.info["memory_percent"] or 0, 1), "status": proc.info["status"], }) except (psutil.NoSuchProcess, psutil.AccessDenied): pass except: pass return processes def get_system_uptime(self, psutil): try: boot = psutil.boot_time() uptime_seconds = time.time() - boot days = int(uptime_seconds // 86400) hours = int((uptime_seconds % 86400) // 3600) minutes = int((uptime_seconds % 3600) // 60) return f"{days}d {hours}h {minutes}m" except: return "N/A" def get_load_average(self): """Get system load average (Unix only)""" try: if not IS_WINDOWS: avg = os.getloadavg() return {"1min": round(avg[0], 2), "5min": round(avg[1], 2), "15min": round(avg[2], 2)} except: pass return None def get_all_data(self, debug=False): """Collect ALL real system data""" psutil = self._import_psutil() if not psutil: return None if debug: print(" [*] Collecting system data...") data = { "agent_version": "2.0.0", "platform": platform.system(), "hostname": self.hostname, "os": self.os_name, "architecture": self.architecture, "uptime": self.get_system_uptime(psutil), "timestamp": datetime.now().isoformat(), "cpu": self.get_cpu_info(psutil), "memory": self.get_memory_info(psutil), "disks": self.get_disk_info(psutil), "network": self.get_network_info(psutil), "processes": self.get_process_info(psutil), "users": self._get_users(psutil), "load_avg": self.get_load_average(), } if debug: print(f" [\u2713] Data: CPU {data['cpu']['percent']}% | " f"MEM {data['memory']['percent']}% | " f"{len(data['network'].get('connections',[]))} connections | " f"{len(data['processes'])} processes") return data def _get_users(self, psutil): try: return [{ "name": u.name, "terminal": u.terminal or "N/A", "host": u.host or "local", "started": datetime.fromtimestamp(u.started).isoformat() if u.started else "", } for u in psutil.users()] except: return [] # ============================================================================= # Agent Communication # ============================================================================= class AgentClient: def __init__(self, server_url="https://iot.unays.net", interval=2, debug=False): self.server_url = server_url.rstrip("/") self.interval = interval self.debug = debug self.monitor = SystemMonitor() self.running = False self._requests = None def _import_requests(self): """Import requests with helpful error""" if self._requests: return self._requests try: import requests as r self._requests = r return r except ImportError: print(f"\n [!] {'='*40}") print(f" [!] MISSING DEPENDENCY: requests") print(f" [!] {'='*40}") print(f" [!] Install it:") if IS_WINDOWS: print(f" [!] pip install requests") else: print(f" [!] pip3 install requests") print(f" [!] {'='*40}\n") return None def test_connection(self): """Test if we can reach the server""" requests = self._import_requests() if not requests: return False print(" [*] Testing server connectivity...") # Test 1: Basic connectivity try: r = requests.get(self.server_url, timeout=10, verify=False) print(f" [\u2713] Server reachable: HTTP {r.status_code}") except requests.exceptions.ConnectionError: print(f" [!] CANNOT REACH SERVER: {self.server_url}") print(f" [!] Check:") print(f" [!] - Is the URL correct?") print(f" [!] - Is your internet working?") print(f" [!] - Is the server online?") return False except Exception as e: print(f" [!] Connection test failed: {e}") return False # Test 2: Agent endpoint try: test_data = { "agent_version": "2.0.0", "platform": platform.system(), "hostname": self.monitor.hostname, "cpu": {"percent": 0}, "timestamp": datetime.now().isoformat(), } r = requests.post( f"{self.server_url}/api/agent/report", json=test_data, timeout=10, verify=False, ) print(f" [\u2713] Agent endpoint: HTTP {r.status_code}") if r.status_code == 200: print(f" [\u2713] Server accepted test report!") return True else: print(f" [!] Server returned: {r.text[:100]}") return False except Exception as e: print(f" [!] Agent endpoint test failed: {e}") return False def send_data(self, data): """Send monitoring data to the server""" requests = self._import_requests() if not requests: return False try: # Try with SSL verification first, fallback if it fails try: response = requests.post( f"{self.server_url}/api/agent/report", json=data, timeout=15, headers={"User-Agent": "UnaysNET-Agent/2.0"}, ) except requests.exceptions.SSLError: if self.debug: print(" [!] SSL verification failed, retrying without verification") import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) response = requests.post( f"{self.server_url}/api/agent/report", json=data, timeout=15, verify=False, headers={"User-Agent": "UnaysNET-Agent/2.0"}, ) if response.status_code == 200: return True else: if self.debug: print(f" [!] Server HTTP {response.status_code}: {response.text[:200]}") return False except requests.exceptions.ConnectionError as e: print(f" [!] Connection failed: {e}") return False except requests.exceptions.Timeout: print(f" [!] Connection timed out (15s)") return False except Exception as e: print(f" [!] Send error: {e}") if self.debug: import traceback traceback.print_exc() return False def run(self): """Main agent loop""" requests = self._import_requests() if not requests: return # Test connection first if not self.test_connection(): print("") print(" [!] Connection test failed. Will retry in the loop...") print(" [!] Press Ctrl+C to exit.") print("") self.running = True print("") print("=" * 55) print(f" UNAYSNET AGENT v2.0 - MONITORING ACTIVE") print(f" Host: {self.monitor.hostname}") print(f" OS: {self.monitor.os_name}") print(f" Server: {self.server_url}") print(f" Interval: {self.interval}s") print(f" Debug: {self.debug}") print("=" * 55) print("") print(" Press Ctrl+C to stop") print("") last_send = 0 fails = 0 try: while self.running: now = time.time() if now - last_send >= self.interval: data = self.monitor.get_all_data(debug=self.debug) if data is None: print(" [!] Failed to collect data (psutil missing?)") time.sleep(5) continue now_str = datetime.now().strftime("%H:%M:%S") print(f" [{now_str}] Sending {data['cpu']['percent']}% CPU | " f"{data['memory']['percent']}% MEM...", end=" ", flush=True) if self.send_data(data): print("[\u2713]") fails = 0 # Print a brief summary line conns = len(data['network'].get('connections', [])) procs = len(data['processes']) disks_str = data.get('disks', [{}])[0].get('percent', '?') if data.get('disks') else '?' print(f" \u2192 {data['hostname']} | " f"{conns} connections | {procs} processes | {disks_str}% disk") else: print("[!]") fails += 1 if fails >= 10 and fails % 10 == 0: print(f" [!] {fails} consecutive failures. Check connection.") print("") last_send = now time.sleep(1) except KeyboardInterrupt: print("\n Agent stopped by user.") finally: self.running = False # ============================================================================= # One-line installer script generator # ============================================================================= def generate_install_script(platform_name): """Generate a self-contained install & run script""" if platform_name == "linux": return """#!/bin/bash # UnaysNET Agent - Linux Installer set -e echo " === UnaysNET Agent Installer (Linux) ===" echo "" # Install dependencies echo " [*] Installing dependencies..." if command -v apt &>/dev/null; then sudo apt update -qq && sudo apt install -y -qq python3-pip python3-psutil python3-requests 2>/dev/null || \ pip3 install --user psutil requests elif command -v yum &>/dev/null; then sudo yum install -y python3-pip python3-psutil python3-requests 2>/dev/null || \ pip3 install --user psutil requests elif command -v pacman &>/dev/null; then sudo pacman -S --noconfirm python-psutil python-requests 2>/dev/null || \ pip3 install --user psutil requests else pip3 install --user psutil requests fi # Download agent echo " [*] Downloading agent..." curl -sk "https://iot.unays.net/download-agent?platform=linux" -o unaysnet_agent.py # Run echo "" echo " [*] Starting agent (may need sudo)..." echo "" sudo python3 unaysnet_agent.py """ elif platform_name == "macos": return """#!/bin/bash # UnaysNET Agent - macOS Installer set -e echo " === UnaysNET Agent Installer (macOS) ===" echo "" # Install dependencies echo " [*] Installing dependencies..." pip3 install --user psutil requests 2>/dev/null || \ python3 -m pip install --user psutil requests # Download agent echo " [*] Downloading agent..." curl -sk "https://iot.unays.net/download-agent?platform=macos" -o unaysnet_agent.py # Run echo "" echo " [*] Starting agent..." echo "" sudo python3 unaysnet_agent.py """ elif platform_name == "windows": return """@echo off REM UnaysNET Agent - Windows Installer echo. echo === UnaysNET Agent Installer (Windows) === echo. REM Install dependencies echo [*] Installing dependencies... pip install psutil requests REM Download agent echo [*] Downloading agent... powershell -Command "Invoke-WebRequest -Uri 'https://iot.unays.net/download-agent?platform=windows' -OutFile 'unaysnet_agent.py'" REM Run echo. echo [*] Run the agent as Administrator: echo. echo Right-click the file and select "Run with Python" echo OR echo Right-click and select "Run as Administrator" echo. pause """ return "# Unsupported platform" # ============================================================================= # Main Entry Point # ============================================================================= def print_banner(): print("") print(" \u2554" + "\u2550" * 47 + "\u2557") print(" \u2551 UnaysNET System Agent v2.0 \u2551") print(" \u2551 Cross-Platform System Monitor \u2551") print(" \u255a" + "\u2550" * 47 + "\u255d") print("") def install_dependencies(): """Auto-install dependencies""" missing = [] try: import psutil except ImportError: missing.append("psutil") try: import requests except ImportError: missing.append("requests") if not missing: return True print(f" [*] Installing missing dependencies: {', '.join(missing)}") try: subprocess.check_call( [sys.executable, "-m", "pip", "install"] + missing, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=60 ) print(" [\u2713] Dependencies installed!") return True except Exception as e: print(f" [!] Auto-install failed: {e}") print(f" [!] Run: pip install {' '.join(missing)}") return False def main(): # Parse command-line args server_url = "https://iot.unays.net" interval = 2 debug = False test_mode = False gen_script = None i = 1 while i < len(sys.argv): arg = sys.argv[i] if arg == "--server" and i + 1 < len(sys.argv): server_url = sys.argv[i + 1] i += 2 elif arg == "--interval" and i + 1 < len(sys.argv): interval = int(sys.argv[i + 1]) i += 2 elif arg == "--debug": debug = True i += 1 elif arg == "--test": test_mode = True i += 1 elif arg == "--generate-installer" and i + 1 < len(sys.argv): gen_script = sys.argv[i + 1] i += 2 elif arg in ("--help", "-h"): print("UnaysNET Agent v2.0 - Cross-Platform System Monitor") print("") print("Usage:") print(" python agent.py # Run normally") print(" python agent.py --server http://... # Custom server") print(" python agent.py --interval 5 # Change interval") print(" python agent.py --debug # Verbose output") print(" python agent.py --test # One-shot test") return else: i += 1 print_banner() # Generate installer script if requested if gen_script: script = generate_install_script(gen_script) filename = f"install_unaysnet_{gen_script}.sh" if gen_script != "windows" else "install_unaysnet_windows.bat" with open(filename, "w") as f: f.write(script) print(f" [\u2713] Created installer: {filename}") return # Install dependencies if not install_dependencies(): print(" [!] Cannot continue without dependencies.") return # Request elevated privileges (skipped in test mode) if not test_mode: request_elevation() # Create and run client client = AgentClient(server_url=server_url, interval=interval, debug=debug) if test_mode: print(" [*] Test mode: sending one report...") data = client.monitor.get_all_data(debug=True) if data: client.send_data(data) print(f" [\u2713] Test complete. Check your dashboard.") return try: client.run() except Exception as e: print(f" [!] Agent error: {e}") if debug: import traceback traceback.print_exc() print("\n Agent finished.") if __name__ == "__main__": main()