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.servicerunning the honeypot as the unprivilegedcowrieuser- Emulated SSH honeypot on
2222and Telnet honeypot on2223 cowrie-firstboot.servicefor 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.
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
2222and2223(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 StandardConnect 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.
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.
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.txtThe 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.
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.
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.
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 2222After 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 eventsEdit /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 imageSecurity 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
Overview
Cowrie is an open-source, medium-interaction SSH and Telnet honeypot. It presents a convincing but entirely sandboxed fake UNIX shell. Anyone who brute-forces their way in gets a realistic environment, while every login attempt, every command and every file download is recorded. Cowrie is one of the most widely deployed honeypots for studying automated attacks and for placing an early-warning tripwire inside a network.
This SecureAnyCloud image is a ready-to-use appliance. cowrie.service is enabled and starts on boot, so the honeypot is already listening by the time you connect over SSH.
What you get:
- A headless service with no web interface. The decoy SSH listens on port 2222 and the decoy Telnet on port 2223.
- Decoy ports kept separate from the real administrative sshd on port 22, so deploying the honeypot never interferes with how you manage the instance. The image never redirects port 22 to the honeypot.
- A shipped security group that opens port 22 only. A honeypot should be exposed only on purpose, so the decoy ports stay closed until you deliberately open them.
- No shared or baked-in host identities. Cowrie ships no real login credential, and a fresh decoy SSH host key is generated on each instance's first boot, so honeypots do not share one fingerprint.
- Every interaction written as a structured JSON event that you can ship to your SIEM or analytics pipeline.
- The honeypot home, including captured logs, replayable session recordings and downloaded payload samples, on a dedicated, independently resizable EBS data volume mounted at
/home/cowrie. The growing evidence store lives on durable storage that you can expand without touching the boot volume.
Prerequisites
Before you deploy this image, make sure you have:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network
- The AWS CLI (version 2) installed locally if you plan to deploy from the command line
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for Cowrie. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings, select your VPC and subnet, and either create or select a security group that opens port 22 from your management network. Leave the root volume at the default size or larger.
Select Launch instance. First-boot initialisation takes a short time after the instance state becomes Running and the status checks pass. The image resolves the instance address, writes the per-instance welcome notes, generates a unique decoy host key and starts the honeypot.
Launch the Instance from the AWS CLI
Run the following command to launch an instance from the SecureAnyCloud Cowrie Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens port 22 from your management network.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--metadata-options "HttpTokens=required" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=cowrie}]'When the instance state is Running and both status checks pass, note its public or private IP address for the SSH step.
Connect over SSH
Connect to the instance on the real administrative port 22 with your key pair. This is your normal, untouched admin access, not the honeypot.
Connecting to your instance
On Ubuntu 24.04, the SSH login user is ubuntu.
ssh -i /path/to/<key-name>.pem ubuntu@<public-ip>Read the Per-Instance Welcome Notes
On first boot, the image writes a root-only notes file that records this instance's decoy ports and the paths where captured evidence is stored. It is an information file, not a credential file, because Cowrie ships no real login secret.
sudo cat /root/cowrie-info.txtThe file lists the decoy SSH and Telnet port numbers, the JSON and text event log paths, the session recording and downloaded payload directories, and the fake user database path:
# Cowrie 3.0.8 - generated on first boot. Unique to this instance. COWRIE_ADMIN_SSH_PORT=22 COWRIE_SSH_DECOY_PORT=2222 COWRIE_TELNET_DECOY_PORT=2223 COWRIE_JSON_LOG=/home/cowrie/cowrie/var/log/cowrie/cowrie.json COWRIE_TTY_DIR=/home/cowrie/cowrie/var/lib/cowrie/tty COWRIE_USERDB=/home/cowrie/cowrie/etc/userdb.txtConfirm the Honeypot Is Running
Check that the honeypot service is active:
systemctl is-active cowrie.serviceThe command returns active. For the full unit detail, including the Python process that runs the honeypot, run:
systemctl status cowrie.service --no-pagerSee the Two Separate SSH Surfaces
The decoy SSH and your real administrative SSH are two entirely separate listeners. Confirm that all three ports are bound: the real sshd on 22, the decoy SSH on 2222 and the decoy Telnet on 2223.
ss -ltn | grep -E ':(22|2222|2223)\b'The decoy SSH deliberately presents a fake server identity, so it looks like a different, older machine to an attacker. The admin sshd on port 22 is your genuine access. Compare the two banners side by side:
echo "decoy SSH 2222:"; timeout 8 bash -c 'exec 3<>/dev/tcp/127.0.0.1/2222; head -1 <&3' | tr -d '\r'
echo "admin sshd 22:"; timeout 8 bash -c 'exec 3<>/dev/tcp/127.0.0.1/22; head -1 <&3' | tr -d '\r'Open the Decoy Ports to Start Attracting Activity
The shipped security group opens port 22 only, so out of the box nothing can reach the decoy. To start attracting and logging activity, open the decoy ports in the instance security group to the networks you want to observe. Expose a honeypot only deliberately, and only to networks you understand. Replace <security-group-id> with your instance's security group and <your-mgmt-cidr> with the range you want to watch.
aws ec2 authorize-security-group-ingress \
--group-id <security-group-id> \
--ip-permissions \
IpProtocol=tcp,FromPort=2222,ToPort=2223,IpRanges='[{CidrIp=<your-mgmt-cidr>}]'Watch a Captured Session in the JSON Event Log
Cowrie writes every connection, login attempt, command and download to the JSON event log as it happens. Tail the log and watch the events arrive:
sudo tail -n 20 /home/cowrie/cowrie/var/log/cowrie/cowrie.jsonA successful brute-force login and the commands that follow appear as structured events, ready for a SIEM or analytics pipeline. The cowrie.login.success event records the username and password the attacker tried. Each cowrie.command.input event records exactly what they ran inside the emulated shell.
Replay a Recorded Session
Cowrie records each interactive session as a replayable TTY log under the session recordings directory. List the recordings, then replay one with the bundled playlog tool. Replace <session-id> with a filename from the listing.
sudo -u cowrie /home/cowrie/cowrie/bin/playlog /home/cowrie/cowrie/var/lib/cowrie/tty/<session-id>Tune the Fake User Database
The fake user database at /home/cowrie/cowrie/etc/userdb.txt controls which username and password combinations the honeypot accepts. Each line is a rule. The shipped default accepts common brute-force guesses, so the honeypot is inviting out of the box. To make the honeypot pickier or more permissive, edit this file and restart the service. This changes the running honeypot, so make the change only when you are ready.
sudo -u cowrie nano /home/cowrie/cowrie/etc/userdb.txt
# edit your accept/deny rules
sudo systemctl restart cowrie.service
# apply the changesOptionally Expose the Decoy on the Standard SSH Port
Some operators want the decoy to answer on the standard SSH port 22 so it catches untargeted scans. Port 22 is your real administrative access, so first move your admin sshd to another port and confirm that you can still log in there. Then redirect inbound port 22 traffic to the decoy on 2222. This changes how you reach the instance, so plan it carefully. Replace <admin-port> with the new administrative port you moved sshd to.
# Only AFTER you have moved your admin sshd to <admin-port> and confirmed access there:
sudo iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2222The Captured Evidence and the Data Volume
The entire honeypot home at /home/cowrie lives on a dedicated, independently resizable EBS data volume rather than the operating system root. It holds the JSON and text logs, the TTY session recordings and any downloaded payload samples. Confirm that it is its own filesystem:
findmnt /home/cowrieBecause the evidence store is on its own disk, you can grow it as your sensor collects more data without touching the boot volume. Snapshots of just the evidence are also simple to take.
Support
SecureAnyCloud publishes this image with 24/7 technical support by email and chat. We can help with decoy service configuration, the fake filesystem and user database, JSON and SIEM output, session replay, downloaded payload handling, opening and placing the decoy ports safely, backups, and upgrade planning.
Cowrie is distributed under the BSD 3-Clause License. SecureAnyCloud is not affiliated with or endorsed by the Cowrie project or its authors. 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 AWS
Launch Cowrie on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com