Skip to content

Plugins

Plugins are what drive service emulation and determine the level of interaction possible with a given service. Plugins can either be based on TCP or UDP protocols. Plugins also determine what events and data are logged.

Events

For TCP plugins, all connection (CONNECT) events, data received (RX) events, and data transmitted (TX) events are logged.

For UDP plugins, all data received (RX) events and data transmitted (TX) events are logged. With UDP there are no CONNECT events.

Either TCP or UDP plugins may also log information (INFO) events. These events contain specific data of interest, typically extracted from an RX event. For example, usernames and passwords may be captured in an INFO event.

A few INFO events have the same shape in every plugin that emits them, so one query selects them across plugins. Each carries event_type and schema_version (currently 1) next to the fields below. A list with nothing in it is omitted from the event.

Event Fields Description
cryptomining_indicators pools, wallets (each address and chain: bitcoin, ethereum, monero, tron or unknown), miners, source_field, truncated Mining pool endpoints, wallet addresses and miner program names found in attacker-supplied text. source_field names where they were found. truncated is true only when the 50 ms scan budget expires; input is also cut at 65,536 characters without setting it.
dropper_indicators tools, urls, hosts, filenames, source_field, truncated A download tool together with a URL, or a /dev/tcp/ or /dev/udp/ host, found in attacker-supplied text.
info_event_cap_reached none Marker sent once per connection when the per-connection INFO event limit is hit. Only Docker_tcp, Electrum_tcp, BitcoinP2P_tcp, CgminerAPI_tcp, ClaymoreAPI_tcp and XMRigAPI_tcp emit it.
crypto_recon_command command, pattern, truncated A shell command that searches for wallets or keys. Emitted by SSH_tcp and Telnet_tcp.
crypto_lure_access path, command, lure_kind, truncated A shell command that reads, copies, archives, encodes or sends a crypto lure file. Emitted by SSH_tcp and Telnet_tcp while a crypto node persona is active.
crypto_lure_request target, path, lure_kind An HTTP request for a crypto lure file such as /.env or /wallet.dat. Emitted by HTTP_tcp.
jsonrpc_probe path, methods, batch_size A JSON-RPC request to a well-known RPC path. Emitted by HTTP_tcp.

An indicator event larger than 64 KiB is shortened and carries payload_truncated: true. Indicator events exist to carry attacker infrastructure, so only the agent's own IP address is scrubbed from them. Mining pool hosts, dropper URLs, IP addresses and wallet addresses given by the attacker are preserved.

Plugin Configuration Files

Many plugins support an optional JSON configuration file that customizes the plugin's behavior. To use one, reference the file from the service definition with the config key:

config      = /etc/honeydb/example.json

All plugin configuration keys are optional. If no config key is present, the plugin runs with its defaults. If the file cannot be read or parsed, the agent logs a warning and the plugin runs with its defaults.

The agent packages install only agent.conf and services.conf; no per-service JSON file is installed. Create the file yourself.

Several newer plugins also take options directly in their service section of services.conf, such as persona, transport, token_policy and auth_mode. These are documented in each plugin's Config table under Service section keys. Where a setting can be given in both places, the service section wins (for example persona, max_body and auth_mode).

For the blockchain and cryptocurrency plugins, the JSON file is a partial document. It contains only the keys you want to change, and it is merged over the plugin's built-in document rather than replacing it. The one exception is HTTP_tcp, where a custom configuration replaces the builtin server.json. How far the merge goes differs by plugin:

Behavior Plugins Effect of the keys in your file
Deep merge BeaconAPI_tcp, IPFS_tcp, LND_tcp, SubstrateRPC_tcp Objects are merged key by key at any depth, so you can change one nested value. Lists and scalar values replace the built-in value.
Top-level replace BitcoinP2P_tcp, CgminerAPI_tcp, ClaymoreAPI_tcp, Electrum_tcp, XMRigAPI_tcp Each top-level key you give replaces the built-in value whole. A limits object you give replaces the built-in limits; limit keys you leave out use the plugin's default. personas is merged by name, and a persona you name replaces that persona whole. BitcoinP2P_tcp requires every key of a persona, so a partial one is rejected and the built-in fallback is used. CgminerAPI_tcp and ClaymoreAPI_tcp accept a partial persona and fill the gaps from code defaults, not from the bundled persona of that name.
Named keys only EVMRPC_tcp, SolanaRPC_tcp limits is merged key by key and seed is replaced. personas is merged by name, and a persona you name replaces that persona whole. A top-level persona key is honoured (the service section's persona wins); other top-level keys are ignored.
Named keys only BitcoinRPC_tcp, MoneroRPC_tcp limits (and, for MoneroRPC_tcp, chain) is merged key by key; seed and weak_credentials are replaced. personas is merged by name, and the keys you give for a persona replace the same keys of that persona while the rest are kept. A top-level persona key is honoured (the service section's persona wins); other top-level keys are ignored.
Per-key replace Docker_tcp The plugin has built-in defaults and no persona document. Each recognized key you give replaces its default. An invalid value is logged and the default is used.

"Merged over the built-in document" does not mean a bad value is repaired. In SubstrateRPC_tcp, one unknown top-level key makes the whole document fall back to the built-in fallback persona. In IPFS_tcp, any type error replaces the whole merged document with the fallback. In BeaconAPI_tcp, invalid chain values are silently dropped to their defaults. Persona names are lower-cased when the service option is read but looked up case-sensitively in the JSON file, so use lowercase persona names.

Plugins List

The blockchain and cryptocurrency plugins emulate nodes, wallets, miners and related services that attackers scan the Internet for: BeaconAPI_tcp, BitcoinP2P_tcp, BitcoinRPC_tcp, CgminerAPI_tcp, ClaymoreAPI_tcp, Docker_tcp, Electrum_tcp, EVMRPC_tcp, IPFS_tcp, LND_tcp, MoneroRPC_tcp, SolanaRPC_tcp, SubstrateRPC_tcp and XMRigAPI_tcp. All of them are disabled (enabled = No) in the services.conf that ships with the agent, and they are intended for agents with an Internet-facing address. They require HoneyDB Agent 2.10.0 or later; an older agent does not know these plugin names. The SSH_tcp, Telnet_tcp and HTTP_tcp plugins also gained crypto-related options in 2.10.0, described in their entries below.

BeaconAPI_tcp

A low interaction TCP service that emulates the HTTP APIs of an Ethereum staking operator: a consensus-layer beacon node (Beacon API), a validator client's Keymanager API, a Web3Signer remote signer, and an execution client's JWT-authenticated Engine API. One persona is served per service section, and responses reproduce the status line, header order and JSON key order of captured client builds. The synthesized mainnet chain advances with the wall clock and is always synced. Keystore imports and deletes, fee-recipient and withdrawal changes, voluntary exits, signing requests, pool submissions, bearer tokens and JWTs are captured and answered with fabricated results. Nothing is signed, executed or relayed, no outbound connection is made, and per-source session state is kept in memory only.

Example service configuration:

[BeaconAPI]
plugin      = BeaconAPI_tcp
low_port    = tcp:5052
port        = tcp:5052
description = Ethereum beacon node REST API (Lighthouse).
enabled     = Yes
persona     = beacon
flavor      = lighthouse

Default sections (all ship with enabled = No):

Section Port Persona Notes
BeaconAPI 5052 beacon flavor = lighthouse.
BeaconAPI.keymanager 5062 keymanager flavor = lighthouse, token_policy = accept_any.
BeaconAPI.web3signer 9000 web3signer Web3Signer in eth2 mode.
BeaconAPI.engine 8551 engine Execution client authrpc, JWT.

Leave tls = No: the real services are plain HTTP, usually behind a reverse proxy. Each section runs one persona, so enable only the sections you want exposed.

Config

Service section keys:

Key Type Default Description
persona string beacon API to emulate: beacon, keymanager, web3signer or engine. An invalid value falls back to beacon and logs a warning.
flavor string lighthouse Client to impersonate. beacon accepts lighthouse, prysm, teku and nimbus; keymanager accepts lighthouse, prysm and teku. Ignored by web3signer and engine. An invalid value falls back to lighthouse.
token_policy string accept_any Keymanager bearer-token handling: accept_any accepts any non-empty bearer token, so imports, deletes and fee-recipient changes are captured; reject refuses every token with the client's 401 or 403. Only the keymanager persona uses it.
lure_validator_count int 8 Number of synthetic active validators, 1 to 64. A value outside the range is replaced by the default, not clamped.
head_lag_slots int 0 How many slots the synthesized head sits behind the wall-clock slot, 0 to 32. A value outside the range is replaced by the default.
max_body int 1048576 Request body cap in bytes, 1024 to 1073741824. Overrides limits.max_request_bytes from the JSON file. A value outside the range is replaced by the cap already in effect.
config string none Path to a JSON file merged over the built-in document.

Option values for persona, flavor and token_policy are case-insensitive.

JSON file keys:

The file is a partial document containing only the keys to change. It is deep-merged over the built-in document: objects merge key by key and any other value replaces the built-in one. The built-in document is part of the agent; no JSON file ships in packages.

Key Type Default Description
seed string null A non-empty string pins the identity seed that the synthetic keys and identities derive from.
limits object see below Transport, state and event bounds. Each value must be a positive number; invalid values keep the default and unknown names are ignored.
chain, flavors, peer_agents, public_shapes object or list built-in Captured chain parameters and per-client response templates. They can be overridden, but are not intended to be tuned.

Keys in limits (name and default):

Group Keys
Request transport max_request_bytes 1048576, max_header_bytes 65536, max_chunk_line_bytes 1024, idle_timeout_seconds 30, request_deadline_seconds 60, max_requests_per_connection 1000, max_requests_per_read 16, max_unflushed_bytes 4194304, max_tx_event_bytes 65536, max_stream_seconds 300
Connections and state max_streams_per_source 2, max_connections 512, max_connections_per_source 32, max_sessions 4096, max_engaged_sessions 1024, session_ttl_seconds 86400, max_session_keys 64, max_list_items 256, max_validators_per_query 64, max_root_lookback_slots 8192
Large responses large_responses_per_source_per_minute 4, large_responses_per_minute 20
Events max_routine_events_per_connection 64, max_high_value_events_per_connection 256, max_capture_events_per_batch 32, max_rpc_call_events_per_batch 16, max_rpc_call_summaries 64, high_value_events_per_source_per_minute 120, routine_events_per_source_per_minute 240, high_value_events_per_second 40, routine_events_per_second 80, max_rate_entries 4096, credential_events_per_source_per_minute 30, credential_events_per_second 50, credential_repeat_window_seconds 60, info_field_max_chars 2048

max_streams_per_source and max_stream_seconds bound the Server-Sent Events streams that the beacon persona serves. large_response_bytes and max_secret_chars are accepted but not read; secrets are always truncated at 1024 characters.

INFO Events

Every event carries event_type, schema_version, persona and flavor. Tokens, passwords and signatures are recorded in full, bounded to 1024 characters. Attacker infrastructure such as fee-recipient addresses and remote-signer URLs is preserved.

Event Description
api_request Per-connection summary of each method path requested: query, user agent, Accept, whether the route is known, a map of status codes to counts, and a request count.
bearer_token_presented A bearer token sent to the Keymanager API, with path, method, whether it was accepted, the policy, and a repeat count.
engine_auth_attempt A JWT presented to the Engine API: the token, decoded header and claims, the JSON-RPC method, and the outcome. No token can verify.
signing_request A Web3Signer signing request: public key, signing type, slot or epoch, signing root, fork version, and whether the key is known.
keystore_import_attempt A keystore import: public keys, passwords, slashing-protection data and per-key statuses.
keystore_delete_attempt A keystore or remote-key delete: kind, public keys and statuses.
remote_key_import_attempt A remote-signer key import: public keys and the attacker's signer URLs.
fee_recipient_change_attempt A fee-recipient change by Keymanager, proposer preparation or validator registration: validator, address, gas limit and signature.
validator_setting_change_attempt A gas limit or graffiti change for a validator.
voluntary_exit_attempt A voluntary exit through the pool or the Keymanager: validator, epoch and signature.
withdrawal_change_attempt A BLS-to-execution withdrawal credential change: validator, source key, target address and signature.
pool_submission A block, attestation or other pool submission: kind, count, slots, validator indices and a truncated body.
events_dropped Marker emitted when volume limits dropped events: scope, event class and count dropped.
cve_attempt Canonical CVE event for a detected exploit attempt (see below).

CVEs Detected

  • CVE-2021-44228 (Log4Shell, log4shell_jndi): a JNDI lookup in the request target, any header value or the body. Teku and Web3Signer are Java products.

BitcoinP2P_tcp

A low to medium interaction TCP service that emulates a Bitcoin peer-to-peer node. It completes the version/verack handshake as Bitcoin Core, Litecoin Core or Dogecoin Core and records what the peer reveals: its version message, announced and pushed transactions and blocks, address gossip and requests. After the handshake it answers ping, answers getheaders with an empty headers message, answers getdata with notfound for the types in the persona's notfound_types, and sends getheaders and getdata requests of its own (bounded). On the dogecoin persona it also sends reject for an obsolete or duplicate version, and mempool and filter* commands close the connection when the persona's bloom_disconnect is true. It serves no blocks, headers, transactions or addresses, never answers getaddr, never relays anything and makes no outbound connections. BIP324 version 2 encrypted transport is not implemented: a version 2 attempt is recorded and the connection is closed without a reply.

Example service configuration:

[BitcoinP2P]
plugin      = BitcoinP2P_tcp
low_port    = tcp:8333
port        = tcp:8333
description = Bitcoin Core P2P node.
enabled     = Yes
persona     = bitcoin

Default sections:

Section Port Persona Notes
BitcoinP2P 8333 bitcoin Bitcoin Core 31.1.0 (/Satoshi:31.1.0/, protocol 70016).
BitcoinP2P.litecoin 9333 litecoin Litecoin Core 0.21.5.8 (/LitecoinCore:0.21.5.8/, protocol 70017).
BitcoinP2P.dogecoin 22556 dogecoin Dogecoin Core 1.14.9 (/Shibetoshi:1.14.9/, protocol 70015).

The three default ports do not conflict.

Config

Service section keys

Key Type Default Description
persona string default_persona from the JSON document ("bitcoin") One of bitcoin, litecoin, dogecoin (lower-cased), or a persona you add in the JSON file. An unknown or invalid persona logs a warning and falls back to default_persona, then to a built-in Bitcoin Core persona; the plugin still starts.
config path none Optional JSON file of overrides.

The JSON file is a partial document containing only the keys to change, merged over the built-in document. The merge is shallow at the top level: a top-level key that you supply replaces the built-in value as a whole, except that personas is merged by name (a persona with the same name as a built-in one is replaced whole). A supplied limits object therefore replaces the built-in limits object; limits you omit take the built-in default value. No file ships in packages.

JSON file keys

Key Type Default Description
default_persona string "bitcoin" Persona used when the service section sets none, and the fallback for an unusable persona.
limits object see below Resource and event limits. An invalid value logs a warning and keeps the default; values are truncated to integers.
personas object bitcoin, litecoin, dogecoin Persona name to persona definition.

A persona definition has these keys: port, magic (4 bytes, hex), protocol_version, min_peer_version, user_agent, services, first_bytes (v2_sniff or legacy), max_message_bytes, wtxidrelay, addrv2, post_verack, sendheaders_after_headers, getheaders_version, feefilter, bloom_disconnect, reject_messages, reject_obsolete_text, notfound_types, auxpow, mweb, cve_oversized_header, genesis, block1, anchor (height, time, hash), block_interval_seconds, max_money and address (p2pkh, p2sh, hrp). Every key is mandatory: a partial persona is rejected and the built-in fallback is used. Persona names are matched in lower case, so use a lower-case name for a persona you add.

Limits (all under limits)

Key Default Description
handshake_timeout_seconds 60 Close a peer that has not completed the handshake.
idle_timeout_seconds 600 Close a peer that sends nothing.
max_connection_seconds 3600 Maximum connection lifetime.
ping_interval_seconds 120 Interval of the plugin's own pings.
max_connections 64 Concurrent connections.
max_connections_per_source 4 Concurrent connections per source address.
max_buffered_payload_bytes 1048576 Largest message held in memory; larger ones are streamed and discarded.
max_parsed_bytes 8388608 tx and block bytes parsed per connection.
max_block_txs 4000 Blocks with more transactions are summarized.
max_messages 20000 Messages per connection before it is closed.
max_info_events 64 INFO events per connection (the peer_request summary is additional).
info_events_per_source_per_minute 120 INFO events per source per minute.
summaries_per_source_per_minute 30 peer_request summaries per source per minute.
info_field_max_chars 2048 Cap on bounded text fields in INFO events.
max_rx_log_events 512 RX log events per connection.
max_tx_log_events 512 TX log events per connection.
max_rx_log_bytes 65536 Bytes of one message kept in the RX log.
max_txids 32 Transaction IDs listed in one tx_announce.
max_outputs 16 Outputs listed in one tx_relay.
max_addr_sample 16 Entries sampled in one addr_gossip.
max_hashes 8 Hashes listed in one block_announce.
max_getdata_echo 64 Entries echoed in one notfound.
max_getdata_request 50 Transactions requested per getdata.
max_tx_requests 200 Transactions requested per connection.
max_getheaders_replies 8 getheaders sent in reply to block announcements.
max_headers 2000 Headers examined in one headers message.
max_rate_entries 4096 Source addresses tracked by rate limits.
tx_request_delay_seconds 2 Delay before requesting announced transactions.
send_getheaders true Send getheaders after the handshake.
request_announced_tx true Request announced transactions.

INFO Events

Every event carries event_type and schema_version. Hashes are in display (explorer) byte order. Only the agent's own address is scrubbed; gossiped peers and the peer's own addr_from are kept as attacker infrastructure. The agent's address is zeroed in logged frames, so a logged frame's checksum may not match.

Event Description
peer_version The peer's version message: protocol version, services, timestamp, user agent, start height, relay flag, nonce and addr_from when set.
tx_announce Transactions announced by inv: count and the first 32 hashes with their type.
block_announce Blocks announced by inv, headers or block: source, count, the first 8 hashes and, for a full block, size, previous hash, merkle root, time, bits, version and transaction count.
tx_relay A pushed transaction: txid, wtxid, size, version, locktime, input and output counts, the first 16 outputs (value, script type, address), total output value and requested (whether this agent asked for it). An MWEB transaction emits a summary-only event with size and mweb.
addr_gossip Address gossip: format (addr or addrv2), count and a sample of the first 16 entries.
peer_request One per connection at close: transport (v1, v1_foreign_magic, v2_attempt or unknown), command counts, whether the handshake completed, duration and error counters.
v2_transport_attempt The peer tried the BIP324 encrypted transport. No fields.
unknown_command A message with an unrecognized command: command name and length.
info_event_cap_reached Emitted once per connection when the per-connection INFO event cap is hit.
cve_attempt A known exploit pattern was seen, at most once per CVE per connection.

CVEs Detected

Checks run only on exactly parsed structures.

CVE short_name Trigger
CVE-2010-5139 btc_value_overflow_tx An output value below zero or above the maximum supply, or outputs summing above it.
CVE-2012-2459 btc_duplicate_tx_merkle_block A block whose transaction list repeats a txid.
CVE-2015-3641 btc_oversized_message_header A message header declaring a payload above 4 MB and within 32 MiB (disabled on the litecoin persona; also requires the persona's max_message_bytes to be 4000000).
CVE-2018-17144 btc_duplicate_input_block A block transaction spending the same outpoint twice.
CVE-2024-52912 btc_version_timestamp_overflow A version timestamp 2^62 seconds or more from now.
CVE-2024-52915 btc_inv_block_flood One inv with more than 500 block entries.
CVE-2024-52916 btc_genesis_parent_headers A header chained onto genesis that is not the real block 1.
CVE-2024-52920 btc_getdata_unknown_invtype A getdata entry of an unknown inventory type.
CVE-2024-52921 btc_mutated_block A block whose recomputed merkle root differs from its header's, reported only when no txid repeats (CVE-2012-2459 takes precedence).

BitcoinRPC_tcp

A medium interaction TCP service that emulates the JSON-RPC interface of bitcoind and five forks (Litecoin Core, Dogecoin Core, Dash Core, Bitcoin Cash Node and zcashd) over HTTP. An attacker sees a synced node with an encrypted lure wallet that holds a seeded balance. The plugin keeps a wallet session per source IP address and records every credential pair tried, wallet passphrase guesses, key export and import attempts, and the destination of attempted sends. A send builds a fabricated transaction that is never broadcast; nothing is relayed, no outbound connection is made, and no usable private key exists for any lure address. One section emulates one coin.

Example service configuration:

[BitcoinRPC]
plugin      = BitcoinRPC_tcp
low_port    = tcp:8332
port        = tcp:8332
description = Bitcoin Core JSON-RPC node.
enabled     = Yes
persona     = bitcoin

Default sections:

Section Port Persona Notes
BitcoinRPC 8332 bitcoin Bitcoin Core 31.1.0, descriptor wallet.
BitcoinRPC.litecoin 9332 litecoin Litecoin Core 0.21.5.8.
BitcoinRPC.dogecoin 22555 dogecoin Dogecoin Core 1.14.9.
BitcoinRPC.dash 9998 dash Dash Core 23.1.8.
BitcoinRPC.bitcoincash 8332 bitcoincash Bitcoin Cash Node 29.2.0. Uses the same port as BitcoinRPC: change one of the two ports if both are enabled.
BitcoinRPC.zcash 8232 zcash zcashd 6.20.0, transparent wallet.

Config

Service section keys

All keys are optional. Values are trimmed and choices are case-insensitive. An invalid value logs a warning and the default is used.

Key Type Default Description
persona string "bitcoin" One of bitcoin, litecoin, dogecoin, dash, bitcoincash, zcash. Precedence: this key, then persona in the JSON file, then the built-in document, then bitcoin.
auth_policy string "list" list, after_n_attempts or never. See below.
auth_after_n int 3 Failed logins from a source before after_n_attempts starts accepting it. Minimum 1.
use_lure_credentials bool yes Accept this agent's lure bitcoin.conf rpcuser and rpcpassword pair, the same pair shown by the SSH, Telnet and HTTP lures. Accepts yes/no, true/false, 1/0, on/off.
passphrase_policy string "after_n_attempts" after_n_attempts or always_fail.
passphrase_after_n int 3 Wallet passphrase guesses per source that are rejected (error -14) before the wallet unlocks. Minimum 0.
config path none Optional JSON file of overrides.

auth_policy values:

  • list: accepts the pairs in the built-in weak_credentials list and, unless use_lure_credentials = no, the lure pair.
  • after_n_attempts: still accepts the lure pair; once a source has failed auth_after_n logins, every later request from it that carries credentials is accepted. The weak-credential list is not consulted under this policy.
  • never: nothing logs in, not even the lure pair.

A refused login gets 401 after a 250 ms delay. A request with no credentials gets an immediate 401 and is not counted as a failure. With passphrase_policy = after_n_attempts, the passphrase that unlocked the wallet becomes that source's wallet passphrase; always_fail never unlocks.

JSON file keys

The JSON file is a partial document containing only the keys to change; it is merged over the built-in document, which is generated and not meant to be edited. The merge is by key: limits is merged key by key, seed and weak_credentials are replaced as a whole, and for each entry in personas the supplied fields replace the same fields of the built-in persona of that name (an unknown name adds a new persona). No file ships in packages.

Key Type Default Description
persona string "bitcoin" Persona to use when the service section sets none.
seed string "" Seed for wallets and chain state. An empty value derives it from the host identity; set it to pin state.
limits object see below Resource and event limits. Invalid values log a warning and keep the default.
weak_credentials list 35 built-in pairs List of [user, password] pairs accepted under auth_policy = list. A supplied list replaces the built-in one.
personas object built-in personas Persona name to field overrides.

Limits (all under limits)

Key Default Description
max_request_bytes 1048576 Request body cap.
max_header_bytes 65536 Header block cap.
max_chunk_line_bytes 1024 Chunk size line cap.
idle_timeout_seconds 30 Close after this long with no data.
request_deadline_seconds 60 Whole-request deadline.
max_requests_per_connection 1000 Keep-alive request cap.
max_requests_per_read 16 Pipelined requests handled per read.
max_unflushed_bytes 25165824 Abort a client that does not read its responses.
max_tx_event_bytes 65536 Cap on transaction event data.
max_batch 100 Calls per batch; a larger batch gets one -32600.
capture_scan_limit 20 Members of an oversized batch still captured.
max_response_bytes 16777216 Encoded reply budget per request.
large_response_bytes 65536 Accepted and validated, but not read by any code path at this release.
large_responses_per_source_per_minute 4 Large replies (verbose block renders) per source per minute.
large_responses_per_minute 20 Large replies per minute, plugin-wide.
auth_failure_delay_ms 250 Delay before a refused login is answered.
auth_repeat_window_seconds 600 Window in which a repeated credential pair is counted rather than re-emitted.
auth_events_per_source_per_minute 300 rpc_auth_attempt budget per source per minute.
auth_events_per_second 100 rpc_auth_attempt budget per second, plugin-wide.
max_sessions 16384 Per-source wallet sessions kept.
max_engaged_sessions 2048 Sessions protected from eviction once a source has interacted with the wallet.
session_ttl_seconds 86400 Idle lifetime of a session.
max_session_sends 200 Sends recorded per session.
max_session_wallets 16 Wallets a session may create.
max_raw_tx_bytes 400000 Largest raw transaction decoded.
max_tx_inputs 2000 Inputs decoded per transaction.
max_tx_outputs 3000 Outputs decoded per transaction.
block_memo_heights 32 Recently rendered block heights memoized by the chain emulation.
max_rate_entries 8192 Source addresses tracked by rate limits.
info_field_max_chars 8192 Cap on bounded text fields in INFO events.
max_rpc_call_events_per_batch 32 rpc_call events per request body.
max_capture_events_per_batch 16 High-value events per request body.
max_rpc_call_summaries 32 rpc_call summaries emitted at disconnect.
max_routine_events_per_connection 200 Routine events per connection.
max_high_value_events_per_connection 64 High-value events per connection.
routine_events_per_source_per_minute 120 Routine events per source address per minute.
high_value_events_per_source_per_minute 60 High-value events per source address per minute.
routine_events_per_second 50 Routine events per second, plugin-wide.
high_value_events_per_second 20 High-value events per second, plugin-wide.

INFO Events

Every event carries event_type, schema_version and coin (the persona name). Only the agent's own address is scrubbed; attacker IPs and destination addresses are preserved. Credentials, passphrases and attacker keys are logged in full, with a length cap. Amounts are decimal strings such as "0.10000000".

Event Description
client_fingerprint Each new client fingerprint: user agent, path, authorization scheme, JSON-RPC version and content type.
rpc_auth_attempt The first occurrence of each distinct credential pair per source (repeats are counted): scheme, username, password, missing and malformed flags, whether it was accepted, credential_source (lure, weak_list, policy, rejected or missing), path and repeat_count. A refused login also carries methods (up to 20 distinct) and call_count, the only record of calls sent before login.
rpc_call Method calls of authenticated requests: method, parameter count, batch size, count and whether the method is known.
wallet_passphrase_attempt walletpassphrase, walletpassphrasechange and encryptwallet: wallet, passphrase, new passphrase, timeout, attempt number and whether it was accepted.
send_attempt sendtoaddress and sendmany: wallet, destinations (address, amount, validity, script type), comment, fee rate, outcome and error_code.
raw_transaction sendrawtransaction, signrawtransaction* and decoderawtransaction: decoded outputs, txid, input count, whether it spends a lure output, and the raw transaction.
key_export_attempt dumpprivkey, dumpwallet, listdescriptors and backupwallet: wallet, address, filename, path_traversal, whether the wallet was unlocked and, for listdescriptors, a private flag.
key_import_attempt importprivkey, importdescriptors and keys passed to signrawtransaction: the key or descriptors, label and rescan flag.
wallet_path_probe createwallet, loadwallet and unloadwallet: wallet name, path_traversal and passphrase.
lure_address_query getaddressinfo, validateaddress, gettransaction or getrawtransaction on a lure address or the lure funding transaction.
address_query The same calls on any other address or transaction.
events_dropped A volume budget was exceeded: scope, class (routine, high_value or credential) and count.

State is per source IP address and in memory: sessions expire after 24 hours idle and are lost on restart, and attackers never see each other's changes. Sends stay at zero confirmations and are never mined.

CgminerAPI_tcp

A low interaction TCP service that emulates the management API of a cgminer-family mining rig (Antminer, Avalon and Whatsminer). It serves one request per connection, as a text command|parameter line or a JSON object, replies with a NUL-terminated message and closes. Read commands return a plausible rig whose hashrate, temperatures, fans and uptime are seeded per agent. Privileged commands (pool changes, restarts, configuration) are accepted, though pool commands return error statuses for bad input (52 missing details, 53 invalid details, 8 no pools, 25 missing id, 26 invalid id) and setconfig answers 83 Unknown config. Pool state is remembered per source IP so a hijacked pool appears in the next pools reply. Commands, pool URLs, users, passwords, Whatsminer tokens and indicators are captured. Nothing is executed, no pool is contacted, and state is kept in memory only and lost on restart.

Example service configuration:

[CgminerAPI]
plugin      = CgminerAPI_tcp
low_port    = tcp:4028
port        = tcp:4028
description = cgminer/bmminer mining rig management API.
enabled     = Yes
persona     = antminer_s9

The shipped file defines one section and ships it with enabled = No. To present a second rig on another port, add a section with the same plugin and a different persona, for example whatsminer_m30s on tcp:4029.

Personas:

Persona Emulates
antminer_s9 Antminer S9 (bmminer), 3 boards of 63 chips, 13500 GH/s nominal. Default.
antminer_s19j_pro Antminer S19j Pro, 3 boards of 114 chips, 104000 GH/s nominal.
avalon_a10 Avalon A10 (CGMiner 4.11.1, API 3.7), MH-based rates.
whatsminer_m30s Whatsminer M30S+ (btminer), JSON {"cmd": ...} commands and the encrypted write channel.

Config

Service section keys:

Key Type Default Description
persona string antminer_s9 Rig to emulate: any persona name in the loaded document, case-insensitive. An unknown name falls back to the default persona and logs a warning.
config string none Path to a JSON file merged over the built-in document.

JSON file keys:

The file is a partial document containing only the keys to change, merged over the document built into the agent. The merge is shallow: a top-level key you supply replaces the built-in value, except that personas is merged by persona name, so a persona you define replaces the built-in persona of the same name as a whole. A supplied limits object replaces the built-in one, and any key it omits takes its default. No JSON file ships in packages.

Key Type Default Description
default_persona string antminer_s9 Persona used when the section does not set one.
seed string "" Seed for the generated telemetry. Empty derives it from the agent identity, so it is stable per agent.
personas object four built-in personas Rig definitions keyed by persona name. Persona fields include family (cgminer or whatsminer), miner_key, version, api_version, miner_version, type, description, devices, chips_per_device, nominal_ghs, frequency, fans, rate_unit and default_pools (a list of url, user, password).
limits object see below Each value must be a positive number; an invalid value keeps its default.

Keys in limits (name and default): max_request_bytes 8192, idle_timeout_seconds 10, max_connection_seconds 30, max_connections 256, max_connections_per_source 16, max_sources 8192, max_pools_per_source 16, source_ttl_seconds 86400, max_info_events 500, max_scans_per_connection 64, info_field_max_chars 8192.

A per-source, per-minute INFO rate gate (max_info_events times 4, bounded by max_sources) silently drops events from a very busy source.

INFO Events

Only the agent's own address is scrubbed; attacker pool URLs, hosts, wallets, users and passwords are preserved. Identical events are reported once per connection. The envelopes cryptomining_indicators, dropper_indicators and info_event_cap_reached are emitted as described in the Events section.

Event Description
miner_api_command Every command received: command, parameter, format (text, json or encrypted) and whether it is privileged.
pool_change_attempt A pool add, switch, enable, disable or remove: command, pool URL, user, password and pool index.
api_token_attempt A Whatsminer API token recovered from a decrypted write that carries one: command and token.
restart_attempt restart or quit on the cgminer wire; restart_btminer, reboot, power_off or factory_reset only inside a decrypted Whatsminer write. A plain reboot on the text wire is recorded only as miner_api_command with privileged false, as is every unencrypted Whatsminer command.
cryptomining_indicators Shared envelope for pools, wallets and miner names found in client data.
dropper_indicators Shared envelope for download tools, URLs, hosts and filenames found in client data.
info_event_cap_reached Marker emitted once when the per-connection event cap (max_info_events) is reached.

ClaymoreAPI_tcp

A low interaction TCP service that emulates the management API of Claymore Dual Miner, ethminer and PhoenixMiner GPU miners: JSON-RPC over raw TCP. It answers status and control methods, captures the optional password (psw or api_authorize) from each request, and decodes miner_file writes in memory to extract pool, wallet and dropper indicators. Uploaded files are never written to disk or executed, and no pool is contacted. The active pool and uploaded files are remembered per source IP in memory, so miner_getfile and the pool shown by miner_getstat1 and miner_getstat2 reflect a hijack. A miner_file write followed by a reboot is reported as CVE-2018-1000049.

Example service configuration:

[ClaymoreAPI]
plugin      = ClaymoreAPI_tcp
low_port    = tcp:3333
port        = tcp:3333
description = Claymore/ethminer GPU miner management API.
enabled     = Yes
persona     = claymore

The shipped file defines one section and ships it with enabled = No. To present another miner, add a section with the same plugin and a different persona on another port (the shipped file's commented example uses ethminer on tcp:3334).

Personas:

Persona Emulates
claymore Claymore Dual Miner "15.0 - ETH". One JSON request per connection, then the connection closes. Serves config.txt, epools.txt and dpools.txt. Default.
ethminer ethminer 0.19.0. Persistent newline-delimited JSON-RPC 2.0. Unknown methods and miner_file return error -32601; a miner_file write is still captured and evaluated against the CVE rules first.
phoenixminer PhoenixMiner "PM 6.2c - ETH" on the Claymore wire format. Serves config.txt and epools.txt.

Unknown methods on the Claymore wire format are logged and the connection is closed without a reply. An HTTP request line on the port gets a minimal HTTP 200 page.

Config

Service section keys:

Key Type Default Description
persona string claymore Miner to emulate: any persona name in the loaded document, case-insensitive. An unknown name falls back to the default persona and logs a warning.
config string none Path to a JSON file merged over the built-in document.

JSON file keys:

The file is a partial document containing only the keys to change, merged over the document built into the agent. The merge is shallow: a top-level key you supply replaces the built-in value, except that personas is merged by persona name, so a persona you define replaces the built-in persona of the same name as a whole. A supplied limits object replaces the built-in one, and any key it omits takes its default. No JSON file ships in packages.

Key Type Default Description
default_persona string claymore Persona used when the section does not set one.
seed string "" Seed for generated telemetry. Empty derives it from the agent identity.
personas object three built-in personas Miner definitions keyed by persona name. Persona fields: family (claymore or ethminer), version_string, project_name, gpus, nominal_mhs_per_gpu, default_pool, default_wallet, reboot_hooks (filenames that trigger the CVE rule), files (filename to content, served by miner_getfile) and http_page.
limits object see below Each value must be a positive number; an invalid value keeps its default.

Keys in limits (name and default): max_request_bytes 65536, max_file_bytes 262144 (decoded miner_file payload cap; excess is truncated), idle_timeout_seconds 30, max_connection_seconds 120, max_connections 256, max_connections_per_source 16, max_sources 8192, max_files_per_source 8, source_ttl_seconds 86400, cve_window_seconds 300 (how long after a miner_file write a reboot completes the CVE rule), max_info_events 500, max_scans_per_connection 64, info_field_max_chars 8192, content_capture_chars 8192 (file content kept in the event). max_connections_per_source_state and max_api_request_events are accepted but never read.

A per-source, per-minute INFO rate gate (max_info_events times 4, bounded by max_sources) silently drops events from a very busy source.

INFO Events

Only the agent's own address is scrubbed; attacker pools, wallets, URLs and hosts are preserved. The envelopes cryptomining_indicators, dropper_indicators and info_event_cap_reached are emitted as described in the Events section; the indicator envelopes carry a source_field such as miner_file.config.txt.

Event Description
miner_api_command Every method received: method, parameters (JSON, up to 2048 characters), format and whether it is privileged.
pool_change_attempt An ethminer miner_addconnection, miner_setactiveconnection or miner_removeconnection: pool_url is host:port with scheme and credentials stripped, and user is everything before the last @, unsplit. The password is never emitted.
api_password_attempt A password presented in a top-level psw (every persona), or in an api_authorize call, which only the ethminer persona handles; on the Claymore wire an unknown method closes the connection.
file_write_attempt A miner_file write: filename, size, SHA-256, decoded content, truncation flag, and the pools, wallets and URLs found in it.
restart_attempt A miner_reboot or miner_restart call.
cryptomining_indicators Shared envelope for pools, wallets and miner names found in client data.
dropper_indicators Shared envelope for download tools, URLs, hosts and filenames found in client data.
cve_attempt Canonical CVE event, one per triggering file (see below). Its indicators carry trigger (reboot_hook or file_then_reboot), filename, size, sha256 and the extracted pools, wallets, urls and hosts.
info_event_cap_reached Marker emitted once when the per-connection event cap (max_info_events) is reached.

CVEs Detected

  • CVE-2018-1000049 (claymore_miner_api_rce): Claymore Dual Miner remote management API. Fires when a miner_file write names a reboot hook (reboot.bat, reboot.sh or reboot.bash, case-insensitive, any directory prefix), or when any other miner_file write is followed by miner_reboot or miner_restart from the same source within cve_window_seconds.

ClickhouseHTTP_tcp

A low interaction TCP service that emulates the ClickHouse HTTP interface. It responds to standard ClickHouse endpoints (/, /ping, /replicas_status, /play, /dashboard, /metrics), answers SQL queries with canned responses, and captures credential attempts, queries, and probes of unknown paths.

Example service configuration:

[ClickhouseHTTP]
plugin      = ClickhouseHTTP_tcp
low_port    = tcp:8123
port        = tcp:8123
description = Clickhouse HTTP interface
enabled     = Yes
config      = /etc/honeydb/clickhouse.json

Config

Key Type Default Description
clickhouse_version string "24.3.2.23" Advertised ClickHouse version string.
clickhouse_server_display_name string "ch-edge-01" Value for the X-ClickHouse-Server-Display-Name header.
clickhouse_timezone string "UTC" Value for the X-ClickHouse-Timezone header.
auth_policy string "always_succeed" One of "always_succeed", "always_fail", "match_list".
credentials list [["default", ""], ["admin", "admin"], ["clickhouse", "clickhouse"]] List of [user, password] pairs used with auth_policy: match_list.
require_credentials bool false When true, anonymous requests receive a 401 challenge.
accepted_auth_schemes list ["basic","header","query"] Subset of auth surfaces to recognize.
enabled_endpoints list ["/", "/ping", "/replicas_status", "/play", "/dashboard", "/metrics", "/js/*"] Glob-aware allowlist of paths to serve; others receive 404.
force_close_per_response bool false Close connection after every response.
honor-xff-header bool false Trust the X-Forwarded-For header to resolve the effective client IP.
max_request_bytes int 1048576 Request size cap; larger payloads receive 413.
max_requests_per_connection int 1000 Force Connection: close after this many requests.
idle_timeout_seconds int 60 Keep-alive idle timeout in seconds.
structured_info_events bool true Emit JSON-encoded INFO payloads; false reverts Basic auth events to legacy free-text.
query_indicator_max_bytes int 8192 Truncation cap for the query field in query events.

INFO Events

Event Description
http_client Captures the User-Agent, Content-Type, method, path, and query string of each HTTP request.
xff_seen Fires when an X-Forwarded-For header is present; records the peer, XFF value, whether it was honored, and the resolved client.
auth_attempt Captures an authentication attempt (auth type, username, password, success).
query Captures a received ClickHouse SQL query, its delivery channel and format, and whether a canned response matched.
unknown_path Captures a request to an unrecognized HTTP path (method, path, query).

CouchDB_tcp

A low interaction TCP service that emulates an Apache CouchDB HTTP server. Supports two version profiles (1.x and 3.x), a realistic database and document API, Basic and cookie authentication, and detection of known CVE exploit patterns (CVE-2017-12635, CVE-2017-12636).

Example service configuration:

[CouchDB]
plugin      = CouchDB_tcp
low_port    = tcp:5984
port        = tcp:5984
description = CouchDB HTTP interface
enabled     = Yes
config      = /etc/honeydb/couchdb.json

Config

Key Type Default Description
profile string "1.x" Version profile: "1.x" or "3.x".
couchdb_version string "1.6.1" / "3.3.3" Advertised CouchDB version (default varies by profile).
erlang_version string "R16B03" / "24.3.4.13" Erlang OTP version in the Server header (default varies by profile).
server_version string — Overrides the full Server header verbatim when set.
vendor_name string "Ubuntu" OS vendor name in the welcome body.
vendor_version string "22.04" OS vendor version in the welcome body.
auth_policy string "always_succeed" One of "always_succeed", "always_fail", "admin_only".
preseed_dbs list profile defaults Override the list of databases pre-populated at connect time.
max_request_bytes int 1048576 Request size cap; larger payloads receive 413.
max_dbs_per_connection int 1000 Maximum databases that may be created in one session.
max_docs_per_db int 1000 Maximum documents per database per session.
max_requests_per_connection int 1000 Force connection close after this many requests.
idle_timeout_seconds int 60 Keep-alive idle timeout in seconds.
tag_known_cves bool true Enable CVE pattern detection events.
structured_info_events bool true Emit JSON-encoded INFO payloads; false reverts Basic auth events to legacy free-text.
honor_xff_header bool false Trust the X-Forwarded-For header to resolve the effective client IP.

INFO Events

Event Description
auth_attempt Captures a Basic or cookie/session login attempt (auth type, username, password, success).
cve_attempt Fires when a request matches a known CouchDB CVE signature (CVE id, method, path, indicators).
novel_path Captures a request to a path outside the known/profiled route set.
db_operation Captures a database-level operation (create/delete/info, database name, success).
doc_operation Captures a document-level operation (database, document id, success).

DNS_tcp

A low interaction TCP Domain Name Service (DNS). Answers queries against a configurable synthetic zone, supports query pipelining on a single connection, detects non-DNS traffic (such as TLS handshakes against the DNS port), and can optionally engage zone transfer (AXFR) requests. Abuse patterns such as DNS tunneling, DGA-like names, and enumeration bursts are detected and logged. Rate limiting state is shared with DNS_udp, so an attacker rate-limited on UDP is also rate-limited on TCP.

Example service configuration:

[DNS.tcp]
plugin      = DNS_tcp
low_port    = tcp:53
port        = tcp:53
description = DNS service.
enabled     = Yes
config      = /etc/honeydb/dns.json

Config

The configuration schema is identical to DNS_udp (see below) plus the TCP-specific keys in this table. Pointing both [DNS.udp] and [DNS.tcp] at the same JSON file keeps the synthetic zone and detector settings in sync.

Key Type Default Description
tcp_idle_timeout_seconds int 30 Connection closes after this many seconds of silence.
max_request_bytes int 65535 TCP framing cap. Messages whose length prefix exceeds this close the connection.
axfr_policy string "refused" One of "refused" or "engage". Engagement streams the full synthetic zone in a multi-message AXFR.
max_axfr_engagements_per_minute int 1 Per-source cap on AXFR engagements. 0 disables engagement entirely.
max_axfr_messages_per_engagement int 100 Hard cap on AXFR stream length. Larger zones are truncated.

INFO Events

Event Description
dns_query Captures each parsed DNS query (qname, qtype, returned rcode).
abuse_pattern Fires when a query matches an abuse detector or error condition; a pattern field discriminates the type (parse_error, rate_limited, internal_error, chaos_probe, amplification probe, zone-transfer attempt, DNSSEC probe, tunneling, DGA-like apex, enumeration burst, and the TCP-only non_dns_traffic).

DNS_udp

A low interaction UDP Domain Name Service (DNS). Answers queries against a configurable synthetic zone (a default example.com. zone is built in), responds to CHAOS-class fingerprint queries (version.bind, etc.), and detects abuse patterns such as DNS tunneling, DGA-like names, enumeration bursts, and amplification probes.

Example service configuration:

[DNS.udp]
plugin      = DNS_udp
low_port    = udp:53
port        = udp:53
description = DNS service.
enabled     = Yes
config      = /etc/honeydb/dns.json

Config

Key Type Default Description
bind_version string "8.2.2-P5" Fills the version.bind and version.server CHAOS responses when those aren't explicitly set in chaos.
chaos dict built-in defaults Per-CHAOS-name TXT strings (version.bind, version.server, hostname.bind, id.server, authors.bind).
zones list built-in example.com zone List of zone definitions (see zone schema below).
out_of_zone_policy string "nxdomain" Response for out-of-zone queries: "nxdomain", "refused", or "random_a".
rate_limit dict qps=10, burst=20, max_sources=10000 Per-source-IP rate limit. qps: 0 disables. Shared across DNS_udp and DNS_tcp.
max_response_bytes_edns int 1232 Response size cap when the query carries EDNS0.
max_response_bytes_legacy int 512 Response size cap when the query does not carry EDNS0.
tag_known_abuse bool true Master switch for the abuse-pattern detectors (tunneling, DGA, enumeration, etc.).
tunneling_qname_length_threshold int 80 Query name length that triggers tunneling detection.
tunneling_entropy_threshold float 3.8 Label entropy that triggers tunneling detection.
tunneling_high_entropy_min_label_len int 12 Minimum label length for high-entropy tunneling detection.
dga_entropy_threshold float 3.5 Entropy threshold for DGA-like name detection.
dga_min_label_len int 10 Minimum second-level label length for DGA-like name detection.
dga_max_vowel_ratio float 0.15 Maximum vowel ratio for DGA-like name detection.
enum_burst_threshold int 20 Distinct child labels under one parent that triggers enumeration detection.
enum_burst_window_seconds int 60 Sliding window for enumeration tracking.
structured_info_events bool true Set to false to revert to the original free-text INFO format.
override_name bool false Set to true to report the service name from the config file; otherwise DNS is used.

Zone schema

Each entry in zones is a dict:

Key Type Description
apex string Zone apex, e.g. "example.com.". Required.
ttl int Default TTL for records in this zone (default 3600).
soa dict SOA fields: mname, rname, serial, refresh, retry, expire, minimum.
ns list or dict NS hostnames. List = apex; dict = {label: [hostnames]}.
a, aaaa, txt, cname, ptr list or dict List = apex; dict = {label: [values]}.
mx list or dict List of {preference, exchange} dicts.
srv list or dict List of {priority, weight, port, target} dicts.
caa list or dict List of {flags, tag, value} dicts.

Wildcard labels (*) are not supported.

INFO Events

Event Description
dns_query Captures each parsed DNS query (qname, qtype, returned rcode).
abuse_pattern Fires when a query matches an abuse detector or error condition; a pattern field discriminates the type (parse_error, rate_limited, internal_error, chaos_probe, amplification probe, zone-transfer attempt, DNSSEC probe, tunneling, DGA-like apex, enumeration burst).

Docker_tcp

A low interaction TCP service that emulates an unauthenticated Docker Engine API over plain HTTP, the exposed port 2375 that cryptojacking campaigns scan for. It presents as Docker Engine 29.8.0 (API 1.56, minimum 1.40) on a synthetic Ubuntu 24.04.2 LTS host, and answers the stock docker CLI and raw HTTP tooling well enough for an attacker to ping, inspect, pull an image, create and start a container, and exec into it. Each step is recorded, including registry credentials, container commands, environment, bind mounts and Dockerfiles. Nothing is ever pulled, built, started or executed, and no outbound connection is made. Created containers, images and execs are kept per source IP in memory and expire after 3600 seconds idle. Exec returns canned output or nothing.

Example service configuration:

[Docker]
plugin      = Docker_tcp
low_port    = tcp:2375
port        = tcp:2375
description = Low interaction Docker Engine API service.
enabled     = Yes

Paths are served with or without a /v1.NN version prefix. Any image can be pulled; creating a container from an image that is neither configured nor pulled returns 404 No such image, which drives the CLI to pull it. Foreground runs exit 0 immediately with no output, and detached containers stay running. Unknown paths return {"message":"page not found"}.

Config

Service section keys:

Key Type Default Description
config string none Path to a JSON file of settings. The plugin reads no other section options. Without it the plugin runs on its built-in defaults.

JSON file keys:

The file is a partial document containing only the keys to change; every key is optional and an omitted key keeps its built-in default. An invalid value (wrong type, out of range, a string over 256 characters) is replaced by the default and a warning is logged. If min_api_version is greater than api_version, both are reset. No JSON file ships in packages, and the file is read only when referenced by config.

Key Type Default Description
docker_version string 29.8.0 Daemon version presented.
api_version string 1.56 Highest API version served; a /v1.NN prefix above it is rejected.
min_api_version string 1.40 Lowest API version.
accept_older_api_versions bool true Serve prefixes below the minimum. When false, return the real "client version is too old" error.
git_commit, go_version, build_time, containerd_version, containerd_commit, runc_version, runc_commit, init_version, init_commit, os, arch string 3ce5872, go1.26.8, 2026-09-03T21:50:08.000000000+00:00, v2.3.5, 1294c24a7da8e5a793ed378161673abe94118892, 1.5.1, v1.5.1-0-g8f2685a4, 0.19.0, de40ad0, linux, amd64 Component details returned by /version and /info.
kernel_version, operating_system, os_version string 6.8.0-71-generic, Ubuntu 24.04.2 LTS, 24.04 Synthetic host details.
ncpu, mem_total int 4, 8323874816 Synthetic CPU count and memory in bytes.
host_name, host_id string "" Name and ID in /info. Empty derives a stable value per agent.
images list nginx:latest, redis:7, alpine:3.20 Pre-existing images, each an object with ref, created (epoch seconds) and size (bytes).
containers list one running web container Pre-existing containers, each an object with name, image, command and state.
exec_outputs object id and whoami Map of exact command line to output. Other commands return nothing.
foreground_exit_delay_seconds number 0.1 Delay before an attached run finishes, 0 to 3600.

Bounds (name and default; positive integers): max_header_bytes 16384, max_body_bytes 1048576, max_rx_body_bytes 65536, max_rx_bytes_per_connection 1048576, max_body_discard_bytes 67108864, max_requests_per_connection 200, idle_timeout_seconds 60, request_timeout_seconds 30, stream_timeout_seconds 60, max_connection_seconds 600, max_connections 256, max_connections_per_source 16, max_info_events 500, max_api_request_events 100, max_scans_per_connection 64, max_sources 256, max_containers_per_source 16, max_images_per_source 32, max_execs_per_source 16, max_streams_per_container 8, state_ttl_seconds 3600.

INFO Events

Only the agent's own address is scrubbed; attacker pool hosts, dropper URLs, registries and registry credentials are preserved, and credentials are recorded in full. Fields the client did not send are omitted. The envelopes cryptomining_indicators, dropper_indicators and info_event_cap_reached are emitted as described in the Events section; their source_field names the origin, such as container_create.cmd, image_pull.image or build_request.dockerfile.

Event Description
api_request Every request except /_ping: method, path without version prefix, query string, API version and user agent.
image_pull POST /images/create: image, tag or digest, registry, import source, and the decoded X-Registry-Auth credentials.
container_create POST /containers/create: image, command, entrypoint, environment, bind mounts, privileged, network and PID mode, and name.
host_mount_attempt A bind mount that exposes a sensitive host path (such as /, /etc, /root, /proc, /var/run/docker.sock, /var/lib/docker or /var/spool/cron): the sensitive subset of the binds.
exec_create POST /containers/{id}/exec: command, privileged and user.
build_request POST /build: remote context, Dockerfile content and tags.
cryptomining_indicators Shared envelope for pools, wallets and miner names found in commands, environment, images and Dockerfiles.
dropper_indicators Shared envelope for download tools, URLs, hosts and filenames found in commands, environment and Dockerfiles.
info_event_cap_reached Marker emitted once when the per-connection event cap (max_info_events) is reached.

Echo_tcp

A low interaction TCP echo service (RFC 862). Any data sent to this service will be echoed back to the client. Received data is also checked for credential-like strings, which are captured as INFO events.

Example service configuration:

[Echo]
plugin      = Echo_tcp
low_port    = tcp:7
port        = tcp:7
description = Echo back data received via tcp.
enabled     = Yes

Config

Key Type Default Description
detect_scanner_fingerprints bool true Enable scanner-attribution INFO events.
detect_credential_like bool true Enable credential-shape INFO events.
event_field_max_bytes int 1024 Per-string byte truncation cap inside event payloads.
override_name bool false When false, the service is reported as "Echo" to normalize naming with Echo_udp. When true, the configured service name is used.

INFO Events

Event Description
scanner_fingerprint Fires when received bytes match a known scanner fingerprint (scanner name, pattern id, payload size).
credential_like_string Fires when received bytes contain credential-like strings.

Echo_udp

A low interaction UDP echo service (RFC 862). Data sent to this service is echoed back to the client, capped at max_echo_bytes (default 64 bytes) to prevent the service from being abused as a DDoS reflection/amplification vector. Received data is also checked for credential-like strings and amplification probes.

Example service configuration:

[Echo.udp]
plugin      = Echo_udp
low_port    = udp:7
port        = udp:7
description = Echo back data received via udp.
enabled     = Yes

Config

Key Type Default Description
max_echo_bytes int 64 Maximum bytes reflected back to the source. 0 = never reflect (receive-only).
detect_scanner_fingerprints bool true Enable scanner-attribution INFO events.
detect_credential_like bool true Enable credential-shape INFO events.
detect_amplification_probe bool true Enable amplification-probe INFO events.
amplification_probe_size_threshold int 64 Datagram size threshold for the oversize amplification indicator.
amplification_probe_repeated_byte_ratio float 0.80 Repeated-byte ratio threshold for the filler amplification indicator.
event_field_max_bytes int 1024 Per-string byte truncation cap inside event payloads.
override_name bool false When false, the service is reported as "Echo" to normalize naming with Echo_tcp.

Note

Earlier versions of this plugin reflected the full received datagram with no size cap. To restore that behavior, set max_echo_bytes to a sufficiently large value.

INFO Events

Event Description
scanner_fingerprint Fires when the datagram matches a known scanner fingerprint (scanner name, pattern id, payload size).
credential_like_string Fires when the datagram contains credential-like strings.
amplification_probe_suspected Fires when a datagram looks like a UDP amplification probe (size / repeated-byte heuristics).

Elasticsearch_tcp

A low interaction TCP Elasticsearch service. Emulates the Elasticsearch REST API (root endpoint, /_nodes, /_search, /_cat/indices, /_cluster/health, and other commonly probed recon endpoints) with three selectable version profiles. Detects known CVE exploit patterns (CVE-2014-3120, CVE-2015-1427, CVE-2021-44228/Log4Shell).

Example service configuration:

[Elasticsearch]
plugin      = Elasticsearch_tcp
low_port    = tcp:9200
port        = tcp:9200
description = Send basic elasticsearch replies.
enabled     = Yes
config      = /etc/honeydb/elasticsearch.json

Config

Key Type Default Description
name string "Flake" Elasticsearch node name advertised in responses.
cluster_name string "elasticsearch" Cluster name advertised in responses.
version_profile string "1.x" Version profile: "1.x", "7.x", or "8.x". Controls the response shape for / and /_nodes.
version_number string profile default Overrides the version.number field.
build_hash string profile default Overrides the version.build_hash field.
build_timestamp string profile default Overrides the version.build_timestamp (or build_date) field.
lucene_version string profile default Overrides the version.lucene_version field.
tagline string "You Know, for Search" Tagline in the root response.
tag_known_cves bool true Enable CVE pattern detection events.
honor-xff-header bool false Trust the X-Forwarded-For header to resolve the effective client IP.

Profile defaults:

Field 1.x 7.x 8.x
version_number 1.4.1 7.17.0 8.11.0
lucene_version 4.10.4 8.11.1 9.7.0

INFO Events

Event Description
user_agent Captures the request User-Agent header.
credentials Captures HTTP Basic Auth credentials when an Authorization header is present.
novel_path Captures a request to a path outside the emulated endpoint set (method, path, query).
body_capture Captures the (truncated) request body.
cve_attempt Fires on a known CVE pattern (CVE-2014-3120, CVE-2015-1427, Log4Shell CVE-2021-44228); records the CVE id and indicators.

Electrum_tcp

A medium interaction TCP service that emulates an Electrum wallet back end: the newline-delimited JSON-RPC 2.0 protocol that Electrum wallets speak to a Fulcrum 2.1.3 or ElectrumX 2.0.0 server. Reply key order, terminators, error texts and (for ElectrumX) packet padding follow the real servers. The service holds no chain data: every script hash has a zero balance and an empty history, subscriptions never fire, and the chain tip advances with the wall clock from the same anchor as BitcoinRPC_tcp and BitcoinP2P_tcp. It captures the client name and protocol range, the script hashes and scriptPubKeys a client watches, the transactions it tries to broadcast and the peers it tries to register. Nothing is executed or relayed: a broadcast that decodes is acknowledged, remembered per source address for one hour and never sent anywhere, and the service opens no outbound connection.

Example service configuration:

[Electrum]
plugin      = Electrum_tcp
low_port    = tcp:50001
port        = tcp:50001
description = Electrum server (Fulcrum).
enabled     = Yes
persona     = fulcrum

Default sections (all ship with enabled = No):

Section Port Persona Notes
[Electrum] 50001 fulcrum Plain TCP.
[Electrum.tls] 50002 fulcrum tls = Yes. Presents the plugin's own self-signed certificate (RSA-2048, O=Fulcrum, no host or address named), stored in the agent state directory as electrum-tls.cert and electrum-tls.key, not the agent's default certificate.

The ports do not conflict with another shipped section.

Config

The service section is read for persona and config. The bundled persona and chain document is always loaded; a config JSON file is a partial document: it contains only the top-level keys to change and is merged over the built-in document. The merge is shallow: a top-level key in the file replaces the built-in key, except personas, which is merged per persona name. No file ships in packages; create your own.

Service section keys:

Key Type Default Description
persona string fulcrum fulcrum (Fulcrum 2.1.3, protocol 1.4 to 1.6, CRLF terminator, server.version not required first) or electrumx (ElectrumX 2.0.0, protocol 1.4 to 1.7.0, LF terminator with padding, server.version required first, so the connection is closed otherwise). Case-insensitive. An unknown value falls back to fulcrum with a logged warning.
tls string No Yes wraps the port in TLS with the plugin's own certificate.
config string none Path to a JSON file as described above.

JSON file keys:

Key Type Default Description
banner string persona text Text returned by server.banner. Truncated to 16384 characters.
donation_address string persona value Text returned by server.donation_address. Truncated to 80 characters.
announce_host string unset Host name reported in server.features (fulcrum persona only). It must be a host name containing a letter; an IP address is ignored with a warning. When unset, a fabricated private address is reported.
seed string derived per agent Non-empty string that replaces the per-agent seed of the synthetic chain.
limits object see below Any of the limits below. A key you omit keeps its default; a value that is not a positive number is ignored with a warning.
default_persona string fulcrum Persona used when the section has no persona.
personas object fulcrum, electrumx Persona definitions, merged by name.
chain object built-in Chain anchor, genesis and real_headers. An invalid value falls back to the built-in chain.
wallet_commands list built-in Command names that trigger wallet_rpc_probe.

Commonly set limits keys:

Key Type Default Description
max_connections int 64 Concurrent connections.
max_connections_per_source int 12 Concurrent connections per source address.
max_line_bytes int 1000000 Longest accepted request line.
max_batch int 345 Calls accepted in one batch.
max_calls_per_connection int 20000 Calls before the connection is closed.
max_connection_seconds int 3600 Longest connection lifetime.
max_subscriptions int 1000 Subscriptions per connection.
max_info_events int 128 General INFO events per connection.
max_query_events int 1000 Query events (scripthash_query, scriptpubkey_query, outpoint_query, address_query) per connection, a separate budget.
info_events_per_source_per_minute int 240 General INFO events per source per minute.
query_events_per_source_per_minute int 2000 Query events per source per minute.
info_field_max_chars int 256 Truncation of captured text fields.
raw_tx_event_chars int 4096 Hex characters of a broadcast transaction kept in tx_broadcast.

Other limits keys accepted, with defaults: max_batch_capture 32, summaries_per_source_per_minute 30, max_rate_entries 4096, max_tx_bytes 100000, max_remembered_txs 16, max_remembered_bytes 262144, max_store_bytes 16777216, store_ttl_seconds 3600, max_outputs 16, max_echo_chars 2048, max_method_names 64, max_rx_log_bytes 65536, max_tx_log_bytes 16384, max_rx_log_events 512, max_tx_log_events 512, max_reply_bytes_per_line 2097152, max_reply_bytes_per_connection 33554432, reply_bytes_per_source_per_minute 67108864, header_periods_per_source_per_minute 20, header_periods_per_minute 200, max_pong_bytes 65536, backlog_seconds 15, close_grace_seconds 5. A source that exhausts a budget is disconnected.

INFO Events

Every event is JSON with event_type and schema_version: 1. Only the agent's own address is scrubbed; script hashes, addresses, decoded transactions and advertised peer hosts are preserved.

Event Description
client_version Each server.version call: client name, protocol minimum and maximum, negotiated version, extra_args (a count of extra arguments) and a repeat flag.
rpc_call Once per distinct call shape per connection: method, parameter count, whether the method is known, and whether it arrived before server.version.
scripthash_query First use of each script hash on a connection.
scriptpubkey_query First use of each scriptPubKey (protocol 1.7), with script type and derived address.
outpoint_query First use of each outpoint (protocol 1.7).
address_query A legacy blockchain.address.* call.
tx_broadcast A broadcast, broadcast_package or testmempoolaccept call: decoded transaction id, raw hex (first 4096 characters), size, version, locktime, input and output counts, and each output's value, script type and address.
tx_lookup transaction.get, get_merkle, id_from_pos and the Fulcrum lookups.
peer_advertise A server.add_peer call: the advertised hosts and ports, server version, protocol range and genesis hash, or a malformed marker.
wallet_rpc_probe A wallet or node daemon command (getbalance, payto, dumpprivkey and similar) on the line transport, or an HTTP request sent to the port.
session_summary Once at disconnect: methods called, call, line and batch counts, max_batch_size, other_calls, parse errors, oversized_lines, rx_log_suppressed, tx_log_suppressed, negotiated version, subscriptions and duration. events_dropped holds per-reason counts (cap, rate, query_cap, query_rate) of events dropped by a budget.
info_event_cap_reached Shared marker, emitted when the per-connection INFO cap is hit.

EVMRPC_tcp

A medium interaction TCP service that emulates the JSON-RPC API of an Ethereum-family execution client (Geth, op-geth, BSC, Bor, Erigon, Nethermind, Anvil, Hardhat or Ganache) over HTTP. It keeps a stateful synthetic chain and records the destination of attempted transfers, wallet passphrases, imported private keys, signing requests and raw transactions (the sender is recovered from the signature). Submitted transactions are accepted and stored but never mined, broadcast or relayed, and the plugin makes no outbound connections. WebSocket (port 8546) is not supported; the plugin serves HTTP only.

Example service configuration:

[EVMRPC]
plugin      = EVMRPC_tcp
low_port    = tcp:8545
port        = tcp:8545
description = Ethereum-family JSON-RPC node (Geth, Erigon, Nethermind, Anvil, Hardhat, Ganache).
enabled     = Yes
persona     = geth-mainnet

Only one section ships. Run one persona per section; to emulate several, add sections on distinct ports.

Config

Service section keys

Key Type Default Description
persona string "geth-mainnet" Persona name (case-sensitive). Precedence: this key, then persona in the JSON file, then persona in the built-in document, then geth-mainnet. An unknown or invalid persona logs a warning and falls back to a built-in geth-mainnet with one account; the plugin still starts.
config path none Optional JSON file of overrides.

The JSON file is a partial document containing only the keys to change; it is merged over the built-in document. The merge is by key: limits is merged key by key, seed is replaced, and a persona with the same name as a built-in one is replaced as a whole while the other built-in personas remain available. No file ships in packages; create one only if you need to override something.

JSON file keys

Key Type Default Description
persona string "geth-mainnet" Persona to use when the service section sets none.
seed string "" Seed for chain state, block hashes, balances and identity. An empty value derives it from the host identity. Set it to pin state across hosts or restarts; without a stable host identity the chain changes on every restart and a warning is logged.
limits object see below Resource and event limits. An invalid value (wrong type, boolean, non-positive) logs a warning and keeps the default; unknown keys are ignored.
personas object built-in personas Persona name to persona definition. Add a persona or replace a built-in one by name.

A persona definition accepts: family (geth, erigon, nethermind, anvil, hardhat, ganache; required), wire (Geth family only: v1.17, v1.16, v1.13), client_version (required), chain_id (integer or "seed"; required), network_id (integer, "seed" or "start_time_ms"; default chain_id), block_flavor (ethereum, ethereum-cancun, op-stack, bsc, polygon, dev; required), block_interval (seconds, greater than 0; required), anchor (required: mode fixed with number and timestamp, or mode uptime with min_age_seconds and max_age_seconds), namespaces (required), accounts, unlock_policy (mode: always_fail, always_succeed or succeed_after, plus attempts), fees (base_fee_gwei, priority_fee_gwei, gas_limit), peer_count, cors ("*" or null), strict_paths (default false: any URL path is answered; no effect on the Erigon family), dev_mode, datadir, node_name, listen_port and error_text. A same-name persona replaces the built-in one whole, so a partial definition fails validation; the plugin then logs a warning and falls back to the built-in geth-mainnet.

Limits (all under limits)

Key Default Description
max_request_bytes 1048576 Request body cap.
max_header_bytes 65536 Header block cap.
max_chunk_line_bytes 1024 Chunk size line cap.
idle_timeout_seconds 30 Close after this long with no data.
request_deadline_seconds 60 Whole-request deadline, not reset by data.
max_requests_per_connection 1000 Keep-alive request cap.
max_requests_per_read 16 Pipelined requests handled per read.
max_unflushed_bytes 4194304 Abort a client that does not read its responses.
max_tx_event_bytes 65536 Cap on transaction event data.
max_batch 100 Calls per batch.
capture_scan_limit 100 Members of an oversized batch still captured.
max_response_bytes 2097152 Encoded reply budget per request.
max_pending_transactions 1024 Stored transactions (count).
max_pending_bytes 8388608 Stored transactions (bytes).
max_stored_input_bytes 16384 Call data kept per stored transaction.
pending_ttl_seconds 3600 Lifetime of a stored transaction.
max_unlock_entries 4096 Unlock-state entries tracked.
max_rate_entries 8192 Source addresses tracked by rate limits.
recovery_rate_per_second 20 Sender recoveries per second, plugin-wide.
recovery_burst 20 Burst for the plugin-wide recovery rate.
recovery_per_remote_per_second 2 Inline recoveries per second per source.
recovery_per_remote_burst 4 Burst for per-source inline recoveries.
max_inline_recoveries_per_request 4 Inline recoveries per request.
recovery_queue_size 512 Deferred recoveries queued, plugin-wide.
recovery_queue_per_remote 32 Deferred recoveries queued per source.
info_field_max_chars 8192 Cap on bounded text fields in INFO events.
max_rpc_call_events_per_batch 32 rpc_call events per request body.
max_capture_events_per_batch 16 High-value and cheatcode_call events per request body.
max_rpc_call_summaries 32 rpc_call summaries emitted at disconnect.
max_routine_events_per_connection 256 Routine events per connection.
max_high_value_events_per_connection 256 High-value events per connection.
routine_events_per_source_per_minute 120 Routine events per source address per minute.
high_value_events_per_source_per_minute 60 High-value events per source address per minute.
routine_events_per_second 50 Routine events per second, plugin-wide.
high_value_events_per_second 20 High-value events per second, plugin-wide.

Personas

Persona Emulates Chain ID Notes
geth-mainnet Geth (default) 1 eth, net, web3; three unlocked accounts; unlock always fails.
geth-private-personal Geth private chain seed-derived Widest API surface (admin, debug, eth, miner, net, personal, txpool, web3); three locked accounts; unlock succeeds after 3 attempts.
op-geth-optimism op-geth, Optimism 10 Two unlocked accounts.
op-geth-base op-geth, Base 8453 Two unlocked accounts.
erigon-mainnet Erigon 1 No accounts.
nethermind-mainnet Nethermind 1 Adds txpool; two unlocked accounts.
bsc-mainnet BSC (Geth) 56 Three unlocked accounts.
polygon-mainnet Bor (Geth) 137 CORS *; two unlocked accounts.
anvil Anvil 31337 Dev mode; 10 accounts; any from accepted; unlock always succeeds; CORS *.
hardhat Hardhat 31337 Dev mode; 20 accounts; unlock always succeeds; CORS *.
ganache Ganache 1337 Dev mode; 10 accounts; network ID is the start time in milliseconds; unlock always succeeds.

Public-chain personas anchor to real block numbers from the time of the release; the blocks themselves are synthetic. Account addresses are synthetic and no private key exists for any of them.

INFO Events

Every event carries event_type and schema_version. Only the agent's own address is scrubbed; attacker IPs and wallet addresses are preserved. Passphrases and private keys are logged unscrubbed. Quantities are decimal strings and addresses are lowercase.

Event Description
client_fingerprint First request on a connection and whenever a field changes: user agent, origin, content type, path, query string, HTTP method and JSON-RPC version.
rpc_call Each distinct method in a request body, with whether any persona family knows it; repeats are counted and summarized at disconnect.
account_unlock_attempt personal_unlockAccount: address, passphrase and duration.
transaction_attempt eth_sendTransaction or personal_sendTransaction: sender, destination, value, gas, fees, nonce, call data and selector, ERC-20 token function fields, contract creation and passphrase.
raw_transaction eth_sendRawTransaction: decoded legacy, 2930, 1559, 4844 and 7702 transactions with recovered sender, destination, value, hash, type, chain ID and raw bytes.
raw_transaction_sender Follow-up carrying the sender once deferred recovery finishes under load.
key_import_attempt personal_importRawKey: private key and passphrase.
sign_request eth_sign, personal_sign or eth_signTransaction: address, message and method.
admin_action One of 14 methods: admin_addPeer, admin_removePeer, admin_addTrustedPeer, admin_removeTrustedPeer, miner_setEtherbase, miner_start, miner_stop, miner_setGasPrice, miner_setExtra, miner_setGasLimit, debug_setHead, parity_setEngineSigner, parity_setEngineSignerSecret and parity_clearEngineSigner.
cheatcode_call Any anvil_*, hardhat_* or evm_* call on any persona, with method, parameters and target address.
events_dropped A volume limit dropped events: count, scope (request, connection, source or plugin) and class (routine or high_value).

Every call is recorded before the persona decides whether it can serve it, so a method that the emulated client does not implement still produces its event. Cheat codes are recorded but have no effect on later reads.

FTP_tcp

A low/medium interaction TCP FTP service. Captures credentials and attacker commands, and detects known CVE exploit patterns (CVE-2011-0762 vsftpd backdoor, CVE-2015-3306 ProFTPD mod_copy). At the low interaction level all logins are denied; at medium, anonymous logins and logins from the password file are allowed, along with file uploads and downloads.

Example service configuration:

[FTP]
plugin      = FTP_tcp
low_port    = tcp:21
port        = tcp:21
description = FTP service.
enabled     = Yes
config      = /etc/honeydb/ftp.json

Config

Key Type Default Description
interaction_level string "medium" "low" denies all logins; "medium" allows anonymous logins and logins from the password file.
version_profile string "vsftpd_3" Sets the default banner: vsftpd_2, vsftpd_3, proftpd, or pure_ftpd.
welcome_message string (profile default) Overrides the version profile banner when set.
ftp_root string /tmp/honeydb/ftp FTP root directory. This is where FTP user folders are created and file uploads are stored.
password_file string (built-in list) File containing FTP usernames and passwords in the format user:password, one entry per line.
tag_known_cves bool true Enable CVE pattern detection events.
{
    "interaction_level": "medium",
    "version_profile": "vsftpd_3",
    "welcome_message": "(vsFTPd 3.0.3)",
    "ftp_root": "/tmp/honeydb/ftp",
    "password_file": "/etc/honeydb/ftppasswd.dat"
}

INFO Events

Event Description
username Captures the username from the USER command.
credentials Captures the username/password pair from the PASS command.
cve_attempt Fires on a CVE indicator: a USER ending in :) (CVE-2011-0762 vsftpd backdoor) or a SITE CPFR/CPTO sequence (CVE-2015-3306 ProFTPD mod_copy).
client Captures the reported client version from the CLNT command.
auth_mechanism Captures the mechanism requested by the AUTH command.
probe Fires on a SYST or FEAT probe command.
port_command Captures the parsed IP and port from a PORT command.
eprt_command Captures the parsed protocol, address, and port from an EPRT command.
site_command Captures a SITE subcommand and its parameters.
directory_traversal Fires when a RETR/STOR/LIST/MKD/DELE path contains ../ or ..\.

Gas_tcp

A low interaction TCP gas tank service. Emulates a Veeder-Root TLS Automatic Tank Gauge (ATG) — the industrial control system used at gas stations to monitor underground fuel storage tanks. Responds to common read and write commands with realistic sensor data, and captures attempts to change tank labels or the system date/time.

Example service configuration:

[Gas]
plugin      = Gas_tcp
low_port    = tcp:10001
port        = tcp:10001
description = Gas pump protocol.
enabled     = Yes
config      = /etc/honeydb/gas.json

Config

Key Type Default Description
station_name string random from built-in list Fixed station name; overrides random selection.
product1 string "SUPER" Tank 1 product label.
product2 string "UNLEAD" Tank 2 product label.
product3 string "DIESEL" Tank 3 product label.
product4 string "PREMIUM" Tank 4 product label.

INFO Events

Event Description
protocol_violation Fires when a received ATG command is malformed (missing the SOH start byte or too short to be valid).
atg_command Captures a recognized ATG command and its type, including date/time-set (S001) and tank/label-set (S602xx) write attempts; unrecognized commands are captured with their raw bytes.

HashCountRandom_tcp

A low interaction TCP service. This service will return an MD5 hash and integer to the client. For each client connection, the counter will increment by 1 on each RX event.

Example service configuration:

[HashCountRandom]
plugin      = HashCountRandom_tcp
low_port    = tcp:4096
port        = tcp:4096
description = Send random data prefixed with a hash of a counter via tcp.
enabled     = Yes

HTTP_tcp

A low interaction TCP HTTP service. This service will provide a generic HTTP page to client requests. For certain known targeted applications like phpMyAdmin, wordpress, weblogic, tomcat, and jboss, static responses specific to those applications are returned to the client.

Beyond the generic page, the builtin server.json also answers a set of cryptocurrency-related requests: crypto lure files such as /.env and /wallet.dat, BTCPay Server and LNbits API paths (including the /lnd-rest/btc/... LND REST proxy path), and the Antminer S9 web interface CGI paths behind HTTP digest authentication. JSON-RPC probe paths are answered by the plugin itself. A custom config replaces the builtin server.json, so only the JSON-RPC probes and the lures of entries that carry lure remain. A persona option makes the whole site look like one of three applications. These features require HoneyDB Agent 2.10.0 or later.

Example service configuration:

[HTTP]
plugin      = HTTP_tcp
low_port    = tcp:80
port        = tcp:80
description = HTTP service.
enabled     = Yes
config      = 

Config

Service section keys:

Key Type Default Description
config path none Absolute path to a custom JSON configuration. It replaces the builtin server.json entirely, so only the paths it lists are served. It must contain paths and default-page, and every response file it names must exist under html_root; otherwise the agent logs an error and uses the builtin configuration.
persona string none btcpay-server, lnbits or antminer (lower case). Overlays that persona's paths onto the active path set. An unknown name logs a warning and the default set is served. See Personas below.
digest_credentials string none Comma-separated user:password pairs (at most 16) that grant access wherever digest authentication is required. A pair splits at its first colon, so a password may contain colons but not commas. Overrides the credentials of every digest_auth option on the agent; with no value, each option keeps its own ([["root", "root"]] by default). An invalid value is ignored with a warning.
digest_accept_any Yes or No No When Yes, any well-formed digest header grants access. Overrides accept_any of every digest_auth option on the agent.

JSON file keys (top level):

Key Type Default Description
paths object none (required) Map of request path to path entry. See the path entry fields below.
default-page object none (required) response_headers and response_body files served for the path / only; an unmatched path gets the not-found error page. May carry digest_auth.
personas object none Persona name to path overlay. A custom config must define the persona for persona = to resolve.
error_pages object builtin Response files for the not-found, method-not-allowed and bad-request pages.
html_root string /etc/honeydb/html Directory holding the response files.
server_version string Apache/2.4.29 (Ubuntu) Value substituted for _SERVER_VERSION_ in response head files.
honor-xff-header boolean false Whether to honor the X-Forwarded-For header.

Path entry fields:

Field Required Description
name Yes Target identifier used in INFO events.
request_methods Yes JSON array of allowed HTTP methods.
match No exact (default) or prefix. A path key containing ? matches on query-parameter presence.
response_headers Yes File name in html_root.
response_body Yes File name in html_root.
cves No List of CVE identifiers reported when the path is requested.
lure No Serve a per-agent crypto lure instead of response_body: dotenv_generic, bitcoin_wallet, wallet_zip, keystore_index, eth_keystore or solana_id. An unknown id serves response_body and logs a warning.
lure_kind No lure_kind reported in crypto_lure_request. Defaults to the lure id.
capture_headers No List of request header names (case-insensitive) whose values are logged as api_credential_presented events, for example ["Authorization"] or ["X-Api-Key"]. Authorization: Basic is left to the basic-auth capture. Host, Content-Length and Transfer-Encoding are rejected.
captured_response No response_headers and response_body served instead of the base pair when at least one capture_headers header is present.
method_responses No Per-method override: an object keyed by upper-case method (listed in request_methods) holding response_headers, response_body and optionally captured_response.
digest_auth No Require HTTP digest authentication on the path: realm, credentials (list of [user, password] pairs, default [["root", "root"]], at most 16), accept_any (default false), challenge_headers and challenge_body.
reassemble_body No Integer cap from 1 to 262144 bytes. Buffers a request body that arrives in several TCP segments, or chunked, up to the cap.
handler No Capture handler run on every request to the path, authenticated or not: antminer_set_miner_conf, antminer_passwd, antminer_restart, antminer_form_command, antminer_firmware_upload or antminer_restore.

An invalid optional field is logged as an error at load and dropped; the path is still served with its base response. Response head files may contain the placeholders _SERVER_VERSION_, _DATE_, and, in a digest challenge, _DIGEST_REALM_ and _DIGEST_NONCE_.

Personas

By default the service serves the whole builtin profile set at once, including a cPanel default page and Grafana at /login. Some applications own the site root and /login, which that mix cannot give them without losing other profiles. A persona overlays one application's paths onto the set; persona paths win where they collide.

Persona What it serves
btcpay-server A BTCPay Server 2.4.4 front end. / redirects to /login?ReturnUrl=%2F. /login serves the sign-in page (GET) and an "Invalid login attempt." page on POST, capturing Email and Password. /register redirects to /. /stores, /server/users, /server/policies, /account, /api-keys/authorize and /docs redirect to the login page. /i/ and /.well-known/lnurlp/ answer with BTCPay's 404 pages.
lnbits An LNbits 1.6.2 front end. / serves the Vue shell, /admin answers 401, /docs serves Swagger UI, /openapi.json a trimmed OpenAPI document, /favicon.ico answers 307 and /first_install answers 400. Nothing else is shadowed.
antminer The whole site is an Antminer S9 web interface (lighttpd 1.4.32) behind digest authentication, realm antMiner Configuration, factory login root / root. Pages include /, /index.html, /minerConfiguration.html, /minerStatus.html, /network.html, /networkDiagnostics.html, /upgrade.html, /administration.html, /reboot.html, /monitor.html and /kernelLog.html. Every other path is challenged and, once logged in, gets a lighttpd 404, 405 or 400 page. It replaces the cPanel default page and the builtin 404, 405 and 400 pages.

Warning

The btcpay-server persona claims /login, which shadows the builtin Grafana login profile on that agent. The CVE attributions attached to that profile (CVE-2021-43798, CVE-2022-31107 and CVE-2023-22462) are shadowed on an agent running this persona. Use it on an agent where you do not need the Grafana login profile.

Without a persona, the 20 Antminer S9 /cgi-bin/*.cgi paths (minerStatus.cgi, get_miner_status.cgi, minerConfiguration.cgi, get_miner_conf.cgi, set_miner_conf.cgi, minerAdvanced.cgi, get_system_info.cgi, get_network_info.cgi, set_network_conf.cgi, network_diag.cgi, get_kernel_log.cgi, monitor.cgi, passwd.cgi, reboot.cgi, reset_conf.cgi, kill_cgminer.cgi, create_conf_backup.cgi, upload_conf.cgi, upgrade.cgi and upgrade_clear.cgi) already answer with the digest challenge and an S9's replies. With the builtin server.json, the BTCPay Server and LNbits API paths and the crypto lures are also always on, as are the JSON-RPC probe paths.

Example of a persona with custom digest logins:

[HTTP]
plugin             = HTTP_tcp
low_port           = tcp:80
port               = tcp:80
description        = Antminer web interface.
enabled            = Yes
persona            = antminer
digest_credentials = root:root,admin:s3cret
digest_accept_any  = No

Crypto lures and JSON-RPC probes

The lures are on with the builtin server.json; a custom config serves one only on an entry with lure. The JSON-RPC probes are always on. A scanner fetching /.env now produces crypto_lure_request instead of unknown_path.

Paths (GET) Response lure_kind
/.env, /.env.bak, /.env.local, /.env.production .env with PRIVATE_KEY=, MNEMONIC=, an RPC URL and KEYSTORE_PASSWORD= dotenv
/wallet.dat, /wallet_backup.dat, /backup/wallet.dat, /.bitcoin/wallet.dat A 16 KiB Berkeley DB shaped wallet file bitcoin_wallet
/wallet.dat.zip, /wallet.zip A ZIP holding that wallet.dat wallet_archive
/keystore/, /keystore/UTC--* A directory index listing, and a Web3 secret-storage v3 keystore eth_keystore
/id.json, /.config/solana/id.json A Solana keypair (a JSON array of 64 integers) solana_keypair

The lure material is synthetic, unfunded, generated locally on first run and unique per agent. It is the same material the SSH_tcp and Telnet_tcp crypto node persona serves, and it is kept in crypto-lures.json in the state_dir of agent.conf.

A POST to /rpc, /jsonrpc, /solana, /eth or /v1 whose body parses as JSON-RPC emits jsonrpc_probe and gets a static JSON-RPC reply. Nothing is relayed anywhere. For a fuller chain emulation use EVMRPC_tcp.

Digest authentication

A path with digest_auth behaves like a server that protects the path with HTTP digest authentication (RFC 2617, MD5, qop=auth).

  • A request without valid digest credentials gets the challenge, with a fresh nonce. The client repeats the request on a new connection, because HTTP_tcp answers one request per connection.
  • Access is granted only when the response verifies for one of the configured credentials (user and password), the realm matches, the nonce was issued by this agent in the last five minutes and the digest uri matches the request. With accept_any set, any well-formed digest header is accepted. Nonces are invalidated by an agent restart.
  • Every digest login on any path is logged as http_digest_auth. When the response verifies against a configured credential or one of 24 common device passwords, the event carries the plaintext password; otherwise the logged fields allow offline recovery.
  • Capture does not depend on authentication: a path's handler and CVE detection also run on the unauthenticated request, so a client that sends its body before and after the challenge can produce the handler's events twice. The authenticated field tells them apart.

Request body reassembly

By default a request is parsed from one TCP segment. A path with reassemble_body buffers the rest of the body (by Content-Length, or until the terminating chunk) up to the cap, for at most 10 seconds in total and 5 seconds without data. Across the agent, at most 64 reassemblies run at once, 2 per source address, and 8 MiB is reserved in total; a request over those limits is handled from its first segment. Expect: 100-continue is answered with 100 Continue.

INFO Events

Event Description
fingerprint Captures the client fingerprint submitted to the JS-based /session endpoint.
credentials Captures username/password from a POST form or JSON body login for a matched target.
client_headers Captures the User-Agent and/or Referer sent to a matched target path.
basic_auth Captures HTTP Basic Auth credentials for a target.
api_credential_presented Captures a request header listed in a path's capture_headers (target, header, value, path, method, scheme). The BTCPay Server and LNbits API paths use this to capture API keys and tokens.
crypto_lure_request Fires on a request for a crypto lure file (target, path, lure_kind).
jsonrpc_probe Fires on a JSON-RPC request to a probe path (path, methods, batch_size).
http_digest_auth Captures an Authorization: Digest header on any path: username, realm, uri, nonce, response, qop, nc, cnonce, algorithm, opaque, and password when recovered. accepted is added on a digest-protected path; an unparseable header gives malformed and raw.
pool_change_attempt Fires once per filled pool slot when new pool settings are posted to the Antminer set_miner_conf.cgi (pool_url, user, password, pool_index, authenticated). A miner_api_command event accompanies it, and a cryptomining_indicators event when pools or wallets are found.
password_change_attempt Fires on a post to the Antminer passwd.cgi, or a GET carrying current_pw, new_pw or new_pw_ctrl in the query string (current_password, new_password, confirm_mismatch, authenticated).
restart_attempt Fires on the Antminer reboot.cgi, kill_cgminer.cgi and reset_conf.cgi (command, authenticated).
miner_api_command Fires on Antminer set_miner_conf.cgi, network_diag.cgi and set_network_conf.cgi requests only (method, path, privileged, params, authenticated). command_injection is true when a network form field holds shell metacharacters, and a dropper_indicators event follows.
firmware_upload_attempt Captures a firmware upload to the Antminer upgrade.cgi (filename, size as declared by Content-Length, sha256 over the bytes actually received, authenticated).
config_restore_attempt Captures a configuration restore upload to the Antminer upload_conf.cgi (filename, size, sha256, entries, compressed, stock_script, authenticated).
cryptomining_indicators Mining pools, wallets or miners in submitted Antminer pool settings (see Events).
dropper_indicators Download tools, URLs, hosts and file names in an injected Antminer network form command (see Events).
cve_attempt Canonical CVE detection, one event per CVE (cve, short_name, indicators). Fires when a request matches a path entry with cves, a CVE pattern in the path, body or headers, or a detection signature such as CVE-2024-3721 (TBK DVR command injection; further events carry the injected command, dropper indicators and loader signatures).
cve_pattern Fires on a non-CVE attack pattern (SSTI, SQL injection, XSS, directory traversal) in the path, body or headers. Carries cve (null), label, pattern and location.
unknown_path Captures a request to an unmatched (404) path (method, path, query string, User-Agent).

The path field of these events holds the request path only; the raw query string is carried in query_string. Only the agent's own IP address is scrubbed, so attacker infrastructure in a request is preserved.

CVEs Detected

The plugin reports many CVEs through cve_attempt. The detections tied to the cryptocurrency profiles described above are:

CVE Short name Detection
CVE-2018-11220 antminer_restore_backup_rce Bitmain Antminer restore-backup RCE: a configuration archive posted to upload_conf.cgi that carries a non-stock restoreConfig.sh. Indicators include the archive file name, its entries and the script with its SHA-256.
CVE-2025-32013 lnbits_lnurlauth LNbits LNURL-auth SSRF: a POST to /api/v1/lnurlauth.

iKettle_tcp

A low interaction TCP smart kettle service. Emulates the Smarter iKettle 2.0 smart kettle, which communicates over plain TCP with no authentication and is actively indexed by Shodan and probed by automated scanners. Captures which commands attackers issue — device fingerprinting, control attempts (boil, stop, set temperature), and supplied parameters.

Example service configuration:

[iKettle]
plugin      = iKettle_tcp
low_port    = tcp:2081
port        = tcp:2081
description = iKettle smart kettle emulation.
enabled     = Yes

INFO Events

Event Description
version_query Fires on a firmware/version query command (0x11).
status_query Fires on a status query command (0x21).
stop_command Fires on a stop command (0x61).
boil_command Fires on a boil command (0x65); captures the target and keep-warm temperatures.
set_temperature Fires on a set-temperature command (0x69); captures the target temperature.
unknown_command Fires on an unrecognized command byte.

IMAP_tcp

A low interaction TCP IMAP service. Emulates an IMAP4rev1 server to attract credential-stuffing attacks, automated mail-client probes, and post-authentication enumeration activity. Captures login credentials, mailbox selections, search criteria, and appended messages.

Example service configuration:

[IMAP]
plugin      = IMAP_tcp
low_port    = tcp:143
port        = tcp:143
description = IMAP service.
enabled     = Yes
config      = /etc/honeydb/imap.json

Config

Key Type Default Description
server_name string "localhost" Hostname shown in the IMAP greeting and STATUS responses.
version_string string "Dovecot ready" Banner string appended to the greeting.
valid_passwords list ["admin","letmein","password123","password"] Passwords accepted for any username.
capabilities_pre_auth list ["IMAP4rev1","LOGIN"] Capabilities advertised before authentication.
capabilities_post_auth list ["IMAP4rev1","IDLE","NAMESPACE"] Capabilities advertised after authentication.
mailboxes list ["INBOX","Sent","Drafts","Trash","Spam"] Mailboxes available to clients.

INFO Events

Event Description
credentials Captures the username/password from a LOGIN command.
imap_select Fires on SELECT or EXAMINE; records the mailbox and read-only flag.
imap_search Captures the criteria from a SEARCH command.
imap_append Captures the mailbox and uploaded message body from an APPEND command.

IPFS_tcp

A low to medium interaction TCP service that emulates the Kubo (go-ipfs) RPC API of an IPFS node whose API port 5001 was exposed by mistake, which attackers use for free hosting and remote node control. It speaks the HTTP dialect of Kubo 0.43.1 (status codes, headers, JSON and NDJSON bodies and error texts from a real node) and answers the ipfs CLI, curl and scanners. The real CID of every upload is computed while streaming; the content is discarded and only a bounded sample and hash are kept. Pins, keys, configuration, peers and the MFS tree are remembered per source in memory. Content is never fetched, dialed, relayed, served back or executed, no outbound connection is made, and the node never joins the IPFS network. Reads of content the node does not have hold the connection open, like an online node that cannot find it.

Example service configuration:

[IPFS]
plugin      = IPFS_tcp
low_port    = tcp:5001
port        = tcp:5001
description = IPFS Kubo RPC API.
enabled     = Yes

Leave tls = No: the RPC API is plain HTTP. As Kubo does, a POST to a known /api/v0 command (after the 405 method check) receives 403 - Forbidden when its Origin or Referer is not localhost:<api port> or 127.0.0.1:<api port>, or when it carries neither and the user agent starts with Mozilla.

Config

Service section keys:

Key Type Default Description
agent_version_suffix string none Appended to AgentVersion (kubo/0.43.1/acc53c0/<suffix>). Kubo's Docker image uses docker. When set, the default debug command line also gains --migrate=true and --agent-version-suffix=<suffix>. Overrides the JSON key; a blank value is ignored.
config string none Path to a JSON file merged over the built-in document.

JSON file keys:

The file is a partial document containing only the keys to change. It is deep-merged over the document built into the agent: objects merge key by key, and lists and scalars replace the built-in value. An unusable document falls back to a built-in Kubo 0.43.1 persona and logs a warning. No JSON file ships in packages.

Key Type Default Description
agent_version_suffix string "" See the service section key.
version object Kubo 0.43.1 Version, Commit, Repo, System and Golang; all five must be non-empty strings.
listen.interface_ipv4 string or null null LAN address shown in the node's addresses. null uses a seeded 10.x.x.x address, never the agent's own.
listen.swarm_port int 4001 Swarm port shown in the node's addresses.
repo.size_base, repo.num_objects_base, repo.storage_max int 27550, 1, 10000000000 Repo statistics baseline.
repo.path, repo.fs_repo string /data/ipfs, 18 Repo path and version.
pubsub_enabled bool false When false, pubsub/* records the call and returns Kubo's "not enabled" error.
connect_succeeds bool false When false, swarm/connect fails with the captured dial-failure text; when true it returns the success shape.
debug.enabled bool true When false, /debug/* and /logs return 404.
debug.cmdline list ["ipfs", "daemon"] Command line shown by the debug endpoints (up to 16 items of 256 characters). Not present in the built-in document; the default applies when it is empty.
seed string "" Replaces the host identity seed material.
webui_cid string built-in CID served for /webui; must start with bafy.
config object captured Kubo configuration Baseline for config/show.
config_types object built-in Map of configuration key to Go type, which drives the exact decode-error text.
protocols, log_subsystems, peers list built-in Libp2p protocol ids, log subsystem names, and bootstrap peers (each with peer and addr).
limits object see below Bounds. An out-of-range value is clamped to the key's valid range (LIMIT_RANGES in the plugin) with a warning; unknown names are ignored.

Keys in limits (name and default):

Group Keys
Transport max_header_bytes 16384, max_rx_body_bytes 65536, max_rx_bytes_per_connection 1048576, max_upload_bytes 67108864, max_body_discard_bytes 268435456, max_requests_per_connection 200, idle_timeout_seconds 60, request_timeout_seconds 120, max_connection_seconds 900, max_hold_seconds 600, stream_timeout_seconds 60, max_connections 256, max_connections_per_source 16, max_response_bytes 8388608, max_list_items 1024, max_tx_log_bytes 65536, max_script_steps 64, debug_bytes_per_source_per_minute 16777216, debug_bytes_per_minute 134217728, max_journal_entries 2048, max_journal_entries_per_source 32
Uploads sample_bytes 4096, max_parts 64, max_filename_chars 1024, max_path_depth 32, max_directory_frames 512, max_leaves 65536, min_chunk_size 1024, min_exact_chunk_size 64, max_car_header_bytes 4096, cdc_bytes_per_source_per_minute 134217728, cdc_bytes_per_minute 536870912, small_leaves_per_source_per_minute 262144, small_leaves_per_minute 1048576, max_document_bytes 262144, max_key_bytes 8192, max_stored_document_bytes 65536
Holds (seconds) dial_wait_seconds 5, pin_wait_seconds 3, lookup_wait_seconds 6, findpeer_wait_seconds 12, ping_lookup_seconds 10, provide_wait_seconds 1, remote_pin_wait_seconds 30
Repo state max_pins 1024, max_known 4096, max_keys 64, max_ipns 64, max_bootstrap 64, max_peering 64, max_config_overrides 128, max_mfs_entries 1024, max_mfs_leaves 8192, max_filters 64, max_remote_services 16, max_routing_records 64, max_children_per_entry 1024, max_name_chars 256, max_value_chars 4096, max_ipns_value_chars 1024, key_derivations_per_source_per_minute 20
Events info_field_max_chars 8192, max_routine_events_per_connection 100, max_high_value_events_per_connection 200, max_capture_events_per_batch 66 (raised to max_parts + 2 if lower), max_rpc_call_events_per_batch 32, max_rpc_call_summaries 32, routine_events_per_second 50, high_value_events_per_second 20, routine_events_per_source_per_minute 300, high_value_events_per_source_per_minute 120, max_rate_entries 8192, max_scans_per_connection 64

An upload larger than max_upload_bytes gets no response and the connection is dropped; the content_add event is marked truncated.

INFO Events

Only the agent's own address is scrubbed; attacker multiaddrs, URLs, configuration values and API keys are preserved. cid, sha256 and sniffed content type are derived from client bytes. The envelopes cryptomining_indicators and dropper_indicators are emitted as described in the Events section, from upload samples, configuration values, pubsub payloads, IPNS values, pinning-service endpoints, peer multiaddrs and routing record samples.

Event Description
api_request Every request: method, path, arguments, query, user agent, origin, whether the command is known, and body size.
api_auth An Authorization header: scheme, and username and password (Basic), token (Bearer) or the raw value.
content_add Each part of an add, block/put, dag/put, dag/import or files/write: endpoint, filename, sniffed type, size, SHA-256, CID, a bounded sample, and layout and chunker for adds.
pin_request pin/add, rm, update or verify, and the roots of a dag/import: action, CID and options.
config_change config set, config/replace or config/profile/apply: action, key, value, document hash and size, and profile name.
key_request key/gen, import, rm, rename, sign or verify: action, name, type, size, key hash and sample, and signing data.
peer_connect swarm/connect or disconnect, peering, bootstrap and swarm filter changes: action, multiaddrs and peer id.
mfs_request files/* operations and add with to-files: action, paths, source and CID.
routing_request routing/*, dht/query, ping, resolve and name/get, put or inspect: action, key, CID, peer or name, and record hash and sample.
remote_pin_request pin/remote/*: action, service name, endpoint, API key, CID, name and status.
ipns_publish name/publish: path, CID, key, lifetime, TTL and allow_offline.
pubsub_request pubsub/*: action, decoded topic, payload and payload size.
shutdown_request A shutdown call (acknowledged and ignored).
cryptomining_indicators Shared envelope for pools, wallets and miner names found in client data.
dropper_indicators Shared envelope for download tools, URLs, hosts and filenames found in client data.
events_dropped Marker emitted when volume limits dropped events: scope, event class and count dropped.

IPP_tcp

A low interaction TCP Internet Printing Protocol (IPP/2.0) service. Accepts both HTTP-wrapped IPP requests (as used by CUPS, Windows, and exploit frameworks) and raw IPP binary. Captures print-job metadata, usernames, targeted printer URIs, and CVE exploit patterns (CVE-2024-47176, CVE-2024-47177).

Example service configuration:

[IPP]
plugin      = IPP_tcp
low_port    = tcp:631
port        = tcp:631
description = Internet Printing Protocol service.
enabled     = Yes
config      = /etc/honeydb/ipp.json

Config

Key Type Default Description
upload_dir string "var/uploads/print_jobs" Directory where captured print job files are saved.
save_print_jobs bool true Set to false to disable saving print job files while still emitting INFO events.
printer_name string "HP LaserJet Pro MFP" Printer name returned in Get-Printer-Attributes responses.
printer_location string "Office - Floor 2" Location string returned in Get-Printer-Attributes responses.

INFO Events

Event Description
ipp_username Captures the requesting-user-name attribute and the operation.
ipp_abuse_pattern Fires on a shell-injection (CVE-2024-47177) or suspicious printer-uri (CVE-2024-47176) pattern.
ipp_print_job Fires on a Print-Job operation.
ipp_validate_job Fires on a Validate-Job operation.
ipp_create_job Fires on a Create-Job operation.
ipp_send_document Fires on a Send-Document operation.
ipp_cancel_job Fires on a Cancel-Job operation; records the job id.

Kubernetes_tcp

A low interaction TCP Kubernetes service. Emulates a Kubernetes API server, responding to common kubectl API paths (nodes, pods, secrets, namespaces, deployments, RBAC) with plausible JSON payloads. Captures bearer tokens, anonymous access, request bodies, and pod exec/attach/portforward attempts.

Example service configuration:

[Kubernetes]
plugin      = Kubernetes_tcp
low_port    = tcp:6443
port        = tcp:6443
description = Send basic Kubernetes server replies.
enabled     = Yes

INFO Events

Event Description
http_request Captures each API request's method, path, and query string.
user_agent Captures the request User-Agent header.
bearer_token Captures a Bearer token presented in the Authorization header.
anonymous_access Fires on a request made with no authentication credentials.
body_capture Captures the (truncated) request body.
exec_attempt Fires on a pod exec/attach/portforward subresource request.
cryptomining_indicators Fires when a POST, PUT or PATCH body (other than an admission webhook review) contains mining pools, wallets or miner names (see Events). The JSON body is flattened first, so command, args and env entries are read as a shell would, and base64-wrapped commands are unwrapped. source_field is the resource collection written (pods, deployments, daemonsets, statefulsets, replicasets, replicationcontrollers, jobs, cronjobs or configmaps), or body.
dropper_indicators Fires when such a body contains a download tool together with a URL, or a /dev/tcp host (see Events).
cve_attempt Fires on a CVE detection (see CVEs Detected below).

CVEs Detected

CVE Short name Detection
CVE-2026-3288 ingress_nginx_rewrite_target_injection The ingress-nginx rewrite-target annotation value breaks out of its directive.
CVE-2026-1580 ingress_nginx_auth_method_injection The auth-method annotation value is more than a bare HTTP method.
CVE-2026-24512 ingress_nginx_path_injection An Ingress rule path is not a clean URI path.
CVE-2026-4342 ingress_nginx_annotation_injection Injection in another annotation (for example configuration-snippet) or in two or more annotations.
CVE-2025-24514 ingress_nginx_auth_url_injection The auth-url annotation value contains an nginx break-out character.
CVE-2025-1097 ingress_nginx_auth_tls_match_cn_injection The auth-tls-match-cn annotation value contains a break-out character.
CVE-2025-1098 ingress_nginx_mirror_target_injection The mirror-target or mirror-host annotation value contains a break-out character.
CVE-2026-35469 kubelet_spdy_frame_exhaustion An exec, attach or portforward request whose Upgrade value contains spdy. This is an attempt signal only.
CVE-2021-44228 log4shell_jndi Log4Shell JNDI lookup in the request target, a header value or the body.
CVE-2024-9042 kubelet_nodelogquery_cmdi kubelet NodeLogQuery command injection: a shell metacharacter in the query parameter of a /api/v1/nodes/<node>/proxy/logs/ request.

The ingress-nginx detections inspect an Ingress write (POST, PUT or PATCH to /apis/networking.k8s.io/v1/namespaces/<ns>/ingresses) and an AdmissionReview posted to a path ending in /networking/v1/ingresses, which the plugin answers with an allowed review. JSON-patch bodies are not inspected.

LDAP_tcp

A low interaction TCP LDAP service. Captures bind attempts (anonymous and credential), directory search queries, and write-operation attempts. Detects Log4Shell JNDI injection (CVE-2021-44228) and classic LDAP filter-injection patterns. Binds using any password from a built-in common-password list are accepted; all other passwords are rejected.

Example service configuration:

[LDAP]
plugin      = LDAP_tcp
low_port    = tcp:389
port        = tcp:389
description = LDAP server
enabled     = Yes

INFO Events

Event Description
cve_attempt Fires on a Log4Shell JNDI pattern (CVE-2021-44228) detected in request text.
injection_attempt Fires on an LDAP filter-injection pattern detected in request text.
anonymous_bind Fires on an anonymous (empty-credential) bind.
bind_attempt Captures an authenticated bind attempt and supplied credentials.
search_query Captures an LDAP search request.
modify_attempt Captures an LDAP modify request.
add_attempt Captures an LDAP add request.
delete_attempt Captures an LDAP delete request.

LND_tcp

A medium to high interaction TCP service that emulates the REST API (grpc-gateway, HTTP/1.1 over TLS) of lnd 0.21.4-beta, the Lightning Network Daemon. It is the service a stolen admin.macaroon gets presented to: macaroon authentication, a wallet state machine, the read endpoints scanners and BTCPay, LNbits, Zeus or Thunderhub clients call, and the spend endpoints an attacker holding a macaroon tries (pay invoice, send coins, open or close a channel, bake a macaroon). Every macaroon, wallet password, seed, invoice and destination presented is recorded. Nothing is executed or relayed: spends are fabricated, consistent per source address in memory only, and the service opens no outbound connection, holds no real key and writes no file.

Example service configuration:

[LND]
plugin      = LND_tcp
low_port    = tcp:8080
port        = tcp:8080
tls         = Yes
description = LND Lightning node REST API.
enabled     = Yes

The shipped section sets no other option. Port 8080 is not used by another shipped section. The service presents its own ECDSA P-256 certificate (O=lnd autogenerated cert, CN=<hostname>, ALPN http/1.1), not the agent's default certificate.

Config

There is no persona key. The emulated node is the bundled funded lure node (three channels, about 412,853 sat on chain), shaped by wallet_state and post_init_view. The bundled document is always loaded; a config JSON file is a partial document containing only the keys to change, deep-merged over it: nested objects are merged key by key, while lists (for example lure.channels) and scalars are replaced. No file ships in packages; create your own.

Service section keys:

Key Type Default Description
macaroon_policy string accept accept: any well-formed macaroon (v2 binary or v1 packet, with a location and identifier) is served. lure_only: only this agent's own admin.macaroon lure, and the per-source macaroon issued by initwallet (credential_source init), are served. reject: every macaroon is rejected with lnd's real errors.
wallet_state string unlocked unlocked: /v1/state reports SERVER_ACTIVE. locked: /v1/state reports LOCKED, protected calls answer "wallet locked", and unlockwallet and changepassword reject every password after about one second. none: a fresh uninitialised node (NON_EXISTING) on which initwallet succeeds for the calling source.
post_init_view string empty Only meaningful with wallet_state = none. empty: after a takeover the source sees a real fresh wallet with no funds, channels, peers or history, and an identity derived from the seed it submitted. seeded: the source sees the funded lure node.
alias string first 20 hex characters of the node public key Node alias. Blank means default; truncated to 32 bytes.
max_body int 1048576 Request body cap in bytes. Overrides limits.max_request_bytes.
idle_timeout int 30 Idle and stream timeout in seconds. Overrides limits.idle_timeout_seconds.
event_cap int 200 High-value events per connection. Overrides limits.max_high_value_events_per_connection.
tls string Yes in the shipped section Keep Yes; the service speaks TLS.
config string none Path to a JSON file as described above.

Values of macaroon_policy, wallet_state and post_init_view are case-insensitive; an invalid value falls back to the default with a logged warning.

JSON file keys (top level):

Key Type Default Description
seed string "" (derived per agent) Pins the node identity and synthetic chain data.
lure object see description onchain_confirmed_sat (412853), onchain_unconfirmed_sat (0), channels (list of channel objects) and peer_onion_addresses.
node object see description color, features, num_peers, num_channels, num_closed_channels, num_pending_channels, graph_num_nodes, graph_num_channels, graph_total_capacity_sat.
chain object mainnet anchor anchor_height, anchor_time, block_interval_seconds (604), network. Shares the anchor with the bitcoin persona of BitcoinRPC_tcp.
limits object see below Resource and rate limits; positive numbers only, invalid values are ignored with a warning.

The bundled document also carries version, getinfo_version, wallet, fixtures and templates (response bodies); these merge the same way and are not intended as options.

Commonly set limits keys: max_connections 512, max_connections_per_source 32, max_requests_per_connection 1000, max_secret_chars 4096 (credentials are logged in full up to this length), info_field_max_chars 4096, max_high_value_events_per_connection 200, max_routine_events_per_connection 1000, high_value_events_per_source_per_minute 60, routine_events_per_source_per_minute 120, unlock_failure_delay_seconds 1.0, init_wallet_delay_seconds 2.2, connect_peer_delay_seconds 3.0. The bundled limits object also holds the transport and session bounds (max_header_bytes, max_chunk_line_bytes, request_deadline_seconds, max_requests_per_read, max_unflushed_bytes, max_tx_event_bytes, max_stream_seconds, max_sessions, max_session_invoices, max_session_root_keys, max_session_macaroons, max_payment_request_chars, max_mnemonic_words, max_rate_entries, routine_events_per_second, high_value_events_per_second, genseed_delay_seconds, wallet_startup_seconds).

INFO Events

Every event carries event_type, schema_version: 1, method, path and wallet_state (under wallet_state = none also wallet_initialized and post_init_view). Only the agent's own address is scrubbed; node public keys, hosts, invoice destinations and payout addresses are preserved. Macaroons, wallet passwords, mnemonics and passphrases are recorded in full.

Event Description
macaroon_presented One per request carrying a Grpc-Metadata-macaroon header (and one with missing: true per protected request without it): the macaroon, its parsed identifier, root key id, permissions and caveats, whether it was accepted, and credential_source (lure, policy, init, rejected, malformed or missing).
wallet_unlock_attempt A call to unlockwallet, changepassword or genseed: the passwords, recovery window, aezeed passphrase and the response given.
wallet_init_attempt A call to initwallet: the mnemonic and its validity, aezeed passphrase, wallet password, extended master key, channel backups and the response given.
payment_attempt A payment or invoice decode (router_send, sendpayment_sync, sendtoroute_sync, payreq_decode): the payment request with its decoded BOLT11 fields, keysend fields, fee limit and result.
onchain_send_attempt sendcoins or sendmany: destination address and its validity and network, amount, fee rate and result.
channel_action Channel open or close, or peer connect or disconnect: node public key, host as sent, funding amount, channel point and result.
macaroon_bake_attempt Macaroon bake, delete or list: requested permissions, root key id and the macaroon returned.
rest_call Every request: route pattern (raw path for unknown paths, 256 characters), authenticated, known, status and a per-connection count.
events_dropped Marker that events were dropped by a rate limit.

LPD_tcp

A low interaction TCP Line Printer Daemon (LPD) service (RFC 1179). LPD is a legacy print-spooling protocol commonly found on embedded network printers, older UNIX hosts, and industrial print servers. Captures submitted print jobs, including job metadata (hostname, user, job name) and print data format.

Example service configuration:

[LPD]
plugin      = LPD_tcp
low_port    = tcp:515
port        = tcp:515
description = LPD service.
enabled     = Yes
config      = /etc/honeydb/lpd.json

Config

Key Type Default Description
save_jobs bool false Write received print job files to disk.
upload_dir string /tmp/honeydb/var/uploads/print_jobs Directory for saved print job files and metadata. Only used when save_jobs is true.

INFO Events

Event Description
job_info Captures print-job metadata from the control file (hostname, user, job name, source filename, queue).
data_info Captures the print-job data summary (detected print format and data size).
unexpected_queue Fires when a job targets a print queue name not in the known-queues list.

Memcached_tcp

A low interaction TCP Memcached service. Accepts connections and returns plausible Memcached text-protocol responses without storing any data. Captures which cache keys clients probe, write attempts, and destructive commands such as flush_all.

Example service configuration:

[Memcached]
plugin      = Memcached_tcp
low_port    = tcp:11211
port        = tcp:11211
description = Send basic memcached replies.
enabled     = Yes
config      = /etc/honeydb/memcached.json

Config

Key Type Default Description
version string "1.6.12" Memcached version string returned in VERSION and STATS responses.

INFO Events

Event Description
memcached_keys_probed Captures a read command (get/gets) and the keys requested.
memcached_write_attempt Captures a write command (set/add/replace/append/prepend) and its key/storage metadata.
memcached_flush Captures a flush_all command and its optional delay.

Modbus_tcp

A low interaction TCP Modbus service. Emulates a Modbus TCP PLC with selectable vendor profiles, handling the common read/write function codes and device identification requests. Captures register/coil read and write attempts and detects scanning behavior (sequential address walks, multi-function-code enumeration).

Example service configuration:

[Modbus]
plugin      = Modbus_tcp
low_port    = tcp:502
port        = tcp:502
description = Modbus service.
enabled     = Yes
config      = /etc/honeydb/modbus.json

Config

Key Type Default Description
vendor_profile string "abb" Profile key: abb, schneider, siemens, allen_bradley, or generic.
vendor_name string (from profile) Override vendor name from profile.
product_code string (from profile) Override product code from profile.
product_name string (from profile) Override product name from profile.
model_name string (from profile) Override model name from profile.
major_minor_revision string (from profile) Override firmware revision from profile.
vendor_url string (from profile) Override vendor URL from profile.
user_application_name string (empty) Override user application name from profile.
holding_registers object — Map of address string → value string to pre-set holding register values.
input_registers object — Map of address string → value string to pre-set input register values.
coils object — Map of address string → value string (0 or 1) to pre-set coil values.
discrete_inputs object — Map of address string → value string (0 or 1) to pre-set discrete input values.

Vendor profiles:

Profile Key Vendor Product Revision
abb ABB AC500 3.0.2
schneider Schneider Electric Modicon M340 2.6.1
siemens Siemens SIMATIC S7-1200 4.4.0
allen_bradley Rockwell Automation MicroLogix 1400 21.003
generic Generic PLC Generic PLC 1.0.0

INFO Events

Event Description
function_code Captures a valid Modbus function-code request (FC, name, unit/transaction IDs, request parameters).
write_attempt Captures a write function code that modifies the simulated data store.
scan_pattern Fires on detected scanning behavior (sequential address walk or multi-function-code enumeration).
parse_error Fires when a frame fails to parse; captures the raw hex of the offending PDU.

MoneroRPC_tcp

A high interaction TCP service that emulates the HTTP JSON-RPC interfaces of a Monero node: monerod v0.18.5.3 (unrestricted, or in the restricted public-node form) and monero-wallet-rpc v0.18.5.1 with an open, funded wallet. Status lines, headers, JSON layout and error codes follow real captures, including epee quirks. The service captures mining redirection, transfers, key and seed requests, wallet open and restore attempts, daemon redirection, daemon administration calls and submitted raw transactions. Nothing is executed or relayed: requests are accepted and remembered per source address in memory only, no transaction or block is sent anywhere, and the service opens no outbound connection and writes no file. Lure keys derive from the agent seed and are never funded.

Example service configuration:

[MoneroRPC]
plugin      = MoneroRPC_tcp
low_port    = tcp:18081
port        = tcp:18081
description = monerod JSON-RPC (unrestricted).
enabled     = Yes
persona     = daemon

Default sections (all ship with enabled = No):

Section Port Persona Notes
[MoneroRPC] 18081 daemon Unrestricted monerod.
[MoneroRPC.restricted] 18089 daemon_restricted Public-node form: hidden methods answer -32601, hidden endpoints 404, /get_transactions capped at 100 hashes.
[MoneroRPC.wallet] 18082 wallet monero-wallet-rpc with an open, funded wallet of two accounts.

The shipped sections set no option other than persona, so HTTP digest authentication is off and no rpc_auth_attempt events occur until rpc_login is enabled. The plugin is plain HTTP; there is no tls option. The ports do not conflict with another shipped section.

Config

A config JSON file is a partial document containing only the keys to change, merged over the bundled document. The merge is shallow: limits and chain are merged one level (a key you give replaces the same key; nested values such as chain.fees are replaced whole), seed and weak_credentials are replaced whole, and personas is merged by persona name with each persona's top-level keys replaced. No file ships in packages; create your own.

Service section keys:

Key Type Default Description
persona string daemon daemon, daemon_restricted or wallet. Case-insensitive. Falls back to the file's persona, then the bundled persona, then daemon; an unknown value uses daemon with a logged warning.
rpc_login flag no yes presents HTTP digest authentication (realm monero-rpc), as --rpc-login does. Accepts yes/true/1/on and no/false/0/off.
auth_policy string list Which digests are accepted: list (the weak_credentials pairs), after_n_attempts (any valid digest after auth_after_n failures from that source) or never. Only used with rpc_login.
auth_after_n int 3 Failures before after_n_attempts accepts. Minimum 1.
key_policy string synthetic synthetic: query_key returns the lure seed and keys. error: query_key is hidden (-32601), as under --restricted-rpc.
wallet_password_policy string any Which passwords open_wallet accepts for the lure wallet: any, list (only weak_credentials passwords, or one set by change_wallet_password in the session; the lure wallet's own password is the empty string, so an empty password also opens it) or never. Wallets the session created, restored or generated always open with their own password.
wallet_dir string /home/monero/wallet Directory quoted in open_wallet's "file not found" text.
config string none Path to a JSON file as described above. The bundled document is always loaded first.

An invalid value for any option is replaced by its default with a logged warning.

JSON file keys:

Key Type Default Description
persona string daemon Persona used when the section has no persona.
seed string "" (derived from agent identity) Pins the chain and lure keys. When empty and no stable host identity exists, they change on every restart (a warning is logged).
weak_credentials list ten user and password pairs Pairs accepted by auth_policy = list and wallet_password_policy = list.
limits object see below Resource and rate limits.
chain object mainnet anchor anchor_height, anchor_timestamp, anchor_difficulty, block_interval (120 s), fees, hard_forks, peer and rate values. One block is produced per interval from the anchor.
personas object three personas Per-persona overrides, for example wallet_dir or the wallet account balances.

Commonly set limits keys: max_request_bytes 1048576, max_requests_per_connection 1000, idle_timeout_seconds 30, max_sessions 4096, session_ttl_seconds 86400, max_high_value_events_per_connection 64, max_routine_events_per_connection 200, high_value_events_per_source_per_minute 60, routine_events_per_source_per_minute 120, auth_events_per_source_per_minute 300, info_field_max_chars 8192, cve_26819_min_requests 64. The bundled limits object also holds transport, response-size, session-count and per-call bounds not listed here.

INFO Events

Every event is JSON with event_type, schema_version and persona. Only the agent's own address is scrubbed; miner and destination addresses, banned hosts and bootstrap-daemon targets are preserved. Passwords, seeds and keys are recorded in full up to 1024 characters.

Event Description
client_fingerprint User-Agent, path, HTTP method, auth scheme, JSON-RPC version and content type.
rpc_call Method (JSON-RPC method or plain path), parameter count, batch size, count and whether the method is known.
rpc_auth_attempt A digest authentication attempt (only with rpc_login): username, realm, URI, nonce, response, whether it was accepted and credential_source.
mining_redirect_attempt /start_mining, a wallet start_mining or the wallet address in get_block_template: miner address and its validity, threads and background-mining flags.
transfer_attempt transfer, transfer_split, sweep_all, sweep_single or sweep_dust: destinations with amounts and address validity, priority, ring size, payment id and result.
key_exfil_attempt query_key, export_key_images, export_outputs, prepare_multisig, transaction key or proof requests and signing: the key type or signature type, policy and result.
raw_transaction /send_raw_transaction or block submission: transaction hex (truncated), validity, transaction id and result.
wallet_open_attempt open_wallet, create_wallet, generate_from_keys or change_wallet_password: filename, passwords, view and spend keys, address and whether the path attempted traversal.
seed_restore_attempt restore_deterministic_wallet: the submitted seed in full, seed offset, password, restore height and whether the seed is valid (25, 24, 13, 12 or invalid).
daemon_redirect_attempt set_daemon or /set_bootstrap_daemon: target address, credentials, trust, SSL and proxy settings.
daemon_admin_call Bans, log level, peer and bandwidth limits, flush_txpool, flush_cache, /update, /save_bc, /set_log_categories, /set_log_hash_rate, /pop_blocks, /stop_daemon and the wallet's stop_wallet: the parameters sent.
events_dropped Marker that events were dropped by a rate limit.
cve_attempt Canonical CVE detection event, see CVEs Detected.

CVEs Detected

CVE Short name Detection
CVE-2025-26819 monero_rpc_response_exhaustion A client floods requests without reading the replies, as monerod 0.18.3.4 and earlier kept every response in memory. Emitted once per connection when the write buffer fills after at least cve_26819_min_requests answered requests.

MOTD_tcp

A low interaction TCP Message Of The Day (MOTD) service. On connect, sends a banner selected at random from the configured list (or built-in IoT/embedded-device defaults: OpenWrt router, Hikvision IP camera, Synology NAS, Home Assistant hub) and closes the connection.

Example service configuration:

[MOTD]
plugin      = MOTD_tcp
low_port    = tcp:8
port        = tcp:8
description = Send a message via tcp and close connection.
enabled     = Yes

Config

Key Type Default Description
banners list built-in IoT list Banner strings to send on connect. One is selected at random per session.
detect_scanner_fingerprints bool true Enable scanner-attribution INFO events.
detect_credential_like bool true Enable credential-shape INFO events.
event_field_max_bytes int 1024 Per-string byte truncation cap inside event payloads.
override_name bool false When false, the service is reported as "MOTD" to normalize naming with MOTD_udp.
{
  "banners": [
    "My Custom Device v1.0\r\n",
    "Another Device Banner\r\n"
  ]
}

INFO Events

Event Description
scanner_fingerprint Fires when received bytes match a known scanner fingerprint.
credential_like_string Fires when received bytes contain credential-like strings.

MOTD_udp

A low interaction UDP Message Of The Day (MOTD) service. Replies to each received datagram with a banner selected at random from the configured list (or built-in IoT/embedded-device defaults: OpenWrt router, Hikvision IP camera, Synology NAS, Home Assistant hub).

Example service configuration:

[MOTD.udp]
plugin      = MOTD_udp
low_port    = udp:8
port        = udp:8
description = Send a message via udp.
enabled     = Yes

Config

Key Type Default Description
banners list built-in IoT list Banner strings to send in reply. One is selected at random per datagram.
detect_scanner_fingerprints bool true Enable scanner-attribution INFO events.
detect_credential_like bool true Enable credential-shape INFO events.
event_field_max_bytes int 1024 Per-string byte truncation cap inside event payloads.
override_name bool false When false, the service is reported as "MOTD" to normalize naming with MOTD_tcp.

INFO Events

Event Description
scanner_fingerprint Fires when received datagram bytes match a known scanner fingerprint.
credential_like_string Fires when received datagram bytes contain credential-like strings.

MQTT_tcp

A low interaction TCP MQTT service. Emulates an MQTT broker that accepts all connections, capturing credentials, topic subscriptions, published payloads, and known IoT device patterns (Home Assistant, Tasmota, Zigbee2MQTT, Shelly, and others) from connecting clients.

Example service configuration:

[MQTT]
plugin      = MQTT_tcp
low_port    = tcp:1883
port        = tcp:1883
description = MQTT
enabled     = Yes

INFO Events

Event Description
connect Captures a CONNECT packet (client ID, protocol version, supplied/absent credentials).
will Captures a declared Last Will (topic, message size/preview).
subscribe Captures a SUBSCRIBE (topic, wildcard flag, known IoT topic pattern).
publish Captures a PUBLISH (topic, payload size/preview, known IoT topic pattern).
large_message Fires when a publish message exceeds the logging cap (total/logged/dropped bytes).
disconnect Fires on a DISCONNECT packet.

MSSQL_tcp

A low interaction TCP Microsoft SQL Server service using the TDS protocol. Handles client PRELOGIN and LOGIN7 handshakes and captures SQL and Windows (NTLM) credentials. When configured with allow_login: true, it accepts a fake login and also captures post-authentication SQL queries, stored procedure calls, attack patterns (such as xp_cmdshell usage), and known attack tool fingerprints.

Example service configuration:

[MSSQL]
plugin      = MSSQL_tcp
low_port    = tcp:1433
port        = tcp:1433
description = MSSQL server
enabled     = Yes
config      = /etc/honeydb/mssql.json

Config

Key Type Default Description
mssql_version string "0f000000" Single SQL Server version hex string advertised in PRELOGIN. Ignored if mssql_versions is set.
mssql_versions list (built-in pool) Pool of version strings; one is selected at random per connection. The built-in pool covers SQL Server 2012–2022.
server_name string "CustomerDB" Server name returned in TDS error tokens.
allow_login bool false If true, all login attempts are granted a fake successful login and post-auth queries are captured.

Version hex string reference:

SQL Server Version Hex string
2012 (v11) 0b000000
2014 (v12) 0c000000
2016 (v13) 0d000000
2017 (v14) 0e000000
2019 (v15) 0f000000
2022 (v16) 10000000

INFO Events

Event Description
prelogin Captures a parsed PRELOGIN packet and the client's pre-login options.
advertised_version Records the server version advertised back during pre-login.
client_login Captures a parsed LOGIN7 packet (login details, auth type, result).
ntlm_auth Captures NTLM authentication data (domain, username, workstation) from a Windows-auth login.
query Captures the decoded SQL text of a client batch query.
rpc Captures a parsed RPC request (procedure name, first string parameter).
attack_pattern Fires when query/RPC text matches an attack pattern (xp_cmdshell, sp_configure, UNC injection, enumeration).
tool_fingerprint Fires when the client app/library name matches a known tool fingerprint.
parse_error Fires when a TDS header or packet fails to parse.

MySQL_tcp

A low interaction TCP MySQL service. Emulates a MySQL 5.7/8.x server and simulates a complete authenticated session — every login is accepted — to capture credentials, post-login SQL queries, attack patterns (file read/write, UDF code execution, schema enumeration), and attack tool fingerprints (sqlmap, metasploit, hydra, and others).

Example service configuration:

[MySQL]
plugin      = MySQL_tcp
low_port    = tcp:3306
port        = tcp:3306
description = MySQL server
enabled     = Yes
config      = /etc/honeydb/mysql.json

Config

Key Type Default Description
mysql_version string (uses pool) Single version string to advertise in the server greeting.
mysql_versions list built-in pool Pool of version strings to randomize from per connection — takes precedence over mysql_version.
os_version string "ubuntu0.20.04.3" OS suffix appended to the version string in the greeting.
{
    "mysql_versions": ["8.0.32", "8.0.36", "5.7.44-log"],
    "os_version": "ubuntu0.22.04.1"
}

INFO Events

Event Description
client_info Captures client handshake-response info during login.
credentials Captures the username and auth data from the client login.
query Captures the scrubbed SQL text of a COM_QUERY.
db_change Captures a database switch (COM_INIT_DB) and the target database.
unknown_command Fires on an unrecognized MySQL command byte.
attack_pattern Fires when query text matches a known attack pattern.
tool_fingerprint Fires when a client name or query matches a known tool fingerprint.
parse_error Fires when a packet fails to parse.

NTP_udp

A low interaction UDP NTP service. Emulates a stratum-2 NTP server, responding to standard NTP client requests. Detects NTP Mode 7 monlist requests associated with the CVE-2013-5211 NTP amplification DDoS attack.

Example service configuration:

[NTP]
plugin      = NTP_udp
low_port    = udp:123
port        = udp:123
description = NTP service.
enabled     = Yes

INFO Events

Event Description
ntp_mode7 Fires on an NTP Mode 7 private-mode packet; tags CVE-2013-5211 on monlist request codes.
ntp_client_info Captures a parsed standard NTP request (client version, mode, stratum).
ntp_error Fires when packet parsing raises an error.

Oracle_tcp

A low interaction TCP Oracle Database service. Emulates an Oracle TNS listener, capturing connect strings, client versions, privilege escalation attempts (AS SYSDBA/AS SYSOPER), and login credentials. When allow_login is enabled, it simulates a successful login and captures post-authentication SQL and attack patterns. Detects CVE-2012-1675 (TNS Poison) indicators.

Example service configuration:

[Oracle]
plugin      = Oracle_tcp
low_port    = tcp:1521
port        = tcp:1521
description = Oracle TNS listener
enabled     = Yes
config      = /etc/honeydb/oracle.json

Config

Key Type Default Description
oracle_version string "19.0.0.0.0" Oracle version string included in the banner and ACCEPT packet.
oracle_os string "Linux" OS label in the banner string (Linux or Windows).
allow_login bool true When true, simulate a successful login and capture post-auth activity. When false, reject with ORA-01017 immediately after credentials are captured.
timeout int 30 Seconds before closing a connection that has not completed authentication.
post_auth_timeout int 30 Seconds of inactivity after authentication before closing.

INFO Events

Event Description
connect_info Captures a TNS CONNECT (service name, client id, username, raw connect string).
cve Fires when the service name matches CVE-2012-1675 (TNS Poison) indicators.
privilege_escalation Fires when a connect string requests SYSDBA or SYSOPER privileges.
client_version Captures the decoded client version when present in the connect string.
auth_attempt Captures the submitted username and password.
post_auth_command Captures a post-auth SQL statement (type, raw SQL, tables, columns).
attack_pattern Fires when post-auth SQL matches a known Oracle attack pattern.
post_auth_summary Reports the count of post-auth packets seen at timeout or connection close.

POP3_tcp

A low interaction TCP POP3 service. Attracts credential-stuffing attacks, automated mail-client probes, and post-authentication enumeration activity. Captures usernames, passwords, and message retrieval activity.

Example service configuration:

[POP3]
plugin      = POP3_tcp
low_port    = tcp:110
port        = tcp:110
description = POP3 service.
enabled     = Yes
config      = /etc/honeydb/pop3.json

Config

Key Type Default Description
server_name string "localhost" Hostname shown in the POP3 greeting.
version_string string "POP3 server ready" Banner string appended to the greeting.
valid_passwords list ["admin","letmein","password123","password"] Passwords accepted for any username.
capabilities list ["USER","UIDL","TOP"] Capabilities advertised by the CAPA command.

INFO Events

Event Description
username Captures the username from the USER command.
credentials Captures the username/password pair from the PASS command.
pop3_retr Captures the message number from a RETR command.
pop3_uidl Captures the message number from a UIDL command.
pop3_top Captures the message number and requested line count from a TOP command.

PostgreSQL_tcp

A low interaction TCP PostgreSQL service (wire protocol v3). Captures credential spray attempts, client tool fingerprints (hydra, nmap, sqlmap, metasploit, and others), and — when allow_login is enabled — post-authentication queries and attack patterns, including CVE-2019-9193 (COPY ... FROM PROGRAM) attempts.

Example service configuration:

[PostgreSQL]
plugin      = PostgreSQL_tcp
low_port    = tcp:5432
port        = tcp:5432
description = PostgreSQL server
enabled     = Yes
config      = /etc/honeydb/postgresql.json

Config

Key Type Default Description
pg_version string "14.2" PostgreSQL version string advertised after login and embedded in auth failure messages.
os_version string "14.2-1.pgdg20.04+1" OS suffix appended to the version string as (Ubuntu <os_version>). Leave empty to omit.
max_connections int 100 Advertised after successful auth (allow_login mode).
allow_login bool false When true, authentication succeeds (fake) and the session advances to query capture mode. When false, authentication always fails after capturing credentials.

INFO Events

Event Description
startup_info Captures a valid startup message (user, database, encoding, application_name, protocol version).
tool_detection Fires when the application_name matches a known client/scanner fingerprint.
auth_attempt Captures a password message (user, database, submitted password).
query Captures the SQL text of a simple Query message.
attack_pattern Fires when query SQL matches a detected attack pattern.
unexpected_message Fires when a non-password message arrives during the auth phase.
parse_error Fires on an oversized or malformed startup/password/query message.

ProConOs_tcp

A low interaction TCP ProConOs service. Emulates a Phoenix Contact ProConOs PLC runtime — the environment used by Phoenix Contact Inline, AXC, and RFC series PLCs — with selectable device profiles. Captures device identification probes, project info queries, and high-severity PLC start/stop control attempts.

Example service configuration:

[ProConOs]
plugin      = ProConOs_tcp
low_port    = tcp:20547
port        = tcp:20547
description = ProConOs PLC runtime service.
enabled     = Yes
config      = /etc/honeydb/proconos.json

Config

Key Type Default Description
device_profile string "il_2050_me" Profile key; selects all identity strings as a group. One of il_2050_me, axc_f_2152, rfc_460r, generic.
ladder_runtime string (from profile) ProConOs runtime version string returned in the identify response.
plc_type string (from profile) PLC model and firmware string returned in the identify response.
project_name string (from profile) Project name returned in identify and project info responses.
boot_project string (from profile) Boot project name returned in identify and project info responses.
project_source string "n/a" Project source returned in identify and project info responses.
plc_state string (from profile) PLC operating state (RUN, STOP, or HALT).
probe_threshold int 3 Number of commands in one session before a scan-pattern INFO event fires.

Device profiles:

Profile Key PLC Type Project State
il_2050_me IL 2050 ME V 3.95A.6 QuickMix RUN
axc_f_2152 AXC F 2152 V 2.0.4 MainProcess RUN
rfc_460r RFC 460R PN 3TX V 5.20 WaterControl STOP
generic Generic PLC V 1.0 Project RUN

INFO Events

Event Description
identify Fires on an IDENTIFY (device fingerprint) request.
plc_state_query Fires on a PLC state query.
project_info Fires on a project-info request.
write_attempt Fires on a PLC start/stop control command (high severity).
unknown_command Fires on an unrecognized command byte; captures the byte and raw hex.
scan_pattern Fires when the per-session command count reaches the probe threshold.
parse_error Fires on a buffer-overflow or frame-dispatch error; captures the raw hex.

Random_tcp

A low interaction TCP service that responds with random data. Responds to any inbound connection with a burst of random base64-encoded data, and keeps the connection open — replying to each client payload with a fresh random blob — to engage slow/persistent probers until the client disconnects or the per-session exchange limit is reached.

Example service configuration:

[Random]
plugin      = Random_tcp
low_port    = tcp:2048
port        = tcp:2048
description = Send random data via tcp.
enabled     = Yes

Config

Key Type Default Description
max_exchanges int 100 Maximum number of exchanges per session. When reached, the server sends one final random response and closes the connection.

RAW_tcp

A low interaction TCP JetDirect (RAW printing) service. Captures print jobs sent to the printer port, detects the print data format (PDF, PostScript, PCL, PJL, and others), extracts PJL job metadata, and detects abuse patterns and CVE exploit indicators (CVE-2024-47076, CVE-2024-47177).

Example service configuration:

[RAW]
plugin      = RAW_tcp
low_port    = tcp:9100
port        = tcp:9100
description = JetDirect raw printing service.
enabled     = Yes
config      = /etc/honeydb/raw.json

Config

Key Type Default Description
upload_dir string "var/uploads/print_jobs" Directory where captured print job files and metadata are saved.
banner string (none) Bytes sent to the client on connect. Preset values: "hp_laserjet", "brother", "xerox". Any other non-empty string is sent verbatim. Omit or set to empty to send nothing (default).
tag_known_cves bool true Enable CVE pattern detection events.

INFO Events

Event Description
print_format Captures the detected print format of each print job (PJL, PostScript, PCL, etc.).
pjl_job_name Captures the job name from a PJL JOB NAME directive.
pjl_username Captures the username from a PJL JOB/SET directive.
pjl_info_probe Fires on a PJL INFO/ECHO probe directive.
pjl_filesystem_access Fires on a PJL filesystem-access command.
postscript_dangerous_operator Fires when a dangerous PostScript operator appears in a job.
cve_attempt Fires on path traversal in a PJL FS command (CVE-2024-47076) or Foomatic RIP shell injection in a PJL directive (CVE-2024-47177).

RDP_tcp

A low interaction TCP RDP service. Emulates the RDP connection handshake (X.224, TLS upgrade, MCS channel negotiation) to maximize credential capture, then terminates the connection after the client submits credentials. Captures requested security protocols, routing cookies, and submitted domain/username/password values. Detects CVE-2019-0708 (BlueKeep) exploit attempts.

Example service configuration:

[RDP]
plugin      = RDP_tcp
low_port    = tcp:3389
port        = tcp:3389
description = RDP service.
enabled     = Yes

INFO Events

Event Description
cookie Captures the mstshash routing-cookie identifier when present.
requested_protocols Captures the requested security protocols from the RDP negotiation request.
cve Fires when BlueKeep (CVE-2019-0708) ms_t120 channel binding is detected.
credentials Captures the domain, username, and password from the Info PDU.

Redis_tcp

A low interaction TCP Redis service. Emulates a Redis 7.2.4 server, capturing authentication attempts, configuration changes, Lua script execution, replication commands, and module load attempts. Detects known Redis attack patterns including CVE-2022-0543 (Lua sandbox escape), config-based RCE, and module-based RCE.

Example service configuration:

[Redis]
plugin      = Redis_tcp
low_port    = tcp:6379
port        = tcp:6379
description = Basic Redis
enabled     = Yes
config      = /etc/honeydb/redis.json

Config

Key Type Default Description
decoy_password string or null null Exact password that results in a fake authenticated session; null or empty disables the feature.

INFO Events

Event Description
auth_attempt Captures the password (and ACL username on Redis 6+) supplied with an AUTH command.
auth_result Fires when a submitted password matches the configured decoy password.
config_set Captures a CONFIG SET key/value; tags config-based RCE setups.
lua_script Captures an EVAL Lua script body. A sandbox-escape or overflow indicator is reported as a separate cve_attempt event.
script_load Captures a Lua script body from SCRIPT LOAD, inspected like lua_script.
evalsha Captures the SHA passed to EVALSHA.
slaveof Captures the host/port targeted by SLAVEOF/REPLICAOF.
slaveof_no_one Fires on SLAVEOF/REPLICAOF NO ONE (replication detachment).
module_load Captures a MODULE LOAD path used for module-injection RCE.
cryptomining_indicators Fires when a value written by SET, SETNX, GETSET, APPEND, SETEX, PSETEX, MSET or CONFIG SET contains mining pools, wallets or miner names (see Events). source_field is the lower-cased command, or config_set for CONFIG SET. Base64-wrapped payloads are unwrapped, and an identical finding on one connection is reported once.
dropper_indicators Fires when a value written by the same commands contains a download tool together with a URL, or a /dev/tcp host, the usual cron payload (see Events).
cve_attempt Fires on a CVE detection (see CVEs Detected below).

CVEs Detected

CVE Short name Detection
CVE-2022-0543 lua_sandbox_escape An EVAL or SCRIPT LOAD script contains package.loadlib, io.open, os.execute, os.popen or io.popen.
CVE-2024-31449 redis_lua_bit_tohex_overflow An EVAL or SCRIPT LOAD script calls bit.tohex(. When the second argument is an integer literal, an abnormal value is flagged. EVALSHA is not inspected.

SIP_udp

A low interaction UDP SIP service. Emulates a SIP registrar/proxy to capture toll fraud attempts, credential stuffing (Digest auth brute-forcing via REGISTER floods), and reconnaissance probes from automated scanners. Known SIP scanner tools (sipvicious, friendly-scanner, sipsak, and others) are detected and flagged.

Example service configuration:

[SIP]
plugin      = SIP_udp
low_port    = udp:5060
port        = udp:5060
description = Session Initiation Protocol (SIP) for voice and video calls.
enabled     = Yes
config      = /etc/honeydb/sip.json

Config

Key Type Default Description
server_header string "Asterisk PBX" Value sent in the SIP Server: response header. Set to match the identity of a real SIP server (e.g. "FreeSWITCH-mod_sofia/1.10.9", "Cisco-SIPGateway/IOS-12.x").

INFO Events

Event Description
sip_request Captures the method and key headers (User-Agent, From/To URI, Call-ID) of an incoming SIP request.
options_probe Fires on a SIP OPTIONS request.
sip_auth_attempt Captures Authorization/Proxy-Authorization credentials (scheme, username, realm, uri, algorithm).
abuse_pattern Fires when the User-Agent matches a known scanner/abuse pattern.

SMTP_tcp

A low interaction TCP SMTP service. Attracts credential-stuffing attacks, open-relay probes, email enumeration attempts, and malware delivery activity. Captures sender/recipient addresses, authentication credentials, and email headers, and detects open-relay probes, header injection, and known-bad EHLO strings.

Example service configuration:

[SMTP]
plugin      = SMTP_tcp
low_port    = tcp:25
port        = tcp:25
description = SMTP service.
enabled     = Yes
config      = /etc/honeydb/smtp.json

Config

Key Type Default Description
server_name string "localhost" Hostname in the banner and EHLO response; also used as the local domain for open-relay detection.
version_string string "ESMTP Exim 4.80" Version string appended to the banner.
{
    "server_name": "mail.example.com",
    "version_string": "ESMTP Exim 4.96"
}

INFO Events

Event Description
helo_domain Captures the domain argument from EHLO/HELO.
from_address Captures the sender from MAIL FROM.
to_address Captures the recipient from RCPT TO.
auth_type Records the requested AUTH mechanism (PLAIN/LOGIN).
auth_credentials Captures the username/password from an AUTH PLAIN or AUTH LOGIN attempt.
vrfy_address Captures the address probed via VRFY.
expn_list Captures the mailing list probed via EXPN.
email_header Captures selected DATA message headers (Subject, From, To, etc.).
abuse_type Fires on an open-relay probe, header injection, or known-bad EHLO string.

SNMP_udp

A low interaction UDP SNMP service (SNMPv1/v2c). Responds to GET, GETNEXT, GETBULK, SET, TRAP, and INFORM requests with a simulated Cisco IOS router MIB. Captures community strings, OID requests, SET write attempts, and MIB walk enumeration, and detects known CVE probe patterns (CVE-2002-0013, CVE-2017-6736/6737/6738).

Example service configuration:

[SNMP]
plugin      = SNMP_udp
low_port    = udp:161
port        = udp:161
description = SNMP service.
enabled     = Yes
config      = /etc/honeydb/snmp.json

Config

Key Type Default Description
mib_overrides dict {} Map of OID string → string value to override default MIB values (e.g. set a custom sysName or sysLocation).
community_string_length_threshold int 64 Byte length above which a community string triggers a CVE-2002-0013 probe event.
mib_walk_max_repetitions_threshold int 10 GETBULK max-repetitions value above which MIB walk detection fires.
mib_walk_getnext_count_threshold int 5 Cumulative GETNEXT count per source IP above which MIB walk detection fires.

Example override to rename the device:

{
  "mib_overrides": {
    "1.3.6.1.2.1.1.5.0": "edge-rtr-01",
    "1.3.6.1.2.1.1.6.0": "Data Centre A"
  }
}

INFO Events

Event Description
snmp_request Captures each SNMP request (version, community, PDU type, OIDs).
set_attempt Captures each varbind OID/value (and writability) on an SNMP SET.
mib_walk_detected Fires on a suspected MIB walk (high GETBULK max-repetitions or repeated GETNEXT).
cve_probe Fires on an oversized community string (CVE-2002-0013) or known Cisco CVE OID prefixes.

SolanaRPC_tcp

A medium interaction TCP service that emulates a Solana RPC node: JSON-RPC 2.0 over HTTP and PubSub over WebSocket. It answers as an Agave mainnet-beta RPC node, a solana-test-validator or Surfpool. It keeps a stateful synthetic chain and records who maps the node, which accounts and programs they watch, and every submitted transaction decoded to its fee payer, programs and transfer destinations. Transactions are accepted, decoded and tracked but never relayed, and the plugin makes no outbound connections. On mainnet the only funded accounts are this agent's own crypto lure keys, plus program accounts and the USDC mint; on test-validator and surfpool, airdropped keys also become funded. Every other public key is unfunded.

Example service configuration:

[SolanaRPC]
plugin      = SolanaRPC_tcp
low_port    = tcp:8899
port        = tcp:8899
description = Solana JSON-RPC node (Agave mainnet, solana-test-validator, Surfpool).
enabled     = Yes
persona     = mainnet

Default sections:

Section Port Persona Notes
SolanaRPC 8899 mainnet HTTP JSON-RPC.
SolanaRPC.ws 8900 mainnet PubSub WebSocket; sets transport = websocket.

Either section can run alone. The two sections share one node (chain state, slot and subscription IDs) only when their persona and seed are both the same, so give both the same persona.

Config

Service section keys

Key Type Default Description
persona string "mainnet" One of mainnet, test-validator, surfpool (case-sensitive), or a persona you add in the JSON file. Precedence: this key, then persona in the JSON file, then the built-in document, then mainnet. An unknown or invalid persona logs a warning and falls back to the built-in mainnet; the plugin still starts.
transport string "http" websocket (case-insensitive) makes the section the PubSub endpoint; any other value serves HTTP JSON-RPC.
config path none Optional JSON file of overrides.

The JSON file is a partial document containing only the keys to change; it is merged over the built-in document. The merge is by key: limits is merged key by key, seed is replaced, and a persona with the same name as a built-in one is replaced as a whole. No file ships in packages.

JSON file keys

Key Type Default Description
persona string "mainnet" Persona to use when the service section sets none.
seed string "" Seed for chain state and identities. An empty value derives it from the host identity; set it to pin state.
limits object see below Resource and event limits. Non-integer, non-positive or unknown values log a warning and keep the default.
personas object built-in personas Persona name to persona definition; add one or replace a built-in one by name.

A persona definition requires kind, version, feature_set, genesis_hash, cluster, anchor, slot_ms, epoch_schedule, skip_per_mille, transactions_per_slot, ledger_retention_slots, snapshot_interval_slots, airdrop, shred_version, cluster_nodes, vote_accounts, delinquent_vote_accounts, prioritization_fees, supply, inflation, max_tx_version_error and ws_server_header. Unknown keys are rejected, apart from the optional surfnet_version and cheatcodes. A rejected persona logs a warning and falls back to the built-in mainnet.

Limits (all under limits)

Key Default Description
max_request_bytes 51200 HTTP request body cap (Agave's own limit); larger bodies receive 413.
max_header_bytes 65536 Header block cap.
max_chunk_line_bytes 1024 Chunk size line cap.
idle_timeout_seconds 30 HTTP idle timeout.
request_deadline_seconds 60 Whole-request deadline.
max_requests_per_connection 1000 Keep-alive request cap.
max_requests_per_read 16 Pipelined requests handled per read.
max_unflushed_bytes 4194304 Abort a client that does not read its responses.
max_tx_event_bytes 65536 Cap on transaction event data.
max_batch 2048 Calls per batch.
capture_scan_limit 64 Members of an oversized batch still captured.
max_response_bytes 8388608 Encoded reply budget per request.
large_response_bytes 262144 Accepted and validated, but not read by any code path at this release; which calls count as large is fixed in the plugin.
large_responses_per_source_per_minute 2 Multi-megabyte replies (such as an unfiltered mainnet getLeaderSchedule) per source per minute; beyond that the call gets -32603.
ws_max_handshake_bytes 8192 WebSocket handshake cap.
ws_max_frame_bytes 65536 WebSocket frame cap.
ws_max_message_bytes 65536 WebSocket message cap.
ws_idle_timeout_seconds 300 WebSocket idle timeout.
ws_max_lifetime_seconds 3600 Maximum WebSocket connection lifetime.
ws_handshake_timeout_seconds 10 Time allowed to complete the handshake.
ws_max_unflushed_bytes 1048576 Abort a WebSocket client that does not read.
ws_max_tx_event_bytes 65536 Cap on transaction event data from notifications.
max_subscriptions_per_connection 64 Subscriptions per connection.
max_subscriptions_per_node 4096 Subscriptions per node.
max_ws_connections 256 Concurrent WebSocket connections.
max_notification_tx_events 20 Notifications per connection logged as transaction events; the rest are counted in the rpc_call summary.
max_signatures 4096 Submitted signatures tracked.
max_signature_bytes 4194304 Bytes of tracked signature data.
max_airdrop_entries 4096 Airdrop entries tracked.
max_rate_entries 8192 Source addresses tracked by rate limits.
info_field_max_chars 8192 Cap on bounded text fields in INFO events.
max_rpc_call_events_per_batch 32 rpc_call events per request body.
max_capture_events_per_batch 16 High-value events per request body.
max_rpc_call_summaries 32 rpc_call summaries emitted at disconnect.
max_routine_events_per_connection 200 Routine events per connection.
max_high_value_events_per_connection 64 High-value events per connection.
routine_events_per_source_per_minute 120 Routine events per source address per minute.
high_value_events_per_source_per_minute 60 High-value events per source address per minute.
routine_events_per_second 50 Routine events per second, plugin-wide.
high_value_events_per_second 20 High-value events per second, plugin-wide.

Personas

Persona Emulates Notes
mainnet Agave 4.3.0 on mainnet-beta Real mainnet genesis hash; requestAirdrop returns -32600, as on an RPC node without a faucet; getClusterNodes lists real public gossip entries plus synthetic validators.
test-validator solana-test-validator (Agave 4.3.0) Per-agent genesis hash and shred version; single-node cluster; pruned ledger; requestAirdrop succeeds and credits the balance.
surfpool Surfpool 1.6.0 (solana-core 4.2.1) Mainnet genesis; airdrop succeeds; accepts surfnet_* cheat codes.

The WebSocket endpoint supports slotSubscribe, rootSubscribe, accountSubscribe, programSubscribe, logsSubscribe and signatureSubscribe with their unsubscribe methods; any other method returns Method not found.

INFO Events

Every event carries event_type and schema_version. Only the agent's own address is scrubbed; attacker IPs and public keys are preserved. Lamport and token quantities are decimal strings.

Event Description
client_fingerprint First request on a connection, and again on HTTP whenever the path, user agent, origin, content type or JSON-RPC version changes: those fields plus transport (http or websocket).
rpc_call Each distinct method per request body with parameter count, batch size and whether the method is known; repeats are summarized per connection (and per WebSocket subscription).
transaction_submit sendTransaction or simulateTransaction: encoding, signature, fee payer, recent blockhash, program IDs, decoded transfers, approvals, authority changes, lookup tables, memos, compute budget settings and the raw transaction (up to 2048 characters).
airdrop_request requestAirdrop: public key and lamports.
account_query Account, program, token-account, signature-history and multi-account queries; a single-account query is recorded only when it names one of this agent's lure keys.
cheatcode_call A surfnet_* call: method and parameters.
subscription A WebSocket subscribe call: method and parameters.
snapshot_request A snapshot download request: path and kind (full, incremental, genesis or snapshot_file).
events_dropped A volume limit dropped events: scope, event class and count.

An unknown method (for example eth_chainId) returns -32601 and is still recorded.

SSH_tcp

A medium interaction TCP SSH service based on Cowrie. To authenticate, use the user root with almost any password; Cowrie's default user database refuses a few, such as root, 123456 and any password containing honeypot.

Example service configuration:

[SSH]
plugin      = SSH_tcp
low_port    = tcp:22
port        = tcp:22
description = SSH service.
enabled     = Yes

Config

These options are set in the service section of services.conf and are off by default. They require HoneyDB Agent 2.10.0 or later.

Key Type Default Description
persona string none Crypto node persona: ethereum, solana or bitcoin. See Crypto node persona below. An unknown value is ignored with a warning.
persona_hostname string eth-validator-NN, sol-validator-NN or btc-node-NN, by persona Hostname the persona shows. A single label of letters, digits and hyphens, up to 63 characters, with no leading or trailing hyphen. An invalid value is replaced by the default with a warning. NN is a two-digit number from 01 to 19 chosen once per agent.

Crypto node persona

Setting persona makes every session look like a blockchain node, so attackers hunting for wallets and keys have something to find.

[SSH]
plugin           = SSH_tcp
low_port         = tcp:22
port             = tcp:22
description      = SSH service.
enabled          = Yes
persona          = ethereum
persona_hostname = eth-rpc-2
Persona Default hostname Lure files under the session home (~) ps auxww shows
ethereum eth-validator-NN .ethereum/keystore/UTC--<ts>--<address> (Web3 secret-storage v3), validator_keys/keystore-m_12381_3600_0_0_0-<ts>.json (EIP-2335), .env, docker-compose.yml geth, lighthouse bn, lighthouse vc
solana sol-validator-NN .config/solana/id.json, validator-keypair.json, vote-account-keypair.json, .env, docker-compose.yml agave-validator
bitcoin btc-node-NN .bitcoin/wallet.dat, .bitcoin/bitcoin.conf (rpcuser/rpcpassword), .lnd/data/chain/bitcoin/mainnet/admin.macaroon, .env, docker-compose.yml bitcoind, lnd

The .env file depends on the persona. ethereum has PRIVATE_KEY, MNEMONIC, an RPC URL, KEYSTORE_PASSWORD, WALLET_ADDRESS and CHAIN_ID; solana has SOLANA_RPC_URL, SOLANA_KEYPAIR_PATH, a base58 PRIVATE_KEY and MNEMONIC; bitcoin has BITCOIN_RPC_URL, BITCOIN_RPC_USER, BITCOIN_RPC_PASSWORD, MNEMONIC and LND_MACAROON_PATH. The lure files are visible to ls, cat, find, stat, cp, tar, base64, scp and SFTP, and /etc/hostname shows the persona hostname.

  • Scope. The embedded Cowrie emulator is one per agent, so the persona applies to every SSH_tcp and Telnet_tcp service in the agent, including sections that do not set persona. The first section that sets persona also supplies persona_hostname. If two sections ask for different personas, the agent logs a warning and runs with no persona at all.
  • Synthetic material. The keys are generated locally on first run, are never funded, and are unique to each agent: a checksum-valid 24-word BIP-39 mnemonic, Ed25519 Solana keypairs, a Web3 keystore that decrypts to the .env private key, and an EIP-2335 keystore. HTTP_tcp serves the same material on its lure paths.
  • State directory. The material is kept in crypto-lures.json (mode 0600) in the state_dir set in the [agent] section of agent.conf, which defaults to the directory holding agent.conf. If that directory is not writable, the agent logs a warning and generates new material on every start. A store that fails validation is renamed to crypto-lures.json.bad-<timestamp> and regenerated.

INFO Events

SSH session INFO events are produced by the Cowrie bridge. Shell input is logged as RX events.

Event Description
login_success Captures the username and password of a successful login.
login_failed Captures the username and password of a failed login.
client_version Captures the SSH client version string.
client_fingerprint Captures the client public key (type and key) with its HASSH fingerprint.
client_key_exchange Captures the client's HASSH key exchange fingerprint.
client_terminal_size Captures the terminal width and height requested by the client.
client_request_env Captures an environment variable name and value requested by the client.
client_arch Captures the client architecture reported for the session.
file_download Captures the URL and hash of a file the attacker downloaded from the shell.
session_summary Captures the session duration in seconds.
cryptomining_indicators Fires when a shell command line contains mining pools, wallets or miner names (see Events). source_field is command. An identical finding is reported once per session. Downloads are reported as file_download, so no dropper_indicators event is emitted.
crypto_recon_command Fires, with or without a persona, when a command searches for wallets or keys. pattern is find_wallet_files, grep_key_material, list_wallet_dirs, node_cli or node_process_recon.
crypto_lure_access Fires only while a persona is active, when a command reads, copies, archives, encodes or sends a lure file (cat, cp, scp, tar, base64, curl, nc). lure_kind is eth_keystore, eth2_validator_keystore, bitcoin_wallet, bitcoin_conf, solana_keypair, lnd_macaroon, dotenv or docker_compose. SFTP downloads of a lure produce no event.
cve_attempt Fires on a CVE detection (see CVEs Detected below).

For crypto_recon_command and crypto_lure_access, command is capped at 1024 characters and path at 256, and each session reports an identical finding once and at most 32 events of these two types. Only the agent's own IP address is scrubbed, so attacker hosts in a command, such as the destination of an scp, are preserved.

CVEs Detected

CVE Short name Detection
CVE-2021-44228 log4shell_jndi Log4Shell JNDI lookup (${jndi:<scheme>://host/...}, plain or obfuscated) in the login username or password, shell input, the client version string or an environment request.
CVE-2025-32433 erlang_otp_ssh_preauth_channel Erlang/OTP SSH pre-authentication channel handling: a key exchange packet with an all-zero cookie, or an SSH connection-protocol message received before authentication succeeds.

SubstrateRPC_tcp

A high interaction TCP service that emulates the JSON-RPC server of a Substrate node (Parity Polkadot 1.24.2). One port serves both HTTP POST JSON-RPC and WebSocket JSON-RPC with subscriptions, as the real node does; the protocol is detected on connect. It answers as a Polkadot or Kusama mainnet node, as the same node started with --rpc-methods unsafe, or as polkadot --dev. It captures probes of validator infrastructure: session key insertions (with the secret URI), key rotations, reserved-peer changes, submitted extrinsics decoded to signer, destination and amount, and storage and runtime queries. Nothing is executed or relayed: state an attacker changes is kept per source address in memory only, signatures and balances are not checked, and the service opens no outbound connection. Real runtime metadata ships with the agent.

Example service configuration:

[SubstrateRPC]
plugin      = SubstrateRPC_tcp
low_port    = tcp:9944
port        = tcp:9944
description = Substrate / Polkadot JSON-RPC node (HTTP and WebSocket).
enabled     = Yes
persona     = polkadot

Default sections (all ship with enabled = No):

Section Port Persona Notes
[SubstrateRPC] 9944 polkadot HTTP and WebSocket.
[SubstrateRPC.legacy] 9933 polkadot The legacy HTTP port. Sections with the same persona share one emulated node, so a key inserted over 9933 is visible over 9944.

Keep tls = No: the real node speaks plain HTTP and WebSocket (TLS is added by a reverse proxy). The ports do not conflict with another shipped section.

Personas

Persona Emulates
polkadot Polkadot mainnet node. Unsafe RPC calls are rejected with the real error and still captured with accepted: false.
kusama Kusama mainnet node. Unsafe RPC calls are rejected and captured.
polkadot-unsafe A Polkadot node started with --rpc-methods unsafe: author_insertKey, author_rotateKeys, system_addReservedPeer and similar calls are accepted and captured.
dev polkadot --dev: unsafe RPC accepted and captured, two well-known development accounts (Alice and Bob).

Config

A config JSON file is a partial document containing only the keys to change, deep-merged over the bundled document: nested objects are merged key by key. The top-level keys accepted are persona, default_persona, seed, limits, personas, methods, unsafe_methods, unsafe_message, storage_keys and storage_labels; one unknown top-level key makes the whole document fall back to the built-in persona. No file ships in packages; create your own.

Service section keys:

Key Type Default Description
persona string polkadot polkadot, kusama, polkadot-unsafe or dev. The value is only trimmed, not lowercased: use the exact lowercase spelling. Falls back to the file's persona, then default_persona; an unusable name uses polkadot with a logged warning.
config string none Path to a JSON file as described above.
tls string No Leave at No.

JSON file keys:

Key Type Default Description
persona string none Persona used when the section has no persona.
default_persona string polkadot Persona used when neither the section nor the file names one.
seed string "" (derived per agent) Pins the node identity and chain data. When empty each agent derives its own, stable across restarts.
limits object see below Resource and rate limits. A value outside its allowed range is clamped with a logged warning.
personas object four personas Add or replace personas.

Commonly set limits keys (allowed range in parentheses):

Key Type Default Description
max_batch int 1000 Calls accepted in one batch (1 to 10000).
max_request_bytes int 1048576 Largest request body (1024 to 16777216).
max_subscriptions int 16 Subscriptions per connection (1 to 1024).
max_notifications_per_connection int 2000 Notifications sent before the connection is closed.
max_ws_connections int 64 Concurrent WebSocket connections.
max_ws_connections_per_source int 8 Concurrent WebSocket connections per source address.
max_requests_per_connection int 1000 Requests per HTTP connection.
idle_timeout_seconds int 30 HTTP idle timeout.
ws_idle_timeout_seconds int 300 WebSocket idle timeout.
ws_max_lifetime_seconds int 3600 Longest WebSocket connection lifetime.
large_responses_per_source_per_minute int 30 Rate limit for large replies such as metadata (about 0.9 MB each).
max_high_value_events_per_connection int 64 High-value events per connection.
max_routine_events_per_connection int 200 Routine events per connection.
high_value_events_per_source_per_minute int 60 High-value events per source per minute.
routine_events_per_source_per_minute int 120 Routine events per source per minute.
info_field_max_chars int 4096 Truncation of captured text fields. It does not govern suri, which is fixed at 4096 characters.

The bundled limits object also holds the remaining transport, WebSocket, session and rate bounds; values are clamped to their ranges.

INFO Events

Every event is JSON with event_type and schema_version: 1, and carries only what the client sent. accepted states whether the persona honours unsafe calls, not whether the call individually succeeded. Only the agent's own address is scrubbed; secret URIs, multiaddr hosts and peer ids, and signer and destination addresses are preserved.

Event Description
client_fingerprint Once per connection: User-Agent, Origin, path and transport (http or websocket).
rpc_call Each call: method, parameter count, batch size, count and whether the method is known.
key_insert_attempt author_insertKey: key type, secret URI in full (up to 4096 characters), public key and accepted.
key_rotate_attempt author_rotateKeys or author_rotateKeysWithOwner: method, owner and accepted.
key_query author_hasKey or author_hasSessionKeys: public key or session keys and accepted.
peer_add_attempt system_addReservedPeer or system_removeReservedPeer: multiaddr, peer id, host, host kind, port and transport protocols.
extrinsic_submit author_submitExtrinsic, author_submitAndWatchExtrinsic, transactionWatch_v1_submitAndWatch or transaction_v1_broadcast: decoded signer, signature type, nonce, tip, era, pallet and call, destination, amount and raw bytes.
extrinsic_query system_dryRun, system_dryRunAt, payment_queryInfo, payment_queryFeeDetails or the TransactionPaymentApi_query_info runtime call: the same decoded fields.
node_config_attempt Log filter changes, offchain storage writes and author_removeExtrinsic: method, parameters and accepted.
storage_query state_* and childstate_* storage, key, proof and call methods, and chainHead_v1_storage or chainHead_v1_call: keys, labels, accounts and block.
subscription Each subscribe method over WebSocket: method and parameters.
events_dropped Marker that events were dropped by a rate limit.

Telnet_tcp

A medium interaction TCP Telnet service. This service will provide generic guessable logins and emulate basic commands post login. It is based on the same embedded Cowrie emulator as SSH_tcp; to authenticate, use the user root with almost any password (Cowrie's default user database refuses a few, such as root, 123456 and any password containing honeypot).

Example service configuration:

[Telnet]
plugin      = Telnet_tcp
low_port    = tcp:23
port        = tcp:23
description = Telnet service.
enabled     = Yes

Config

These options are set in the service section of services.conf and are off by default. They require HoneyDB Agent 2.10.0 or later.

Key Type Default Description
persona string none Crypto node persona: ethereum, solana or bitcoin. See Crypto node persona below. An unknown value is ignored with a warning.
persona_hostname string eth-validator-NN, sol-validator-NN or btc-node-NN, by persona Hostname the persona shows. A single label of letters, digits and hyphens, up to 63 characters, with no leading or trailing hyphen. An invalid value is replaced by the default with a warning. NN is a two-digit number from 01 to 19 chosen once per agent.

Crypto node persona

Setting persona makes every session look like a blockchain node, so attackers hunting for wallets and keys have something to find.

[Telnet]
plugin           = Telnet_tcp
low_port         = tcp:23
port             = tcp:23
description      = Telnet service.
enabled          = Yes
persona          = ethereum
persona_hostname = eth-rpc-2
Persona Default hostname Lure files under the session home (~) ps auxww shows
ethereum eth-validator-NN .ethereum/keystore/UTC--<ts>--<address> (Web3 secret-storage v3), validator_keys/keystore-m_12381_3600_0_0_0-<ts>.json (EIP-2335), .env, docker-compose.yml geth, lighthouse bn, lighthouse vc
solana sol-validator-NN .config/solana/id.json, validator-keypair.json, vote-account-keypair.json, .env, docker-compose.yml agave-validator
bitcoin btc-node-NN .bitcoin/wallet.dat, .bitcoin/bitcoin.conf (rpcuser/rpcpassword), .lnd/data/chain/bitcoin/mainnet/admin.macaroon, .env, docker-compose.yml bitcoind, lnd

The .env file depends on the persona. ethereum has PRIVATE_KEY, MNEMONIC, an RPC URL, KEYSTORE_PASSWORD, WALLET_ADDRESS and CHAIN_ID; solana has SOLANA_RPC_URL, SOLANA_KEYPAIR_PATH, a base58 PRIVATE_KEY and MNEMONIC; bitcoin has BITCOIN_RPC_URL, BITCOIN_RPC_USER, BITCOIN_RPC_PASSWORD, MNEMONIC and LND_MACAROON_PATH. The lure files are visible to ls, cat, find, stat, cp, tar, base64, scp and /etc/hostname shows the persona hostname.

  • Scope. The embedded Cowrie emulator is one per agent, so the persona applies to every SSH_tcp and Telnet_tcp service in the agent, including sections that do not set persona. The first section that sets persona also supplies persona_hostname. If two sections ask for different personas, the agent logs a warning and runs with no persona at all.
  • Synthetic material. The keys are generated locally on first run, are never funded, and are unique to each agent: a checksum-valid 24-word BIP-39 mnemonic, Ed25519 Solana keypairs, a Web3 keystore that decrypts to the .env private key, and an EIP-2335 keystore. HTTP_tcp serves the same material on its lure paths.
  • State directory. The material is kept in crypto-lures.json (mode 0600) in the state_dir set in the [agent] section of agent.conf, which defaults to the directory holding agent.conf. If that directory is not writable, the agent logs a warning and generates new material on every start. A store that fails validation is renamed to crypto-lures.json.bad-<timestamp> and regenerated.

INFO Events

Telnet session INFO events are produced by the same Cowrie bridge as SSH_tcp, including the events below. Shell input is logged as RX events.

Event Description
login_success Captures the username and password of a successful login.
login_failed Captures the username and password of a failed login.
client_request_env Captures an environment variable name and value sent by the client during Telnet option negotiation (one event per variable).
file_download Captures the URL and hash of a file the attacker downloaded from the shell.
session_summary Captures the session duration in seconds.
cryptomining_indicators Fires when a shell command line contains mining pools, wallets or miner names (see Events). source_field is command. An identical finding is reported once per session. Downloads are reported as file_download, so no dropper_indicators event is emitted.
crypto_recon_command Fires, with or without a persona, when a command searches for wallets or keys. pattern is find_wallet_files, grep_key_material, list_wallet_dirs, node_cli or node_process_recon.
crypto_lure_access Fires only while a persona is active, when a command reads, copies, archives, encodes or sends a lure file (cat, cp, scp, tar, base64, curl, nc). lure_kind is eth_keystore, eth2_validator_keystore, bitcoin_wallet, bitcoin_conf, solana_keypair, lnd_macaroon, dotenv or docker_compose.
cve_attempt Fires on a CVE detection (see CVEs Detected below).

For crypto_recon_command and crypto_lure_access, command is capped at 1024 characters and path at 256, and each session reports an identical finding once and at most 32 events of these two types. Only the agent's own IP address is scrubbed, so attacker hosts in a command, such as the destination of an scp, are preserved.

CVEs Detected

CVE Short name Detection
CVE-2026-24061 telnet_auth_bypass Telnet authentication bypass: a username injected during Telnet option negotiation bypasses the password prompt. Indicators are injected_username, original_username and attempted_command.
CVE-2021-44228 log4shell_jndi Log4Shell JNDI lookup (${jndi:<scheme>://host/...}, plain or obfuscated) in the login username or password, shell input, the CVE-2026-24061 exploit fields, or any environment variable value (field env:<name>).
CVE-2000-0733 sgi_telnetd_format_string SGI IRIX telnetd format-string bug: a printf-style format-string payload (%n, a positional %N$ form, or two or more conversions such as %x%x) in a NEW-ENVIRON variable value, the login username or password, shell input, or the CVE-2026-24061 exploit fields (telnet.exploit_success); or a _RLD* environment variable carrying bin/sh.

TFTP_udp

A low interaction UDP TFTP service. Serves a configurable decoy file for any read request and accepts write uploads (logging the first bytes without writing to disk). Detects abuse patterns including path traversal and IoT firmware download attempts.

Example service configuration:

[TFTP]
plugin      = TFTP_udp
low_port    = udp:69
port        = udp:69
description = TFTP service.
enabled     = Yes
config      = /etc/honeydb/tftp.json

Config

Key Type Default Description
decoy_netascii string or null null Text content served for netascii read requests. Falls back to a built-in decoy file if absent.
decoy_octet string or null null Base64-encoded bytes served for octet read requests. Falls back to a built-in decoy file if absent.
upload_capture_bytes int 512 Maximum bytes captured from each upload for logging.
max_upload_size_bytes int 2000384 Maximum total upload size before an error packet is sent.
session_timeout_seconds int 60 Sessions with no activity for this many seconds are cleaned up.
max_active_sessions int 1000 Cap on concurrent tracked sessions.
iot_firmware_keywords list [] Additional filename keywords that trigger IoT firmware detection. Merged with the built-in list (firmware, boot.img, uimage, bzimage, vmlinuz, rootfs, kernel.img, factory.bin).

INFO Events

Event Description
get_file Captures the filename and mode from an RRQ (read request).
put_file Captures the filename and mode from a WRQ (write request).
upload_data Captures buffered hex of an uploaded file (blocks received, completion/truncation flags).
abuse_pattern Fires on path traversal, IoT firmware keywords, invalid transfer mode, or binary-in-netascii.
parse_error Fires when a datagram cannot be parsed; captures the error and raw hex.

VNC_tcp

A low interaction TCP VNC service (RFB protocol). Implements the RFB handshake (versions 3.3/3.7/3.8), configurable security-type negotiation, dictionary-attack VNC authentication, and a synthetic post-auth desktop served as a static screenshot. Captures handshake details, authentication attempts, and post-auth keyboard/mouse/clipboard activity. Detects CVE-2006-2369 (RealVNC authentication bypass) probes.

Example service configuration:

[VNC]
plugin      = VNC_tcp
low_port    = tcp:5900
port        = tcp:5900
description = Low interaction VNC service
enabled     = Yes
config      = /etc/honeydb/vnc.json

Config

Key Default Description
rfb_version "003.008" One of "003.003", "003.007", "003.008".
security_types_preset "honeypot-default" One of "tightvnc-like", "tigervnc-like", "realvnc-like", "honeypot-default".
security_types null Explicit list of security type integers (overrides preset when set).
server_name "ubuntu-server" Desktop name sent to the client.
framebuffer.width / framebuffer.height 1024 / 768 Synthetic framebuffer dimensions. Screenshot images that don't match are excluded at load time.
screenshots.directory null Directory of same-dimension images. One is picked per source IP, so the same scanner sees the same "desktop" across reconnects.
screenshots.path null Single image (alternative to directory).
screenshots.max_loaded 32 Cap on cached screenshot images.
password_wordlist_path null Optional path to a password wordlist used for VNC-Auth; falls back to an embedded ~100-entry default.
tcp_idle_timeout_seconds 60 Per-connection idle timeout.
max_message_bytes 8192 Per-message size cap.
max_buffer_bytes 65536 Per-connection buffer cap.
post_auth.framebuffer_enabled true Switch for serving the screenshot framebuffer.
post_auth.max_post_auth_messages_per_session 200 Cap on post-auth client messages per session.
structured_info_events true false falls back to human-readable INFO strings.
tag_known_abuse true false suppresses abuse-pattern events.

Security-type presets:

Preset Advertised types Emulates
tightvnc-like [16, 2] TightVNC server
tigervnc-like [2, 19] TigerVNC server
realvnc-like [2] RealVNC Free
honeypot-default [1, 2, 16, 19] Maximally attractive — all four probe surfaces

Note

Operator-supplied screenshot images are sent verbatim to attackers — never include real desktop content; use synthetic or generic images only.

INFO Events

Event Description
rfb_handshake Captures the server/client RFB versions and downgrade flag.
security_choice Captures the advertised security types and the selected type.
auth_attempt Captures the VNC-auth challenge/response and any matched wordlist password.
client_init Captures the ClientInit shared-desktop flag.
set_pixel_format Captures the client-supplied pixel format.
set_encodings Captures the client's advertised encoding list and total count.
framebuffer_update_request Captures the requested rectangle (x/y/w/h) and incremental flag.
key_event Captures keyboard events (keysym, down flag, ASCII).
pointer_event Captures pointer position and button mask.
client_cut_text Captures clipboard cut-text length and content.
abuse_pattern Fires on CVE/fingerprint probes (e.g. CVE-2006-2369) and malformed/oversize/unknown client messages.

XMRigAPI_tcp

A low interaction TCP service that emulates the HTTP API of an XMRig 6.26.0 CPU miner on Linux. It serves GET /1/summary, /2/summary, /2/backends, /1/config and /2/config, and accepts PUT or POST to the config paths (answered 204; the upload is stored per source IP, shown back on the next read, and its pool is reported as connected after settle_seconds). POST /json_rpc pause, resume and stop succeed and change that source's summary. Every Authorization header, uploaded config and pool in an upload is captured, which exposes cryptojacking hijack attempts. Nothing is executed or written to disk, no pool is contacted and no host name is resolved. State is kept in memory only.

Example service configuration:

[XMRigAPI]
plugin      = XMRigAPI_tcp
low_port    = tcp:44444
port        = tcp:44444
description = XMRig miner HTTP API.
enabled     = Yes
persona     = xmrig_6_26_linux
auth_mode   = any_token

XMRig has no default API port; 44444 is the port its documentation uses.

Authorization modes:

auth_mode Behavior
any_token No Authorization header gets 401. Any Bearer token is accepted and logged; a non-Bearer scheme gets 403.
token Only the access_token from the JSON file is accepted; other bearer tokens get 403.
restricted Reads work without a token; GET config and every write get 403. Any Authorization header gets 401.

In every mode that lets a write through (any_token and token), a write must carry exactly Content-Type: application/json; anything else, including application/json; charset=utf-8, gets 415.

The request body is captured before the reply is chosen, so a refused upload still yields pools and wallets. A config above max_config_bytes_per_source (16384) still gets 204 but is not stored.

Config

Service section keys:

Key Type Default Description
persona string xmrig_6_26_linux Miner persona, case-insensitive. xmrig_6_26_linux is the only persona shipped. An unknown name falls back to the default and logs a warning.
auth_mode string any_token any_token, token or restricted (case-insensitive). Overrides the JSON auth_mode. An unknown value falls back to any_token, as does token when no access_token is set.
config string none Path to a JSON file merged over the built-in document.

JSON file keys:

The file is a partial document containing only the keys to change, merged over the document built into the agent. The merge is shallow: a top-level key you supply replaces the built-in value, except that personas is merged by persona name, so a persona you define replaces the built-in persona of the same name as a whole. A supplied limits object replaces the built-in one, and any key it omits takes its default. No JSON file ships in packages.

Key Type Default Description
default_persona string xmrig_6_26_linux Persona used when the section does not set one.
seed string "" Seed for the per-agent identity. Empty derives it from the agent identity.
auth_mode string any_token Used when the service section sets no auth_mode.
access_token string "" Token accepted in token mode. This key is read only from the JSON file, never from services.conf.
personas object one built-in persona Miner definitions keyed by persona name, including default_config, the configuration the miner serves before any upload.
limits object see below Each value must be a positive number; an invalid value keeps its default.

Keys in limits (name and default): max_request_bytes 262144, max_header_bytes 16384, idle_timeout_seconds 15, request_deadline_seconds 30, max_requests_per_connection 1, max_connections 256, max_connections_per_source 16, max_sources 1024, source_ttl_seconds 86400, max_config_bytes_per_source 16384, max_pools_per_upload 16, max_info_events 200, max_api_request_events 50, max_scans_per_connection 16, info_events_per_minute_per_source 240, settle_seconds 20.

INFO Events

Only the agent's own address is scrubbed; attacker pools, hosts, wallets and tokens are preserved. Values are clipped to 512 characters. The envelopes cryptomining_indicators, dropper_indicators and info_event_cap_reached are emitted as described in the Events section. Under the per-source rate limit, routine miner_api_command events are dropped first.

Event Description
api_credential_presented An Authorization header: scheme, value, path and method.
config_write_attempt A PUT or POST to a config path, whatever the reply: size, SHA-256, whether it was authorized, pool count, the http and api settings, donate_level, and the top-level key names. parse_error is set only when the body fails to parse; valid JSON that is not an object is recorded raw without it. raw is capped at 2048 characters, and truncated and incomplete flags mark a body that was cut short.
pool_change_attempt One per pool in an uploaded config (first 16): URL, user, password, index and path, plus algorithm, coin, rig id, TLS, NiceHash, daemon, SOCKS5 and self-select settings when sent.
restart_attempt A JSON-RPC pause, resume, stop or start call.
miner_api_command Every request: HTTP verb or JSON-RPC method, path, whether it is privileged, and parameters.
cryptomining_indicators Shared envelope for pools, wallets and miner names found in an upload.
dropper_indicators Shared envelope for download tools, URLs, hosts and filenames found in an upload.
info_event_cap_reached Marker emitted once when the per-connection event cap (max_info_events) is reached.