ai-network-llms / README.md
JoeiBanana's picture
Upload batch 8/8
036a93f verified
|
Raw
History Blame Contribute Delete
11.4 kB
---
license: apache-2.0
base_model: NousResearch/Hermes-3-Llama-3.1-8B
tags:
- lora
- peft
- cisco
- networking
- security
- wazuh
- incident-response
- network-automation
- restconf
- ospf
- bgp
language:
- en
pipeline_tag: text-generation
---
# Wazuh-LLM Cisco Network Incident Response
Automated network incident response system for Cisco IOS-XE routers and switches.
Takes Wazuh SIEM alerts, classifies them with a fine-tuned LLM, queries live device
state via RESTCONF, generates CLI fix commands using domain-specific LoRA adapters,
and applies the fixes automatically via RESTCONF PATCH.
Two backends are provided: a **manual 3-script pipeline** for operator-controlled
workflows, and a **fully autonomous daemon** that watches Wazuh logs and resolves
incidents end-to-end without human intervention.
---
## Architecture
### Backend 1 β€” Manual Pipeline (3 scripts)
```
Wazuh alerts file
|
v
[runners/prefilter.py] filter level-12, drop auth noise
|
v
[runners/pipeline.py]
Stage 1 Wazuh LLM (Ollama) incident_type, severity, IOCs
Stage 2 Show command lookup deterministic table (incident -> show cmds)
Stage 3 RESTCONF mapping deterministic table (show cmd -> YANG path)
Stage 4 Domain routing selects correct LoRA adapter
|
v creates show_outputs/alert_NNN_DEVICE_INCIDENT/
restconf_commands.json <- execute these GETs against routers
alert_info.json
(operator executes RESTCONF GETs and drops response JSONs into the folder)
|
v
[runners/run_fix.py] polls folders, runs domain LoRA
|
|-- fix_commands.txt CLI fix commands (human readable)
+-- restconf_fix_commands.json RESTCONF PATCH ops to apply the fix
+-- pipeline_fix_output.jsonl full record of all alerts processed
```
### Backend 2 β€” Autonomous Daemon (always-on)
```
/var/ossec/logs/alerts/alerts.json (Wazuh live output, tailed continuously)
|
v
[backend/daemon.py]
Watch tail alerts file, detect new entries (level 7-12)
Detect SSH brute-force: 5+ failures from same IP within 5-minute window
|
v per alert, fully automatic:
[1] Extract device IP -> device map
[2] Classify Ollama wazuh-llama -> incident_type, IOCs, severity
[3] Show commands deterministic table lookup
[4] RESTCONF GETs execute live against device, collect YANG state
[5] Domain LoRA generate CLI fix commands
[6] RESTCONF PATCHes apply fixes directly to device
[7] Log result managed_incidents.jsonl + managed_incidents.log
|
v per-alert folder:
restconf_get_results.json what the device reported
fix_commands.txt CLI commands the LLM generated
restconf_fix_commands.json PATCH ops with YANG bodies
patch_results.json HTTP status of each PATCH
```
---
## LoRA Adapters
18 domain-specific adapters fine-tuned on Hermes-3-Llama-3.1-8B (r=8, alpha=32):
| Domain | Adapter | Incidents covered |
|---------|----------------------------------|--------------------------------------------------------|
| OSPF | `incidents/ospf/ospf1` | Neighbor down, full-to-down, adjacency loss |
| OSPF | `incidents/ospf/ospf2` | ExStart/Exchange stuck, Init stuck, 2-Way |
| OSPF | `incidents/ospf/ospf3` | Auth, hello/dead mismatch, area, network-type, MTU |
| OSPF | `incidents/ospf/ospf4` | LSA flood, LSDB inconsistency, redistribution |
| BGP | `incidents/bgp/lora_llm_bgp1` | Session flap, hold-timer expiry, neighbor reset |
| BGP | `incidents/bgp/lora_llm_bgp2` | Prefix limit, route leak, path selection |
| BGP | `incidents/bgp/lora_llm_bgp3` | Missing RIB routes, next-hop-self, AFI-SAFI mismatch |
| Sec | `incidents/security/lora_llm_sec1` | ACL blocking legitimate traffic |
| Sec | `incidents/security/lora_llm_sec2` | ACL misconfiguration (protocol, wildcard, direction)|
| Sec | `incidents/security/lora_llm_sec3` | Excessive denies, brute force, port scan |
| Switch | `incidents/switch/lora_llm_switch1` | MAC flapping, STP topology change, err-disable |
| Switch | `incidents/switch/lora_llm_switch2` | Port security, duplex/speed mismatch |
| Switch | `incidents/switch/lora_llm_switch3` | VLAN mismatch, trunk negotiation, storm control |
| Service | `incidents/service/lora_llm_service1` | DHCP conflict, starvation, IP conflict |
| Service | `incidents/service/lora_llm_service2` | DNS failure, NTP unsync, ARP spoofing |
| Sys | `incidents/sys/lora_llm_sys1` | High CPU, memory exhaustion, process crash |
| Sys | `incidents/sys/lora_llm_sys2` | Interface flap, duplex/speed mismatch |
| Sys | `incidents/sys/lora_llm_sys3` | Reload, environmental, general system health |
---
## Requirements
```bash
pip install -r requirements.txt
```
The Wazuh LLM stage uses **Ollama** with a local `wazuh-llama` model:
```bash
# Install Ollama: https://ollama.com
ollama create wazuh-llama -f Modelfile
```
---
## Quick Start β€” Manual Pipeline
```bash
# Step 1 β€” pre-filter raw Wazuh export
python runners/prefilter.py --input alerts.json --output s_alerts.jsonl
# Step 2 β€” classify + build RESTCONF show commands + create per-alert folders
python runners/pipeline.py --input s_alerts.jsonl --show-dir show_outputs
# Step 3 β€” execute the RESTCONF GETs listed in each folder's restconf_commands.json
# and save JSON responses into the same folder
# Step 4 β€” run domain LoRA, generate fix commands + RESTCONF PATCH ops
python runners/run_fix.py --show-dir show_outputs
```
Per-alert output folder after all steps:
```
show_outputs/alert_001_R1_ospf_neighbor_down/
alert_info.json alert metadata
restconf_commands.json GET commands (written by pipeline.py)
show_ip_ospf_neighbor.json RESTCONF GET response (you drop this)
fix_commands.txt CLI fix commands (written by run_fix.py)
restconf_fix_commands.json RESTCONF PATCH ops (written by run_fix.py)
```
---
## Quick Start β€” Autonomous Daemon
```bash
# Standard β€” watch live Wazuh alerts, auto-apply fixes (level 7-12)
python backend/daemon.py
# Dry run β€” classify + generate commands, but do NOT PATCH devices
python backend/daemon.py --dry-run
# Custom alert file and thresholds
python backend/daemon.py \
--alerts /var/ossec/logs/alerts/alerts.json \
--min-level 7 \
--ssh-threshold 5 \
--ssh-window 300 \
--poll 3
```
The daemon tail-follows the Wazuh alerts file and processes each alert
automatically end-to-end with no operator involvement.
### Daemon output files
| File | Content |
|------|---------|
| `managed_incidents.jsonl` | Machine-readable: one JSON record per handled alert |
| `managed_incidents.log` | Human-readable: one summary block per alert |
| `daemon.log` | Full debug log of all daemon activity |
| `show_outputs/alert_NNN_*/` | Per-alert audit folder (GET results, fix, patch results) |
### SSH Brute-Force Detection
The daemon tracks failed SSH login alerts independently of the level filter.
When **5 or more failures from the same source IP occur within 5 minutes**,
a synthetic `ssh_brute_force` incident is triggered and the full pipeline runs β€”
even if each individual alert is below the level threshold.
Tune with `--ssh-threshold N --ssh-window SECONDS`.
---
## Device Configuration
Edit the maps at the top of `runners/pipeline.py` and `backend/daemon.py` to match your network:
```python
SOURCE_IP_DEVICE_MAP = {
"10.10.10.10": "R1",
"2.2.2.2": "R2",
# ...
}
DEVICE_MGMT_IP = {
"R1": "10.10.10.10", # management IP used for RESTCONF
"R2": "2.2.2.2",
# ...
}
```
Router credentials: `ROUTER_USER` / `ROUTER_PASS` constants (default: `admin` / `cisco123!`).
---
## RESTCONF
All communication uses RESTCONF over HTTPS (port 443) with Cisco IOS-XE YANG models.
**Read (GET)** β€” `_RESTCONF_RULES` table maps each show command to its YANG path:
```
show ip ospf neighbor -> /restconf/data/Cisco-IOS-XE-ospf-oper:ospf-oper-data/ospf-state
show ip bgp summary -> /restconf/data/Cisco-IOS-XE-bgp-oper:bgp-state-data/bgp-route-vrfs
show interfaces -> /restconf/data/Cisco-IOS-XE-interfaces-oper:interfaces
...
```
**Write (PATCH)** β€” CLI fix commands are parsed into context blocks and converted
to RESTCONF PATCH operations with YANG-native JSON bodies:
```
interface GigabitEthernet0/0 -> PATCH .../interface/GigabitEthernet=0%2F0
ip ospf hello-interval 10 body: Cisco-IOS-XE-ospf:ospf hello-interval 10
router bgp 65001 -> PATCH .../router/bgp=65001
neighbor 10.0.0.2 timers 30 90 body: neighbor timers keepalive 30 holdtime 90
ip access-list extended INBOUND -> PATCH .../ip/access-list/extended=INBOUND
```
Supported YANG modules include:
`Cisco-IOS-XE-ospf-oper`, `Cisco-IOS-XE-bgp-oper`, `Cisco-IOS-XE-interfaces-oper`,
`Cisco-IOS-XE-acl-oper`, `Cisco-IOS-XE-spanning-tree-oper`, `Cisco-IOS-XE-vlan-oper`,
`Cisco-IOS-XE-dhcp-oper`, `Cisco-IOS-XE-arp-oper`, `Cisco-IOS-XE-nat-oper`,
`Cisco-IOS-XE-ntp-oper`, `Cisco-IOS-XE-process-cpu-oper`,
`Cisco-IOS-XE-process-memory-oper`, `Cisco-IOS-XE-native`
---
## Training
Training scripts and datasets are in `training/` and `datasets/`.
Each adapter was trained on 900–1500 examples with LoRA (r=8, alpha=32, dropout=0.1)
targeting `q_proj` and `v_proj` on Hermes-3-Llama-3.1-8B.
```bash
python training/train_ospf1.py
python training/train_bgp1.py
# etc.
```
---
## Lab Topology
Tested on a 4-router + 4-switch Cisco IOS-XE lab:
- **R1 / R2 / R3 / R4** β€” IOS-XE routers running OSPF + BGP
- **SW1 / SW2** β€” distribution switches
- **ACCESS-SW1 / ACCESS-SW2** β€” access switches
- **R4** β€” DHCP server (192.168.40.0/24 pool)
- Wazuh manager collecting syslog from all devices
---
## Project Files
| Path | Description |
|------|-------------|
| `runners/prefilter.py` | Pre-filter raw Wazuh export (level filter + brute-force detection) |
| `runners/pipeline.py` | Manual backend Phase 1: classify, map RESTCONF GETs, create folders |
| `runners/run_fix.py` | Manual backend Phase 2: run domain LoRA, generate and map fix commands |
| `backend/daemon.py` | Autonomous daemon: watches live Wazuh alerts, resolves incidents end-to-end |
| `Modelfile` | Ollama model definition for the Wazuh alert classifier |
| `models/base/` | Hermes-3-Llama-3.1-8B base model |
| `models/incidents/` | 18 domain-specific LoRA adapters |
| `models/registry.json` | Adapter name -> path registry |
| `datasets/` | Training datasets (JSONL, one incident type per file) |
| `training/` | Training scripts (one per adapter) |
| `cases/` | Incident test cases used for evaluation |
---
## Citation
```bibtex
@misc{wazuh-llm-cisco-2025,
title = {Wazuh-LLM Cisco Network Incident Response},
year = {2025},
url = {https://huggingface.co/YOUR_USERNAME/wazuh-llm-cisco}
}
```