Installing an OS in VirtualBox on a Headless FreeBSD Server

Using Virtualization one is able to run a full computer operating system inside of an existing operating system. I’ve been using VirtualBox for years to virtualize many kinds of operating systems for many different reasons on my desktop computers. I first started using VirtualBox to run a Windows installation so I could do things I needed to do in Windows that I had not yet figured out how to do with a free/open source operating system (at that time Ubuntu). As I came to familiarity with *nix platforms, I wanted to try out new techniques I learned and I used VirtualBox to accomplish this. With this program I could have a sandbox where I could easily create, save, snapshot and destroy virtual desktops, servers, and networks. On my new FreeBSD server I wanted to use virtualization to create test servers that I could use while I learn about new software and refine what I know about system administration and computer programming.

The thing this time around is my server has no dedicated monitor. I’ve always used the GUI to interact with the VirtualBox software, but now I needed a way to do all the things I do with VirtualBox with a Command Line Interface (CLI). And that’s how I became introduced to VBoxManage. If you have your system’s VirtualBox package installed you should have VBoxManage installed as well:

~$> VBoxManage
Oracle VM VirtualBox Command Line Management Interface Version 4.3.10_OSE
(C) 2005-2014 Oracle Corporation
All rights reserved.


VBoxManage [] General Options: [-v|--version] print version number and exit [-q|--nologo] suppress the logo [--settingspw ] provide the settings password
[--settingspwfile ] provide a file containing the settings password


list [--long|-l] vms|runningvms|ostypes|hostdvds|hostfloppies|
---output omitted---

Typing in VBoxManage every time I wanted to issue a command to VirtualBox did not appeal to me at all so I quickly made a bash alias:

~$> echo "alias vbm='VBoxManage'" >> .bash_aliases && source .bash_aliases

Before we go any further, VirtualBox requires some kernel modules to be loaded.

~$ sudo kldload vboxdrv
~$ sudo kldload vboxnetadp

Okay, now we can get some work done. First create the VM and the virtual disk this machine will use.

~$ vbm createvm --name t0 --ostype FreeBSD --register
UUID: e18a1e47-69a0-4487-8114-2d4381141d32
Settings file: '/home/jason/VirtualBox VMs/t0/t0.vbox'
~$ vbm createhd --filename VirtualBox\ VMs/t0/t0.vdi --size 2000
Disk image created. UUID: 1a1ff4fa-db67-4b1b-b597-fd0453ed82ac

We can now list out the VMs to verify we created the device, then take a look at the profile of a virtual machine with the showvminfo command.

~$ vbm list vms
"t0" {e18a1e47-69a0-4487-8114-2d4381141d32}
~$ vbm showvminfo t0
---output omitted---
~$ ls VirtualBox\ VMs/t0/
t0.vbox t0.vbox-prev t0.vdi

Now that the machine exists (virtually), we need to install a storage bus, and then add devices – namely a hard drive and a dvd drive – to it.

~$ vbm storagectl t0 --name sata_bus --add sata --portcount 4 --bootable on
~$ vbm storageattach t0 --storagectl sata_bus --port 1 --type hdd --medium VirtualBox\ VMs/t0/t0.vdi
~$ vbm storageattach t0 --storagectl sata_bus --port 2 --type dvddrive --medium downloads/FreeBSD-10.0-RELEASE-i386-disc1.iso

Let’s verify:

~$ vbm showvminfo t0|grep sata_bus
Storage Controller Name (0): sata_bus
sata_bus (1, 0): /usr/home/jason/VirtualBox VMs/t0/t0.vdi (UUID: 1a1ff4fa-db67-4b1b-b597-fd0453ed82ac)
sata_bus (2, 0): /usr/home/jason/downloads/FreeBSD-10.0-RELEASE-i386-disc1.iso (UUID: c277d5b5-e7e6-4172-9ea7-253a5a23d38e)

So there exists a virtual machine and it has a blank virtual hard drive and a dvd drive installed. Inside the dvd drive is the FreeBSD installation disc. At this point we could start the VM and install the OS, but how do we connect to the virtual server? Well we need to install a virtual network interface card and setup bridged networking. This will allow us to easily connect to the VM and give it access to the Internet so we can download any packages necessary for installation.

~$ ifconfig
ath0: flags=8802 metric 0 mtu 2290
ether 00:25:56:22:d5:60
nd6 options=21 media: IEEE 802.11 Wireless Ethernet autoselect (autoselect) status: no carrier alc0: flags=8843 metric 0 mtu 1500
options=c3198 ether 00:23:5a:e0:0e:42 inet netmask 0xfffffff0 broadcast inet6 fe80::223:5aff:fee0:e42%alc0 prefixlen 64 scopeid 0x2 nd6 options=29 media: Ethernet autoselect (100baseTX )
status: active
lo0: flags=8049 metric 0 mtu 16384
options=600003 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3 inet netmask 0xff000000 nd6 options=21 ~$ vbm modifyvm t0 --nic1 bridged --bridgeadapter1 alc0 --nictype1 82540EM ~$ vbm showvminfo t0 | grep NIC NIC 1: MAC: 08002770C671, Attachment: Bridged Interface 'alc0', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth group: none NIC 2: disabled NIC 3: disabled NIC 4: disabled NIC 5: disabled NIC 6: disabled NIC 7: disabled NIC 8: disabled

Above, the first thing that I did was list out the network interfaces of the physical machine (with ifconfig). I did this to determine the which network interface I was going to bridge to (the one connect to the outside network). Each VM can have 8 NICs. With second command I set NIC 1 to be a bridged interface to alc0, my wired ethernet, and to emulate an Intel 82540EM Gigabit Ethernet Controller. Now when the VM powers up it will have network connectivity.

Now we can install the operating system. Because the FreeBSD install disc does not establish an IP address without user interaction, I needed to forward X11 through my SSH connection. At first I received an error when I tried to do the X11 forwarding, but I followed this tutorial and cleared that error.

jason@desktop ~$ ssh -X jason@hostserver
~$ # I connected to host server with ssh -X for ssh forwarding
~$ # now I start the vm on the host server and I can interact
~$ # with it with the GUI on my desktop
~$ vbm startvm t0

With our setup the VM will boot the FreeBSD installation media in our dvd drive

After the OS is installed, you’ll want to eject the dvd drive so that when you reboot, you won’t reboot back into the install cd.

~$ vbm storageattach t0 --storagectl sata_bus --port 2 --medium none

Now the OS is installed and (if you set it up that way) it will obtain an IP address on boot and start the SSH server that you can connect to from another machine

~$ vbm startvm t0 --type headless
Waiting for VM "t0" to power on...
VM "t0" has been successfully started.

Preventing SSH Known Hosts Enabled Island Hopping

Upon connecting to an OpenSSH server, the server sends its public key to the
client so that the user on the client side can verify that the server they
are trying to connect to is indeed the server they expect it to be (and not an
attacker spoofing the desired SSH server). Once initially verified, the server’s
key is then stored in the $HOME/.ssh/known_hosts file. Proper use
of this system mitigates SSH Spoofing attacks, but by default it also
presents a data leak that could be utilized by someone who has cracked your system.

When securing a system, we would like to believe our efforts will thwart any
any such attempts at penetration; but any good security plan should consider how
to minimize damage in the event that an intruder does gain access. By default
the keys in known_hosts are referenced in plain text:

$ cat $HOME/known_hosts
$, ssh-rsa AAAAB3NzaC1yz2EAAAADAQABAAABAQC/TLO38IPrLW18kgKx4BQmPGmOXaIKRyTGTFtOT4tCph9ORyb7Mh0SlIe1bowqOFcNI6LUNcrloiTFd9wvAljTHriZJASEOy6uCBf1cKcwX/TpjtiA2uJ7mzosmeoB0PFAxCmKvb2xGXGIsjFOHYWSOitKqxj9r9JUAAURgzb5teml9/bcsMz05qZtkS4EmvYAFXXSaqLNiT+Q3UCjj2GD3mSGqyuy4ad+pEENXNf10D/hMxQBiedH4jNhUJSqTCtJtfVf7532OP7qvQ4PISbh3itEmrFBelkDxlC+3mxFFOzk/SyYWf16Roc9xsnR5HK7mGYG4N4YcxYaioCV1Nd9

The problem here is that if an attacker found a vulnerability in your security
and gained access to a single machine, all they would need to do is run the above
command and they would have a list of hosts on the network that possibly have
the same vulerability. This is a type of an Island Hopping attack, in
which an attacker gains access to a ‘weak link’ in the network and then ‘hops’
around from system to system. We can prevent this type of attack by hashing the
hostnames in our known_hosts file.

Hashing will take our human readable hostname (and ip address) and transform
it into something like


Which is virtually useless to an attacker, but OpenSSH will have no problem
utilizing. To configure our server to hash hostnames automatically, set the
following directive in /etc/ssh/ssh_config:

HashKnownHosts yes

To hash existing entries in your known_hosts use:

ssh-keygen -H

This command will copy your $HOME/.ssh/known_hosts file to
$HOME/known_hosts.old with all the plain text hostnames and replace
the known_host file with hashed hostnames. It would be wise to verify
this replacement file will allow you to connect to remote hosts before removing
the known_hosts.old file.

Creating VLANs Using Cisco IOS

VLANs can easily be implemented on Cisco switches to improve network layout as well as security and efficiency. With VLANs we are able to, with software, logically separate ports on a switch (or other network device) into discrete groups that function as their own independent LANs. For example, let’s say we are designing a network for a small school that will provide access to the Internet via a 48 port switch. We want to separate the Faculty and Staff network devices from Students and Guests.

For our internal network we will be using a network address, and we will divide our network into two subnets, for the faculty and staff (Fac/Staff) and for students and the Public (Students). Now let’s set up our VLANs on the switch.

In IOS, enter config mode

Switch#configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.

Next we will create the VLANs and give them a name. I don’t think naming the VLAN is required, but it is recommended.

Switch(config)#vlan 10
Switch(config-vlan)#name facstaff
Switch(config)#vlan 20
Switch(config-vlan)#name students
%SYS-5-CONFIG_I: Configured from console by console

Let’s take a look at our VLAN set up.

Switch#show vlan brief

VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
1    default                          active    Fa0/1, Fa0/2, Fa0/3, Fa0/4
Fa0/5, Fa0/6, Fa0/7, Fa0/8
Fa0/9, Fa0/10, Fa0/11, Fa0/12
Fa0/13, Fa0/14, Fa0/15, Fa0/16
Fa0/17, Fa0/18, Fa0/19, Fa0/20
Fa0/21, Fa0/22, Fa0/23, Fa0/24
Gig1/1, Gig1/2
10   facstaff                         active
20   students                         active
1002 fddi-default                     active
1003 token-ring-default               active
1004 fddinet-default                  active
1005 trnet-default                    active

VLAN 1 is the default VLAN and all ports are members of it. VLANs 1002 – 1005, are also assigned by default, as show. We are going to split the 24 FastEthernet ports between the two new VLANs. We will take advantage of the ability in IOS to configure a range of interfaces at a time.

Switch#configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.
Switch(config)#interface range fastEthernet 0/1-12
Switch(config-if-range)#switchport mode access
Switch(config-if-range)#switchport access vlan 10
Switch(config)#interface range fastEthernet 0/13-24
Switch(config-if-range)#switchport mode access
Switch(config-if-range)#switchport access vlan 20

%SYS-5-CONFIG_I: Configured from console by console

Switch# show vlan brief

VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
1    default                          active    Gig1/1, Gig1/2
10   facstaff                         active    Fa0/1, Fa0/2, Fa0/3, Fa0/4
Fa0/5, Fa0/6, Fa0/7, Fa0/8
Fa0/9, Fa0/10, Fa0/11, Fa0/12
20   students                         active    Fa0/13, Fa0/14, Fa0/15, Fa0/16
Fa0/17, Fa0/18, Fa0/19, Fa0/20
Fa0/21, Fa0/22, Fa0/23, Fa0/24
1002 fddi-default                     active
1003 token-ring-default               active
1004 fddinet-default                  active
1005 trnet-default                    active

Protecting Against SSH Server Spoofing

To defend against SSH server spoofing – where an attacker sets up an SSH server and masquerades as another in order to capture users’ login credentials – every SSH server has a unique public key that can be utilized to verify that servers identity. This key is located in the /etc/ssh/ directory, and is used by clients to encrypt communications with the server. In turn, the server must use its private key to decrypt these communications.

The key is a rather long string of random characters and not very useful for humans, but a fingerprint of the key can be produced which is more compatible with the operating system of the mind. The first time an SSH client connects to an SSH server, this fingerprint is displayed.

The authenticity of host ' (' can't be established.
ECDSA key fingerprint is 03:ed:6d:1f:ff:56:9d:5f:f3:65:20:b5:ad:55:55:87.
Are you sure you want to continue connecting (yes/no)?

This prompt is asking the user to verify the offered fingerprint (the fingerprint of the server) against a known good fingerprint under their control. But how is this done? At the time the SSH server is installed and the public/private key pairs are generated, the SSH server administrator can fingerprint the server and distribute this fingerprint to users who will access the server. One can do such fingerprinting with the ssh-keygen program:

ssh-keygen -lf /etc/ssh/ 
256 03:ed:6d:1f:ff:56:9d:5f:f3:65:20:b5:ad:55:55:87  host (ECDSA)

The -l option instructs the program to show the fingerprint, and f for a key file. Simply direct the output the above command to a file and distribute that file to users who will be connecting to the server.

ssh-keygen -lf /etc/ssh/ > server_fingerprint.txt

To get a look at the server’s public key fingerprint before attempting a connection, one can utilize the ssh-keyscan program

ssh-keyscan -t ecdsa > tmp
ssh-keygen -lf tmp 
256 03:ed:6d:1f:ff:56:9d:5f:f3:65:20:b5:ad:55:55:87 (ECDSA)

Here the -t is for type of key to be scanned (which can be rsa1 for protocol version 1, dsa, ecdsa, ed25519, or rsa for protocol version 2). The output is redirected to a temporary file named tmp, then the file is checked with the ssh-keygen program.

Once client has verified the fingerprint, it will store a copy of the server’s public key in $HOME/.ssh/known_hosts and will check the stored key on subsequent connections to that host. If the server has changed its keys, or another machine is attempting to spoof the real server, the client will notice and will not allow connections to that host.