
Mittelinteraktiver SSH/Telnet-Honeypot, erstellt mit Cowrie, Loki, Promtail und Grafana – bereitgestellt auf DigitalOcean über Terraform mit einer GitLab CI Validierungspipeline.
Ein SSH/Telnet-Honeypot-Stapel, der mithilfe von Terraform auf einem DigitalOcean-Droplet bereitgestellt wird. Angriffe werden von Cowrie erfasst, in Loki gespeichert und in Grafana mit einer Live-Weltkarte der Angriffsursprünge visualisiert.
honeypot/
├── cowrie/
│ └── etc/
│ ├── cowrie.cfg # Cowrie honeypot configuration
│ └── userdb.txt # Accepted and rejected fake credentials
├── geoip/
│ └── .gitkeep # Placeholder - MMDB files are gitignored
├── grafana/
│ ├── provisioning/
│ │ ├── dashboards/
│ │ │ ├── dashboards.yml # Provisioning: dashboard provider
│ │ │ └── honeypot-dashboard.json # Pre-built Attack Monitor dashboard
│ │ └── datasources/
│ │ └── loki.yml # Auto-provisioned Loki datasource
│ └── grafana.ini # Grafana server settings
├── loki/
│ └── config.yml # Loki single-binary config and retention
├── promtail/
│ └── config.yml # Promtail scrape and GeoIP pipeline
├── scripts/
│ ├── geoip-update.sh # Download or refresh GeoIP database
│ └── setup-firewall.sh # Host UFW rules for honeypot ports
├── terraform/
│ ├── templates/
│ │ ├── cloud-init.yaml.tftpl # Droplet first-boot script (Terraform-templated)
│ │ └── env.tftpl # .env lines embedded via Terraform
│ ├── backend.tf # Terraform backend config
│ ├── main.tf # Droplet, SSH key, firewall, cloud-init
│ ├── outputs.tf # IPs and helpful post-apply values
│ ├── terraform.tfvars.example # Example variable values (copy to terraform.tfvars)
│ ├── variables.tf # Terraform input variables
│ └── versions.tf # Terraform and provider version constraints
├── .env.example # Example environment file for manual setup
├── .gitignore # Ignored paths and files
├── .gitlab-ci.yml # CI/CD pipeline: fmt, validate, Checkov
├── docker-compose.yml # Docker Compose file for the honeypot stack
├── LICENSE # GPLv2 license
├── manual-deployment.sh # Legacy VM bootstrap without Terraform
└── README.md # Project documentation
## Hardware-Anforderungen
> Hinweis: Diese Anforderungen basieren auf dem DigitalOcean Basic Droplet-Plan vom Mai 2026 und sind die Mindestanforderungen für den Betrieb des Projekts.
- Provider: DigitalOcean
- Plan: Basic Droplet - 1 Intel vCPU
- RAM: 1 GB (+2 GB Swap)
- Storage: 35 GB NVMe SSD
- OS: Ubuntu 24.04 LTS
## Installation & Einrichtung
>Hinweis: Nach der Installation wird empfohlen, ein neues Terminal zu öffnen und zu überprüfen, ob Sie sich weiterhin über SSH auf `ADMIN_SSH_PORT` (Standard: 2022) anmelden können, bevor Sie Ihre ursprüngliche Sitzung schließen.
### Terraform-Bereitstellung (Empfohlen)
1. Erstellen Sie einen DigitalOcean-API-Token mit Lese-/Schreibberechtigungen:
- Melden Sie sich bei DigitalOcean an und navigieren Sie zu Account > API > Tokens > Generate New Token.
- Benennen Sie Ihren Token (z. B. „Cowrie Honeypot“) und wählen Sie die Berechtigung „Full Access“ aus.
- Klicken Sie auf „Generate Token“ und kopieren Sie den Token-Wert an einen sicheren Ort (Sie werden ihn nicht wieder sehen können).
2. Erstellen Sie ein SSH-Schlüsselpaar auf Ihrem lokalen Rechner und kopieren Sie den Pfad des öffentlichen Schlüssels.
3. Wechseln Sie in das Verzeichnis `terraform`, kopieren Sie dann die Variablendatei und bearbeiten Sie sie:
> Hinweis: `do_token`, `ssh_public_key_path` und `grafana_admin_password` müssen mindestens in `terraform.tfvars` konfiguriert werden, bevor `apply` ausgeführt wird.```bash
cd terraform
cp terraform.tfvars.example terraform.tfvars
Hinweis: Terraform muss auf Ihrem lokalen Rechner installiert sein. Besuchen Sie die Terraform Installationsanleitung für Anweisungen.```bash terraform init # Initialize Terraform and download providers terraform apply
5. Falls Testen - Redeploy mit Ersatz:```bash
terraform apply -replace="digitalocean_droplet.honeypot"
### Manuelle Bereitstellung (Legacy)
1. Erstellen Sie einen DigitalOcean-Droplet mit den oben genannten Hardwareanforderungen und Ihrem SSH-Schlüssel.
2. SSH in den Droplet oder verwenden Sie die DigitalOcean-Webkonsole und führen Sie die folgenden Befehle aus:```bash
ssh root@<your-droplet-ip> # If using DigitalOcean web console, skip this command
git clone https://gitlab.com/Oseguera12/cowrie-honeypot-digitalocean.git /opt/honeypot
cd /opt/honeypot
cp .env.example .env
nano .env
bash manual-deployment.sh
Hinweis: Standardmäßig schreibt Terraform den Zustand in
terraform/terraform.tfstateauf Ihrem lokalen Rechner. Diese Datei enthält sensible Ausgabewerte (Droplet-IP, Grafana-Passwort, SSH-Schlüssel-Fingerabdruck) und darf niemals committet werden..gitignoredeckt*.tfstateund*.tfstate.*ab.
Risiken des lokalen Zustands:
apply können die Datei beschädigenFür alles, das über ein persönliches Labor hinausgeht, wechseln Sie zu einem entfernten Backend. terraform/backend.tf enthält eine auskommentierte DigitalOcean Spaces-Konfiguration (S3-kompatibel).
Um das entfernte Backend zu aktivieren:
terraform.tfvars): ```bash
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
backend "s3"-Block in terraform/backend.tf aus und geben Sie Ihren Bucket-Namen und den Region-Endpunkt ein.terraform init -migrate-state aus, um den vorhandenen lokalen Status zu Spaces zu verschieben..gitlab-ci.yml führt bei jedem Push drei Jobs in einer einzigen validate-Stufe aus:
Hinweis:
terraform:fmtundterraform:validateblockieren die Pipeline bei Fehlschlag.checkov:scanist aufallow_failure: truegesetzt, da einige Ergebnisse bewusste Kompromisse sind. Unterdrücken Sie spezifische akzeptable Ergebnisse mit Inline-# checkov:skip=CKXXX-Kommentaren, anstatt den Job vollständig zu deaktivieren.
CKV_DIO_4 ("Stelle sicher, dass der Firewall-Eingang nicht weit offen ist") wird einmal für die gesamte digitalocean_firewall-Ressource ausgelöst. Es wird durch einen einzelnen # checkov:skip=CKV_DIO_4:-Kommentar unterdrückt, der innerhalb des Ressourcenblocks in terraform/main.tf platziert ist. Die folgende Tabelle dokumentiert, warum jeder offene Port beabsichtigt ist.
flowchart TB internet((Internet))
subgraph tf["Terraform"] fw[DigitalOcean Cloud Firewall] droplet[Ubuntu 24.04 droplet] fw --> droplet end
subgraph compose["Docker Compose on droplet"] cowrie["Cowrie honeypot — SSH on port 22, Telnet on port 23"] promtail[Promtail with GeoIP labels] loki[Loki log store] grafana["Grafana — host :3000"] cowrie -->|JSON logs from ./data/cowrie-logs| promtail --> loki --> grafana end
internet -->|22/23 honeypot| fw internet -->|Admin SSH :2022| fw internet -->|Grafana :3000| fw droplet --> compose
## Beobachtungen
Daten, die über 5 Tage des Live-Einsatzes (05.05.2026 bis 09.05.2026) erfasst wurden:
| Metrik | Wert |
|---------------------------|----------|
| Gesamtverbindungen | 41.700 |
| Anmeldeversuche | 15.400 |
| Erfolgreiche Anmeldungen | 868 |
| Ausgeführte Befehle | 836 |
| Heruntergeladene Dateien | 6 |
| Einzigartige Herkunftsländer | 106 |
### Top Angriffsländer
| Land | Verbindungen |
|--------------------|--------------|
| Deutschland | 9.768 |
| Niederlande | 9.110 |
| Vereinigte Staaten | 7.706 |
| Vereinigtes Königreich | 3.858 |
| Singapur | 1.770 |
| Belgien | 1.422 |
### Anmeldedaten-Muster
Der am häufigsten versuchte Benutzername war `root` mit 3.866 Versuchen, gefolgt von `admin` (728) und `user` (494), was auf automatisierte Scanner hinweist, die auf Standard-Anmeldedaten und bekannte Dienstkonten abzielen. Das am häufigsten verwendete Passwort war `123456` (1.480 Versuche), gefolgt von `123` und `12345`, was auf wörterbuchbasierte Brute-Force-Werkzeuge hindeutet.
### Angreiferverhalten in der gefälschten Shell
868 Anmeldeversuche waren gegenüber dem gefälschten Anmeldedatensatz erfolgreich. Von diesen Sitzungen wurden 836 Befehle ausgeführt. Der häufigste Befehl war `uname -s -v -n -r -m` (360 Ausführungen) – ein standardmäßiger System-Fingerprinting-Befehl, der von automatisierten Post-Exploitation-Skripten ausgeführt wird, um das Zielbetriebssystem und die Architektur zu identifizieren, bevor eine Payload bereitgestellt wird. Weitere beobachtete Befehle umfassten `export HISTFILE=/dev/null` zur Deaktivierung der Shell-Verlaufsprotokollierung und `export HISTSAVE=/dev/null`, was darauf hindeutet, dass Angreifer aktiv versuchen, ihre Spuren zu verwischen, selbst in dem, was sie für ein kompromittiertes System hielten.
### Wichtigste Erkenntnis
Das Volumen des automatisierten Scan-Traffics – 41.700 Verbindungen in 5 Tagen aus 106 Ländern – bestätigt, dass jeder öffentlich zugängliche SSH-Dienst innerhalb von Stunden nach der Freischaltung ständigen Brute-Force-Versuchen ausgesetzt ist. Das Verhaltensmuster, sofort `uname` auszuführen, gefolgt von Befehlen zur Unterdrückung des Verlaufs, stimmt mit automatisierten Post-Exploitation-Frameworks überein, die mit minimaler menschlicher Beteiligung arbeiten.
## Verwendung
### Verwendung des Grafana-Dashboards
> Hinweis: Die Dashboard-Anmeldedaten werden in terraform.tfvars oder .env (für manuelle Bereitstellung) festgelegt.
Das Dashboard kann unter folgender Adresse aufgerufen werden:```
http://<your-droplet-ip>:3000
Anmelden mit admin / <GRAFANA_ADMIN_PASSWORD>.
cowrie/etc/userdb.txt - enthält die akzeptierten Anmeldeinformationen für den Honeypot.
Bearbeiten Sie diese Datei, um die Honeypot-Anmeldeinformationen anzupassen.
Akzeptierte Anmeldungen setzen den Angreifer in eine gefälschte Shell, in der alle Befehle protokolliert werden.
Abgelehnte Einträge werden als fehlgeschlagene Versuche protokolliert.
Dieser Abschnitt beschreibt die getroffenen Entscheidungen und aufgetretenen Probleme während der Entwicklung dieses Projekts. Er dient als Reflexion des Entwicklungsprozesses und der gewonnenen Erkenntnisse. Überspringen Sie zu Sicherheitshinweise, wenn Sie nur wissen möchten, wie das Projekt zu verwenden ist.
Warum Cloud-Hosting?
Warum DigitalOcean?
Warum Terraform?
manual-deployment.sh, ist für Benutzer gedacht, die keine Erfahrung mit Terraform haben oder es nicht verwenden möchten. Dieser Pfad erfordert die Bereitstellung eines Droplets, das Herstellen einer Verbindung, das Klonen des Repositorys und das Ausführen des Skripts. Mit Terraform ist eine schnellere Iteration möglich: Bearbeiten Sie die Codebasis und stellen Sie sie erneut bereit, ohne jeden manuellen Schritt von Ihrem lokalen Rechner aus zu wiederholen. Es erleichtert auch das Abbauen der Infrastruktur und den Neustart. Wenn das Projekt von einem einzelnen Honeypot zu einem Honeynet wächst, skaliert Terraform sauberer als die manuelle Bereitstellung oder das alte Skript allein.Warum Cowrie?
Warum Loki?
Warum Grafana?
Warum Promtail?
Warum GeoIP?
scripts/geoip-update.sh: kein Konto oder API-Schlüssel erforderlich, was die Bereitstellung für jeden, der das Repo klont, einfach hält. Die integrierte GeoIP-Stufe von Promtail liest die lokale MMDB-Datei und fügt Labels für das Grafana-Geomap-Panel hinzu.Schritt-für-Schritt-Übersicht darüber, was passiert, wenn der Honeypot mit Terraform oder dem manuellen Bereitstellungsskript eingerichtet wird.
Auf Ihrem Rechner:
terraform/terraform.tfvars: API-Token, Pfad zum öffentlichen SSH-Schlüssel, Grafana-Passwort, Repo-URL/Branch, optionales manage_do_firewallterraform init aus: installiert den DigitalOcean-Provider lokalterraform apply aus: Terraform erstellt einen Plan und dann die Ressourcen oder aktualisiert sieIn DigitalOcean:
droplet_image, droplet_size, region usw.user_data wird auf das gerenderte cloud-init gesetzt: Beim ersten Start erhält die VM den Admin-SSH-Port, das Repository repo_url / repo_branch und eine base64-codierte Kopie der generierten .env (Grafana-Passwort und ADMIN_SSH_PORT aus env.tftpl)manage_do_firewall wahr ist):
terraform/main.tf)Auf dem Droplet wird cloud-init automatisch ausgeführt:
package_update / package_upgrade, dann installierte Pakete (curl, git, ufw, …). Früh im Startvorgang erstellt write_files /root/honeypot.env (von Terraform gerendertes env.tftpl als base64: Grafana-Passwort, ADMIN_SSH_PORT, usw.)runcmd-Bootstrap-Skript (Reihenfolge in terraform/templates/cloud-init.yaml.tftpl): Setzen von iptables / ip6tables auf Legacy-Backends/swapfile, fstab, swappiness)Innerhalb von Docker Compose:
/ready auf Port 3100 im Container; auf dem Host nur 127.0.0.1:3100)depends_on in docker-compose.yml), und starten danndata/cowrie-logs, die von Promtail gelesen werdenBenutzer erstellt die VM, verbindet sich per SSH und führt das Skript aus dem geklonten Repo aus.
manual-deployment.sh führt Folgendes aus:
.env laden und validierenapt update & apt upgradeufw und iptablessshd auf ADMIN_SSH_PORT und ssh.socket deaktivierenscripts/setup-firewall.shscripts/geoip-update.sh und monatlicher Crondocker compose pull / up -d, dann wartet das Skript auf Loki- und Grafana-Healthchecks und gibt eine Zusammenfassung ausIn Betracht gezogene Lösungen:
Lösung:
Kompromisse:
Erkenntnisse:
docker compose up fehl, da Port 22 bereits verwendet wurde und von Cowrie nicht gebunden werden konnte.In Betracht gezogene Lösungen:
sshd war falsch konfiguriert oder hörte auf dem falschen PortLösung:
sshd wird zuerst auf ADMIN_SSH_PORT (Standard 2022) verschoben und neu gestartet, dann wird ssh.socket gestoppt und deaktiviert, um Port 22 für Docker freizugeben, damit Cowrie ihn binden kann. UFW-Regeln werden nach beiden Schritten angewendet, um den neuen Admin-Port zuzulassen.Kompromisse:
Erkenntnisse:
ssh.socket eine systemd-Socket-Unit, die Port 22 für die On-Demand-SSH-Aktivierung reserviert hält. Sie muss gestoppt und deaktiviert werden, bevor Docker den Host-Port 22 für Cowrie binden kann. Wenn sie noch aktiv ist, schlägt docker compose up mit „address already in use“ fehl.GeoIP-Funktionalität
Grafana HTTPS
Proxy-Server-Funktionalität
terraform.tfvars wird ignoriert und darf niemals committet werden.GNU General Public License Version 2.0 (GPLv2) Siehe den vollständigen Lizenztext in der LICENSE-Datei.
| Job | Tool | Purpose |
|---|
terraform:fmt | hashicorp/terraform:1.8 | Formatierung: schlägt fehl, wenn eine Datei terraform fmt benötigt |
terraform:validate | hashicorp/terraform:1.8 | Gültigkeit der Konfiguration ohne Kontaktaufnahme mit DigitalOcean |
checkov:scan | bridgecrew/checkov:latest | IaC-Fehlkonfigurationen im Terraform-Code |
| Check ID | Resource | Finding | Decision |
|---|
CKV_DIO_4 | digitalocean_firewall.honeypot — Admin-SSH eingehend | Admin-SSH-Port offen für 0.0.0.0/0 | Akzeptiert – Einschränkung auf eine feste IP ist für ein portables Labor unpraktisch; in der Produktion empfohlen |
CKV_DIO_4 | digitalocean_firewall.honeypot — Port 22 eingehend | Port 22 offen für 0.0.0.0/0 | Beabsichtigt – Dies ist die SSH-Honeypot-Oberfläche; die Einschränkung der Quelle würde den Zweck zunichte machen |
CKV_DIO_4 | digitalocean_firewall.honeypot — Port 23 eingehend | Port 23 offen für 0.0.0.0/0 | Beabsichtigt – Telnet-Honeypot-Oberfläche; gleiche Begründung wie bei Port 22 |
CKV_DIO_4 | digitalocean_firewall.honeypot — Port 3000 eingehend | Grafana HTTP offengelegt für 0.0.0.0/0 | Akzeptiert für Lab-Zugänglichkeit – bekannte Einschränkung, dokumentiert in Sicherheitsüberlegungen; Produktionsbereitstellungen sollten auf eine bekannte IP einschränken oder über HTTPS auf Port 443 proxen |
| Panel | Beschreibung |
|---|
| Attack World Map | Geomap mit Heatmap- + Markierungsebenen, die den Ursprung jeder Verbindung anzeigen |
| Total Connections | Anzahl der eingehenden Honeypot-Sitzungen im ausgewählten Zeitraum |
| Login Attempts | Gesamtzahl der Brute-Force-Versuche auf Anmeldedaten |
| Successful Logins | Angreifer, die mit userdb.txt-Anmeldedaten übereinstimmten |
| Commands Executed | In der falschen Shell ausgeführte Shell-Befehle |
| Files Downloaded | Über wget/curl erfasste Malware/Skripte |
| Connection Rate | Zeitreihe: Verbindungen/s, fehlgeschlagene Anmeldungen/s, Erfolge/s |
| Top Usernames | Am häufigsten versuchte SSH-Benutzernamen |
| Top Passwords | Am häufigsten versuchte Passwörter |
| Top Commands | Am häufigsten ausgeführte Shell-Befehle |
| Attacks by Country | Länderspezifische Verbindungstabelle |
| Recent Events | Live-Log-Stream der neuesten Ereignisse |
| File Downloads | Tabelle aller Dateien, die ein Angreifer herunterzuladen versuchte |
systemctl enable --now dockersshd auf ADMIN_SSH_PORT; ssh.socket deaktivieren, damit Host-Port 22 für Cowrie frei istgit clone von repo_url / repo_branch nach /opt/honeypot (muss docker-compose.yml und Konfigurationen enthalten).env auf der Festplatte: /root/honeypot.env nach /opt/honeypot/.env verschieben (Modus 600)scripts/setup-firewall.sh (UFW für Admin-SSH, 22, 23, 3000)scripts/geoip-update.sh (DB-IP City Lite nach geoip/); einen monatlichen Cron-Eintrag für dasselbe Skript anhängendata/cowrie-logs und data/cowrie-dl mit Berechtigungen erstellen, die Compose erwartet/opt/honeypot aus docker compose pull und dann docker compose up -d