Skip to content

Instantly share code, notes, and snippets.

@velis74
Last active May 21, 2018 18:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save velis74/ab75a46893eaed8bd08b8c6292b2737a to your computer and use it in GitHub Desktop.
Save velis74/ab75a46893eaed8bd08b8c6292b2737a to your computer and use it in GitHub Desktop.
Setting up a virtual LAN

Setting up a virtual LAN

Our goal: enable bidirectional access between host computer and hosted virtual machines on a shared virtual network. After setting this up, we will (be able to):

  • access VM from host
  • access host from VM
  • have internet access in VMs
  • declare port-forwarding from host to VMs

Generally, it will be (almost) like we inserted an additional router between our internet connection and VM host. The host itself will be part of two networks while the VMs will be available from host directly or from anywhere using NAT - port forwarding.

The guide lacks a configuration line for DHCP server to allocate IPv6 addresses as well. I'll get around to that as well some day.

Note

This guide was created setting this up on Ubuntu 17.10. YMMV with other flavours / versions.

1. Install bridge utilities

This provides us with capability to declare a bridge adapter which will host our DHCP server and forward VM internet traffic to our internet-connected network adapter.

sudo apt install bridge-utils

2. Add the necessary adapters to network configuration

We need to create a bridge adapter and a tap adapter which the VMs will use for their NIC.

file

/etc/network/interfaces

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

# Our additions start here:
# tap interface (VMs will use this one)
# also note the route add command, it adds reverse route for accessing office LAN via the OpenVPN connection
auto tap0
iface tap0 inet manual
    pre-up ip tuntap add tap0 mode tap user root
    up ip link set dev tap0 up
    up ip route add 192.168.237.0/24 via 192.168.100.10
    post-down ip link del dev tap0

# bridge
auto br0
iface br0 inet static
    address 192.168.100.1
    netmask 255.255.255.0
    bridge_ports tap0

3. Set up DHCP server

We're going to be using dnsmasq for that as it's quite easy to set up and use.

sudo apt install dnsmasq
file

/etc/dnsmasq.conf

domain-needed
bogus-priv
no-resolv
domain=vmhost.local
interface=br0
dhcp-range=192.168.100.5,192.168.100.254,255.255.255.0,1d
server=192.168.1.1  # whatever your actual DNS server is
server=8.8.4.4      # google's DNS server

# If you’d like to have dnsmasq assign static IPs to some 
# clients, bind the VM NIC MAC addresses:
# dhcp-host=aa:bb:cc:dd:ee:ff,192.168.100.4

4. Set up IP forwarding

We need it so that VMs actually gain internet access. Without this they will only have access to this virtual network that we just set up.

If we want this permanent, we also need the iptables-persistent package which will reload the iptables rules on boot.

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i br0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o br0 -j ACCEPT

Replace eth0 with your actual adapter with internet access.

sudo apt install iptables-persistent

If you already have iptables-persistent installed, you only need to save the current rules:

sudo iptables-save > /etc/iptables/rules.v4

Last we need to edit the sysctl.conf file so that we permanently enable IP forwarding. The two lines you need to uncomment (remove the leading #) are:

file

/etc/sysctl.conf

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

5. UFW rules

NAT

If you needed ufw to NAT the connections from the external interface to the internal the solution is pretty straight forward. In the file /etc/default/ufw change the parameter DEFAULT_FORWARD_POLICY

DEFAULT_FORWARD_POLICY="ACCEPT"

And then the locking of external interface / unlocking internal ones:

ufw allow in on eth0 to any port 1194
ufw allow in on eth0 port ssh
# the following two only if you require http redirection
ufw allow in on eth0 port http
ufw allow in on eth0 port https
ufw allow out on br0
ufw allow in on br0
ufw allow out on tap0
ufw allow in on tap0
ufw deny in on eth0

6. Run your virtual machine(s)

Make sure you set up network using a bridged adapter to tap0 we have set up.

7. Enabling memory page fusion

Base page https://www.virtualbox.org/manual/ch04.html#idm2459

My windows guest got completely messed up when I enabled this on it. Had to reinstall from scratch.

VBoxManage modifyvm <VM name> --pagefusion on

# See what metrics are supported
VBoxManage metrics list

# setup metrics collection (once per second, keep latest 5 samples)
VBoxManage metrics setup --period 1 --samples 5 host CPU/Load,RAM/Usage

# A complete metric name may include an aggregate function. The name has the following form: Category/Metric[/SubMetric][:aggregate]. For example, RAM/Usage/Free:min stands for the minimum amount of available memory over all retained data if applied to the host object.

# to query metric data on the CPU time spent in user and kernel modes by the virtual machine named "test", you can use the following command:
VBoxManage metrics query test CPU/Load/User,CPU/Load/Kernel

# RAM/VMM/Shared - shows total amount of page fused memory on host
# Guest/RAM/Usage/Shared - shows page fused memory on guest

8. Automatic start / stop of VMs

In /etc create two files:

vm_start

#!/bin/bash

# start VirtualBox VMs
/usr/bin/VBoxManage startvm "Windows development" --type headless
/usr/bin/VBoxManage startvm "linux development" --type headless
/usr/bin/VBoxManage startvm "django server template" --type headless

vm_stop

#!/bin/bash

iter=1
while [[ $(/usr/bin/VBoxManage list runningvms) ]]
do
    (VBoxManage list runningvms | grep -o '".*"' | tr -d '"') | while read vm;
    do
        echo "shutting down $vm"
        /usr/bin/VBoxManage controlvm "$vm" acpipowerbutton
    done

    sleep 1
    echo waiting for VMs to shutdown

    if [ "$iter" = "15" ]; then break; fi
    let "iter++"
done
ln -s /etc/rc.local /etc/vm_start
ln -s /etc/rc6.d/A00 /etc/vm_stop

SSH tunnels to virtual machines within

The following command is run on the client machine:

ssh -i ~/.ssh/id_tunnel -fNT -L 2000:192.168.100.20:3389 tunnel_host@server.velis.si

The other options are:

  • f tells ssh to background itself after it authenticates, so you don't have to sit around running something on the remote server for the tunnel to remain alive.
  • N says that you want an SSH connection, but you don't actually want to run any remote commands. If all you're creating is a tunnel, then including this option saves resources.
  • T disables pseudo-tty allocation, which is appropriate because you're not trying to create an interactive shell.

When the tunnel is created, you will have port 2000 accessible on your local machine for accessing the (RDP server) on one of the VMs at the server.

Of course, the server shoud have a dummy account for this purpose.

SSL certificates with letsencrypt and certbot

apt install python3-certbot-nginx

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