Course: VCA-NET-301 — Advanced Networking
Requires: NET-201 toolchain already installed; Docker + Containerlab operational
System Requirements
- Linux (Ubuntu 22.04+ or Debian 12+) or macOS 13+; Windows via WSL2
- 16 GB RAM minimum (32 GB recommended for multi-node Containerlab topologies)
- Recent Linux kernel: 5.15+ for eBPF/XDP labs; 6.x preferred
- Docker Engine 24+ (rootful mode required for Containerlab)
- 40 GB free disk (topology images + NSM corpus)
Tool 1: Containerlab (Advanced)
NET-201 installed Containerlab; NET-301 extends it with production-grade topologies.
# Verify version -- 0.54+ required for EVPN/MPLS labs
containerlab version
# Upgrade if needed
bash -c "$(curl -sL https://get.containerlab.dev)"
NET-301 labs require FRRouting 9.x container image:
docker pull frrouting/frr:v9.1.0
Tool 2: MPLS in Linux Kernel
Chapter 1 (MPLS/Segment Routing) labs require MPLS kernel modules:
# Enable MPLS forwarding
sudo modprobe mpls_router
sudo modprobe mpls_gso
sudo modprobe mpls_iptunnel
# Make persistent
echo -e "mpls_router\nmpls_gso\nmpls_iptunnel" | sudo tee /etc/modules-load.d/mpls.conf
# Verify
lsmod | grep mpls
Tool 3: RPKI Validator (Routinator)
Chapter 3 (Internet-scale BGP / RPKI) uses Routinator from NLnet Labs:
# Via Docker (simplest)
docker pull nlnetlabs/routinator
docker run -d --name routinator -p 3323:3323 -p 8323:8323 nlnetlabs/routinator
# Verify after ~5 min (initial RPKI data sync)
curl http://localhost:8323/api/v1/status | python3 -m json.tool | grep valid_roas
Tool 4: Ansible Network Automation
Chapter 4 (network automation) requires Ansible with network collections:
pip3 install ansible ansible-lint netmiko napalm nornir nornir-napalm nornir-netmiko
# Install network collections
ansible-galaxy collection install cisco.ios juniper.junos arista.eos ansible.netcommon
# Verify
ansible --version
nornir --version # via: python3 -c "import nornir; print(nornir.__version__)"
Tool 5: eBPF/XDP Toolchain
Chapter 5 (performance engineering) requires the full eBPF development environment:
# Kernel headers
sudo apt-get install linux-headers-$(uname -r)
# eBPF/XDP tools
sudo apt-get install clang llvm libbpf-dev linux-tools-$(uname -r) bpftool
# libbpf (for compiling XDP programs)
sudo apt-get install libbpf-dev
# BPFtrace (dynamic tracing)
sudo apt-get install bpftrace
# Verify
bpftool version
bpftrace --version
eBPF/XDP programs require kernel 5.15+. Verify:
uname -r # should be 5.15+ for all XDP features; 6.x for BTF-based programs
Tool 6: Kubernetes + Cilium (Lab 6a)
Lab 6a (Cilium service-mesh) uses kind (Kubernetes in Docker):
# kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind && sudo mv ./kind /usr/local/bin/kind
# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl && sudo mv kubectl /usr/local/bin/kubectl
# Cilium CLI
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
curl -L --fail --remote-name-all \
"https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz"
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
cilium version --client
Tool 7: Suricata + Zeek (Cluster-Scale)
NET-201 installed single-instance Suricata and Zeek. NET-301 extends to clustered Suricata and log-pipeline Zeek:
# Suricata 7.x (cluster-capable)
sudo apt-get install suricata
# Verify cluster support
suricata --build-info | grep -i "af-packet\|runmode"
# Zeek (from repos -- distro packages are often old)
# Follow https://docs.zeek.org/en/master/install.html for current packages
# Verify Zeek cluster capability
zeek --version # should be 6.x+
Tool 8: SIEM (Wazuh or Elasticsearch)
Lab 7 (NSM pipeline) uses Wazuh or Elasticsearch/Kibana as the SIEM target. Docker Compose is the simplest path:
# Wazuh single-node Docker
curl -sO https://packages.wazuh.com/4.x/docker/docker-compose.yml
docker compose up -d
# OR Elasticsearch single-node
docker run -d --name elasticsearch \
-e discovery.type=single-node \
-p 9200:9200 elasticsearch:8.12.0
# Verify
curl -k http://localhost:9200/_cluster/health | python3 -m json.tool | grep status
Tool 9: QUIC/HTTP3 Tools
Chapter 9 (modern protocols) uses quiche CLI:
# Cloudflare quiche (Rust crate -- install via cargo or pre-built binary)
cargo install quiche-client quiche-server # if Rust is installed
# OR curl with HTTP/3 support
curl --version | grep HTTP3 # modern distro curls often include it
# Wireshark with QUIC dissector (version 3.6+)
wireshark --version | head -1
Tool 10: Wireless Lab Tools (Chapter 8)
Chapter 8 (wireless deep-dive) requires a wireless adapter that supports monitor mode:
# Aircrack-ng suite
sudo apt-get install aircrack-ng
# Hostapd (for lab AP setup)
sudo apt-get install hostapd
# RTL-SDR (if using hardware capture -- same adapter from wir-101)
sudo apt-get install rtl-sdr
# Verify monitor mode capability on your adapter
sudo airmon-ng check kill # kill conflicting processes
sudo airmon-ng start wlan0 # start monitor mode
sudo iwconfig wlan0mon # verify
NSM Corpus: Academy Lab pcap Stash
Labs 8 and 9 use the academy NSM corpus. Check it is available:
ls ~/academy-corpus/ 2>/dev/null || \
echo "Get corpus from: portal.virtuscyberacademy.org/net-301/corpus-download"
# Corpus contents:
# - normal-traffic-24h.pcap (~2 GB)
# - intrusion-lateral.pcap (~500 MB) -- multi-phase intrusion scenario
# - c2-beacon.pcap (~100 MB) -- C2 beaconing traffic
# - exfiltration-dns.pcap (~200 MB) -- DNS exfiltration scenario
Tool Journal: NET-301 Initial Entries
Add these entries to your Toolchain Diary on setup completion:
| # | Tool | Version | First use | Notes |
|---|---|---|---|---|
| 1 | Containerlab | containerlab version |
Lab 1 | Advanced: multi-AS MPLS topologies |
| 2 | FRRouting (9.x) | docker run frr vtysh --version |
Lab 1 | MPLS, Segment Routing, EVPN support |
| 3 | Routinator | docker run nlnetlabs/routinator routinator -V |
Lab 3 | RPKI validator; NLnet Labs |
| 4 | Ansible Network | ansible --version |
Lab 4 | Idempotent multi-device config automation |
| 5 | Nornir | python3 -c "import nornir; print(nornir.__version__)" |
Lab 4 | Python-native network automation framework |
| 6 | clang/llvm (eBPF) | clang --version |
Lab 5 | Compiles eBPF/XDP programs to BPF bytecode |
| 7 | bpftool | bpftool version |
Lab 5 | Load/inspect eBPF programs in kernel |
| 8 | BPFtrace | bpftrace --version |
Lab 5 | Dynamic tracing scripts; "dtrace for Linux" |
| 9 | Cilium CLI | cilium version |
Lab 6a | eBPF-native Kubernetes networking |
| 10 | kind | kind version |
Lab 6a | Kubernetes-in-Docker for Cilium labs |
| 11 | Suricata 7.x | suricata --build-info |
Lab 7 | Cluster-mode IDS/IPS |
| 12 | Wazuh / Elastic | curl localhost:9200 |
Lab 7 | SIEM ingestion target for Zeek logs |
Verify Everything
#!/bin/bash
# NET-301 setup verification script
echo "=== NET-301 Setup Verification ==="
echo ""
echo "Containerlab: $(containerlab version 2>/dev/null | grep version || echo MISSING)"
echo "Docker FRR image: $(docker image ls frrouting/frr:v9.1.0 --format 'OK' 2>/dev/null || echo MISSING)"
echo "MPLS kernel modules: $(lsmod | grep mpls_router | awk '{print $1}' || echo MISSING)"
echo "Ansible: $(ansible --version 2>/dev/null | head -1 || echo MISSING)"
echo "Nornir: $(python3 -c 'import nornir; print(nornir.__version__)' 2>/dev/null || echo MISSING)"
echo "clang: $(clang --version 2>/dev/null | head -1 || echo MISSING)"
echo "bpftool: $(bpftool version 2>/dev/null | head -1 || echo MISSING)"
echo "bpftrace: $(bpftrace --version 2>/dev/null || echo MISSING)"
echo "Cilium CLI: $(cilium version --client 2>/dev/null | head -1 || echo MISSING)"
echo "Suricata: $(suricata --version 2>/dev/null | head -1 || echo MISSING)"
echo "NSM corpus: $(ls ~/academy-corpus/*.pcap 2>/dev/null | wc -l || echo 0) pcap files"