honeypot.observer

Actually read what you caught.

A visitor asks to open the importer’s directory. The simulated shell says it does not exist. The connection ends. A filter keeps only sessions that attempted to read the backup, so this one never reaches the analyst. The decoy has hidden its own defect inside the discard pile.

This is an invented exchange, but it exposes a real design choice in triage. A rule about what deserves attention also decides which failures the operator gets to see.

Session replay and structured logging are established tools. Cowrie, for example, records session identifiers and event types and supports replaying terminal sessions.1 The harder decision is what to put in the reading queue.

Read both sides#

Begin with an exchange, including the responses. A command list can show a request for a filename without showing that the decoy supplied it a moment earlier. It can also show a departure without showing the error immediately before it.

For the fictional importer, the sequence fits in a few lines:

Invented exchange for review, not an observed session
text
Visitor: open /srv/importer
Decoy:   directory not found
Visitor: end connection

The fault is visible without deciding whether the visitor was a human, an agent or a fixed script. The directory advertised by the decoy was unavailable. That is enough to put a repair on the list.

Use the collector’s session identifier to assemble the exchange. An address alone is a poor substitute: several connections can share it, and one connection’s events can be interleaved with another’s. Where the record cannot reconstruct a session, keep that gap visible.

Keep a second queue#

There is a good reason to group repeated sequences. Reading the same exchange repeatedly uses attention that could go to a changed response, a new path or a failure in the decoy. Keep representative examples and the size of each group. Collapsing repetitions should shorten the queue without erasing how common they were.

Then reserve some attention for the excluded material. Draw a small, regular sample from each point where exchanges stop. The sample should include ordinary cases, not just the strangest ones chosen after a glance.

For the importer, that means looking separately at:

  • Connections that end before any file listing is offered.
  • Exchanges that receive the listing but do not request the archive.
  • Requests for the archive that the decoy fails to answer.
  • Exchanges that continue after the archive is delivered.

The third group is easy to miss if the queue is built around completed delivery. It is exactly where a broken handler would hide.

Keep the original records under a defined retention policy. Exclusion from today’s reading queue is an analytical choice. It should not automatically become deletion from the source material.

A rare command is a lead#

An unusual request deserves a look because it can reveal a gap in the operator’s expectations. Rarity alone does not make it valuable. A typo can be rare. A routine request can reveal that a frequently used response is wrong.

The useful question is what the exchange changes about the understanding of this decoy. Did a visitor request a filename that only appeared in its reply? Did a fallback answer conceal an unsupported operation? Did the same sequence end differently after a revision?

Selection rule
The condition that puts an exchange in the reading queue. Keep it with the review, so another reader can see which interactions were left out.

The rule becomes part of every conclusion drawn from that queue. “Most reviewed exchanges requested the archive” says little if requesting the archive was the condition for review. Keep the denominator beside the claim: all connections, sessions offered a listing, or only the selected sample.

Timing is useful context, but a pause does not identify a person. Clients wait, retry and schedule work. Record the pause if it matters to the sequence; do not turn it into an identity label.

Make the reading produce a decision#

A useful review note names the exchange, the selection rule, the offered response and the next attempted action. Then it states what needs doing. For the missing directory, the decision is straightforward: repair the advertised path and replay it locally before judging interest in the archive.

Other notes can end with “keep watching.” An odd request does not oblige the operator to add a feature. It earns a place in the record so a later repetition or a changed response can be compared with it.

A filter that finds interesting visitors while hiding a broken instrument is doing half the job. Give the discarded exchanges a route back into review. Part 4 follows the missing-directory problem into a repair question: which seams are worth fixing first?

Footnotes#

  1. Cowrie’s event reference documents session identifiers and event types; its project documentation describes replayable session logs. The example here is deliberately independent of a particular log schema. ↩