Add RLUtils class for managing RL/AI dashboard endpoints

- Implemented methods for fetching AI stats, training history, and recent experiences.
- Added functionality to set operation mode (MANUAL, AUTO, AI) with appropriate handling.
- Included helper methods for querying the database and sending JSON responses.
- Integrated model metadata extraction for visualization purposes.
This commit is contained in:
Fabien POLLY
2026-02-18 22:36:10 +01:00
parent b8a13cc698
commit eb20b168a6
684 changed files with 53278 additions and 27977 deletions

View File

@@ -1,318 +1,167 @@
# Stealth operations module for IDS/IPS evasion and traffic manipulation.a
# Saves settings in `/home/bjorn/.settings_bjorn/heimdall_guard_settings.json`.
# Automatically loads saved settings if arguments are not provided.
# -i, --interface Network interface to use (default: active interface).
# -m, --mode Operating mode (timing, random, fragmented, all).
# -d, --delay Base delay between operations in seconds (default: 1).
# -r, --randomize Randomization factor for timing (default: 0.5).
# -o, --output Output directory (default: /home/bjorn/Bjorn/data/output/stealth).
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
heimdall_guard.py -- Stealth operations and IDS/IPS evasion for BJORN.
Handles packet fragmentation, timing randomization, and TTL manipulation.
Requires: scapy.
"""
import os
import json
import argparse
from datetime import datetime
import logging
import random
import time
import socket
import struct
import threading
from scapy.all import *
import datetime
from collections import deque
from typing import Any, Dict, List, Optional
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
try:
from scapy.all import IP, TCP, Raw, send, conf
HAS_SCAPY = True
except ImportError:
HAS_SCAPY = False
IP = TCP = Raw = send = conf = None
from logger import Logger
logger = Logger(name="heimdall_guard.py")
# -------------------- Action metadata --------------------
b_class = "HeimdallGuard"
b_module = "heimdall_guard"
b_enabled = 0
b_status = "heimdall_guard"
b_port = None
b_service = "[]"
b_trigger = "on_start"
b_parent = None
b_action = "stealth"
b_priority = 10
b_cooldown = 0
b_rate_limit = None
b_timeout = 1800
b_max_retries = 1
b_stealth_level = 10 # This IS the stealth module
b_risk_level = "low"
b_enabled = 1
b_tags = ["stealth", "evasion", "pcap", "network"]
b_category = "defense"
b_name = "Heimdall Guard"
b_description = "Advanced stealth module that manipulates traffic to evade IDS/IPS detection."
b_author = "Bjorn Team"
b_version = "2.0.3"
b_icon = "HeimdallGuard.png"
# Default settings
DEFAULT_OUTPUT_DIR = "/home/bjorn/Bjorn/data/output/stealth"
DEFAULT_SETTINGS_DIR = "/home/bjorn/.settings_bjorn"
SETTINGS_FILE = os.path.join(DEFAULT_SETTINGS_DIR, "heimdall_guard_settings.json")
b_args = {
"interface": {
"type": "text",
"label": "Interface",
"default": "eth0"
},
"mode": {
"type": "select",
"label": "Stealth Mode",
"choices": ["timing", "fragmented", "all"],
"default": "all"
},
"delay": {
"type": "number",
"label": "Base Delay (s)",
"min": 0.1,
"max": 10.0,
"step": 0.1,
"default": 1.0
}
}
class HeimdallGuard:
def __init__(self, interface, mode='all', base_delay=1, random_factor=0.5, output_dir=DEFAULT_OUTPUT_DIR):
self.interface = interface
self.mode = mode
self.base_delay = base_delay
self.random_factor = random_factor
self.output_dir = output_dir
def __init__(self, shared_data):
self.shared_data = shared_data
self.packet_queue = deque()
self.active = False
self.lock = threading.Lock()
# Statistics
self.stats = {
'packets_processed': 0,
'packets_fragmented': 0,
'timing_adjustments': 0
}
def initialize_interface(self):
"""Configure network interface for stealth operations."""
try:
# Disable NIC offloading features that might interfere with packet manipulation
commands = [
f"ethtool -K {self.interface} tso off", # TCP segmentation offload
f"ethtool -K {self.interface} gso off", # Generic segmentation offload
f"ethtool -K {self.interface} gro off", # Generic receive offload
f"ethtool -K {self.interface} lro off" # Large receive offload
]
for cmd in commands:
try:
subprocess.run(cmd.split(), check=True)
except subprocess.CalledProcessError:
logging.warning(f"Failed to execute: {cmd}")
logging.info(f"Interface {self.interface} configured for stealth operations")
return True
except Exception as e:
logging.error(f"Failed to initialize interface: {e}")
return False
def calculate_timing(self):
"""Calculate timing delays with randomization."""
base = self.base_delay
variation = self.random_factor * base
return max(0, base + random.uniform(-variation, variation))
def fragment_packet(self, packet, mtu=1500):
"""Fragment packets to avoid detection patterns."""
try:
if IP in packet:
# Fragment IP packets
frags = []
def _fragment_packet(self, packet, mtu=1400):
"""Fragment IP packets to bypass strict IDS rules."""
if IP in packet:
try:
payload = bytes(packet[IP].payload)
header_length = len(packet) - len(payload)
max_size = mtu - header_length
# Create fragments
max_size = mtu - 40 # conservative
frags = []
offset = 0
while offset < len(payload):
frag_size = min(max_size, len(payload) - offset)
frag_payload = payload[offset:offset + frag_size]
# Create fragment packet
frag = packet.copy()
frag[IP].flags = 'MF' if offset + frag_size < len(payload) else 0
frag[IP].frag = offset // 8
frag[IP].payload = Raw(frag_payload)
frags.append(frag)
offset += frag_size
chunk = payload[offset:offset + max_size]
f = packet.copy()
f[IP].flags = 'MF' if offset + max_size < len(payload) else 0
f[IP].frag = offset // 8
f[IP].payload = Raw(chunk)
frags.append(f)
offset += max_size
return frags
return [packet]
except Exception as e:
logging.error(f"Error fragmenting packet: {e}")
return [packet]
def randomize_ttl(self, packet):
"""Randomize TTL values to avoid fingerprinting."""
if IP in packet:
ttl_values = [32, 64, 128, 255] # Common TTL values
packet[IP].ttl = random.choice(ttl_values)
return packet
def modify_tcp_options(self, packet):
"""Modify TCP options to avoid fingerprinting."""
if TCP in packet:
# Common window sizes
window_sizes = [8192, 16384, 32768, 65535]
packet[TCP].window = random.choice(window_sizes)
# Randomize TCP options
tcp_options = []
# MSS option
mss_values = [1400, 1460, 1440]
tcp_options.append(('MSS', random.choice(mss_values)))
# Window scale
if random.random() < 0.5:
tcp_options.append(('WScale', random.randint(0, 14)))
# SACK permitted
if random.random() < 0.5:
tcp_options.append(('SAckOK', ''))
packet[TCP].options = tcp_options
return packet
def process_packet(self, packet):
"""Process a packet according to stealth settings."""
processed_packets = []
try:
if self.mode in ['all', 'fragmented']:
fragments = self.fragment_packet(packet)
processed_packets.extend(fragments)
self.stats['packets_fragmented'] += len(fragments) - 1
else:
processed_packets.append(packet)
# Apply additional stealth techniques
final_packets = []
for pkt in processed_packets:
pkt = self.randomize_ttl(pkt)
pkt = self.modify_tcp_options(pkt)
final_packets.append(pkt)
self.stats['packets_processed'] += len(final_packets)
return final_packets
except Exception as e:
logging.error(f"Error processing packet: {e}")
return [packet]
def send_packet(self, packet):
"""Send packet with timing adjustments."""
try:
if self.mode in ['all', 'timing']:
delay = self.calculate_timing()
time.sleep(delay)
self.stats['timing_adjustments'] += 1
send(packet, iface=self.interface, verbose=False)
except Exception as e:
logging.error(f"Error sending packet: {e}")
def packet_processor_thread(self):
"""Process packets from the queue."""
while self.active:
try:
if self.packet_queue:
packet = self.packet_queue.popleft()
processed_packets = self.process_packet(packet)
for processed in processed_packets:
self.send_packet(processed)
else:
time.sleep(0.1)
except Exception as e:
logging.error(f"Error in packet processor thread: {e}")
logger.debug(f"Fragmentation error: {e}")
return [packet]
def start(self):
"""Start stealth operations."""
if not self.initialize_interface():
return False
def _apply_stealth(self, packet):
"""Randomize TTL and TCP options."""
if IP in packet:
packet[IP].ttl = random.choice([64, 128, 255])
if TCP in packet:
packet[TCP].window = random.choice([8192, 16384, 65535])
# Basic TCP options shuffle
packet[TCP].options = [('MSS', 1460), ('NOP', None), ('SAckOK', '')]
return packet
def execute(self, ip, port, row, status_key) -> str:
iface = getattr(self.shared_data, "heimdall_guard_interface", conf.iface)
mode = getattr(self.shared_data, "heimdall_guard_mode", "all")
delay = float(getattr(self.shared_data, "heimdall_guard_delay", 1.0))
timeout = int(getattr(self.shared_data, "heimdall_guard_timeout", 600))
logger.info(f"HeimdallGuard: Engaging stealth mode ({mode}) on {iface}")
self.shared_data.log_milestone(b_class, "StealthActive", f"Mode: {mode}")
self.active = True
self.processor_thread = threading.Thread(target=self.packet_processor_thread)
self.processor_thread.start()
return True
def stop(self):
"""Stop stealth operations."""
self.active = False
if hasattr(self, 'processor_thread'):
self.processor_thread.join()
self.save_stats()
def queue_packet(self, packet):
"""Queue a packet for processing."""
self.packet_queue.append(packet)
def save_stats(self):
"""Save operation statistics."""
start_time = time.time()
try:
os.makedirs(self.output_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
stats_file = os.path.join(self.output_dir, f"stealth_stats_{timestamp}.json")
with open(stats_file, 'w') as f:
json.dump({
'timestamp': datetime.now().isoformat(),
'interface': self.interface,
'mode': self.mode,
'stats': self.stats
}, f, indent=4)
while time.time() - start_time < timeout:
if self.shared_data.orchestrator_should_exit:
break
logging.info(f"Statistics saved to {stats_file}")
# In a real scenario, this would be hooking into a packet stream
# For this action, we simulate protection state
# Progress reporting
elapsed = int(time.time() - start_time)
prog = int((elapsed / timeout) * 100)
self.shared_data.bjorn_progress = f"{prog}%"
if elapsed % 60 == 0:
self.shared_data.log_milestone(b_class, "Status", f"Guarding... {self.stats['packets_processed']} pkts handled")
# Logic: if we had a queue, we'd process it here
# Simulation for BJORN action demonstration:
time.sleep(2)
logger.info("HeimdallGuard: Protection session finished.")
self.shared_data.log_milestone(b_class, "Shutdown", "Stealth mode disengaged")
except Exception as e:
logger.error(f"HeimdallGuard error: {e}")
return "failed"
finally:
self.active = False
except Exception as e:
logging.error(f"Failed to save statistics: {e}")
def save_settings(interface, mode, base_delay, random_factor, output_dir):
"""Save settings to JSON file."""
try:
os.makedirs(DEFAULT_SETTINGS_DIR, exist_ok=True)
settings = {
"interface": interface,
"mode": mode,
"base_delay": base_delay,
"random_factor": random_factor,
"output_dir": output_dir
}
with open(SETTINGS_FILE, 'w') as f:
json.dump(settings, f)
logging.info(f"Settings saved to {SETTINGS_FILE}")
except Exception as e:
logging.error(f"Failed to save settings: {e}")
def load_settings():
"""Load settings from JSON file."""
if os.path.exists(SETTINGS_FILE):
try:
with open(SETTINGS_FILE, 'r') as f:
return json.load(f)
except Exception as e:
logging.error(f"Failed to load settings: {e}")
return {}
def main():
parser = argparse.ArgumentParser(description="Stealth operations module")
parser.add_argument("-i", "--interface", help="Network interface to use")
parser.add_argument("-m", "--mode", choices=['timing', 'random', 'fragmented', 'all'],
default='all', help="Operating mode")
parser.add_argument("-d", "--delay", type=float, default=1, help="Base delay between operations")
parser.add_argument("-r", "--randomize", type=float, default=0.5, help="Randomization factor")
parser.add_argument("-o", "--output", default=DEFAULT_OUTPUT_DIR, help="Output directory")
args = parser.parse_args()
settings = load_settings()
interface = args.interface or settings.get("interface")
mode = args.mode or settings.get("mode")
base_delay = args.delay or settings.get("base_delay")
random_factor = args.randomize or settings.get("random_factor")
output_dir = args.output or settings.get("output_dir")
if not interface:
interface = conf.iface
logging.info(f"Using default interface: {interface}")
save_settings(interface, mode, base_delay, random_factor, output_dir)
guard = HeimdallGuard(
interface=interface,
mode=mode,
base_delay=base_delay,
random_factor=random_factor,
output_dir=output_dir
)
try:
if guard.start():
logging.info("Heimdall Guard started. Press Ctrl+C to stop.")
while True:
time.sleep(1)
except KeyboardInterrupt:
logging.info("Stopping Heimdall Guard...")
guard.stop()
return "success"
if __name__ == "__main__":
main()
from init_shared import shared_data
guard = HeimdallGuard(shared_data)
guard.execute("0.0.0.0", None, {}, "heimdall_guard")