Mutation and Randomization
DECNET's value as a deception network depends on the decoy fleet looking heterogeneous at deploy time and shifting over its lifetime. This page documents the two mechanisms that deliver that: randomization at build, and mutation at runtime.
See also: CLI reference, Archetypes, Distros.
Randomization at deploy time
--randomize-services
When decnet deploy is invoked with --randomize-services, each decky receives a randomly drawn service set instead of the fixed list passed via --services or the set implied by --archetype.
The selection logic lives in build_deckies() (decnet/fleet.py). For each decky:
- A count
kis drawn uniformly from[1, min(3, len(pool))]. kservice names are sampled without replacement from the pool (all_service_names(), or the archetype service list if an archetype is set).- The chosen set is compared against a
used_combos: set[frozenset]that tracks combinations already assigned in this deploy. If it collides with an existing combination, the draw is retried. - After 20 retries, the last draw is accepted even if duplicated. With small pools and many deckies, exact uniqueness is not always possible — the retry cap prevents an infinite loop.
Random hostnames
Hostnames are generated by random_hostname(distro_slug) in decnet/distros.py. The style depends on the distro profile's hostname_style field:
| Style | Example | Distros |
|---|---|---|
generic |
SRV-PROD-42 |
Debian, Ubuntu |
rhel |
web37.localdomain |
Rocky, CentOS, Fedora |
minimal |
alpha-18 |
Alpine |
rolling |
nova-backup |
Kali, Arch |
Word pool and numeric range are defined in _NAME_WORDS and the random.randint(10, 99) call in the same file.
Random distros
random_distro() picks a uniform-random entry from the DISTROS dict (decnet/distros.py). Each entry is a DistroProfile with a slug, a Docker image, a display name, a hostname style, and a build base image used for service Dockerfiles (which assume apt-get, so non-Debian distros fall back to debian:bookworm-slim for builds).
The current set: debian, ubuntu22, ubuntu20, rocky9, centos7, alpine, fedora, kali, arch.
MAC addresses
MAC addresses are not assigned by DECNET. The MACVLAN driver auto-generates a MAC for each container interface at container start. There is no knob to pin or rotate them from the deploy config; if you need deterministic MACs, attach them out-of-band at the Docker network layer.
Mutation at runtime
Randomization only fires at build time. To keep the fleet moving, DECNET supports per-decky service rotation.
Storage
Every DeckyConfig (decnet/config.py) carries two mutation-related fields:
mutate_interval: int | None— minutes between rotations for this decky.Nonedisables automatic rotation for that decky.last_mutated: float— Unix timestamp of the most recent successful mutation.
The top-level DecnetConfig also holds a fleet-wide mutate_interval, which defaults to DEFAULT_MUTATE_INTERVAL = 30 (minutes) from decnet/config.py. Per-decky values override the fleet default.
Engine
decnet/mutator/engine.py exposes three async entry points, all operating against a BaseRepository:
mutate_decky(decky_name, repo)— Intra-archetype shuffle for one decky. Rebuilds the service list by sampling 1-3 services from the decky's archetype pool (or the full registry if no archetype is set), retrying up to 20 times to avoid picking the exact same set. Updateslast_mutated, persists state, rewrites the compose file, and runsdocker compose up -d --remove-orphans.mutate_all(repo, force=False)— Iterates all deckies. For each, computeselapsed = now - last_mutatedand callsmutate_deckywhenelapsed >= interval * 60.force=Truebypasses the schedule.run_watch_loop(repo, poll_interval_secs=10)— Infinite loop that callsmutate_alleverypoll_interval_secs. Invoked bydecnet mutate --watch.
Trigger from the CLI
# Deploy a fleet that rotates every 15 minutes
decnet deploy --mode unihost --deckies 5 --interface eth0 \
--randomize-services --mutate-interval 15
# Mutate a single decky now (forces immediately, ignores schedule)
decnet mutate --decky decky-03
# Mutate all deckies now
decnet mutate --all
# Run the watcher in the foreground
decnet mutate --watch
# Run the watcher as a detached daemon
decnet mutate --watch --daemon
decnet deploy also starts a background watcher automatically; the standalone decnet mutate --watch is for operators who want to run the loop themselves.
Operational trade-offs
Mutation is a blunt instrument. The interval you pick is a trade between deception fidelity and observability:
- Short intervals (≤ 5 min): The fleet looks lively and fingerprint scans will never converge, but every rotation churns containers, rewrites compose files, and wipes short-lived attacker state — half-finished brute-force sessions, partially uploaded payloads, active TCP connections. You will lose IOCs that would otherwise have been captured.
- Default (30 min): Reasonable balance. Most scan-and-go attackers see a consistent snapshot; long-dwell attackers see the fleet shift under them, which itself is a useful signal.
- Long intervals (hours) or
None: The fleet looks static. An attacker who fingerprints twice gets identical results, which is not how real networks behave under patching and reconfiguration.
For research deployments where you want a specific attacker session recorded end-to-end, disable mutation on the decky under observation (mutate_interval=None on that decky only) while leaving the rest of the fleet rotating.
Sources
decnet/distros.py—DISTROS,random_hostname,random_distrodecnet/fleet.py—build_deckiesdecnet/mutator/engine.py—mutate_decky,mutate_all,run_watch_loopdecnet/config.py—DEFAULT_MUTATE_INTERVAL,DeckyConfig,DecnetConfigdecnet/cli.py—deploy,mutatecommands
DECNET
User docs
- Quick-Start
- Installation
- Requirements-and-Python-Versions
- CLI-Reference
- INI-Config-Format
- Custom-Services
- Services-Catalog
- Service-Personas
- Archetypes
- Distro-Profiles
- OS-Fingerprint-Spoofing
- Networking-MACVLAN-IPVLAN
- Deployment-Modes
- SWARM-Mode
- MazeNET
- Remote-Updates
- Environment-Variables
- Teardown-and-State
- Database-Drivers
- Systemd-Setup
- Logging-and-Syslog
- Service-Bus
- Web-Dashboard
- REST-API-Reference
- Mutation-and-Randomization
- Troubleshooting
Developer docs
DECNET — honeypot deception-network framework. Pre-1.0, active development — use with caution. See Sponsors to support the project. Contact: samuel@securejump.cl