It’s time to automate my lab builds with Vagrant. I decided to try and complete 2 Pluralsight courses at the same time over the next 3 months, Suricata: Getting Started, and Scanning for Vulnerabilities with NSE. If you’ve watched any of my previous courses you know that I often do a basic walk through of the lab environment I use, and leave it to you if you want to replicate it.

I just want to say, I don’t like doing this. I apologize that up until now, I didn’t have a better solution. The reason for a brief explanation is due to time constraints. I don’t think anyone wants a 1+ hour walk through of a lab build. However, based on some of you that reached out, my current guide is not enough.

After a week of long nights after work, I have a solution that you can easily deploy using Vagrant. I created three vagrant boxes and stored them on the Vagrant cloud (https://app.vagrantup.com/mattglass). Then I wrote a Vagrant file that you can use to deploy the lab in Virtualbox. I also wrote a file to deploy each machine individually if you want. The machines download and come preconfigured to route between your LAN and an internal Virtualbox network. You just need to make some minor configuration changes to this file.

The Vagrantfile

If want to get started now, here is the file to deploy three machines:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# This script deploys the network for Suricata: Getting Started in VirualBox

# IMPORTANT: If you want to automate as much as possible, you need to 
#   reconfigure the bridge to map to your interface name and the 
#   default gateways to your networks.


Vagrant.configure("2") do |config|
  config.vm.synced_folder '.', '/vagrant', disabled: true
  
  config.ssh.username = 'vagrant'
  config.ssh.password = 'vagrant'
  config.ssh.keys_only = false
  
  # Create Ubuntu Machine
  config.vm.define "ubuntu" do |ubuntu|
    ubuntu.vm.box = "mattglass/ubuntu18-PS"
	ubuntu.vm.box_version = "0.0.2"
    ubuntu.disksize.size = '30GB'

    # Modify the bridge name to match your interface
	ubuntu.vm.network "public_network", bridge: "Intel(R) Dual Band Wireless-AC 7260", 
	  auto_config: false
    ubuntu.vm.network "private_network", virtualbox__intnet: "LAN",
	  auto_config: false


    # Modify the default gateway here to match your network
	$script = <<-SCRIPT
	echo Configuring network routing and forwarding...
    iptables -t nat -D POSTROUTING 1
	route add default gw 192.168.1.1
	route delete default gw 10.0.2.2 dev enp0s3
	SCRIPT
	
	# Applies the script above
	ubuntu.vm.provision "shell", run: "always", inline: $script

	
	# Virtualbox settings
	ubuntu.vm.provider "virtualbox" do |vb|
	  vb.gui = true
	  vb.name = "Ubuntu 18.04"
	  vb.memory = "1024"
	  vb.cpus = "2"
    end
  end
  
  config.vm.define "meta2" do |meta2|
    meta2.vm.box = "mattglass/metasploitable2-PS"
    meta2.vm.box_version = "0.0.1"

    meta2.vm.network "private_network", virtualbox__intnet: "LAN", auto_config: false
	
	$script = <<-SCRIPT
	echo Configuring network routing and forwarding...
	route add default gw 10.0.0.251
	route delete default gw 10.0.2.2 dev eth0
	SCRIPT
	
	# Applies the script above
	meta2.vm.provision "shell", run: "always", inline: $script

    meta2.vm.provider "virtualbox" do |vb|
      vb.gui = true
      vb.memory = "512"
	  vb.cpus = "1"
	  vb.name = "Metasploitable 2"
    end
  end
  
  config.vm.define "meta3" do |meta3|
    meta3.vm.box = "rapid7/metasploitable3-ub1404"
	meta3.vm.box_version = "0.1.12-weekly"
	meta3.vm.hostname = "metasploitable3-ub1404"
	
	meta3.vm.network "private_network", ip: "10.0.0.101", virtualbox__intnet: "LAN"
	
	$script = <<-SCRIPT
	echo Configuring network routing and forwarding...
	route add default gw 10.0.0.251
	route delete default gw 10.0.2.2 dev eth0
	SCRIPT
	
	# Applies the script above
	meta3.vm.provision "shell", run: "always", inline: $script
	
	meta3.vm.provider "virtualbox" do |vb|
	  vb.name = "Metasploitable3-ub1404"
	  vb.memory = "2048"  
    end
  end
end

Vagrantfile Walkthrough

If you’re new to Vagrant, then you may benefit from a more detailed explanation of each of these parts and pieces. First, the beginning of the Vagrant file. This section contains comments describing function, purpose, and important notes. The first line initiates the build (Vagrant.configure…). This line begins all Vagrant files and identifies the “config” variable used in the next few lines.

# -*- mode: ruby -*-
# vi: set ft=ruby :

# This script deploys the network for Suricata: Getting Started in VirualBox

# IMPORTANT: If you want to automate as much as possible, you need to 
#   reconfigure the bridge to map to your interface name and the 
#   default gateways to your networks.


Vagrant.configure("2") do |config|

Next are some global settings that apply to all three machines. Each machine uses the default Vagrant credentials (vagrant/vagrant). All machines use username and password for authentication instead of the Vagrant SSH keys. Metasploitable 3 uses username and password, so I set all of the machines to use the same. As a result, my environment doesn’t operate like a typical Vagrant environment, but the machines run and operate as I intended.

  config.vm.synced_folder '.', '/vagrant', disabled: true
  
  config.ssh.username = 'vagrant'
  config.ssh.password = 'vagrant'
  config.ssh.keys_only = false

Now It Makes the VMs

After the global configuration options comes the Ubuntu machine that is acting as a router between the two networks. This allows you to control access to these vulnerable VMs (although the firewall is completely open initially). You can also simulate accessing these machines from the Internet. Ubuntu is the primary machine for Suricata: Getting Started.

The first block gets my Ubuntu image from the Vagrant cloud and resizes the disk to 30GB. The next section configures the machine with 2 additional interfaces set to a bridged network and an internal Virtualbox network called LAN. Vagrant automatically configures an interface set to NAT. This VM provisions with a script to remove that gateway and ensure traffic routes to my LAN. My initial box had NAT configured using iptables, but I decided to remove that using the iptables line in the script.

Finally, there are Virtualbox specific configurations that display the GUI on load, rename the machine, configure the amount of RAM (1GB), and assign the number of CPUs.

config.vm.define "ubuntu" do |ubuntu|
    ubuntu.vm.box = "mattglass/ubuntu18-PS"
	ubuntu.vm.box_version = "0.0.2"
    ubuntu.disksize.size = '30GB'

    # Modify the bridge name to match your interface
	ubuntu.vm.network "public_network", bridge: "Intel(R) Dual Band Wireless-AC 7260", 
	  auto_config: false
    ubuntu.vm.network "private_network", virtualbox__intnet: "LAN",
	  auto_config: false


    # Modify the default gateway here to match your network
	$script = <<-SCRIPT
	echo Configuring network routing and forwarding...
    iptables -t nat -D POSTROUTING 1
	route add default gw 192.168.1.1
	route delete default gw 10.0.2.2 dev enp0s3
	SCRIPT
	
	# Applies the script above
	ubuntu.vm.provision "shell", run: "always", inline: $script

	
	# Virtualbox settings
	ubuntu.vm.provider "virtualbox" do |vb|
	  vb.gui = true
	  vb.name = "Ubuntu 18.04"
	  vb.memory = "1024"
	  vb.cpus = "2"
    end
  end

Creating the other two…

The rest of the script follows the same pattern to deploy a Metasploitable 2 and Metasploitable 3 Ubuntu VM. The Metasploitable 2 VM is my first attempt at creating a Vagrant box from an existing VM. It’s not perfect, but it does work well enough, and I apologize in advance. Metasploitable 3 deploys directly from Rapid7’s Vagrant cloud. I made a couple of changes to networking to make it work from this internal network.

  config.vm.define "meta2" do |meta2|
    meta2.vm.box = "mattglass/metasploitable2-PS"
    meta2.vm.box_version = "0.0.1"

    meta2.vm.network "private_network", virtualbox__intnet: "LAN", auto_config: false
	
	$script = <<-SCRIPT
	echo Configuring network routing and forwarding...
	route add default gw 10.0.0.251
	route delete default gw 10.0.2.2 dev eth0
	SCRIPT
	
	# Applies the script above
	meta2.vm.provision "shell", run: "always", inline: $script

    meta2.vm.provider "virtualbox" do |vb|
      vb.gui = true
      vb.memory = "512"
	  vb.cpus = "1"
	  vb.name = "Metasploitable 2"
    end
  end
  
  config.vm.define "meta3" do |meta3|
    meta3.vm.box = "rapid7/metasploitable3-ub1404"
	meta3.vm.box_version = "0.1.12-weekly"
	meta3.vm.hostname = "metasploitable3-ub1404"
	
	meta3.vm.network "private_network", ip: "10.0.0.101", virtualbox__intnet: "LAN"
	
	$script = <<-SCRIPT
	echo Configuring network routing and forwarding...
	route add default gw 10.0.0.251
	route delete default gw 10.0.2.2 dev eth0
	SCRIPT
	
	# Applies the script above
	meta3.vm.provision "shell", run: "always", inline: $script
	
	meta3.vm.provider "virtualbox" do |vb|
	  vb.name = "Metasploitable3-ub1404"
	  vb.memory = "2048"  
    end
  end
end

Enjoy the script, and I look forward to your comments on my two new courses at the end of the year. As always, feedback on how this can be improved is welcome.