Building a Security Test Lab with QEMU: From Zero to Network Monitoring

Source: Dev.to | Dec 26, 2025 (UTC)

Why QEMU for Your Test Lab?

As software engineers and security professionals, we constantly need isolated environments to test new tools, experiment with network configurations, or validate security measures before production deployment. While solutions like VirtualBox and VMware are popular, QEMU offers something special: lightweight, scriptable, headless operation perfect for automation and CI/CD pipelines.

In this guide, I’ll walk you through building a complete QEMU-based test lab focused on network security and infrastructure testing. By the end, you’ll have a reproducible environment for testing firewalls, monitoring tools, and distributed systems.

What We’ll Build

We’re creating a multi-VM test lab that simulates a realistic network environment:

  • Gateway VM: Acts as router/firewall
  • Application VM: Simulates production workloads
  • Attacker VM: For security testing and validation

This setup mirrors real-world scenarios where you need to test network policies, intrusion detection, or packet filtering.

Prerequisites

Before we start, ensure you have:

  • A Linux host (Ubuntu/Debian in examples, but adaptable to any distro)
  • At least 8GB RAM and 20GB free disk space
  • Basic command-line familiarity
  • Sudo access for network configuration

Step 1: Installing QEMU

First, let’s get QEMU installed with all necessary components:

# Ubuntu/Debian sudo apt update sudo apt install qemu-kvm qemu-utils libvirt-daemon-system virtinst bridge-utils # Verify installation qemu-system-x86_64 --version

Enter fullscreen mode

Exit fullscreen mode

For other distributions:

# Fedora/RHEL sudo dnf install qemu-kvm qemu-img libvirt virt-install # Arch sudo pacman -S qemu libvirt virt-manager

Enter fullscreen mode

Exit fullscreen mode

Add your user to necessary groups to avoid constant sudo:

sudo usermod -aG libvirt,kvm $USER # Log out and back in for changes to take effect

Enter fullscreen mode

Exit fullscreen mode

Step 2: Creating Your First VM – The Gateway

Let’s start with the gateway VM, which will be our network’s control point.

Creating the Disk Image

# Create a working directory mkdir -p ~/qemu-lab/images cd ~/qemu-lab # Create a 20GB disk image (qcow2 format for snapshots) qemu-img create -f qcow2 images/gateway.qcow2 20G

Enter fullscreen mode

Exit fullscreen mode

Why qcow2? It supports snapshots, copy-on-write, and compression – essential for test environments where you’ll want to reset frequently.

Download a Minimal OS

For security testing, I recommend Alpine Linux (lightweight) or Debian netinst:

# Alpine Linux (very lightweight, boots in seconds) wget https://dl-cdn.alpinelinux.org/alpine/v3.23/releases/x86_64/alpine-virt-3.23.0-x86_64.iso \ -O images/alpine.iso # Or Debian if you prefer more familiar tools # wget https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.2.0-amd64-netinst.iso \ # -O images/debian.iso

Enter fullscreen mode

Exit fullscreen mode

First Boot and Installation

qemu-system-x86_64 \ -name gateway \ -m 1024 \ -smp 2 \ -hda images/gateway.qcow2 \ -cdrom images/alpine.iso \ -boot d \ -enable-kvm \ -nic user,model=virtio \ -nographic

Enter fullscreen mode

Exit fullscreen mode

Flag breakdown:

Quick Alpine Installation:

# Once booted, login as root (no password) setup-alpine # Follow prompts: # - Keyboard: us # - Hostname: gateway # - Network: eth0, dhcp # - Password: (set a strong one) # - Timezone: your timezone # - Disk: sda, sys (use entire disk)

Enter fullscreen mode

Exit fullscreen mode

After installation completes, power off the VM (type poweroff).

Step 3: Setting Up Advanced Networking

This is where QEMU shines for security testing. We’ll create an isolated network that simulates real infrastructure.

Create a Network Configuration Script

# Create scripts directory mkdir -p ~/qemu-lab/scripts # Network setup script cat > ~/qemu-lab/scripts/setup-network.sh << 'EOF' #!/bin/bash # Create an isolated bridge for our test lab sudo ip link add name br-testlab type bridge sudo ip addr add 10.0.100.1/24 dev br-testlab sudo ip link set br-testlab up # Enable IP forwarding (so gateway can route) sudo sysctl -w net.ipv4.ip_forward=1 # Create TAP interfaces for VMs for i in 0 1 2; do sudo ip tuntap add tap$i mode tap user $USER sudo ip link set tap$i master br-testlab sudo ip link set tap$i up done echo "Test lab network ready: 10.0.100.0/24 on br-testlab" EOF chmod +x ~/qemu-lab/scripts/setup-network.sh

Enter fullscreen mode

Exit fullscreen mode

you will end up with this network topology

10.0.100.1/24 Network | [Bridge](br-testlab) / | \ TAP0 TAP1 TAP2 VM1 VM2 VM3

Enter fullscreen mode

Exit fullscreen mode

Characteristics:

Network Teardown Script

cat > ~/qemu-lab/scripts/teardown-network.sh << 'EOF' #!/bin/bash # Remove TAP interfaces for i in 0 1 2; do sudo ip link set tap$i down 2>/dev/null sudo ip link delete tap$i 2>/dev/null done # Remove bridge sudo ip link set br-testlab down 2>/dev/null sudo ip link delete br-testlab 2>/dev/null echo "Test lab network removed" EOF chmod +x ~/qemu-lab/scripts/teardown-network.sh

Enter fullscreen mode

Exit fullscreen mode

Run the setup:

~/qemu-lab/scripts/setup-network.sh

Enter fullscreen mode

Exit fullscreen mode

Step 4: Creating VM Launch Scripts

Rather than typing long QEMU commands, let’s create reusable launch scripts.

Gateway VM Script

cat > ~/qemu-lab/scripts/run-gateway.sh << 'EOF' #!/bin/bash qemu-system-x86_64 \ -name gateway \ -m 1024 \ -smp 2 \ -hda ~/qemu-lab/images/gateway.qcow2 \ -enable-kvm \ -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \ -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:00 \ -netdev user,id=net1 \ -device virtio-net-pci,netdev=net1,mac=52:54:00:12:34:01 \ -nographic \ -serial mon:stdio EOF chmod +x ~/qemu-lab/scripts/run-gateway.sh

Enter fullscreen mode

Exit fullscreen mode

This gateway has TWO network interfaces:

Quick Clone Function for Additional VMs

# Create application VM from gateway template qemu-img create -f qcow2 -b images/gateway.qcow2 -F qcow2 images/app.qcow2 # Create attacker VM qemu-img create -f qcow2 -b images/gateway.qcow2 -F qcow2 images/attacker.qcow2

Enter fullscreen mode

Exit fullscreen mode

These are backing images – they only store differences from the base, saving massive disk space.

Application VM Script

cat > ~/qemu-lab/scripts/run-app.sh << 'EOF' #!/bin/bash qemu-system-x86_64 \ -name app-server \ -m 2048 \ -smp 2 \ -hda ~/qemu-lab/images/app.qcow2 \ -enable-kvm \ -netdev tap,id=net0,ifname=tap1,script=no,downscript=no \ -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:10 \ -nographic \ -serial mon:stdio EOF chmod +x ~/qemu-lab/scripts/run-app.sh

Enter fullscreen mode

Exit fullscreen mode

Attacker VM Script

cat > ~/qemu-lab/scripts/run-attacker.sh << 'EOF' #!/bin/bash qemu-system-x86_64 \ -name attacker \ -m 1024 \ -smp 2 \ -hda ~/qemu-lab/images/attacker.qcow2 \ -enable-kvm \ -netdev tap,id=net0,ifname=tap2,script=no,downscript=no \ -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:20 \ -nographic \ -serial mon:stdio EOF chmod +x ~/qemu-lab/scripts/run-attacker.sh

Enter fullscreen mode

Exit fullscreen mode

Step 5: Network Configuration Inside VMs

Start each VM and configure networking:

Gateway VM (10.0.100.1)

# Start gateway ~/qemu-lab/scripts/run-gateway.sh # Inside VM - configure interfaces # For Alpine Linux: cat > /etc/network/interfaces << 'EOF' auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.0.100.1 netmask 255.255.255.0 auto eth1 iface eth1 inet dhcp EOF # Restart networking rc-service networking restart # Enable forwarding permanently echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf sysctl -p # Setup basic NAT (so internal VMs can reach internet via gateway) apk add iptables iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT iptables -A FORWARD -i eth1 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT # Save iptables rules rc-update add iptables /etc/init.d/iptables save

Enter fullscreen mode

Exit fullscreen mode

Application VM (10.0.100.10)

# Configure static IP cat > /etc/network/interfaces << 'EOF' auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.0.100.10 netmask 255.255.255.0 gateway 10.0.100.1 dns-nameservers 8.8.8.8 EOF rc-service networking restart

Enter fullscreen mode

Exit fullscreen mode

Attacker VM (10.0.100.20)

# Configure static IP cat > /etc/network/interfaces << 'EOF' auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.0.100.20 netmask 255.255.255.0 gateway 10.0.100.1 dns-nameservers 8.8.8.8 EOF rc-service networking restart # Install security testing tools apk add nmap tcpdump hping3 netcat-openbsd

Enter fullscreen mode

Exit fullscreen mode

Step 6: Snapshots for Quick Resets

One of QEMU’s killer features – instant rollback:

# Create a "clean state" snapshot for each VM qemu-img snapshot -c clean-install images/gateway.qcow2 qemu-img snapshot -c clean-install images/app.qcow2 qemu-img snapshot -c clean-install images/attacker.qcow2 # After testing, rollback to clean state qemu-img snapshot -a clean-install images/gateway.qcow2 # List all snapshots qemu-img snapshot -l images/gateway.qcow2

Enter fullscreen mode

Exit fullscreen mode

Step 7: Practical Use Cases

Now your lab is ready! Here are some real-world scenarios:

Testing Network Monitoring Tools

On the gateway VM, install your monitoring solution:

# Example: tcpdump for packet analysis apk add tcpdump # Capture traffic between app and attacker tcpdump -i eth0 -w /tmp/capture.pcap # Or install eBPF-based tools for advanced monitoring # (Great for testing tools like Cilium, Falco, or custom eBPF monitors like Cerberus)

Enter fullscreen mode

Exit fullscreen mode

Simulating Attack Scenarios

From attacker VM:

# Port scan the application nmap -sV 10.0.100.10 # Test firewall rules hping3 -S -p 80 10.0.100.10 # Monitor on gateway to see what's blocked

Enter fullscreen mode

Exit fullscreen mode

Testing Firewall Rules

On gateway, add restrictive rules:

# Block all traffic from attacker to app iptables -I FORWARD -s 10.0.100.20 -d 10.0.100.10 -j DROP # Allow only SSH iptables -I FORWARD -s 10.0.100.20 -d 10.0.100.10 -p tcp --dport 22 -j ACCEPT

Enter fullscreen mode

Exit fullscreen mode

Container Testing

Install Docker on the app VM to test container networking and security policies in isolation.

Step 8: Automation and Management

Create a master control script:

cat > ~/qemu-lab/manage-lab.sh << 'EOF' #!/bin/bash case "$1" in start) ./scripts/setup-network.sh echo "Starting VMs in tmux sessions..." tmux new-session -d -s gateway './scripts/run-gateway.sh' tmux new-session -d -s app './scripts/run-app.sh' tmux new-session -d -s attacker './scripts/run-attacker.sh' echo "Lab started. Attach with: tmux attach -t <gateway|app|attacker>" ;; stop) echo "Stopping all VMs..." tmux kill-session -t gateway 2>/dev/null tmux kill-session -t app 2>/dev/null tmux kill-session -t attacker 2>/dev/null ./scripts/teardown-network.sh ;; reset) echo "Resetting all VMs to clean snapshot..." qemu-img snapshot -a clean-install images/gateway.qcow2 qemu-img snapshot -a clean-install images/app.qcow2 qemu-img snapshot -a clean-install images/attacker.qcow2 echo "Reset complete" ;; *) echo "Usage: $0 {start|stop|reset}" exit 1 ;; esac EOF chmod +x ~/qemu-lab/manage-lab.sh

Enter fullscreen mode

Exit fullscreen mode

Usage:

# Start entire lab ./manage-lab.sh start # Access any VM tmux attach -t gateway # Reset everything to clean state ./manage-lab.sh reset # Shut down cleanly ./manage-lab.sh stop

Enter fullscreen mode

Exit fullscreen mode

Performance Tips

  1. Always use KVM acceleration (-enable-kvm) – it’s 10-20x faster than emulation
  2. Allocate appropriate resources – Don’t over-provision RAM
  3. Use virtio drivers – Much faster than emulated hardware
  4. qcow2 for flexibility, raw for performance – Use raw images if speed is critical
  5. CPU pinning for consistency:

-smp 2,sockets=1,cores=2,threads=1

Enter fullscreen mode

Exit fullscreen mode

Troubleshooting Common Issues

VM won’t start with KVM error:

# Check if KVM is available lsmod | grep kvm # If not, enable in BIOS (Intel VT-x or AMD-V)

Enter fullscreen mode

Exit fullscreen mode

Network not working:

# Verify TAP interfaces are up ip link show | grep tap # Check bridge configuration bridge link show br-testlab

Enter fullscreen mode

Exit fullscreen mode

Cannot connect to VMs:

# From host, ping the bridge IP ping 10.0.100.1 # Check iptables isn't blocking sudo iptables -L -n

Enter fullscreen mode

Exit fullscreen mode

Performance is slow:

# Verify KVM is actually being used ps aux | grep qemu | grep -i kvm

Enter fullscreen mode

Exit fullscreen mode

Next Steps and Advanced Topics

Your test lab is now ready for serious work! Consider exploring:

Conclusion

QEMU provides a powerful, scriptable foundation for testing network security tools and infrastructure. Unlike heavyweight alternatives, it integrates seamlessly into CI/CD pipelines, supports headless operation, and gives you complete control over the network topology.

The lab we built mirrors production environments while remaining completely isolated and reproducible. Use it to validate security tools, test infrastructure changes, or experiment with new technologies risk-free.

All scripts and configurations from this guide are available in my GitHub https://github.com/zrougamed/blog .

What will you test first in your new lab? Drop a comment below!

About the author: I’m a Senior Software Engineer at Deltaflare, where we work on the Phoenix Platform protecting Critical National Infrastructure across energy, water, and transport sectors. I use QEMU extensively for testing security tools and validating infrastructure changes before production deployment in CNI environments. You can find me at https://zrouga.email or check out my open-source work on GitHub.

For further actions, you may consider blocking this person and/or reporting abuse

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Читайте також