The Academy is free // the war room is optional
DAEMONCORE // ACADEMY
← FIELD NOTES

How to build a disposable lab range for network attacks

2026.09.02//5 MIN READlab-setupnetwork-securityvirtualization

// The disposable range principle

Static labs degrade quickly. When you run exploit payloads, test ARP poisoning, or deploy live malware against target virtual machines, the lab environment accumulates state. Log files swell, misconfigurations compound, and network noise from previous exercises bleeds into new testing sessions.

A disposable range solves this by treating every machine and virtual network as ephemeral. The entire environment should spin up from declarative configuration files in under three minutes and be torn down completely when the session ends. More importantly, it must guarantee zero route leak to your production network, your home LAN, or the internet.

// Isolation requirements and network architecture

Running offensive network tradecraft requires three distinct zones:

  • Attacker node: A VM containing your tooling (Kali, Arch, or custom debian rootfs) with raw socket capabilities.
  • Target network: One or more isolated subnets containing vulnerable services, domain controllers, or misconfigured routers.
  • Host hypervisor boundary: The physical host providing compute, which must actively reject forwarding between the virtual switch and physical egress interfaces.

Do not rely on hypervisor UI defaults for network isolation. Standard NAT modes often allow outbound traffic to external networks, and "host-only" configurations can still permit the host to act as a router if ip_forward is enabled in the Linux kernel. Isolation must be enforced explicitly at the host firewall level.

// Automated deployment with Vagrant and Libvirt

Using KVM/libvirt managed via Vagrant gives you reproducible, headless environments with minimal overhead compared to heavy GUI hypervisors. Below is an example Vagrantfile defining an isolated attack subnet (10.99.0.0/24) with an attack platform and a target system.

Vagrant.configure("2") do |config|
  config.vm.provider :libvirt do |lv|
    lv.driver = "kvm"
    lv.memory = 2048
    lv.cpus = 2
  end

  # Isolated private network without host routing
  config.vm.network "private_network",
    ip: "10.99.0.10",
    libvirt__network_name: "disposable-range",
    libvirt__dhcp_enabled: false,
    libvirt__forward_mode: "none"

  # Attacker box
  config.vm.define "attacker" do |att|
    att.vm.box = "generic/debian12"
    att.vm.hostname = "attacker.local"
    att.vm.network "private_network",
      ip: "10.99.0.10",
      libvirt__network_name: "disposable-range"
  end

  # Vulnerable target
  config.vm.define "target" do |tgt|
    tgt.vm.box = "generic/ubuntu2204"
    tgt.vm.hostname = "target.local"
    tgt.vm.network "private_network",
      ip: "10.99.0.20",
      libvirt__network_name: "disposable-range"
    tgt.vm.provision "shell", inline: <<-SHELL
      apt-get update -y && apt-get install -y vsftpd
      systemctl enable --now vsftpd
    SHELL
  end
end

Setting libvirt__forward_mode: "none" creates an isolated Linux bridge with no external uplink. Packets hitting this bridge cannot leave the host kernel's virtual switch.

// Enforcing host-level packet containment

Even with isolated bridges, host configuration errors or rogue routing rules can result in packet leakage. Enforce containment explicitly using iptables or nftables on your host machine before starting any exercise.

Run the following shell script to lock down the interface assigned to the virtual range:

#!/usr/bin/env bash
set -euo pipefail

BRIDGE_IF="virbr1" # Match your libvirt private bridge

# 1. Block all forwarding from the lab bridge to physical interfaces
 sudo iptables -I FORWARD -i "${BRIDGE_IF}" -j DROP
 sudo iptables -I FORWARD -o "${BRIDGE_IF}" -j DROP

# 2. Block the range from talking to host management daemons
 sudo iptables -I INPUT -i "${BRIDGE_IF}" -p tcp --dport 22 -j DROP
 sudo iptables -I INPUT -i "${BRIDGE_IF}" -p tcp --dport 53 -j DROP

# 3. Verify rules are active
 sudo iptables -L FORWARD -v -n | grep "${BRIDGE_IF}"
echo "[+] Lab bridge ${BRIDGE_IF} strictly contained."

With these rules in place, Layer 2 broadcast attacks (such as ARP poisoning, LLMNR/NBT-NS spoofing) and raw TCP/UDP exploitation attempts remain entirely contained within virbr1.

// Operational lifecycle and state hygiene

When conducting tests, follow a strict lifecycle to maintain confidence in your observations:

1. Bring up the environment: Execute vagrant up to deploy the clean baseline. 2. Verify containment: Run an active scan (nmap -sn 10.99.0.0/24) from the attacker VM to confirm only designated range IPs respond. 3. Execute the exercise: Run your exploits, captures, or configuration audits against target endpoints. 4. Extract telemetry: If you are analyzing artifacts, pull pcap files and service logs off the VMs via vagrant ssh -- sudo cat /var/log/... rather than mounting shared host folders. 5. Destroy the range: Run vagrant destroy -f immediately upon completion.

Never reuse a compromised or manipulated target VM for a subsequent test. Rebuilding from code guarantees that observed telemetry is the direct result of your current test rather than residual noise from a previous exercise.

// Practice in the range

Theory is useless without execution under controlled constraints. The DaemonCore Academy curriculum is completely free. Use the network isolation patterns outlined above to build your own disposable range, run through the hands-on labs, and practice real-world exploitation techniques safely.