đ„· ninja.sh â Handbuch
Last-Triage fĂŒr die RZ-Bereitschaft. Wenn der Load brennt und die SLA-Uhr
lÀuft: ninja.sh macht in Sekunden eine read-only Momentaufnahme, damit du
entscheiden kannst statt zu raten â Bot-Angriff oder WordPress-AnfĂ€nger
mit 500 Plugins?
Leitsatz: Downtime setzen â Momentaufnahme â entscheiden â bestenfalls lösen.
ninja.sh fĂŒhrt nie selbst etwas aus. Es zeigt nur an. Handeln tust du in
einer zweiten bash. Damit Meister schlafen kann. đŠ
1. Was es ist (und was nicht)
| Ist | Ist nicht |
|---|---|
| Read-only Momentaufnahme unter Last | Kein Dauer-Monitoring (dafĂŒr: Icinga/Zabbix) |
| Entscheidungshilfe Angriff vs. Eigenverschulden | Kein Auto-Blocker (kein fail2ban-Ersatz) |
| Ein einzelnes File zum Reinpasten per vim/ssh | Kein BSD (Fokus Debian/Ubuntu; BSD â andere wecken) |
Wichtigste Eigenschaft: schmal & portabel. Eine Datei, keine AbhÀngigkeiten
auĂer Standard-Tools. Auf jede Linux-Box kopierbar.
2. Installation
Reinpasten (vim) oder per scp, dann ausfĂŒhrbar machen:
chmod +x ninja.sh
Optionale Tools (fĂŒr GeoIP-LĂ€nder & whois-CIDR â Debian/Ubuntu):
apt install -y whois geoip-bin geoip-database
Fehlt eins, degradiert ninja.sh sauber: ohne GeoIP keine [CC]-Marker, ohne
whois nur ein Hinweis. Der Rest lÀuft trotzdem.
3. Bedienung
Interaktiv (Default)
./ninja.sh
Ăffnet das MenĂŒ mit Live-Status-Header.
Direkt (ohne MenĂŒ â gut zum Pipen)
./ninja.sh snap # einmalige Momentaufnahme nach stdout
./ninja.sh watch # Live-Aufnahme, Refresh alle 30s
./ninja.sh rec # nur die Handlungs-VorschlÀge
./ninja.sh whois <IP> # eine IP nachschlagen (Land + Org + CIDR)
Snapshot wegspeichern oder verschicken (Farben fallen automatisch weg, wenn
die Ausgabe kein Terminal ist):
./ninja.sh snap > /tmp/triage_$(hostname)_$(date +%H%M).txt
MenĂŒpunkte
| Taste | Aktion |
|---|---|
1 |
Momentaufnahme (ein Screen, alle Sektionen) |
2 |
Live-Watch â Aufnahme alle 30s, Ctrl+C zurĂŒck |
3 |
Web error-log tail -f |
4 |
Auth-log tail -f |
5 |
System-log tail -f |
w |
IP nachschlagen â GeoIP-Land + whois (echte CIDR zum Blocken) |
r |
Handlungs-VorschlÀge (copy-paste-fertig) |
q |
Quit |
In allen
tail -f- und Watch-Ansichten bringt dichCtrl+CzurĂŒck ins
MenĂŒ â es killt nicht das Script.
4. Die Momentaufnahme lesen
Reihenfolge ist Absicht: erst wo bin ich, dann brennt CPU oder Netz, dann
wer.
Kopfzeile
distro=debian init=systemd pkg=apt web=nginx db=mysql
deine SSH-IP: 1.2.3.4 (NICHT droppen)
Was die Umgebungs-Erkennung gefunden hat. Die SSH-IP-Warnung ist deine
Versicherung gegen Selbst-Aussperrung.
LAST & WER FRISST CPU/RAM â der wichtigste Split
- Load 1/5/15 + die Top-Prozesse.
- CPU bei
mysqld/php-fpm+ normales Web-Volumen â Eigenverschulden
(Plugin/Cron-Loop). Nicht blocken â Query/Plugin finden. - Load hoch, aber CPU idle und stattdessen viele Verbindungen â Richtung Netz/Angriff.
đĄ Merke: viele Requests â viel Last. Ein Scanner, den nginx mit
444
wegwirft, macht 400 Requests und 0.02 Load. Erst die Kombination
entscheidet.
WEB â Angriffs-Erkennung
- Rate (
req/s): viel los oder normal? - Top-Talker IPs mit
[Land]: eine IP mit Riesen-Count = simpler Bot.
Eigene IPs sind als<= SELF (nicht droppen)markiert. - Top /24-Netze: Bots verteilen sich ĂŒber Ranges â hier werden sie sichtbar,
auch wenn einzelne IPs niedrig aussehen. - HTTP-Status-Mix: viele
4xx/444= Scanner/Block · viele5xx= App kippt. - VerdÀchtige Pfade:
/.env,wp-login,xmlrpc,/.git= Credential-/WP-Probing. - Top User-Agents: ein einzelner UA mit hohem Count = Bot-Signatur.
AUTH / SSH
Top-Quell-IPs fehlgeschlagener Logins + Gesamtzahl. Hohe Zahl â SSH-Brute â
sshguard/fail2ban (siehe Empfehlungen).
DATENBANK
Live SHOW FULL PROCESSLIST (Sleep-Verbindungen ausgeblendet) â im Akutfall
aussagekrÀftiger als das Slow-Log, weil es zeigt, was jetzt lÀuft. Ohne
passwortlosen Zugang gibt's den fertigen -u root -p-Befehl.
5. Entscheiden & handeln (r)
r druckt copy-paste-fertige Befehle â du setzt sie in der zweiten bash ab:
- Downtime setzen â Monitoring auf Wartung, damit nicht mitten in der
Analyse Pager hochgehen. - IP/Netz sperren â gestaffelt: einzeln â
/24â echte CIDR (viaw).
Inklusive Block prĂŒfen und Block wieder lösen. - Dienste reload/restart â Befehle automatisch im richtigen Init-Format.
- Entscheidungshilfe Angriff vs. Eigenverschulden in Worten.
- nginx-Snippet gegen WP-Bot-Flut (
xmlrpcdeny +wp-loginratelimit).
IP-Lookup (w) fĂŒr den prĂ€zisen Block
./ninja.sh whois 185.12.59.118
Zeigt Land + Org + echte CIDR (route/inetnum, oft /20). Damit blockst
du den realen Netzbereich des Angreifers statt blind /24 zu raten:
iptables -I INPUT -s <CIDR aus whois> -j DROP
6. Sicherheits-Eigenschaften (warum man dem Tool trauen kann)
- Read-only. Keine Sektion verÀndert irgendetwas am System.
- Nie Auto-AusfĂŒhrung. Alle Aktionen sind Text, den du bewusst absetzt.
- Self-Lockout-Schutz. Eigene Server-IPs (v4/v6/Loopback) und die
SSH-Client-IP werden erkannt und in den Talkern markiert â sie landen nicht
versehentlich in einemDROP. - ANSI-Injection entschÀrft. User-Agents/Pfade/Logzeilen sind
angreiferkontrolliert; alle untrusted Felder werden vor der Ausgabe von
Steuerzeichen befreit (clean()), damit ein prÀparierter Log-Eintrag nicht
dein Terminal kapert. set -u. Tippfehler in Variablen brechen frĂŒh ab statt still ins Leere zu laufen.
7. Troubleshooting
| Symptom | Ursache / Fix |
|---|---|
Rate:-Zeile fehlt |
Logformat ohne [dd/Mon/yyyy:HH:MM:SS] â _logepoch()-Regex anpassen |
Keine [CC]-LĂ€nder |
apt install geoip-bin geoip-database (oder GeoLite2-.mmdb fehlt) |
web=none |
Kein Standard-Logpfad gefunden â Pfad in probe() (for f in âŠ) ergĂ€nzen |
| DB-Sektion: âkein passwortloser Zugang" | normal ohne unix_socket-Auth â gezeigten -u root -p-Befehl nutzen |
init=unknown / Service-Befehle stimmen nicht |
exotisches Init â svc_cmd() erweitern |
Farben als \033[âŠ] in einer Datei |
passiert nicht â Farben werden ohne TTY automatisch leer (sonst Bug melden) |
8. Anpassen
Alle Stellschrauben stehen oben im Script:
WATCH_INTERVAL=30â Refresh-Takt im Watch-Modus.TAIL_N=500â wie viele Log-Zeilen analysiert werden.probe()â neue Logpfade/Distros hier eintragen.snap_web()â âVerdĂ€chtige Pfade" â eigene Probe-Muster insgrep -aoiEaufnehmen.
Der Code ist durchgehend kommentiert (was/wo/wie/warum) â fang bei probe()
an, dann liest sich der Rest von selbst.