CYJANKALI ist die offensive Test-Spielwiese für das
Cyjan IDS. Hier sammeln wir
Kali-Linux-Skripte, mit denen man das eigene IDS-Setup unter realistischer
Last attackiert – und dazu jeweils, was im Frontend zu sehen sein
sollte. Wenn die Detection ausbleibt, weißt du wo du nachjustieren
musst.
Das Wortspiel ist Programm: Cyankali (Kaliumcyanid) ist
das Gift, gegen das das System schützt. Kali Linux ist
das Werkzeug, mit dem wir das Gift simulieren.
Lab-Setup
Topologie
Mindestens zwei VMs in einem isolierten Subnet:
Cyjan IDS – installiert aus dem aktuellen ISO, mit Mirror-Interface (z.B. ens19) am Span/Mirror-Port des Lab-Switches.
Kali-Angreifer – Kali Linux, normales Routing-Interface.
Ziel-VM (optional) – damit der Sniffer echten Datenverkehr sieht: ein Web-Server, ein DC, ein DVWA-Container.
Wer keinen physischen Switch mit SPAN-Port hat: in Proxmox/VMware den
vSwitch auf Promiscuous stellen und das Mirror-Interface des IDS
am gleichen vSwitch hängen lassen wie das Routing-Interface der Ziel-VM.
Der Sniffer kapert dann den gesamten Bridge-Traffic.
Kali bereitstellen
Frisches Kali-Image holen und in die VM-Plattform deiner Wahl einspielen:
Empfehlung: die Pre-built Virtual Machines
(.ova / .vmx) sparen einen kompletten Installer-Lauf. Default-Login
kali / kali sofort ändern.
Proxmox: VM-Mirror per Hookscript (kein physischer SPAN-Port nötig)
Wer einen Proxmox-Host nutzt, kann den gesamten Verkehr einer Ziel-VM
auf eine Sniffer-VM spiegeln — ohne Switch-Konfiguration, ohne
Promiscuous-Mode am vSwitch. Das Script unten klemmt sich beim
VM-Start als Hook ein und legt per tc mirred ein
bidirektionales Spiegel auf das Tap-Device der Sniffer-VM.
Damit läuft das ganze Lab-Setup als 3 VMs auf einem
Proxmox-Host:
Master-IDS-VM — Cyjan-IDS-ISO, regulär an deinem Management-Netz. Braucht kein Mirror-Interface.
Tap-VM — Cyjan-Tap-ISO, zwei NICs: Management-NIC + Mirror-NIC an einer eigenen Bridge (z.B. vmbr99). Per cyjan-tap pair mit dem Master gekoppelt.
Kali-Angreifer-VM — generiert den Angriffsverkehr. Hängt am normalen Lab-Netz und wird vom Hookscript automatisch auf die Tap-VM gespiegelt.
Der Tap forwarded die Alerts via mTLS-WSS an den Master. Das
Master-Frontend zeigt die Alarme genauso wie bei einer
Hardware-SPAN-Erfassung — nur dass alles in einer einzigen
Lab-Topologie steckt.
Voraussetzung: dedizierte Mirror-Bridge anlegen
Bevor das Hookscript greift, brauchst du in Proxmox eine eigene
Linux-Bridge nur für den Mirror-Traffic. Der Sinn: die
Sniffer-NIC der Tap-VM hängt isoliert daran und sieht ausschließlich
die per tc mirred reingespiegelten Pakete — kein
sonstiger Lab-Verkehr, keine ARP-Stöme, kein DHCP-Lärm.
Die Bridge hat keinen physischen Port und keine
IP. Das ist gewollt: Pakete bleiben rein virtuell auf dem
Host und kommen nur über das Hookscript-Mirroring rein.
Per GUI (Proxmox-Webinterface):
Datacenter → <node> → System → Network → Create → Linux Bridge
Name: vmbr99 (oder anderer freier vmbrN — muss in SNIFFER_BRIDGE des Hookscripts matchen)
Create, dann oben Apply Configuration klicken (live ohne Reboot)
Oder per Datei (gleichbedeutend) — direkt in
/etc/network/interfaces auf dem Proxmox-Host:
cat >> /etc/network/interfaces <<'EOF'
auto vmbr99
iface vmbr99 inet manual
bridge-ports none
bridge-stp off
bridge-fd 0
#Cyjan Mirror Bridge (kein physischer Port, keine IP)
EOF
ifreload -a # oder: ifup vmbr99
Verifikation:
ip -br link show vmbr99 # → vmbr99 UP ...
bridge link show master vmbr99 # zeigt angeschlossene Taps (anfangs leer)
brctl show vmbr99 # alternative Sicht
Tap-VM mit der Mirror-Bridge verbinden
Die Tap-VM braucht zwei NICs: eine fürs Management
(Pairing zum Master, SSH, Updates) und eine an vmbr99
fürs reine Mithören. Beide werden im First-Boot-Wizard
(ids-setup auf der Tap-VM) als Management- bzw.
Mirror-Interface ausgewählt.
# Beispiel: VM 108 = Tap. net0 ist Management (vmbr0), net1 wird Mirror.
qm set 108 --net1 virtio,bridge=vmbr99
# danach Tap-VM rebooten oder net1 neu anstöpseln, damit das neue Tap
# (tap108i1) am Bridge auftaucht.
qm reboot 108
# Innerhalb der Tap-VM: das neue Interface erscheint als ens19 / eth1.
# Im First-Boot-Wizard (ids-setup) als 'Mirror-Interface' auswählen,
# nicht als Management.
Wichtig: das Mirror-Interface in der Tap-VM bekommt keine
IP (der Wizard setzt iface eth1 inet manual +
promisc-mode). Der Sniffer-Container schluckt es per AF_PACKET
direkt — Routing braucht's nicht.
Drei Variablen oben anpassen:
TARGET_VM (die Quell-VM, die du spiegelst),
SNIFFER_VM (deine Tap-VM-ID) und
SNIFFER_BRIDGE (Proxmox-Bridge der Mirror-NIC der Tap-VM).
Installation am Proxmox-Host
Per SSH als root auf den Proxmox-Host:
# 1. Skript ablegen — der Snippet-Pfad muss exakt unter /var/lib/vz/snippets/
# liegen, da Proxmox dort nach Hookscripts sucht (lokaler Storage 'local').
mkdir -p /var/lib/vz/snippets
cp proxmox-mirror.sh /var/lib/vz/snippets/mirror.sh
chmod +x /var/lib/vz/snippets/mirror.sh
# 2. KONFIG im Skript anpassen — TARGET_VM/SNIFFER_VM/SNIFFER_BRIDGE
nano /var/lib/vz/snippets/mirror.sh
# 3. Hookscript an die TARGET-VM binden (VMID = ID der Kali- bzw. Ziel-VM)
qm set 109 --hookscript local:snippets/mirror.sh
# 4. Pre-Check: läuft die Tap-VM, hängt sie an SNIFFER_BRIDGE?
qm config 108 | grep ^net # → muss eine NIC mit bridge=vmbr99 haben
# 5. Trigger: Target-VM neu starten — der post-start-Hook richtet das
# Mirroring automatisch ein (und startet die Tap-VM ggf. mit, wenn
# AUTO_START_SNIFFER=1).
qm reboot 109
# 6. Verifikation: tc-Regeln am Quell-Tap prüfen
tc qdisc show dev tap109i0
tc filter show dev tap109i0 ingress
journalctl -t mirror-hook -n 50
Wie das Mirroring tatsächlich passiert
Proxmox legt für jede VM-NIC ein tap<VMID>i<index>-
Device an, das an der konfigurierten Bridge hängt. Das Skript:
Setzt eine ingress-qdisc auf das Quell-Tap, damit Pakete von der VM in Richtung Bridge mitgespiegelt werden.
Setzt eine root prio-qdisc auf das Quell-Tap, damit Pakete aus der Bridge in Richtung VM ebenfalls mitgespiegelt werden.
Beide qdiscs bekommen einen matchall-Filter mit mirred egress mirror dev <sniffer-tap> — Kernel kopiert jedes Paket auf das Tap der Sniffer-VM.
Die Sniffer-NIC der Tap-VM sieht den Verkehr wie an einem echten SPAN-Port. Der Sniffer-Container (cyjan-tap-sniffer) liest mit AF_PACKET und reicht durch die Pipeline.
Funktioniert mit und ohne aktivierte Proxmox-Firewall — das Skript
erkennt die zusätzliche fwbr/fwpr-Kette und
findet das Tap der Sniffer-VM trotzdem.
Aufräumen
Beim regulären qm shutdown/stop der Target-VM
werden die tc-Regeln per pre-stop-Hook
automatisch entfernt. Hookscript wieder abklemmen:
qm set 109 --delete hookscript
rm /var/lib/vz/snippets/mirror.sh
Test-Katalog
Jede Kategorie liefert ein Skript, das du auf der Kali-Box laufen lässt,
plus die erwartete Reaktion im Cyjan-Frontend. Wenn der Alert
ausbleibt → Anti-Pattern für eine Regel- oder ML-Modell-Verbesserung.
Konkrete Lab-Resultate aus einer realen Pentest-Reihe gegen
ein Cyjan-IDS-Lab — mit IDS-Antwort pro Test und allen Code-Fixes, die
daraus geflossen sind: → Lab-Bericht
Phasen 1–6
1. Reconnaissance · nmap-Scans
Verschiedene Stealth-Variants gegen die Ziel-VM. Gut um zu prüfen ob
Sniffer-Drop-Pct sauber bleibt und ob Connection-Graph die Kali-IP als
neuen Knoten markiert.
Alert-Manager: Dedup-Window unterdrückt die nikto-Spam-Wave nach 300 s.
3. Brute-Force · hydra gegen SSH
Klassisches SSH-Login-Hammern gegen einen eigenen Lab-Account.
Testet sowohl die Signature-Engine (Connection-Burst-Pattern) als auch
die ML-Anomaly-Detection.
Die Wordlists sind bewusst Variablen — kopiere die Datei nicht
ungeprüft mit rockyou.txt gegen einen produktiven Host.
Lege dir für den Test einen separaten Lab-User mit kontrolliertem,
definitiv erratbaren Passwort an, damit du den Treffer auch
nachweisen kannst, ohne fremde Accounts zu verbrennen.
Klassischer Windows-Lab-Angriff. Wir nutzen
Analysis-Mode (-A): responder beobachtet
LLMNR/NBT-Broadcasts und protokolliert sie, schreibt aber
nichts aktiv ins Netz zurück. Reicht für die IDS-Detection
völlig aus — der Sniffer sieht den Broadcast-Traffic ohnehin —, vermeidet
aber das Spoofen fremder Hostnamen, was ein anderer rechtlicher
Korridor wäre.
#!/usr/bin/env bash
# Passive Analysis-Only: responder loggt LLMNR/NBT-Queries, ohne sie zu
# beantworten. Aktiv-Spoofing (-wF) bewusst NICHT aufgeführt.
IFACE=${1:-eth0}
sudo responder -I "$IFACE" -A
Connection-Graph: Cluster broadcast-aktiver Hosts wird sichtbar; Kali-Box ist passiver Beobachter.
5. DNS-Angriff trotz Resolver-Allowlist
Ein Cyjan-IDS-Operator pflegt die DNS-Resolver-Allowlist
(Settings → System → DNS-Resolver), damit legitime Antwort-Flows nicht
als Pseudo-Port-Scans schreien. Suppressed werden dabei nur
medium- und low-Severity-Alerts. Echte
DNS-Angriffe (high) müssen trotzdem feuern – dieser Test
prüft genau das.
Drei Schritte: zuerst eine harmlose Lookup-Welle gegen den eingetragenen
Resolver (Kontrolle, sollte still bleiben), dann eine
DGA-Simulation und ein Tunneling-Volumen-Test (beide sollen
knallen).
#!/usr/bin/env bash
# Cyjankali DNS-Test: zeigt dass die DNS-Resolver-Allowlist im Cyjan IDS
# nur die low/medium-FPs unterdrückt – high-severity DNS-Angriffe
# (Tunneling, DGA) feuern weiter.
#
# Voraussetzung: $RESOLVER ist im Cyjan-IDS unter Settings → System →
# DNS-Resolver eingetragen.
RESOLVER=${1:-192.168.56.1}
echo "[1/3] Kontrolle: 200 normale Lookups gegen den Resolver"
echo " Erwartung: KEIN Alert (medium/low werden via Allowlist gedroppt)"
for i in $(seq 1 200); do
dig +short +time=1 +tries=1 example.com @"$RESOLVER" > /dev/null
done
echo
echo "[2/3] DGA-Simulation: 50 Random-Subdomains mit variabler IAT, ein Socket"
echo " Erwartung: DNS_DGA_001 (high) feuert trotz Allowlist"
RESOLVER="$RESOLVER" python3 - <<'PY'
import os, random, socket, struct, time
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 0)) # ein Source-Port → ein Flow
target = (os.environ['RESOLVER'], 53)
for _ in range(50):
qname = ''.join(random.choices('abcdefghijklmnop', k=24)) + '.test.invalid'
txid = random.randint(0, 0xffff)
header = struct.pack('!HHHHHH', txid, 0x0100, 1, 0, 0, 0)
parts = qname.split('.')
body = b''.join(bytes([len(p)]) + p.encode() for p in parts) + b'\x00'
body += struct.pack('!HH', 1, 1) # type A, class IN
sock.sendto(header + body, target)
time.sleep(random.uniform(0.05, 0.6)) # → entropy_iat > 2.5
PY
echo
echo "[3/3] Tunneling-Volumen: 1500 Queries mit großen QNAMES, ein Socket"
echo " Erwartung: DNS_TUNNEL_001 (high) feuert trotz Allowlist"
RESOLVER="$RESOLVER" python3 - <<'PY'
import os, random, socket, struct
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 0))
target = (os.environ['RESOLVER'], 53)
for _ in range(1500):
# 60-Hex-Char-Subdomain → ~95 Byte Query, 1500× > 50 KB byte_count
sub = ''.join(random.choices('0123456789abcdef', k=60))
qname = sub + '.exfil.test.invalid'
txid = random.randint(0, 0xffff)
header = struct.pack('!HHHHHH', txid, 0x0100, 1, 0, 0, 0)
parts = qname.split('.')
body = b''.join(bytes([len(p)]) + p.encode() for p in parts) + b'\x00'
body += struct.pack('!HH', 1, 1)
sock.sendto(header + body, target)
PY
echo
echo "Im Cyjan-Frontend (Settings → DNS-Resolver mit $RESOLVER eingetragen):"
echo " Schritt 1 → keine neuen Alerts (Allowlist greift)"
echo " Schritt 2 → DNS_DGA_001 (high) – feuert auch mit Allowlist"
echo " Schritt 3 → DNS_TUNNEL_001 (high) – feuert auch mit Allowlist"
Erwartete IDS-Reaktion
Schritt 1 (Kontrolle): keine Alerts – die Allowlist
unterdrückt SCAN_002 / DNS_AMP_001 / DNS_NONSTANDARD_001 (alle
medium/low) für den eingetragenen Resolver.
Schritt 2 (DGA):DNS_DGA_001 Severity
high – die Allowlist greift hier nicht, weil die Policy
high/critical durchlässt.
Schritt 3 (Tunneling):DNS_TUNNEL_001
Severity high – byte_count > 50 KB im Single-Flow,
gleicher Pfad wie Schritt 2 (kein Suppress).
Stats-Log im alert-manager:dns_allowlisted=N zählt die Schritt-1-Drops mit – so
siehst du serverseitig, ob die Suppression wirklich wirkt.
Wenn Schritt 2 oder 3 nicht feuert, prüfe ob die DNS-Allowlist
versehentlich auch high-severity blockt (Bug) oder ob die Test-Queries
den IDS-Sniffer überhaupt erreichen (dual-NIC: Mirror-Port aktiv?
single-NIC: Resolver muss im selben L2-Segment wie das Mgmt-Interface
liegen).
Weitere Kategorien (folgen)
Slow-DoS (slowloris, hping3 --rand-source)
Metasploit-Module gegen typische Lab-Targets
BloodHound + impacket-Suite (Lateral Movement)
BurpSuite Active Scan gegen DVWA
Pull-Requests willkommen – Schema je Test ist Skript / erwartete
Detection / Severity.
Verifikation im IDS-Frontend
Während du die Kali-Skripte fährst, parallel im Cyjan-Frontend
(http://<mgmt-ip>/) auf folgende Stellen schauen:
UI-Bereich
Was du sehen solltest
Alert-Feed (Live)
WebSocket-Push neuer Alerts in Echtzeit, Severity-Spalte korreliert mit Test-Kategorie.
Connection-Graph
Kali-IP als neuer Hub-Knoten; bei nmap erscheint sie mit hoher Out-Degree-Zahl.
Threat-Level (Header)
Der 15-Minuten-Score-Indikator wandert von grün → gelb → orange → rot, je nach Volumen und Severity.
PCAP-Download
Pro Alert ein ±60 s-PCAP ladbar (sobald MinIO-Upload durch ist).
ML-Status
Anomaly-Score-Histogramm bekommt einen rechten Tail während der Test-Sessions.
Die hier gesammelten Skripte sind für autorisierte
Sicherheitstests im eigenen Lab gedacht. Der Einsatz gegen
fremde Systeme ohne ausdrückliche schriftliche Erlaubnis des Eigentümers
ist nach § 202c StGB (Vorbereitung des Ausspähens und
Abfangens von Daten), § 303a StGB (Datenveränderung)
und § 303b StGB (Computersabotage) strafbar. In den
USA gilt 18 U.S.C. § 1030 (CFAA).
Keine Gewähr. Die Skripte werden „as-is" zu Bildungs-
und Detection-Validation-Zwecken bereitgestellt — ohne Zusicherung von
Funktion, Sicherheit oder rechtmäßiger Verwendung. Wer das CYJANKALI-
Material gegen produktive Systeme richtet, tut das auf eigene
Verantwortung; die Maintainer übernehmen für daraus resultierende
Konsequenzen ausdrücklich keine Haftung.
Markenhinweis: Kali Linux ist eine eingetragene
Marke der OffSec Services Limited. Dieses Projekt steht in keiner
Verbindung zu Kali Linux, OffSec oder dem Kali-Linux-Team. Der Name
„CYJANKALI" referenziert das chemische Gift Cyankali
(Kaliumcyanid) — die Doppeldeutung mit „Kali" ist Wortspiel, keine
Endorsement-Behauptung.