Events
Everything that happens to a decoy is recorded as an event: one JSON
object per line, appended to events_file. The package writes them to
/var/log/easydecoy/events.jsonl. With events_file empty they go to stdout,
and EasyDecoy's own log goes to stderr, so stdout carries nothing but events.
{"time":"2026-11-07T11:20:40.409920Z","decoy":"telnet","kind":"login_attempt","src_ip":"10.0.4.17","src_port":61364,"dst_port":23,"username":"admin","password_length":8}
Each event is flushed as it is written, so tail -f sees it at once and a
crash loses nothing that was already recorded.
Fields in every event
| Field | What it is |
|---|---|
time |
When it happened, UTC, RFC 3339 |
decoy |
telnet or http |
kind |
What happened; see below |
src_ip |
The client's address. An IPv4 client of a dual-stack listener is shown as plain IPv4. |
src_port |
The client's port |
dst_port |
The decoy's port |
Kinds
kind |
Decoy | Extra fields |
|---|---|---|
connect |
any | none. Every connection starts with one. |
login_attempt |
telnet |
username, password_length |
request |
http |
method, path, host, user_agent |
login_attempt |
http |
as request, plus username, password_length |
non_http |
http |
sample: the first 64 bytes the client sent |
A field the client didn't send, such as a request with no User-Agent, is
left out rather than recorded as empty.
Passwords are never recorded
A login attempt keeps the username and the password's length only. Anyone who reaches a decoy might be a colleague typing their real password into the wrong window. The attempt is the signal; the password adds nothing worth that risk.
Client text is cleaned
Everything in an event that came from a client is made safe to store before it is written:
- Control characters, including newlines and terminal escapes, become
., so a client cannot forge a log line or recolour your terminal. - Each field is cut to a fixed length:
method16 characters,username128,hostanduser_agent256,path512.
Reading events with jq
Only the login attempts:
Who knocks most:
Which usernames are being tried:
What scanners asked the web decoy for:
jq -r 'select(.kind == "request") | .path' /var/log/easydecoy/events.jsonl \
| sort | uniq -c | sort -rn | head
Rotation
The package installs /etc/logrotate.d/easydecoy, which rotates the events
file weekly and keeps twelve compressed weeks. It uses copytruncate:
EasyDecoy keeps the file open in append mode, so after the copy it carries on
writing at the start of the emptied file, with no restart needed.
To keep events somewhere else as well, send them to a collector over syslog.