This article is aimed at those who use a headless linux server. It is split into two parts: Virtulization and Networking.
Setting up QEMU-KVM!
QEMU is a sick "generic and open source machine emulator and virtualizer." It's probably available on most Linux distros.
QEMU exists as a binary file. You simply call it (
/usr/lib/x86_64-linux-gnu/qemu) and pass the relevant arguments.
KVM is a component of the Linux kernel. You could think of it as an API for virtualization. Simply; It allows for the QEMU process to communicate with the CPU more efficiently. It also exists as a binary (
/usr/bin/kvm) which serves as a wrapper for the QEMU binary.
Installation is trivial, simply install
qemu-kmv and supporting packages.
apt install qemu-kvm libvirt-clients libvirt-daemon-system virtinst
Then you can setup a virtual machine like so
virt-install \ --name=windows10 \ --virt-type=kvm \ --ram=4096 \ --cpu=host \ --vcpus=2 \ --os-type=windows \ --os-variant=win10 \ --disk path=/mnt/thicc/data/windows10.qcow2,size=40 \ --cdrom /mnt/thicc/data/public/Software/WindowsX.iso \ --network bridge=br1337 \ --graphics vnc,listen=0.0.0.0
Anyway, when you run that command
virt-install will bring the Virtual Machine (VM) up and then wait for the VM to shutdown as signal that the guest Operating System (OS) installation has concluded. Now would be a good time to CTRL+Z and
bg that process, as it will hold your tty.
I'd recommend installing a VNC viewer on your local machine and then port forwarding to your remote remote linux system (if you're on a different network). This is done like so:
ssh -L 5900:127.0.0.1:5900 email@example.com Your SSH client will listen on
5900 at your local system and tunnel data to
You can use
ss -tulpn to figure out which TCP port QEMU is hosting the VNC server on. It should be 5900 for your first running VM, and increments by 1 for every existing instance.
Use the VNC Viewer to complete the OS installation.
Controlling your Virtual Machine
Now that you've setup a VM, you're probably eager to learn how to start it. Enter
virsh is a command line utility provided by
libvirt. It's actually super powerful and extends beyond QEMU - it can be used to manage LXC, Xen, and OpenVZ hosts too, all from the single command line.
Pretty neat, eh?
VMs are referred to as
domains and often you need to specify a domain argument as
Top 10 Anime Betrayals top few commands you should know:
destroy destroy (stop) a domain - Terminates a running VM immedaitly. edit edit XML configuration for a domain - Edits and reloads the XML description for a domain. undefine undefine a domain - Removes a domain from inventory. vol-delete delete a vol - Deletes a volume. Requires a pool argument, if unconfigured use '--pool default'
Yeah so that's cool. You should read the next section on networking for information on how to isolate your virtual machines into segregated networks.
Modifying your Virtual Machine
Pretty straight forward, you can use
virsh and then run
edit --domain myvmname and it'll open up the domain's descriptor file in your editor. When you exit, it'll automatically reload the domain refreshing the changes into inventory.
This is useful if you later setup a VLAN, and then want to change an existing VM to run on said VLAN. You can use
edit and then search for
interface and modify accordingly.
Bridges with brctl
/etc/network/interfaces as it's persistent interface configuration file.
interfaces file may look something like this:
# The loopback network interface auto lo iface lo inet loopback # The primary network interface auto enp37s0 allow-hotplug enp37s0 iface enp37s0 inet dhcp
This is pretty standard, one local loopback device and one ethernet device.
SO BRIDGES are pretty good. They're essentially virtual switches. The kernel (and everything else) treats them just like it would a physical network interface.
apt install bridge-utils
Bridges functionally put a physical ethernet device into a slave state and then provide a virtual interface to use instead (eg:
br0). It is
br0 that your IP address would be bound to.
You can then attach other NICs to that bridge interface, or attach virtual machine NICs to it.
(Out of scope: If you want to use
bridge-utils to route incoming packets over network segments, see
Bridges can be setup transitively via
brctl, or persistently within
# The loopback network interface auto lo iface lo inet loopback # The primary network interface allow-hotplug enp37s0 iface enp37s0 inet manual auto br0 iface br0 inet dhcp bridge-ports enp37s0 up ifconfig enp37s0 up
Note: Physical device
enp37s0 was changed from
manual. Check the manual for
bridge-utils-interfaces - it contains everything you need.
(I'm not sure if you really need
up ifconfig enp37s0 up ¯\(ツ)/¯.
bridge-utils should bring up the interfaces it needs automatically.)
You can use
brctl show to validate the currently configured and operating bridges.
Please be careful when working with headless/remote systems. If you fuck up the network stack you're not going to have a very good time.
Now you've got your VMs operating on your LAN, great! When one of your VMs gets owned the attacker will have access to everything else on your network :D
pfSense and VLANs
First, get yourself a bigboy router. Something that's running pfSense would be great. Checkout ebay or wherever for boards featuring something like the Intel J1800/J1900 or Intel E3845 (has AES-NI) CPU and has at least TWO NICs. Intel would be best, but Realtek is fine too.
A good place to start is literally searching for "pfSense router". Once you've got that covered:
Head to Interfaces -> Assignments -> VLANs and register a VLAN. (
1337 is used as demo throughout this article)
Now Interfaces -> Assignments and assign your VLAN to an interface.
Be sure to enable the interface, set the IPv4 to static (or whatever, it's your network), and specify an address and subnet size. Use an RFC1918 private network.
Go to Firewall -> Aliases and create an alias for the RFC1918 networks.
Go to Firewall -> Rules and set some rules. In the above screenshot I have:
- Allowed DNS traffic to pfSense.
- Blocked traffic to other RFC1915 networks
- Allowed all other traffic
That's pretty much it. You might want to setup a DHCP instance too. Depending on your switch you may also have to explicitly allow trunking on ports.
SO VLANs THEN
Assuming you've already got some VLANs setup on your network, it's super easy to create more bridge devices on those VLANs. Adjust your
/etc/network/interfaces to include something like:
auto br1337 iface br1337 inet manual bridge-ports enp37s0.1337 allow-hotplug enp37s0.1337 iface enp37s0.1337 inet manual vlan-raw-device enp37s0
In case you are lost, that's a VLAN (
1337) interface set to
manual and a bridge named
br1337 to slave it. Also note that the
br1337 device is set to manual. This is so my Virtual Machine host does not interact with the 1337 vlan - it merely exists as a physical host for the bridge interface, and downstream VM.
Anyway, you create an interface to TX/RX on the vlan (
iface enp37s0.1337 inet manual) and then slave it to a bridge. The parent interface is specified, delimited by a period, and then the VLAN ID is appended. (You can also use vlan### if you want. Eg
(In writing this, I wonder if you could do
vlan-raw-device enp37s0.1337 and skip creating the
enp37s0.1337 sub-interface. 🤔)
You should know how to use the
ip command suite by now. If you don't heres a crash course:
ip a - 'ip address' - shows network addresses and broadcast domains - replacement for ifconfig ip l - 'ip link' - shows interface status - replacement for ifconfig ip r - 'ip route' - shows routing information - replacement for route ip n - 'ip neighbor' - shows other known hosts on the network - replacement for arp
If you have more than a couple of VLANs and more than a couple of VMs, that's gonna be a huge list of interfaces and addresses now. You’re a real pro now - congratulations! condolences?
As I described earlier in Modifying your Virtual Machine, you can set the VM to operate on a VLAN bridge interface. In
brctl show that looks like this:
A m80 of mine made this when I fucked up my networking stack.