Add per-service customization, stealth hardening, and BYOS support

- HTTP: configurable server_header, response_code, fake_app presets
  (apache/nginx/wordpress/phpmyadmin/iis), extra_headers, custom_body,
  static files directory mount
- SSH/Cowrie: configurable kernel_version, hardware_platform, ssh_banner,
  and users/passwords via COWRIE_USERDB_ENTRIES; switched to build mode
  so cowrie.cfg.j2 persona fields and userdb.txt generation work
- SMTP: configurable banner and MTA hostname
- MySQL: configurable version string in protocol greeting
- Redis: configurable redis_version and os string in INFO response
- BYOS: [custom-*] INI sections define bring-your-own Docker services
- Stealth: rename all *_honeypot.py → server.py; replace HONEYPOT_NAME
  env var with NODE_NAME across all 22+ service templates and plugins;
  strip "honeypot" from all in-container file content
- Config: DeckyConfig.service_config dict; INI [decky-N.svc] subsections;
  composer passes service_cfg to compose_fragment
- 350 tests passing (100%)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-04 04:08:27 -03:00
parent 07c06e3c0a
commit cf1e00af28
102 changed files with 974 additions and 309 deletions

View File

@@ -8,7 +8,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
ENV PIP_BREAK_SYSTEM_PACKAGES=1
RUN pip3 install --no-cache-dir twisted jinja2
COPY rdp_honeypot.py /opt/rdp_honeypot.py
COPY server.py /opt/server.py
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

View File

@@ -1,3 +1,3 @@
#!/bin/bash
set -e
exec python3 /opt/rdp_honeypot.py
exec python3 /opt/server.py

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""
Minimal RDP honeypot using Twisted.
Minimal RDP server using Twisted.
Listens on port 3389, logs connection attempts and any credentials sent
in the initial RDP negotiation request. Forwards events as JSON to
LOG_TARGET if set.
@@ -15,7 +15,7 @@ from datetime import datetime, timezone
from twisted.internet import protocol, reactor
from twisted.python import log as twisted_log
HONEYPOT_NAME = os.environ.get("HONEYPOT_NAME", "WORKSTATION")
NODE_NAME = os.environ.get("NODE_NAME", "WORKSTATION")
LOG_TARGET = os.environ.get("LOG_TARGET", "")
@@ -34,7 +34,7 @@ def _log(event_type: str, **kwargs) -> None:
event = {
"ts": datetime.now(timezone.utc).isoformat(),
"service": "rdp",
"host": HONEYPOT_NAME,
"host": NODE_NAME,
"event": event_type,
**kwargs,
}
@@ -42,7 +42,7 @@ def _log(event_type: str, **kwargs) -> None:
_forward(event)
class RDPHoneypotProtocol(protocol.Protocol):
class RDPServerProtocol(protocol.Protocol):
def connectionMade(self):
peer = self.transport.getPeer()
_log("connection", src_ip=peer.host, src_port=peer.port)
@@ -61,12 +61,12 @@ class RDPHoneypotProtocol(protocol.Protocol):
_log("disconnect", src_ip=peer.host, src_port=peer.port)
class RDPHoneypotFactory(protocol.ServerFactory):
protocol = RDPHoneypotProtocol
class RDPServerFactory(protocol.ServerFactory):
protocol = RDPServerProtocol
if __name__ == "__main__":
twisted_log.startLogging(sys.stdout)
_log("startup", msg=f"RDP honeypot starting as {HONEYPOT_NAME} on port 3389")
reactor.listenTCP(3389, RDPHoneypotFactory())
_log("startup", msg=f"RDP server starting as {NODE_NAME} on port 3389")
reactor.listenTCP(3389, RDPServerFactory())
reactor.run()