Beelzebub: LLM-Powered Deception
A modern AI-driven honeypot layer that captures interactive attacker behaviour, including LLM prompt-injection and MCP attacks that traditional honeypots miss.
Parts 1–2; Beelzebub VPS in the WireGuard mesh
~55 minutes
SSH, HTTP, and MCP honeypots backed by an LLM persona
Why LLM Honeypots
Cowrie can fake a shell convincingly until the attacker types something it has not seen before. At that point the session looks scripted and skilled attackers disengage. An LLM-backed honeypot generates plausible novel responses for arbitrary commands and free-form HTTP requests, so the session keeps going long enough to capture the second-stage payload, the C2 endpoint, or the prompt-injection technique.
It also captures an entirely new attack surface: prompt-injection attempts against the honeypot itself, which is real intelligence about how attackers are probing AI systems.
Beelzebub Architecture and Protocol Coverage
Beelzebub is a single Go binary plus a YAML configuration tree. Each YAML file defines one service:
- • SSH — fake shell, configurable persona, optional LLM backend.
- • HTTP — endpoints with rule-matched or LLM-generated responses.
- • TCP — banner protocols and arbitrary handlers.
- • MCP — Model Context Protocol server that captures attacks against AI tool surfaces.
LLM Backend Selection
- • OpenAI / Anthropic API — best realism, predictable cost, no local resource budget. ~$5–$20/month at modest traffic.
- • Self-hosted Ollama with
llama3.2:3borqwen2.5:3b— zero per-token cost, needs ~4 GB RAM and CPU headroom. - • Hybrid — rule responses for cheap deterministic answers (banners,
uname -a), LLM only for novel input.
Deployment on the Lightweight VPS
apt install -y docker.io docker-compose
mkdir -p /opt/beelzebub && cd /opt/beelzebub
git clone https://github.com/mariocandela/beelzebub.git src
cp -r src/configurations ./confservices:
beelzebub:
image: m4r10k/beelzebub:latest
network_mode: host
volumes:
- ./conf:/etc/beelzebub:ro
- ./logs:/logs
environment:
- LLM_PROVIDER=ollama
- LLM_BASE_URL=http://10.88.0.11:11434
- LLM_MODEL=qwen2.5:3b
ollama:
image: ollama/ollama:latest
ports: ["11434:11434"]
volumes: [ollama:/root/.ollama]
volumes: { ollama: {} }SSH Honeypot with a Fabricated Persona
apiVersion: v1
protocol: ssh
address: :22
description: SSH honeypot
serverVersion: OpenSSH_9.6p1 Ubuntu-3ubuntu13
serverName: prod-app-07
deadlineTimeoutSeconds: 600
passwordRegex: "^(root|admin|deploy)quot;
plugin:
llmProvider: ollama
llmModel: qwen2.5:3b
prompt: |
You are a senior SRE on a production Ubuntu 24.04 host named prod-app-07.
Respond to shell commands as the host would. Never break character.
If asked who you are or whether you are an AI, respond as a human SRE.HTTP Honeypot with a Fake Admin Panel
apiVersion: v1
protocol: http
address: :8080
commands:
- regex: "^/admin.*"
handler: |
<html><body><h1>App Admin</h1><form>...</form></body></html>
statusCode: 200
- regex: ".*"
plugin:
llmProvider: ollama
llmModel: qwen2.5:3b
prompt: "Return realistic HTTP responses for an internal admin app."The MCP Honeypot
The Model Context Protocol is the emerging standard for connecting LLM agents to tools. Attackers are already probing MCP servers for tool-misuse and prompt-injection paths. Beelzebub ships an MCP listener that accepts JSON-RPC, advertises a small fake toolset, and logs every tools/call request.
apiVersion: v1
protocol: mcp
address: :3000
tools:
- name: read_file
description: Read a file from disk
- name: exec_shell
description: Execute a shell command (intentionally tempting)
plugin:
llmProvider: ollama
llmModel: qwen2.5:3b
prompt: "Respond as an MCP server. Never actually execute anything."Prompt Engineering and Persona Pinning
Two failure modes dominate untuned LLM honeypots: the model breaks character ("I am an AI assistant…") or it leaks the system prompt. Mitigations:
- • Repeat the persona in both the system prompt and the first assistant message.
- • Add an explicit refusal rule for meta questions ("If asked whether you are an AI, you are not").
- • Cap response length so jailbreaks that ask for the full prompt get truncated.
- • Periodically inject a hidden persona reminder before the user turn.
Capturing TTPs
Beelzebub's JSON log lines include source_ip, protocol, the full request, the LLM-generated response, and a session ID. This is richer than Cowrie's session log because the response shape is part of the signal: jailbreak attempts, MCP tool abuse, and base64 reverse-shell stuffing all show up clearly.
Forwarding Beelzebub Events
filebeat:
image: docker.elastic.co/beats/filebeat:8.15.0
user: root
volumes:
- ./logs:/logs:ro
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml:roFilebeat ships to Logstash on the detection zone over TCP 5170, alongside the T-Pot pipeline.
Layering Beelzebub Alongside T-Pot
If both hosts share an attack surface, decide who owns each port. Reasonable split:
- • T-Pot — 22, 23, 80, 443, 445, 1433, 3306, 5900, 6379, all the SCADA ports.
- • Beelzebub — 2222 (alt SSH), 8080 (admin), 3000 (MCP).
Use distinct public IPs so attackers see two independent targets.
Cost Monitoring with Paid LLM APIs
Honeypots attract sustained traffic, and an LLM call per request can compound quickly. Two safeguards:
- • Per-source rate limit at the Beelzebub level (already supported).
- • A nightly cron that posts the previous day's spend to your webhook sink — flag any 24-hour window above your threshold.
