Cowrie SSH Honeypot Deployment: Attack Capture Guide
Docker-deploy Cowrie as an SSH honeypot. Map a public port, parse JSON logs for attacker IPs, wire DingTalk alerts, and turn captures into threat intel.
Scope
Honeypot deployment is for teams that want to capture attacks on purpose. Put a decoy on an internet-facing segment. Record brute force, exploit attempts, and malware drops end to end. Use it for threat intel, attribution, and awareness training. Cowrie is the mature medium-interaction SSH/Telnet honeypot: it fakes a real shell and logs every command. Fits SOC ops and red/blue drills.
Prerequisites
- Linux host reachable from the internet (1 vCPU / 1 GB+ recommended)
- Docker and Docker Compose installed
- Ports: Cowrie listens on 2222 (SSH) by default; can map to public 22
- Firewall rules that will not auto-ban the honeypot on scanner noise
Mechanism
Cowrie is a Twisted fake SSH/Telnet server. After the attacker connects, Cowrie handles auth and the command session, runs input against a restricted virtual filesystem, and logs everything. Events go to JSON: source IP, username/password, full command sequence, downloaded files. The value is bait — real services do not get weak-password probes. Any hit on the honeypot is suspicious by default.
Steps
1. Deploy Cowrie with Docker
`# Create deploy directory
mkdir -p /opt/cowrie && cd /opt/cowrie
# Pull image
docker pull cowrie/cowrie:latest
# Run (public port 2222, fake SSH)
docker run -d --name cowrie \
-p 2222:2222 \
-v /opt/cowrie/log:/cowrie/cowrie-git/var/log/cowrie \
--restart=unless-stopped \
cowrie/cowrie:latest`
2. Base config
`# Dump config template from the container
docker exec -it cowrie cat /cowrie/cowrie-git/etc/cowrie.cfg.dist > /opt/cowrie/cowrie.cfg
# Key settings: listen port and hostname disguise
sed -i 's/^hostname = .*/hostname = web-prod-01/' /opt/cowrie/cowrie.cfg
sed -i 's/^listen_endpoints = .*/listen_endpoints = tcp:2222:interface=0.0.0.0/' /opt/cowrie/cowrie.cfg
# Remount config and restart
docker stop cowrie && docker rm cowrie
docker run -d --name cowrie \
-p 2222:2222 \
-v /opt/cowrie/log:/cowrie/cowrie-git/var/log/cowrie \
-v /opt/cowrie/cowrie.cfg:/cowrie/cowrie-git/etc/cowrie.cfg \
--restart=unless-stopped \
cowrie/cowrie:latest`
3. Public port mapping (disguise as real SSH)
`# If public 22 is free, map it directly
# Change -p to 22:2222
# If 22 is taken by real SSH, iptables redirect (optional; do not copy blindly)
# iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-ports 2222
# Move real SSH to a high port; give public 22 to the honeypot`
Mapping the honeypot to 22 sends all SSH scan traffic into it. Move real SSH off 22 and switch it to key auth.
4. Log analysis and attack extraction
`# Tail JSON logs (one record per session)
tail -f /opt/cowrie/log/cowrie.json | python3 -m json.tool
# Top 10 attempted usernames
grep -o '"username": "[^"]*"' /opt/cowrie/log/cowrie.json | sort | uniq -c | sort -rn | head -10
# Top 10 attacker source IPs
grep -o '"src_ip": "[^"]*"' /opt/cowrie/log/cowrie.json | sort | uniq -c | sort -rn | head -10
# Extract commands the attacker ran
grep -o '"input": "[^"]*"' /opt/cowrie/log/cowrie.json | sort -u`
5. Alert platform integration
`# Real-time alert on new connections (DingTalk / WeCom webhook pattern)
tail -F /opt/cowrie/log/cowrie.json | while read line; do
src=$(echo "$line" | python3 -c "import sys,json;print(json.load(sys.stdin).get('src_ip',''))")
[ -n "$src" ] && curl -s -X POST "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d "{\"msgtype\":\"text\",\"text\":{\"content\":\"Honeypot alert: $src login attempt\"}}"
done`
6. Sink data as threat intel
`# Daily archive of attacker IPs for firewall / threat-intel consumers
grep '"src_ip"' /opt/cowrie/log/cowrie.json | grep -o '"[0-9.]*"' | sort -u > /opt/cowrie/attack_ips_$(date +%F).txt
# Example: Suricata / firewall blacklist
# iptables -A INPUT -s 1.2.3.4 -j DROP`
Verification
`# Check 1: port is listening
ss -tlnp | grep 2222
# Check 2: local fake attack (expect auth-fail log)
ssh -p 2222 root@127.0.0.1
# Any password should be rejected; cowrie.json should gain a new record
# Check 3: logs write in real time
tail -1 /opt/cowrie/log/cowrie.json | python3 -m json.tool`
FAQ
FAQ 1: Can attackers use the honeypot to hit other internal hosts?
Cowrie runs in a container with a restricted virtual filesystem. Commands are not executed for real; it is not a jump host. Still: expose only the honeypot port, cap container resources (`--memory=512m --cpus=1`), enable the host firewall, and isolate the honeypot from production.
FAQ 2: How do I improve catch rate?
Closer to production = better lure. Set `hostname` to a business-style name. Plant bait files such as `/etc/passwd` and DB backups in the VFS (Cowrie ships `fs.pickle`). Enable Telnet. Do not score only on connection count — watch successful logins and command depth.
FAQ 3: Logs are too large. What then?
Rotate JSON daily: `logrotate -f /etc/logrotate.d/cowrie`. Ship to ELK/ClickHouse for aggregation. Alert only on high-risk events (successful login, file download) to avoid fatigue.
Takeaway
A honeypot is a cheap intel probe. Docker Cowrie records full SSH attack sessions in minutes. Archive attacker IPs and credential lists; feed firewalls, Suricata, and threat-intel platforms. Treat it as a supplement to vuln management and baseline hardening.