2
Module Reference Services
anti edited this page 2026-04-18 06:20:17 -04:00

Module Reference — Services

Every module under decnet/services/. This is the code view — for the user-facing description of each honeypot (what it emulates, what the captured attacker interaction looks like, which personas are supported) see Services Catalog. For bring-your-own definitions see Custom Services.

Citation format: decnet/services/<module>.py::<symbol>.


Framework

decnet/services/__init__.py

Empty package marker.

decnet/services/base.py

Defines the contract every plugin implements. The registry auto-discovers every BaseService subclass at import time, so adding a service is just dropping a new file here.

  • decnet/services/base.py::BaseService — abstract base with class attributes name, ports, default_image, fleet_singleton and the abstract compose_fragment(decky_name, log_target=None, service_cfg=None).
  • decnet/services/base.py::BaseService.compose_fragment — return the docker-compose service dict. Networking keys (networks, ipv4_address) are injected by the composer and must NOT be returned here. Include image / build, environment, volumes, restart, and service-specific options.
  • decnet/services/base.py::BaseService.dockerfile_context — return the build-context directory, or None when default_image is used directly.

decnet/services/registry.py

Plugin registry. All modules under decnet.services. are imported lazily on first call; each BaseService subclass in the package is instantiated once and keyed by its .name.

  • decnet/services/registry.py::_load_plugins — walk the package with pkgutil.iter_modules, import everything except base and registry, instantiate every BaseService.__subclasses__().
  • decnet/services/registry.py::register_custom_service — register a dynamically-built CustomService (used for [custom-*] INI sections; see Custom Services).
  • decnet/services/registry.py::get_service — lookup a service by name, raise KeyError on miss.
  • decnet/services/registry.py::all_services — return a copy of the registry dict.

Plugin catalogue

All plugins except sniffer are per-decky (fleet_singleton=False). All plugins set default_image="build", meaning the corresponding templates/<name>/ Dockerfile is built at deploy time with BASE_IMAGE injected from the decky's distro. The NODE_NAME env var is always set to the decky name; the LOG_TARGET env var is set when the composer has a log_target (syslog forward address). Persona keys listed are those consulted by compose_fragment(service_cfg=...) from the INI [decky.service] subsection.

Service Ports Template Persona keys
ssh 22 templates/ssh password, hostname
smb 445, 139 templates/smb service-specific
rdp 3389 templates/rdp service-specific
http 80, 443 templates/http server_header, response_code, fake_app, extra_headers, custom_body, files
https 443 templates/https service-specific
ftp 21 templates/ftp service-specific
mysql 3306 templates/mysql service-specific
postgres 5432 templates/postgres service-specific
redis 6379 templates/redis service-specific
mongodb 27017 templates/mongodb service-specific
mssql 1433 templates/mssql service-specific
elasticsearch 9200 templates/elasticsearch service-specific
telnet 23 templates/telnet service-specific
vnc 5900 templates/vnc service-specific
snmp 161 templates/snmp service-specific
mqtt 1883 templates/mqtt service-specific
sip 5060 templates/sip service-specific
ldap 389, 636 templates/ldap service-specific
llmnr 5355, 5353 templates/llmnr service-specific
k8s 6443, 8080 templates/k8s service-specific
docker_api 2375, 2376 templates/docker_api service-specific
conpot 502, 161, 80 templates/conpot service-specific
tftp 69 templates/tftp service-specific
imap 143, 993 templates/imap service-specific
pop3 110, 995 templates/pop3 service-specific
smtp 25, 587 templates/smtp service-specific
smtp_relay 25, 587 templates/smtp (shared, with SMTP_OPEN_RELAY=1) service-specific
sniffer templates/sniffer — (fleet singleton)

Per-service notes:

  • decnet/services/ssh.py::SSHService — real OpenSSH server (not Cowrie) so that fingerprinting cannot trivially identify the honeypot. Auth, sudo, and interactive commands are forwarded to stdout as RFC 5424 by the container's rsyslog bridge. Bind-mounts a per-decky quarantine directory at /var/lib/decnet/artifacts/<decky>/ssh onto the in-container path /var/lib/systemd/coredump so attacker drops (scp/sftp/wget) are captured out of band while looking benign from inside.
  • decnet/services/smb.py::SMBService — SMB 1/2/3 honeypot on 445 + 139 (NetBIOS).
  • decnet/services/rdp.py::RDPService — Remote Desktop Protocol on 3389.
  • decnet/services/http.py::HTTPService — HTTP/HTTPS on 80 + 443 with optional server_header, response_code, fake_app (e.g. wordpress), extra_headers (dict or JSON string), custom_body, and an optional files=<path> bind mount to serve arbitrary content out of /opt/html_files.
  • decnet/services/https.py::HTTPSService — standalone HTTPS emulator on 443; shares no code with http.
  • decnet/services/ftp.py::FTPService — FTP control channel on 21.
  • decnet/services/mysql.py::MySQLService — MySQL wire protocol on 3306.
  • decnet/services/postgres.py::PostgresService — PostgreSQL startup handshake on 5432.
  • decnet/services/redis.py::RedisService — RESP protocol on 6379.
  • decnet/services/mongodb.py::MongoDBService — MongoDB wire protocol on 27017.
  • decnet/services/mssql.py::MSSQLService — TDS pre-login on 1433.
  • decnet/services/elasticsearch.py::ElasticsearchService — HTTP REST facade on 9200 emulating ES cluster endpoints.
  • decnet/services/telnet.py::TelnetService — Telnet negotiation + login prompt on 23.
  • decnet/services/vnc.py::VNCService — RFB 3.x handshake on 5900, emits VNC client-version fingerprints.
  • decnet/services/snmp.py::SNMPService — SNMP v1/v2c/v3 on 161/UDP.
  • decnet/services/mqtt.py::MQTTService — MQTT broker handshake on 1883.
  • decnet/services/sip.py::SIPService — SIP REGISTER / OPTIONS on 5060.
  • decnet/services/ldap.py::LDAPService — LDAPv3 bind on 389 + 636.
  • decnet/services/llmnr.py::LLMNRService — link-local multicast name resolution on 5355 + 5353 (mDNS bundled).
  • decnet/services/k8s.py::KubernetesAPIService — fake Kubernetes API on 6443 + 8080.
  • decnet/services/docker_api.py::DockerAPIService — fake Docker daemon socket exposed over TCP on 2375 + 2376.
  • decnet/services/conpot.py::ConpotService — upstream Conpot ICS/SCADA honeypot: Modbus (502), SNMP (161 UDP), HTTP (80).
  • decnet/services/tftp.py::TFTPService — TFTP RRQ/WRQ on 69/UDP.
  • decnet/services/imap.py::IMAPService — IMAP4 capability + login on 143 + 993.
  • decnet/services/pop3.py::POP3Service — POP3 USER/PASS on 110 + 995.
  • decnet/services/smtp.py::SMTPService — SMTP EHLO/AUTH on 25 + 587.
  • decnet/services/smtp_relay.py::SMTPRelayService — reuses the smtp template with SMTP_OPEN_RELAY=1 to offer the open-relay persona beloved of spam bots.
  • decnet/services/sniffer.py::SnifferServicefleet singleton. Passive MACVLAN sniffer: no inbound ports, cap_add: [NET_RAW, NET_ADMIN], extracts JA3/JA3S/JA4/JA4L TLS fingerprints plus connection metadata from the wire. Feeds the bounty table via the ingester.

decnet/custom_service.py

See the Core reference. CustomService is a BaseService subclass instantiated from [custom-*] INI sections and registered via register_custom_service().