I set up an SSH honeypot on my server: it pretends to be a defenceless Linux box, accepts almost any password and records everything done inside. There is no real system behind it. In the first five days it received 24,218 sessions from 683 addresses, and almost nine in ten came from a single bot.

I wanted to see attacks on my own server rather than in reports and textbooks: who shows up, what they type, and how one attack differs from another. Other companies' statistics answer "how many"; a honeypot shows "how".

The setup

The honeypot lives next to my portfolio site. It is Cowrie in an unprivileged, read-only container with every outbound connection blocked: whatever an attacker types, nothing leaves the box. Next to it run a tarpit, a port that pretends to be SSH and never finishes its greeting, and Redis, MySQL and Elasticsearch decoys. Incoming web traffic is filtered by CrowdSec.

Every five minutes the logs are turned into summaries: commands are cleaned (links, addresses and random file names become placeholders such as <url> and <file>), and attacker addresses are never published. Everything below is visible live on the site.

Found quickly, and the obvious gets tried first

A new session typically arrives about five seconds after the last one. The server was never advertised: it is found by scanners that constantly sweep the whole internet.

The most common passwords are predictable: 123456, 123, 1234, 12345678. Besides root, the usernames include ubuntu, admin, deploy, postgres and also claude: bots are already looking for accounts of developers who use AI tools. The conclusion is simple: password login on a public server does not last long.

One bot made almost 90% of the noise

The most interesting part was the distribution. 21,217 sessions, or 88%, came from a single family using 18 addresses. It logs in and runs one command:

uname -s -v -n -r -m 

Then it leaves. This does not look like a breach so much as an inventory: the bot checks whether the password worked and what system is inside. I cannot prove it, but the behaviour fits collecting a list of accessible servers to return to later or hand to someone else.

That gave the first practical lesson: counting sessions is useless. One noisy bot drowns out everything else, so I rebuilt the experiments to count addresses instead of sessions.

The most widespread family leaves a key

The family with the most addresses, 291, does something different: it removes the protection from the .ssh folder, deletes it, recreates it and writes its own key. The whole thing takes seconds:

cd ~ && rm -rf .ssh && mkdir .ssh && echo <key> >> .ssh/authorized_keys 

Deleting the old folder matters: on a real server it would lock out both the owner and other bots. And changing the password afterwards does not help, because the key stays. So when you suspect a breach, check not only passwords but also the authorized_keys file, cron jobs and the user list.

What bots left in the honeypot

The honeypot may not make outbound connections, so it cannot download anything. But bots upload files themselves: 22 files have piled up so far, 17 of them Linux programs for several architectures, including x86-64, ARM and AArch64. Several carry signs of XMRig, a cryptocurrency miner. The files are only examined as data and never run. The goal of most attacks is boring: someone else's CPU.

The tarpit: how much time you can steal from bots

The tarpit follows RFC 4253: before the banner a server may send any lines it likes, and the client has to wait. It sends one random line every ten seconds and holds the connection for up to a day. All that time the bot attacks nobody.

A week after launch the counter showed over 2,000 hours stolen from attackers and over 3,400 connections caught. The record is 24 hours, because that is as long as the tarpit holds anyone. If each of those bots had tried one password per second, that would be about 7.5 million password guesses that never happened. At any moment a couple of dozen bots are stuck in it.

How half my defences stayed silent for two days

The most useful part turned out not to be about bots at all. For two days the tarpit and decoy counters sat at zero. The service was running, the firewall rule was in place, and its counter was even growing. A local check passed.

tcpdump helped: requests were arriving, but no replies went out. In the end a second firewall turned up. Permission in one does not override a block in the other: a packet has to pass both. The first firewall's counter said all was well, and that was only half true.

The conclusion: a check from inside does not prove a service is reachable from outside. A firewall counter does not prove it either: it only speaks for its own part of the path. The most reliable answer came from a simple experiment: a real connection from outside while watching the packets.

What's next

The next question is whether bots pay attention to what they are dealing with. Every day the honeypot changes its disguise: the server name and the system version. In a few weeks it will be clear whether bots react or do not care. If they do not care, that is a result too.

The honeypot and the site also carry bait keys: a fake .env with an API key unique to everyone who downloads it. If someone tries the key, I will see how many minutes passed since it was stolen and whether it came from the same address. That gets its own post once there is data.

Live honeypot data is on the live page, every botnet family with its lineage is in the bestiary, and you can check your own auth.log against these bots right in the browser: the log never leaves your machine.

This post was first published in Russian on Habr.