Deployment guide

Cowrie

Overview

Cowrie is a widely deployed open-source SSH and Telnet honeypot. It presents an emulated, deliberately inviting shell to attackers and records everything they do: the usernames and passwords they try, every command they run and every file they try to download. The emulated environment is a sandbox with no access to the real machine, so it gives you rich, safe visibility into who is probing your infrastructure and how. Use it for threat intelligence, attacker technique research and early breach detection.

This SecureAnyCloud image installs Cowrie in a self-contained Python virtualenv at /opt/cowrie/cowrie-env. It runs Cowrie as the cowrie.service systemd unit under a dedicated unprivileged cowrie user and exposes the emulated attacker surface on dedicated high ports: fake SSH on 2222 and fake Telnet on 2223.

Two cleanly separated planes. The image keeps the honeypot and your real administration apart:

  • Admin plane: the operating system's own SSH on port 22, key-only (your Azure SSH key), with no baked-in password and no shared bootstrap credential. This is how you administer the box. The honeypot never listens on port 22.
  • Honeypot plane: the emulated SSH (2222) and Telnet (2223) listeners. These intentionally accept weak logins and drop the attacker into a sandboxed emulated shell. That is the product working as designed, and nothing an attacker does there touches the real system.

Per-VM identity, no shared fingerprint. A honeypot host key baked once and shared across every image would let attackers fingerprint the deployment. On each VM's first boot, cowrie-firstboot.service generates fresh, unique honeypot host keys and records their fingerprints to a root-only info note. No two deployments share an identity, and the image gives nothing away about its origin.

What you get:

  • Cowrie (verified at 3.0.6, BSD 3-Clause) in a self-contained virtualenv at /opt/cowrie
  • cowrie.service running the honeypot as the unprivileged cowrie user
  • Emulated SSH honeypot on 2222 and Telnet honeypot on 2223
  • cowrie-firstboot.service for per-VM honeypot host keys and the instance info note
  • Structured JSON event log and full TTY session replay capture
  • Real admin SSH kept key-only on port 22, separate from the honeypot
  • Ubuntu 24.04 LTS base, patched at build time, unattended security upgrades enabled
  • 24/7 SecureAnyCloud support, 24h response SLA

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet.

Cowrie is lightweight. Standard_B2s (2 vCPU, 4 GB RAM) is ample for most deployments. For a honeypot exposed to heavy internet scanning, Standard_B2ms or Standard_D2s_v5 gives more headroom for session logging. Session logs and TTY captures live on the OS disk, so expand the disk if you expect to collect data over long periods.

1

Deploy the Virtual Machine

Option A: Azure Portal

Search the Marketplace for Cowrie SSH/Telnet Honeypot on Ubuntu 24.04, choose your VM size, and provide your SSH public key. Attach a network security group that allows:

  • TCP 22 (your real admin SSH) from your management network only.
  • TCP 2222 and 2223 (the emulated honeypot) from the networks you want to expose it to. To collect real internet attack traffic, allow these ports from the internet. To run an internal deception sensor, allow them only from the internal ranges you are monitoring.

Option B: Azure CLI

RG="cowrie-prod"; LOCATION="eastus"; VM_NAME="cowrie-01" IMAGE_URN="sac1647283583153:cowrie-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name cowrie-vnet --address-prefix 10.90.0.0/16 --subnet-name cowrie-subnet --subnet-prefix 10.90.1.0/24 az network nsg create -g "$RG" --name cowrie-nsg az network nsg rule create -g "$RG" --nsg-name cowrie-nsg --name allow-admin-ssh --priority 100 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name cowrie-nsg --name allow-honeypot --priority 110 \
  --source-address-prefixes "Internet" --destination-port-ranges 2222 2223 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:cowrie-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
  --size Standard_B2s --storage-sku StandardSSD_LRS \
  --admin-username azureuser --ssh-key-values "$SSH_KEY" \
  --vnet-name cowrie-vnet --subnet cowrie-subnet --nsg cowrie-nsg --public-ip-sku Standard
2

Connect via SSH

Connect on the real admin port 22 with your key. This is the administration plane, which is kept completely separate from the honeypot.

ssh azureuser@<vm-ip>

To find the public IP, run az vm show -d -g cowrie-prod -n cowrie-01 --query publicIps -o tsv.

3

Verify the honeypot is running

Cowrie runs as a systemd service under the unprivileged cowrie user. Confirm that it is active and listening on the two emulated ports, while your real SSH stays on port 22.

sudo systemctl is-active cowrie ss -tln | grep -E ':2222 |:2223 |:22 ' /opt/cowrie/cowrie-env/bin/python -c 'import importlib.metadata as m; print("cowrie", m.version("cowrie"))'

The output shows cowrie reporting active, listening sockets on 0.0.0.0:2222 (honeypot SSH), 0.0.0.0:2223 (honeypot Telnet) and 0.0.0.0:22 (your real admin SSH), and the Cowrie version.

4

Read this VM's instance info

Read the root-only note that the first-boot service wrote. It describes the two planes and this VM's unique honeypot host key fingerprints. No two VMs share these fingerprints, and none was baked into the image.

sudo cat /root/cowrie-info.txt

The note is owned root:root with mode 0600. It records the honeypot endpoints, the per-VM SSH host key fingerprints and the location of the event log.

5

See the honeypot in action

Cowrie accepts weak logins on purpose. Run a quick self-test against the local honeypot. It accepts a throwaway credential and drops you into a fully emulated shell that looks like a real server. The test runs against loopback on the VM itself, so it never leaves the box. Real attackers reach the same emulated shell over the public IP on port 2222.

sshpass -p 'hunter2' ssh -n -p 2222 \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  -o PreferredAuthentications=password -o PubkeyAuthentication=no \
  root@127.0.0.1 'whoami; hostname; uname -a; ls -la /; cat /etc/passwd | head -n 3'

The login succeeds and whoami returns root. The hostname and uname present a convincing fake server, and ls -la / shows an emulated filesystem. All of this runs inside a sandbox with no access to the real machine.

6

Read the captured attack events

Cowrie writes every session to a structured JSON event log. Inspect the events from the session you just ran: the login attempt with the exact credentials, and every command the attacker typed.

sudo tail -n 12 /opt/cowrie/var/log/cowrie/cowrie.json \
  | jq -c '{eventid, username, password, input, src_ip} | with_entries(select(.value != null))'

The log shows a cowrie.login.success event with username and password, and a cowrie.command.input event that captures the exact command line the session ran. Full keystroke replays are stored under /opt/cowrie/var/lib/cowrie/tty/. Replay them with /opt/cowrie/cowrie-env/bin/playlog.

7

Forward events to your SIEM

The JSON event log at /opt/cowrie/var/log/cowrie/cowrie.json is designed to be shipped to a log pipeline. Point Filebeat, Fluent Bit, Vector or rsyslog at that file to forward events to Elasticsearch, Splunk, a Graylog input or any SIEM.

Cowrie also ships optional output plugins (Elasticsearch, syslog and others). Enable them in /opt/cowrie/etc/cowrie.cfg under the matching [output_*] section, then run sudo systemctl restart cowrie.

Optional: catch attackers on the standard SSH port

By default, the honeypot listens on 2222 and 2223 and your real admin SSH owns port 22, so administration works out of the box. To catch attackers who hit the standard SSH port, first move your real administrative SSH to another port, then redirect inbound traffic. If you do this in the wrong order, you will lock yourself out.

# 1. FIRST move real admin SSH to 2022 and confirm you can reconnect on the new port,
# then in a NEW session:
# 2. Redirect inbound tcp/22 to the honeypot on 2222:
sudo iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2222

After you confirm admin access on the new port, persist the iptables rule (for example with iptables-persistent). Update your NSG to allow the new admin port from your management network only.

Managing the service

Use systemd and the log files to manage and monitor the honeypot:

sudo systemctl status cowrie
# health and recent log lines
sudo systemctl restart cowrie
# apply config changes
sudo journalctl -u cowrie -f
# live service log
sudo tail -f /opt/cowrie/var/log/cowrie/cowrie.json
# live attack events

Edit /opt/cowrie/etc/cowrie.cfg to change the emulated hostname, ports, output plugins and shell behaviour. Edit /opt/cowrie/etc/userdb.txt to tune which credentials the honeypot accepts. Restart the service after any change.

Server Components

  • Cowrie 3.0.6: /opt/cowrie (virtualenv /opt/cowrie/cowrie-env)
  • Emulated SSH honeypot: 0.0.0.0:2222
  • Emulated Telnet honeypot: 0.0.0.0:2223
  • Real admin SSH (OpenSSH, key-only): 0.0.0.0:22

Filesystem Layout

  • /opt/cowrie: Cowrie state directory (config, logs, captures)
  • /opt/cowrie/cowrie-env: self-contained Python virtualenv
  • /opt/cowrie/etc/cowrie.cfg: main configuration
  • /opt/cowrie/etc/userdb.txt: honeypot login policy (which credentials are accepted)
  • /opt/cowrie/var/log/cowrie/cowrie.json: structured JSON event log
  • /opt/cowrie/var/lib/cowrie/tty/: full TTY session replays
  • /root/cowrie-info.txt: root-only per-VM instance info note

Persistence, first boot and updates

The Cowrie state, config and logs live under /opt/cowrie on the OS disk and are captured into the image, so a VM launched from this image is ready immediately. On first boot, cowrie-firstboot.service generates the per-VM honeypot host keys, resolves the instance address and writes the root-only info note. It then disables itself so later reboots are unaffected. The OS is patched at build time and ships with unattended security upgrades enabled.

systemctl is-enabled cowrie cowrie-firstboot apt-mark showhold
# expect no held packages on the image

Security Recommendations

  • Keep the NSG rule for port 22 restricted to your management network. Only the honeypot ports (2222/2223) should be broadly reachable.
  • Never place real secrets, credentials or data on this VM. The honeypot is a sensor, and you should treat any host exposed to attackers as disposable.
  • Forward the JSON event log off the box to your SIEM, so the captured intelligence survives even if you rebuild the sensor.
  • Review captured sessions regularly. Rebuild the sensor periodically from a fresh image so each deployment gets new per-VM honeypot host keys.

Support

Every SecureAnyCloud deployment includes 24/7 support with a 24 hour response SLA. Contact sales@secureanycloud.com for help with deployment, configuration or scaling.

This is a repackaged open-source software product with additional charges for SecureAnyCloud support services. Cowrie is distributed under the BSD 3-Clause license and is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch Cowrie on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure