← Back to DevBytes

Honeypots: Setup, Configuration, and Best Practices

What Are Honeypots?

A honeypot is a decoy system or service intentionally deployed to attract and trap malicious actors. It mimics a legitimate target — such as an SSH server, database, web application, or even an entire network segment — but exists solely to be probed, attacked, or compromised. Every interaction with the honeypot is suspicious by definition, because no legitimate user or production traffic should ever touch it. This makes honeypots extraordinarily high-fidelity detection tools: they produce virtually zero false positives.

Honeypots range from simple low-interaction emulators that simulate only a handful of protocol handshakes, to high-interaction systems that give attackers a full operating environment to explore. They can be deployed on-premises, in cloud environments, or inside containerized sandboxes. Regardless of the implementation, the core principle remains the same: lure, log, and learn.

Why Honeypots Matter

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

In modern security operations, alert fatigue is a serious problem. SIEMs and intrusion detection systems generate floods of events, many of which turn out to be benign anomalies. Honeypots invert this problem. Because no legitimate traffic should reach them, every connection attempt is inherently malicious. This gives security teams a clean, noise-free signal that an attacker is conducting reconnaissance or attempting lateral movement.

Beyond detection, honeypots serve several critical functions:

Types of Honeypots

Low-Interaction Honeypots

Low-interaction honeypots emulate specific services at the protocol level without providing a real operating system shell. They simulate login banners, accept credentials, and log everything, but they do not allow the attacker to execute arbitrary commands. Examples include Honeyd, Dionaea, and Cowrie (when run in basic mode). These are safe to deploy because attackers cannot pivot from them into real infrastructure.

High-Interaction Honeypots

High-interaction honeypots give attackers a full, real environment — a complete operating system, shell access, file systems, and sometimes even simulated outbound network connectivity. The attacker believes they have compromised a genuine server. These honeypots yield far richer data but require strict isolation (usually via virtual machines, Docker containers with restricted profiles, or air-gapped VLANs) to prevent the attacker from using the honeypot as a launchpad for further attacks.

Medium-Interaction Honeypots

These sit between the two extremes. They may present a real shell environment but limit available commands, emulate file systems, and restrict outbound traffic. They offer more depth than low-interaction traps while retaining stronger safety guarantees than fully open high-interaction systems.

Specialized Honeypots

Setting Up a Honeypot

Let's walk through deploying a production-ready SSH honeypot using Cowrie, one of the most widely adopted open-source honeypots. Cowrie emulates an SSH/Telnet server, logs all interactions, and can optionally provide a fake shell environment. We will install it on a cloud VM running Ubuntu 22.04.

Step 1: System Preparation

Create a dedicated user account with minimal privileges. Never run honeypots as root, and never place them on machines that host real services or sensitive data.

# Create a dedicated honeypot user
sudo useradd -m -s /bin/bash cowrie
sudo passwd cowrie
# Switch to that user
sudo su - cowrie

Step 2: Install Dependencies

Cowrie requires Python 3, virtual environment tools, and several system libraries for cryptographic operations.

# Update package list and install dependencies
sudo apt update
sudo apt install -y python3 python3-venv python3-pip \
    libssl-dev libffi-dev build-essential \
    libmpdec-dev git authbind

# Enable authbind for the cowrie user on port 22 (requires root)
sudo touch /etc/authbind/byport/22
sudo chown cowrie:cowrie /etc/authbind/byport/22
sudo chmod 770 /etc/authbind/byport/22

Step 3: Clone and Install Cowrie

# Clone the Cowrie repository
git clone https://github.com/cowrie/cowrie.git
cd cowrie

# Create a Python virtual environment
python3 -m venv cowrie-env
source cowrie-env/bin/activate

# Install Cowrie and its Python dependencies
pip install --upgrade pip
pip install -r requirements.txt
pip install cowrie

Step 4: Generate or Copy Configuration

Cowrie ships with a default configuration file. Copy it to the expected location and customize it for your environment.

# Copy the configuration files
cp etc/cowrie.cfg.dist etc/cowrie.cfg
cp etc/userdb.txt.dist etc/userdb.txt

# Edit the main configuration
nano etc/cowrie.cfg

Step 5: Basic Configuration Tuning

Open etc/cowrie.cfg and adjust the following key sections. The configuration uses an INI-style format.

[ssh]
# Port to listen on — use 2222 initially, then move to 22 with authbind
listen_port = 2222
# Interface to bind (0.0.0.0 for all interfaces)
listen_addr = 0.0.0.0
# Banner displayed to connecting clients
banner = SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4

[output_jsonlog]
# Enable JSON structured logging for easy ingestion into SIEMs
enabled = true
logfile = log/cowrie.json

[output_csvlog]
# Enable CSV logging as a fallback format
enabled = false
logfile = log/cowrie.csv

[honeypot]
# Hostname presented in the fake shell
hostname = db-prod-01
# Fake filesystem directory
fs_root = etc/fs.pickle
# Download progress bar emulation
download = true
# Allow attacker to use curl/wget commands in fake shell
curl = true
wget = true

Step 6: Configure Fake Credentials

Edit etc/userdb.txt to define which username/password combinations the honeypot will accept. This file uses a simple format: username:password per line, with optional UID and home directory fields.

# etc/userdb.txt — fake credential database
root:root
root:admin
root:password
root:123456
root:toor
admin:admin
admin:password
ubuntu:ubuntu
oracle:oracle
postgres:postgres
ftp:ftp
guest:guest

Step 7: Launch Cowrie

# Start Cowrie in the foreground (for initial testing)
bin/cowrie start

# For production, run in the background
bin/cowrie start -n

# Verify it's running
ps aux | grep cowrie
netstat -tlnp | grep 2222

Step 8: Move to Port 22

After testing on port 2222, move the honeypot to the standard SSH port 22 using authbind. This dramatically increases the volume of attacker traffic you'll capture, because automated scanners overwhelmingly target port 22.

# Edit etc/cowrie.cfg and change listen_port to 22
# Then restart Cowrie with authbind
authbind bin/cowrie start -n

Configuration Deep Dive

Tuning the Fake Filesystem

Cowrie ships with a pickled filesystem (etc/fs.pickle) that simulates a typical Linux directory tree. You can customize it to plant enticing decoy files — fake database credentials, AWS access keys, or "passwords.txt" files — that trigger alerts when an attacker reads or exfiltrates them.

# Create a custom decoy file in the fake filesystem
echo "DB_HOST=10.0.1.50
DB_USER=service_account
DB_PASS=Spring2024!Secure
DB_NAME=financials_prod" > /tmp/fake_db_creds

# The fs.pickle is a serialized Python object.
# Use Cowrie's utility to modify it:
python3 << 'EOF'
import pickle, os

with open('etc/fs.pickle', 'rb') as f:
    fs = pickle.load(f)

# Add a juicy-looking file in /opt/
fs['/opt/db_credentials.txt'] = {
    'content': open('/tmp/fake_db_creds', 'rb').read(),
    'uid': 0,
    'gid': 0,
    'mode': 0o644,
    'size': os.path.getsize('/tmp/fake_db_creds')
}

with open('etc/fs.pickle', 'wb') as f:
    pickle.dump(fs, f)
EOF

Enabling JSON Logging for SIEM Integration

Structured JSON logs are essential for feeding honeypot data into Elasticsearch, Splunk, or any modern SIEM. Cowrie's JSON output includes timestamped connection metadata, authentication attempts, commands executed, and file downloads.

# In etc/cowrie.cfg, ensure JSON logging is enabled:
[output_jsonlog]
enabled = true
logfile = log/cowrie.json
# Rotate logs daily to prevent runaway file sizes
rotate = daily
rotate_size = 104857600  # 100 MB

Here is an example JSON log entry produced by Cowrie:

{
  "eventid": "cowrie.login.success",
  "timestamp": "2025-01-15T14:22:31.123456Z",
  "src_ip": "185.176.27.66",
  "src_port": 48291,
  "dst_ip": "10.0.1.25",
  "dst_port": 22,
  "session": "a8f3c91e2b47",
  "username": "root",
  "password": "admin",
  "client_version": "SSH-2.0-libssh2_1.10.0"
}

Deploying a Companion Web Honeypot

To capture HTTP-based attacks alongside SSH, deploy Dionaea, a multi-protocol honeypot that emulates SMB, HTTP, FTP, and MySQL. Install it via Docker for rapid deployment.

# Pull and run Dionaea in Docker
docker pull dionaea/dionaea:latest
docker run -d \
  --name dionaea \
  --restart unless-stopped \
  -p 21:21 \
  -p 80:80 \
  -p 135:135 \
  -p 445:445 \
  -p 1433:1433 \
  -p 3306:3306 \
  -v /opt/dionaea/logs:/opt/dionaea/var/log \
  dionaea/dionaea:latest

Network Isolation and Safety

If you deploy a high-interaction honeypot (such as a real Linux VM with an outbound-restricted gateway), you must implement strict network segmentation. Use iptables or nftables to prevent attackers from using the honeypot to scan your internal network or launch outbound attacks.

# On the honeypot host, restrict outbound traffic
# Allow only DNS and minimal HTTP for fake curl/wget
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
# Block everything else outbound
iptables -A OUTPUT -j DROP
# Block all traffic to internal subnets
iptables -A OUTPUT -d 10.0.0.0/8 -j DROP
iptables -A OUTPUT -d 172.16.0.0/12 -j DROP
iptables -A OUTPUT -d 192.168.0.0/16 -j DROP
# Make rules persistent
apt install iptables-persistent
netfilter-persistent save

Best Practices

1. Never Run Honeypots on Production Infrastructure

This rule is absolute. A honeypot's entire value proposition is that it should receive zero legitimate traffic. If you co-locate a honeypot with a real service, you blur the line between genuine and malicious activity, destroying the zero-false-positive property. Use dedicated VMs, containers, or even separate cloud accounts for honeypot deployments.

2. Isolate Aggressively

Treat every honeypot as a potentially compromised host. Apply firewall rules that prevent lateral movement. If you use cloud infrastructure, place honeypots in their own VPC with no peering to production networks. Use security groups that allow only inbound traffic from the internet and restrict outbound traffic to the bare minimum.

3. Use Unique, Non-Production Credentials

The fake credentials in your honeypot must never overlap with real production passwords. If an attacker captures a honeypot credential hash and you've accidentally used a real password, you've just handed them a key to your actual infrastructure. Generate completely synthetic credential sets.

4. Implement Centralized Logging Immediately

Honeypot logs are ephemeral by nature — attackers may attempt to clear logs if they gain shell access. Ship logs off the honeypot host in real time using rsyslog, Filebeat, or a similar agent. Store them in a centralized, immutable logging platform.

# Ship Cowrie JSON logs to a central Logstash/Elasticsearch
# Example: using Filebeat
filebeat.inputs:
- type: log
  paths:
    - /home/cowrie/cowrie/log/cowrie.json
  json.keys_under_root: true
  json.add_error_key: true

output.elasticsearch:
  hosts: ["https://log-central:9200"]
  index: "cowrie-%{+yyyy.MM.dd}"
  username: "honeypot_shipper"
  password: "secure_shipping_password"

5. Rotate and Age Credentials

Periodically update the userdb.txt file with new fake credentials and remove stale ones. This keeps the honeypot fresh and prevents attackers from building static dictionaries that target only known defaults. Add credentials that reflect current password trends (e.g., leaked passwords from recent breaches) to stay relevant.

6. Plant Honeytokens Strategically

Inside the fake filesystem, place honey tokens — files or database entries that, when accessed, trigger an alert. Examples include:

Monitor these tokens with an alerting system. Any access to them is a definitive indicator of compromise.

7. Keep Software Updated

Honeypot software itself receives security patches. An outdated Cowrie or Dionaea instance could have vulnerabilities that allow attackers to escape the emulation layer. Subscribe to the project's release notifications and apply updates promptly.

# Update Cowrie within its virtual environment
cd /home/cowrie/cowrie
source cowrie-env/bin/activate
pip install --upgrade cowrie
# Pull latest config templates and merge changes
git pull origin main
diff etc/cowrie.cfg etc/cowrie.cfg.dist

8. Avoid Attribution Assumptions

IP addresses captured in honeypot logs are frequently spoofed, proxied, or belong to compromised relay hosts. Do not treat source IPs as definitive attribution. Instead, correlate IP data with other threat intelligence feeds and focus on behavioral patterns, tool signatures, and payload analysis.

9. Test Your Honeypot Before Production

Regularly connect to your own honeypot from a known IP to verify logging, alerting, and SIEM ingestion are working correctly. This also validates that your isolation rules are functioning — your test connection should succeed while outbound restrictions remain enforced.

# Test SSH connection to your honeypot
ssh -p 22 root@
# Use any password from userdb.txt
# Then check that the event appears in logs
tail -f /home/cowrie/cowrie/log/cowrie.json | jq .

10. Document and Classify Your Deployment

Maintain clear documentation about which IP addresses and ports host honeypots. Share this information with your SOC team so they can correctly interpret alerts. Classify honeypot infrastructure in your asset management system with a distinct tag (e.g., environment: honeypot) to prevent accidental exposure of real data or services.

Integrating Honeypots into Your Security Pipeline

A standalone honeypot is useful, but its true power emerges when integrated into an automated response pipeline. Here is a practical example using Cowrie's JSON logs, an Elasticsearch alert, and a firewall update script that automatically blocks an attacker's IP across all production systems.

#!/usr/bin/env python3
# auto_block.py — reads Cowrie JSON log, extracts attacker IPs,
# and pushes block rules to production firewall via API

import json
import requests
import sys
from datetime import datetime

LOG_FILE = '/home/cowrie/cowrie/log/cowrie.json'
FIREWALL_API = 'https://firewall.internal/api/v1/rules'
API_TOKEN = 'your-api-token-here'
BLOCK_THRESHOLD = 3  # number of failed attempts before blocking

def extract_attackers(log_file):
    attackers = {}
    with open(log_file, 'r') as f:
        for line in f:
            try:
                event = json.loads(line.strip())
                if event.get('eventid') == 'cowrie.login.failed':
                    ip = event.get('src_ip')
                    attackers[ip] = attackers.get(ip, 0) + 1
            except json.JSONDecodeError:
                continue
    return attackers

def block_ip(ip_address, reason):
    headers = {'Authorization': f'Bearer {API_TOKEN}', 'Content-Type': 'application/json'}
    payload = {
        'action': 'block',
        'ip': ip_address,
        'comment': f'Honeypot auto-block: {reason}',
        'ttl': 86400  # 24 hours
    }
    response = requests.post(FIREWALL_API, headers=headers, json=payload)
    if response.status_code == 200:
        print(f"[+] Blocked {ip_address}")
    else:
        print(f"[-] Failed to block {ip_address}: {response.text}")

if __name__ == '__main__':
    attackers = extract_attackers(LOG_FILE)
    for ip, count in attackers.items():
        if count >= BLOCK_THRESHOLD:
            block_ip(ip, f'{count} failed SSH attempts')

Monitoring and Alerting

Set up alerts for the following high-signal events within your honeypot logs:

Create an alert severity matrix: low-interaction honeypot events may warrant investigation, while high-interaction honeypot compromise should trigger immediate incident response procedures.

Conclusion

Honeypots are among the most powerful yet underutilized tools in a defender's arsenal. They transform network noise into actionable intelligence, provide early warning of reconnaissance activity, and offer a safe environment to study attacker behavior without risking production assets. By deploying low-interaction honeypots like Cowrie on common service ports, instrumenting them with structured logging, and integrating them into automated response pipelines, you create a detection layer that is simultaneously high-fidelity, low-maintenance, and profoundly educational. The key to success lies in meticulous isolation, synthetic credential management, centralized log collection, and continuous tuning. Start with a single SSH honeypot, observe the flood of attacker traffic within minutes, and let that data guide the evolution of your defensive posture. Every connection to a honeypot is a gift — an adversary revealing their presence, their tools, and their intent. Accept those gifts and use them wisely.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles