Skip to content

Instantly share code, notes, and snippets.

@JonTheNiceGuy
Created September 26, 2016 19:33
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JonTheNiceGuy/b278401176a26af1d1ad9018f90b6ea8 to your computer and use it in GitHub Desktop.
Save JonTheNiceGuy/b278401176a26af1d1ad9018f90b6ea8 to your computer and use it in GitHub Desktop.
Building Labs - A Basic Overview

Building a Lab network

The basics

Jon@Sprig.gs / @JonTheNiceGuy / @g7vri


Overview

  • Introduction
  • What is a Lab?
  • A basic lab
  • A note on networking
  • A little bit of config
  • Complicated labs
  • My lab!

Introduction

  • Network Security Professional for > 10 years
  • Interest in Linux and Open Source

What is A Lab

For the purpose of this presentation

"A lab is an environment in which you can perform the same test twice and get the same results"


A Basic Lab

Virtual Machines

  • Virtual Devices
    • VM Snapshots
    • Clone VMs
    • OVA Files
    • Vagrant
  • Physical Devices
    • Appliances
    • Servers
    • Laptops

Note: VM Snapshot: Very fast, adds files to system per snapshot, can be cumulative Clone VMs: May be difficult to do depending on Hypervisor OVA files: Not platform independant, but can be massaged to work between VMWare, VirtualBox, ESXi, Hyper-V. Vagrant: My go-to system. Simple text files, pre-packaged "Box" files. Basically clones VMs from a known working state, and runs post-install customization.


A Basic Lab

Provisioning

  • Home Made
    • Shell Scripts
    • Powershell
    • Batch Files
  • Tools
    • Puppet
    • Chef
    • Ansible
    • Salt

A note on networking

  • You should learn some basic networking before creating labs.
    • Routing
    • Port Forwarding
  • Understand interface types
    • Bridged interfaces are like physically plugging in to your network.
    • NAT interfaces "Hide" behind your host IP address
    • Private networks are (typically!) inside your host machine

A little bit of config

  • Vagrant
    • -> Linux
    • -> Windows
    • -> Several Machines at once
  • Ansible
    • -> Create users

A little bit of config

Vagrant

mkdir Lab-A
cd Lab-A
vagrant init ubuntu/trusty64
vagrant up

Note: Remember that you need to create your vagrantfile in a new directory. The vagrantfile path is exposed to the VM in /vagrant or c:\vagrant

A little bit of config

Vagrant -> Linux

Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.synced_folder "/mnt", "/mnt/host"
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
  end
  config.vm.provision "shell", inline: <<-SHELL
    sudo apt-get update && sudo apt-get install -y sendemail
  SHELL
  config.vm.provision "shell", run: "always", inline: <<-SHELL
    /vagrant/RunProcess | /vagrant/sendemail 
    sudo shutdown -h now
  SHELL
end

Note: Here we define a standard box - This has been created on a public server, it should not be trusted. For confidential builds, build your own and host internally, replace config.vm.box with config.vm.url.

Attention to: synced_folder, vb.memory and provisioning - "run: always" versus "run: once"


A little bit of config

Vagrant -> Windows

Vagrant.configure(2) do |config|
  config.vm.box = "opentable/win-2012r2-standard-amd64-nocm"
  config.vm.hostname = "server"
  
  config.vm.provision :shell, path: "shell/InstallChocolatey.cmd"
  config.vm.provision :shell, path: "shell/InstallBoxStarter.bat"
  config.vm.provision :shell, path: "shell/RunBoxstarter.ps1"
  
  config.vm.network "public_network", bridge: "eth1.200", 
    ip: "192.0.2.10"
  config.vm.provision :shell, run: "always",
    inline: "route delete 0.0.0.0"
  config.vm.provision :shell, run: "always",
    inline: "route add 0.0.0.0 mask 0.0.0.0 192.0.2.1"
end

Note: Really untrustworthy build - not from a vendor.

Attention to: Define hostname, public_network, note that this is a windows box and is running cmd and bat files (also PS1 files). Routing on public network interfaces is problematic at best!!


A little bit of config

Vagrant -> Several Machines at once

Vagrant.configure(2) do |config|
  config.vm.box = "opentable/win-2012r2-standard-amd64-nocm"
  config.vm.define :v401a do |v401a|
    v401a.vm.hostname = "v401a"
    v401a.vm.network "public_network", bridge: "em2.401", 
      ip: "10.40.1.11"
  end
  config.vm.define :v401b do |v401b|
    v401b.vm.hostname = "v401b"
	v401b.vm.box = "ubuntu/trusty64"
    v401b.vm.network "public_network", bridge: "em2.401", 
      ip: "10.40.1.12"
  end
end

Note: Attention to: Config creates two machines, defines hostnames and separates out box files to use. Note no post config is here. Contrived example drawn from complex personal scripts.

A little bit of config

Ansible

ssh-copy-id root@linux1

# Windows Machines need https://raw.githubusercontent.com/ansible/
#  ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1

ansible -m setup 

ansible-playbook site.yml

A little bit of config

Ansible -> Starting up

  • hosts
[Core_AD]
192.0.2.1
[Core_Linux]
192.0.2.1[1-5]
  • group_vars/all/vault
default_password: DreadfullyInsecure
admin_users:
  spriggsj:
    name: Jon Spriggs
users:
  bloggsf:
    name: Fred Bloggs

Note: Use ansible-vault encrypt to convert the plaintext vault file to an encrypted one.


A little bit of config

Ansible -> Create Windows Users

  • ad.yml
- hosts: Core_AD
  roles:
   - ad
  • roles/ad/tasks/main.yml
- name: Create User in AD
  raw: if (dsquery user -samid "{{item.key}}") {"Not Required"} else
    {New-ADUser -SamAccountName "{{item.key}}" -UserPrincipalName 
    "{{item.key}}@labby.mclabface" -Name "{{item.value.name}}" 
    -DisplayName "{{item.value.name}}"
    -GivenName "{{item.value.name.split(" ")[1]}}" 
    -Surname "{{item.value.name.split(" ")[-1]}}" 
    -ChangePasswordAtLogon $true -Enabled $true 
    -AccountPassword (ConvertTo-SecureString "{{default_password}}" 
    -AsPlainText -Force)}
  with_dict: "{{users}}"
  tags: users 

A little bit of config

Ansible -> Create Linux Users

  • linux.yml
- hosts: Core_Linux
  roles: common_linux
  • roles/common_linux/tasks/main.yml
- include: user.yml
  tags: users
  • roles/common_linux/tasks/user.yml
- name: Create role for Sudo Group
  lineinfile: "dest=/etc/sudoers state=present regexp='^%sudo' 
    line='%sudo ALL=(ALL) NOPASSWD: ALL' validate='visudo -cf %s'"
- name: Creating Admin Users
  user: name="{{item.key}}" uid="{{item.value.uid}}" 
    comment="{{item.value.name}}" groups=sudo shell=/bin/bash 
    password="{{default_password | password_hash('sha512') }}" 
    update_password=on_create
  with_dict: "{{admin_users}}"

Complicated Labs

  • VLAN Tag your switches
  • Route (or better - Firewall) between VLANs
  • Create disposable network segments (or "Pods")
  • Unified authentication using Radius, Kerberos and Active Directory
  • Ansible for Infrastructure (Linux, Windows, ESXi, but not switches!)

Note: For all Windows' failings, it's very easy to set up MS Active Directory, and even easier to add Radius Authentication to that model. Linux will do Kerberos authentication against Active Directory, as will ESXi.

The network segments should be isolated from each other by a firewall. This means an impacting change on one pod will not impact any other. The firewall will also perform routing and hide NATs where required.

Ansible is not able to reconfigure older Cisco or Juniper switches. It can be coerced into making changes to Checkpoint firewalls, but will not work out-of-the-box.

My lab

  • Back-to-back firewalls from "Live" areas, into "Core" terminal servers
  • Terminal servers have full access to all pods
  • Terminal servers are MS Windows virtualized on Linux systems - which means SSH can be used to bring them back online.
  • Using ser2net to provide telnet access to serial ports over USB
  • NAS for shared storage of Vagrant Boxes, mounted on all VM servers

My lab

AsciiArt

  • Physical Topology
{CORP_NET} -> {CORP_FW} -> {LAB_FW} -> {LAB_DSL}
                               |
                        {VLAN_SWITCHES}
                               |
                             / | \
            POD_NET1 <------/  |  \----> POD_NET2
                               |
                          {CORE_NET}
  • Firewall Rules
Permit: CORP_NET -> Core_Net : RDP
Deny  : CORP_NET -> Core_Net : Any
Deny  : Any      -> CORP_NET : Any
Permit: Core_Net -> Any      : Any
Deny  : Any      -> Core_Net : Any
Permit: POD_Nets -> Internet : Any
Deny  : Any      -> Any      : Any

Any questions?


@jontheniceguy

@g7vri

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment