Networking: MACVLAN and IPvlan
DECNET's deckies must look like real, independent machines on the LAN. Each decky owns an IP (and ideally a MAC) drawn from the same subnet as the host's real NIC, so that attackers scanning the network see a heterogeneous fleet of hosts rather than a single container host.
This page covers how that is wired up: the two Docker network drivers DECNET supports, the host-side hairpin interface it creates, and the limitations you will hit on WiFi or WSL.
Source of truth: decnet/network.py (constants MACVLAN_NETWORK_NAME,
HOST_MACVLAN_IFACE, HOST_IPVLAN_IFACE; functions setup_host_macvlan,
teardown_host_macvlan, setup_host_ipvlan, teardown_host_ipvlan).
See also: CLI reference, INI format, Teardown.
Topology
Internet / attacker
|
| (public IP, port forwards)
|
+-----------------+
| DECNET host | eth0 -> decnet_lan (MACVLAN / IPvlan L2)
+--------+--------+
|
==============+=================== LAN 192.168.1.0/24
| | |
decky-01 decky-02 decky-03 (each = own IP,
.10 .11 .12 MACVLAN = own MAC too)
|
+-------------+-------------+
| decnet_macvlan0 (host) | hairpin: host <-> deckies reachability
+---------------------------+
--- isolated mgmt path ---
host -> logging/SIEM network
(not reachable from decnet_lan)
The decoy LAN is attacker-facing. The logging/aggregation network is reachable
only from the host and must not be routable from decnet_lan.
Driver 1: MACVLAN (default)
MACVLAN is the default driver. Each decky gets a kernel-assigned MAC address on the parent interface, so it is a distinct L2 endpoint on the LAN.
- Docker network name:
decnet_lan(constantMACVLAN_NETWORK_NAME). - Parent NIC:
--interface(auto-detected viadetect_interface()if omitted). - Mode:
macvlan / bridge(seecreate_macvlan_networkand theip link add ... type macvlan mode bridgecall insetup_host_macvlan). - Requires the parent NIC to support promiscuous mode. Most wired NICs do.
Host hairpin (decnet_macvlan0)
MACVLAN has a well-known limitation: the host cannot talk directly to its own
MACVLAN children on the parent NIC. Without a workaround, decnet status and
the log collector (which run on the host) would be unable to reach deckies.
DECNET fixes this by creating a second host-side MACVLAN interface named
decnet_macvlan0 (constant HOST_MACVLAN_IFACE) attached to the same parent
NIC, assigning it a /32 on the host, and routing the decky IP range out of it.
The relevant sequence in setup_host_macvlan:
ip link add decnet_macvlan0 link <iface> type macvlan mode bridge
ip addr add <host_macvlan_ip>/32 dev decnet_macvlan0
ip link set decnet_macvlan0 up
ip route add <decky_range> dev decnet_macvlan0
Driver 2: IPvlan L2 (--ipvlan)
Pass --ipvlan to opt into IPvlan L2. Each decky gets a unique IP but all
share the host MAC. This is the fallback for environments where MACVLAN is not
workable:
- WiFi. Most access points drop frames whose source MAC is not registered with the radio, so random MACVLAN MACs never reach the LAN. IPvlan L2 works because every frame leaves with the (registered) host MAC.
- NICs that refuse promiscuous mode.
Host hairpin (decnet_ipvlan0)
Same trick as MACVLAN, different link type. setup_host_ipvlan adds a
host-side interface named decnet_ipvlan0 (constant HOST_IPVLAN_IFACE) of
type ipvlan mode l2, gives it a /32, and routes the decky range through it.
teardown_host_ipvlan removes the route and the link on teardown.
Trade-offs
| Aspect | MACVLAN | IPvlan L2 |
|---|---|---|
| Per-decky MAC | yes (unique, kernel-assigned) | no (shares host MAC) |
| Works on WiFi | usually no | yes |
| Promisc NIC needed | yes | no |
| Decoy realism | higher (distinct L2 identities) | lower (all share one MAC) |
Attacker fingerprinting via arp -a |
sees many MACs | sees one MAC, many IPs |
Prefer MACVLAN on wired, bare-metal or VM deployments. Use IPvlan L2 when the environment forces it.
WiFi and WSL limitations
- WiFi: MACVLAN typically does not work. Use
--ipvlan. - WSL2: MACVLAN has known limitations under WSL. Bare metal or a full Linux VM is the supported testing environment (README "Requirements" section).
- Promiscuous mode: some virtualization platforms (including vSphere with default security policies) block promiscuous mode on the vNIC; either relax the policy on the virtual switch or use IPvlan.
Teardown
Teardown of the Docker network and the host hairpin interface is automatic
when you run decnet teardown --all. The relevant steps, from
decnet/engine/deployer.py:
if config.ipvlan:
teardown_host_ipvlan(decky_range)
else:
teardown_host_macvlan(decky_range)
remove_macvlan_network(client)
teardown_host_macvlan / teardown_host_ipvlan each do:
ip route del <decky_range> dev <iface> # decnet_macvlan0 or decnet_ipvlan0
ip link del <iface>
Both use check=False, so a partial or previously-cleaned state is safe.
Removing the Docker network decnet_lan happens separately via
remove_macvlan_network.
See Teardown for the full teardown flow including container removal and state-file cleanup.
Quick checklist
- Host NIC is wired and supports promiscuous mode -> MACVLAN, no flag needed.
- Host NIC is WiFi, or promisc is blocked -> pass
--ipvlan. - Running under WSL -> switch to a Linux VM or bare metal.
decnet statussays a decky is unreachable from the host -> confirmdecnet_macvlan0(ordecnet_ipvlan0) exists withip link show.
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