tutorials8 min read
A Honeypot on a Spare VLAN: Cowrie + CISA's New Decoys Playbook
One spare switch port, one Docker container, and you find out exactly who is scanning your network — and when they touch something that shouldn't exist. Built around Cowrie 3.x and CISA's Sep 16 cyber-decoys guidance.
Carve a honeypot VLAN (no route to prod), run Cowrie in Docker on it, optionally move your real SSH off :22 and let Cowrie take the port, then plant one CISA-style honeytoken on the prod side. Verify with two deliberately-failed tests: a fake ssh that logs in real time, and a touched decoy file that fires an alert.
You find out exactly who is scanning your network — and when they touch something that shouldn't exist. That's the whole payoff: a fake SSH box on its own VLAN that logs every brute-force attempt, plus one planted decoy file on the prod side of the fence that screams if it gets read. Two deliberately-failed tests prove both halves work before you ever need them.
Why this build, now//
Two reasons. First, CISA shipped its first dedicated "Using Cyber Decoys to Strengthen Detection and Response" guidance on Sep 16, 2026 — written explicitly for teams at "varying maturity levels" (SMB is in the audience tags), mapping decoys to MITRE Engage planning and MITRE ATT&CK detection. Its vocabulary is tripwires, breadcrumbs, and honeytokens: assets that look legitimate but are pure signal — any touch is an alert. That's the authoritative "why" for planting a decoy in your own lab instead of guessing whether it's worth it.
Second: this zine has covered honeypots as news (the FBI "Fang Fang" files are about declassified FBI documents, not a build you can run), but never as a procedure. This is the procedure: weekend-scoped, Docker-based, and verifiable before the first real attacker shows up (which, if your WAN IP is public, may be tonight).
Before you start//
- One spare switch port (or an unmanaged switch) + one free VLAN ID on a firewall that can route it — OPNsense, UniFi, or pfSense all work.
- Any x86 box with ≥4 GB RAM where
docker runworks. (A Pi 5 will run Cowrie fine; its high-interaction proxy mode wants more headroom.) - Time: ~3–5 hours including testing and the :22 relocation if you do it.
- Skill floor: intermediate — you know what a VLAN is. If not, the camera-VLAN post from 09-16 is the prerequisite reading; this build reuses its rule-set shape, inverted.
- Blast radius: one new VLAN + firewall rules (nothing prod touches while you build), one Docker container on a box of your choosing, and — only if you do Step 3 — moving your host's SSH daemon off port 22. That last one is the only step with real "I locked myself out" energy, so snapshot/backup before it.
- Verified against: Cowrie INSTALL docs (current 3.x documentation; the pip path requires Cowrie ≥3.0.0) and the
cowrie/cowrieDocker image, both fetched 2026-09-18. CISA decoys guidance as published Sep 16, 2026.
Step 1: Carve the honeypot VLAN (inverted camera-VLAN rules)//
The camera post's rule set said cameras can look out, nobody calls in. The honeypot is the mirror image: the honeypot phones out (DNS/NTP are fine), and nothing reaches it except what your firewall allow-lists.
On OPNsense this is the same mechanics as the camera-VLAN guide — Interfaces → Devices → VLAN, assign to a free interface, give it its own subnet (e.g. 192.168.70.1/24):
Rule 1 ALLOW source: <honeypot host IP> dest: DNS/NTP hosts tcp/53+udp/123 (it must resolve names + keep time)
Rule 2 BLOCK source: prod subnets dest: 192.168.70.0/24 (nothing in prod can poke it — you reach it via the firewall's allow-list, e.g. your laptop on a guest VLAN or SSH through the box)
Rule 3 BLOCK source: 192.168.70.0/24 dest: prod subnets (a compromised honeypot can't walk sideways into your NAS)
Then plug one unmanaged switch (or a single port) into it, and put the Cowrie box on that subnet with a static IP/reservation.
Why: a VLAN is just a boundary you can point at with rules. The whole security claim of this build — "nothing real lives here" — only holds if Rule 3 exists. One missing rule and your fake SSH box becomes a real stepping stone into prod.
Step 2: Stand up Cowrie in Docker (test before exposing)//
The official image's quick trial is one command, on port 2222:
docker run -d --name cowrie \
-p 2222:2222/tcp \
-v ~/cowrie-state:/cowrie/cowrie-git/var \
cowrie/cowrie
Put the state dir on a volume so logs, downloads, and ttylogs survive container rebuilds: in the image it lives at /cowrie/cowrie-git/var (the Dockerfile declares it as a named volume), which is what ~/cowrie-state maps to above. Want Telnet too? The image is configured via env vars — COWRIE_TELNET_ENABLED=yes (the pattern is COWRIE_<SECTION>_<STANZA> in capitals; an etc volume with a cowrie.cfg works the same way).
Then test from your laptop before anyone else can reach it:
ssh -p 2222 root@<honeypot-ip>
You'll get a plausible-looking login prompt. Type anything — whoami, cat /etc/passwd — Cowrie's simulated shell answers, and every keystroke lands in its log. Watch it appear:
tail -f ~/cowrie-state/log/cowrie/cowrie.log # = /cowrie/cowrie-git/var/log/cowrie/cowrie.log inside the image (state dir on the host)
Why: testing from your own laptop first means the only "attack" you have to debug is one you understand. A honeypot that's broken before it's exposed just teaches attackers nothing and costs you a weekend of chasing ghosts.
Step 3 (optional): Take port 22 for real traffic//
Scanners hit 22 first — on 2222 you catch the curious, on 22 you catch everyone. The Cowrie INSTALL docs are explicit that this is two changes: relocate your real SSH daemon first, then bind Cowrie to the low port. Three documented approaches; authbind and setcap let a non-root user bind :22 directly, iptables redirects traffic instead:
# 1. Move the host's real sshd off :22 (e.g. Port 222 in /etc/ssh/sshd_config), restart it
# 2a. authbind path — run Cowrie as a non-root user but bind :22 directly:
sudo apt-get install authbind
sudo touch /etc/authbind/byport/22 && sudo chown cowrie:cowrie /etc/authbind/byport/22 && sudo chmod 770 /etc/authbind/byport/22
# in etc/cowrie.cfg: [ssh] listen_endpoints = tcp:22:interface=0.0.0.0
AUTHBIND_ENABLED=yes cowrie start
# 2b. setcap path — grant the Python binary bind-low-port capability, then same cfg change:
setcap cap_net_bind_service=+ep /usr/bin/python3
# 2c. iptables redirect (system-wide; test from ANOTHER host — rules don't apply to loopback):
sudo iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2222
Why: "Cowrie on :22 swallows your own ssh" is the classic self-inflicted wound of this build — if you bind Cowrie to 22 before moving real sshd, you are the brute-forcer. Do the daemon move first, always, and keep a console/serial path open while you do it.
Step 4: Plant one CISA-style decoy on the prod side//
This is where the decoys playbook earns its slot. The honeypot catches people outside; a honeytoken catches people who got in — and per CISA's framing, that second detection is the one that proves compromise instead of just "something scanned us."
Plant something an attacker would plausibly read but you'd never touch:
# A fake secret file on your NAS or a prod box (CISA's taxonomy calls this class a tripwire/honeytoken):
sudo tee /etc/.k8s-backup.yaml > /dev/null <<'EOF'
apiVersion: v1
kind: Secret
metadata:
name: k8s-backup-creds
data:
password: aHBlcmUtaXQtZmFrZS1idXQtcGxhdXNpYmx5LWJlbGlldmFibGU=
EOF
# A fake account nobody logs in with:
sudo useradd -m -s /usr/sbin/nologin svc-backup
Then wire "touched" to an alert. The cheapest version that works — inotifywait → webhook:
inotifywait -m -e access,open /etc/.k8s-backup.yaml | while read line; do curl -X POST https://your-webhook/honeypot-touch; done
# (or point it at Loki/Grafana if you already run one — same shape)
Why: CISA's stated goals for decoys are continuous monitoring, high-fidelity alerts, reduced alert fatigue, and post-compromise detection including living-off-the-land activity. A file that should never be read has the highest fidelity possible: zero false positives by construction. One tripwire beats a thousand noisy firewall rules when it comes to "are we already in?"
Step 5: Let it run — then actually read the logs//
After a day or two, tail the Cowrie log and ask three questions: who hit you (source IPs, useragents), what did they try (which usernames got brute-forced — the classics are root, admin, test), and what did they type once "inside" (the simulated shell records their commands). Brute-force patterns show up fast on a public IP; even on a private lab, mDNS-adjacent scanners and misrouted traffic make interesting reading.
If you outgrow one honeypot — want multiple decoy services plus an Elastic stack in one compose file — the heavier path is T-Pot CE (Telekom Security's multi-honeypot platform; latest tag 24.04.1, so it's a bit behind Cowrie as of this writing). Mentioned for completeness, not as the main path.
Verify it worked (non-negotiable — two deliberately-failed tests)//
A honeypot you haven't proven is just software running on a VLAN:
- The fake login test: from a laptop plugged into the honeypot VLAN,
ssh -p 2222 root@<honeypot-ip>(or :22 if you did Step 3), type a few commands, exit — and watch the log line appear in real time. If it doesn't show up, your state dir or log path is wrong; fix before exposing. - The honeytoken test:
cat /etc/.k8s-backup.yamlon the prod box (or touch it as any non-root user) and confirm the alert fires — webhook hit, Loki entry, whatever you wired in Step 4. Then delete your own access from its audit trail so a future real touch stands out against a clean baseline. - The VLAN-leak test: before go-live,
pinga prod IP from inside the honeypot VLAN — it should fail (Rule 3). If it succeeds, you found the leak that would have made your fake SSH box a real attack surface.
When it breaks//
- Prod can reach the honeypot (or vice versa) — one wrong firewall rule; symptom is prod pings answering from inside the VLAN or Cowrie seeing your NAS's traffic. Fix: re-check Rule 2/3 direction and scope, re-run the ping test until it fails where it should.
- Your own
ssh"died" — you bound Cowrie to :22 before moving real sshd (the Step 3 warning, in the flesh). Rollback: stop Cowrie (docker stop cowrie), restore sshd's port, restart both. If you're locked out of the host, that's why console/serial access existed. - Disk fills with brute-force noise — months unattended and the state dir grows (ttylogs + downloads). Fix: logrotate the state dir or cap it; a honeypot is cheap to run but not free to store.
Rollback: one firewall rule set deleted, docker rm cowrie, honeytoken file removed. Nothing in this build touches prod firmware — which is exactly why a spare VLAN and a container are the right shape for a first decoy deployment. And per CISA's own framing: you didn't buy detection, you planted it — every touch now means something.
Filed under
Sources
5 cited · 3 primary- docs.cowrie.org/en/latest/INSTALL.htmlReporting
- hub.docker.com/r/cowrie/cowrieReporting
- github.com/cowrie/cowriePrimary
- cisa.gov/resources-tools/resources/using-cyber-decoys-strengthen-detection-and-responsePrimary
- cisa.gov/sites/default/files/2026-09/using-cyber-decoys-to-strengthen-detection-and-response_508c.pdfPrimary
Related dispatches
- tutorialsCamera VLAN With No Internet Route: The Firewall Rules That Let Cameras Call Nobody — 16 SEP 2026
- intelThe 'Fang Fang' Files: 150 Pages of a CCP Honeypot, a Freshman Congressman, and a Case That Vanished — 31 AUG 2026
- intelA Tale of Two SOCs: CISA Ran the Same Red Team at Two Critical-Infrastructure Orgs — One Detected It, One Never Did — 29 AUG 2026