commit 8f2fff86e19faefb13c57f30c13dd37390e76842 Author: anti Date: Sat Apr 18 06:04:57 2026 -0400 wiki: archetypes, distro profiles, OS fingerprint spoofing diff --git a/Archetypes.md b/Archetypes.md new file mode 100644 index 0000000..fd7fe52 --- /dev/null +++ b/Archetypes.md @@ -0,0 +1,60 @@ +# Archetypes + +An **archetype** is a pre-packaged identity for a decky: a realistic combination +of services, a preferred distro rotation, and a TCP/IP OS fingerprint that makes +a decoy look like a specific class of machine without the user picking each piece +by hand. + +Source of truth: `decnet/archetypes.py`. + +## INI snippet + +```ini +[corp-desktops] +archetype=windows-workstation +amount=4 + +[edge] +archetype=deaddeck +amount=1 +``` + +See [INI format](INI-Config-Format). Archetypes can also be selected via +`decnet deploy --archetype ` or rotated automatically with +`--randomize-services`. + +## Registered archetypes + +| Slug | Display name | Services | Preferred distros | nmap_os | +|---|---|---|---|---| +| `windows-workstation` | Windows Workstation | smb, rdp | debian, ubuntu22 | windows | +| `windows-server` | Windows Server | smb, rdp, ldap | debian, ubuntu22 | windows | +| `domain-controller` | Domain Controller | ldap, smb, rdp, llmnr | debian, ubuntu22 | windows | +| `linux-server` | Linux Server | ssh, http | debian, ubuntu22, rocky9, fedora | linux | +| `web-server` | Web Server | http, ftp | debian, ubuntu22, ubuntu20 | linux | +| `database-server` | Database Server | mysql, postgres, redis | debian, ubuntu22 | linux | +| `mail-server` | Mail Server | smtp, pop3, imap | debian, ubuntu22 | linux | +| `file-server` | File Server | smb, ftp, ssh | debian, ubuntu22, rocky9 | linux | +| `printer` | Network Printer | snmp, ftp | alpine, debian | embedded | +| `iot-device` | IoT Device | mqtt, snmp, telnet | alpine | embedded | +| `industrial-control` | Industrial Control System | conpot, snmp | debian | embedded | +| `voip-server` | VoIP Server | sip | debian, ubuntu22 | linux | +| `monitoring-node` | Monitoring Node | snmp, ssh | debian, rocky9 | linux | +| `devops-host` | DevOps Host | docker_api, ssh, k8s | ubuntu22, debian | linux | +| `deaddeck` | Deaddeck (Entry Point) | ssh | debian, ubuntu22 | linux | + +## Notes + +- `deaddeck` exposes a real interactive SSH shell (not a honeypot emulation) and + is intended as the internet-facing entry point. +- `industrial-control` uses Conpot to simulate Modbus / S7 / DNP3. +- The `preferred_distros` list is rotated per-decky so a group of the same + archetype still looks heterogeneous. +- Each archetype's `nmap_os` is applied as network-namespace sysctls on the + decky's base container. See [OS fingerprint spoofing](OS-Fingerprint-Spoofing). + +## See also + +- [Services catalog](Services-Catalog) +- [Distro profiles](Distro-Profiles) +- [Networking](Networking-MACVLAN-IPVLAN) diff --git a/Distro-Profiles.md b/Distro-Profiles.md new file mode 100644 index 0000000..bcd9f3b --- /dev/null +++ b/Distro-Profiles.md @@ -0,0 +1,78 @@ +# Distro profiles + +Each distro profile maps a slug to a Docker image plus OS metadata used to make +deckies look like heterogeneous machines on the LAN. Profiles control the base +container image, the hostname convention, and the build base used for +service-container Dockerfiles. + +Source of truth: `decnet/distros.py`. + +## INI snippet + +```ini +[linux-fleet] +archetype=linux-server +distros=debian,ubuntu22,rocky9,fedora +amount=6 +``` + +See [INI format](INI-Config-Format). At deploy time each decky draws a distro +from the comma-separated list (or from the archetype's preferred rotation when +omitted). + +## Registered profiles + +| Slug | Image | Display name | Hostname style | Build base | +|---|---|---|---|---| +| `debian` | `debian:bookworm-slim` | Debian 12 (Bookworm) | generic | `debian:bookworm-slim` | +| `ubuntu22` | `ubuntu:22.04` | Ubuntu 22.04 LTS (Jammy) | generic | `ubuntu:22.04` | +| `ubuntu20` | `ubuntu:20.04` | Ubuntu 20.04 LTS (Focal) | generic | `ubuntu:20.04` | +| `rocky9` | `rockylinux:9-minimal` | Rocky Linux 9 | rhel | `debian:bookworm-slim` | +| `centos7` | `centos:7` | CentOS 7 | rhel | `debian:bookworm-slim` | +| `alpine` | `alpine:3.19` | Alpine Linux 3.19 | minimal | `debian:bookworm-slim` | +| `fedora` | `fedora:39` | Fedora 39 | rhel | `debian:bookworm-slim` | +| `kali` | `kalilinux/kali-rolling` | Kali Linux (Rolling) | rolling | `kalilinux/kali-rolling` | +| `arch` | `archlinux:latest` | Arch Linux | rolling | `debian:bookworm-slim` | + +## Image vs. build base + +`image` is the distro the decky's **base (IP-holder) container** runs. This is +what an attacker sees when they probe the host — package manager, `/etc/os-release`, +userland, and so on. + +`build_base` is what DECNET's **service containers** are built `FROM`. Because +the service Dockerfiles use `apt-get`, non-Debian distros (Rocky, CentOS, Alpine, +Fedora, Arch) fall back to `debian:bookworm-slim` for their services. Debian, +Ubuntu, and Kali use their own image as the build base since they are apt-based. + +This split keeps the attacker-facing surface diverse while keeping the service +implementations maintainable as a single Debian Dockerfile per service. + +## /etc/os-release + +DECNET does not template `/etc/os-release`. Each distro's file is whatever the +upstream image ships. Hostname style is set per-distro via `random_hostname()`: + +- `generic` — `SRV-WORD-NN` (Debian, Ubuntu) +- `rhel` — `word{10..99}.localdomain` (Rocky, CentOS, Fedora) +- `minimal` — `word-NN` (Alpine) +- `rolling` — `word-word` (Kali, Arch) + +## Default package manager + +| Distro | Package manager | +|---|---| +| debian, ubuntu22, ubuntu20, kali | apt | +| rocky9, centos7, fedora | dnf / yum | +| alpine | apk | +| arch | pacman | + +Service containers built for non-Debian deckies still ship apt-built payloads +because of the shared `build_base` fallback noted above. + +## See also + +- [Archetypes](Archetypes) +- [Services catalog](Services-Catalog) +- [OS fingerprint spoofing](OS-Fingerprint-Spoofing) +- [Networking](Networking-MACVLAN-IPVLAN) diff --git a/OS-Fingerprint-Spoofing.md b/OS-Fingerprint-Spoofing.md new file mode 100644 index 0000000..0e63745 --- /dev/null +++ b/OS-Fingerprint-Spoofing.md @@ -0,0 +1,87 @@ +# OS fingerprint spoofing + +DECNET spoofs the TCP/IP stack fingerprint that nmap (and similar tools) use to +identify the remote operating system. Each archetype declares an `nmap_os` OS +family; the composer applies the matching sysctl set to the decky's base +container network namespace. + +Source of truth: `decnet/os_fingerprint.py`. Injection site: `decnet/composer.py`. + +## INI snippet + +The OS family is chosen by the archetype, so simply picking an archetype is +enough: + +```ini +[windows-hosts] +archetype=windows-workstation ; implies nmap_os=windows +amount=3 + +[ics] +archetype=industrial-control ; implies nmap_os=embedded +amount=1 +``` + +See [INI format](INI-Config-Format) and [Archetypes](Archetypes) for the full +mapping. + +## Supported OS families + +| Slug | Default TTL | TCP timestamps | Window scaling | SACK | ECN | DF (pmtu) | +|---|---|---|---|---|---|---| +| `linux` | 64 | on | on | on | on (2) | off | +| `windows` | 128 | off | on | on | off | off | +| `bsd` | 64 | on | on | on | off | off | +| `embedded` | 255 | off | off | off | off | on | +| `cisco` | 255 | off | off | off | off | on | + +Unknown slugs fall back to `linux`. + +## How injection works + +In `decnet/composer.py` the base (IP-holder) container of every decky receives: + +```python +base["sysctls"] = get_os_sysctls(decky.nmap_os) +base["cap_add"] = ["NET_ADMIN"] +``` + +Service containers attach with `network_mode: service:`, so they share the +base container's network namespace and inherit the same fingerprint — no +`--privileged` required. + +## What gets tuned + +All sysctls in `OS_SYSCTLS` are network-namespace-scoped so they work per +container: + +- `net.ipv4.ip_default_ttl` — primary TTL discriminator (Linux 64, Windows 128, + embedded/Cisco 255). +- `net.ipv4.tcp_syn_retries` — SYN retransmit count (nmap T2–T6 timing group). +- `net.ipv4.tcp_timestamps` — TCP timestamp option (nmap OPS group). +- `net.ipv4.tcp_window_scaling` — window scale option; off on embedded/Cisco. +- `net.ipv4.tcp_sack` — selective ACK option. +- `net.ipv4.tcp_ecn` — ECN negotiation; Linux offers (2), Windows off. +- `net.ipv4.ip_no_pmtu_disc` — DF bit on ICMP replies (nmap IE group). +- `net.ipv4.tcp_fin_timeout` — FIN_WAIT_2 duration. +- `net.ipv4.icmp_ratelimit` / `net.ipv4.icmp_ratemask` — ICMP reply pacing + (nmap IE / U1 groups). + +## Limitations + +- `net.core.rmem_default` is a global (non-namespaced) sysctl and is not set + per container; the kernel default window size (64240) already matches + Windows, so this is mostly fine in practice. +- Only TCP/IP stack behaviour is tuned. Banner grabs, TCP option order outside + the listed set, and application-layer artefacts are handled by the individual + service implementations — see [Services catalog](Services-Catalog). +- The host kernel is still Linux, so nmap's deepest OS-detection probes can + sometimes correctly identify the underlying stack; the goal is to defeat the + common-case fingerprint, not to be indistinguishable. + +## See also + +- [Archetypes](Archetypes) +- [Distro profiles](Distro-Profiles) +- [Networking](Networking-MACVLAN-IPVLAN) +- [Services catalog](Services-Catalog)