h a η m i n ψ • n g

b e s t v i e w e d w i t h

:

f i r e f o x

Security

Modified: 16th August 2008

Tutorial - How to secure your Mac Leopard with VirtualBox (any Virtual machine) and ipfw


Introduction - If you came into this page directly, you can get the introduction here

Objective - The objective of this tutorial is to run a virtual machine (VM) inside a host machine (in this case, a Mac OSX Leopard) to serve the necessary services. The idea is that in the event of a security breach, due to various reason (bug exploit, human error, brute force attack, etc.), only the VM is being compromosed while the host machine will remain operational. It will be like the movie The Thirteenth Floor, a world within a world. For those that haven't really seen this movie, imagine 'The Matrix'. This method not only protect the host machine from becoming the victim of an attack, in the event that the security in the VM has been breached, restoring the system is a much easier process. We shall see this later.

For my real life configuration, I have set up my system to have 2 services running in the VM machine and at the same time try to hide the real SSH of the host machine, as illustrated in Figure 1. The Achilles' heel of this configuration is that, performing a full 65535 port scan on the host machine will reveal 2 SSH services. And if there were to be an exploit or human error on the host machine, the consequences would be severe. However, due to the low number of users (less than 3) on my machine, and hence, the chances of brute-forcing a uncommon username with mix characters and numbers, and guessing a secure password are way too low. And, with the history (not spotless, but clean enough) of the OpenSSH standard, I'm taking the near impossible chance for the sake of convenience. However, for those that are really concern (or as my friend said, paranoid) about server security, you may try the loop back configuration, illustrated in Figure 2. However, in this tutorial, I will cover the configuration of Figure 1, but the additional steps to setup configuration 2 would be the same.


Figure 1: My current configuration, running a Linux in the virtual machine insider my Mac Leopard with ipfw redirecting the incoming traffic to the VM. The only real port available is the SSH service, which I have changed to a higher port number, port X.


Figure 2: A more secure configuration. This configuration utilizes the ipfw to reject all connection from other hosts except our own virtual machine running locally, with a fixed ip. The host.allow (provided by ssh service) list can also be used to provide additional barrier, if necessary. However, from what it seems it does't serve much purpose as ipfw should have taken care of this at the very front end. Unless the Mac is being scanned using the virtual machine, port X will look as if it is closed.

The 'ingredients' - For this 'recipe' demonstration, we use the following items.

  • Host machine : Mac OSX Leopard
  • Virtual machine (VM): VirtualBox
  • VM OS: Linux - Debian
  • Firewall: ipfw
  • The choice of VM software is flexible. However, since VirtualBox is free, it'll make it easier for others to implement. For other VM software, the steps would be relatively the same. As far as I know, for other well established VM softwares such as VMWare Fusion and Parallel, linking the virtual port to the host port is much easier (i.e. GUI selectable). I've not tested them out. Anyone with experience with these two, please let me know.

    As for the VM's OS, I was initially advised by my friend to use FreeBSD as it is the most reliable [uptime chart link to be added here later] hosting OS. However, while VirtualBox does seems to support FreeBSD (it has the FreeBSD option in the list of guest OS), I'm not able to successfully install FreeBSD into VirtualBox. I'm getting various error message upon installing. Same for Fedora. Anyone with luck installing these into VirtualBox, please let me know. NOTE: To avoid flaming, the choice of selecting these OS are relatively random, other than the FreeBSD is seemingly the best amongst the other OS, the sequence of choosing these OS doesn't imply that I think Fedora is better than Debian.

    Step 1: Setting up the VM - Installing the VirtualBox is pretty easy. The VirtualBox 1.6 for Mac that I've used comes in a DMG format with PKG installer, which is basically a click Ok, Next, Next, Next, Finish (not the real click sequence) installation. After the installation, you need to create a VM in VirtualBox. For my machine setting, I use the default and the following configuration.

  • VM Name: DebianVm
  • Hardisk: IDE (SATA controller disabled), 5GB, fix-sized
  • RAM: 1GB (during installation) and 256MB (now after being told that I'm being silly)
  • Network Adapter: Intel PRO/1000 MT Desktop
  • Others: Enable (default) ACPI
  • Most of the settings on the VM are personal preference, and it should not matter much as long as you are able to install the guest OS into the VM. I've shown the VM name that I'm using, because the name matters at the later section on the command to key in. If you were to use a different name, it may be confusing a bit, but not difficult to change the command to suit your VM settings. Similarly, the choice of the network adapter will determine the code used later to bridge/link/connect the VM port to the host machine port (the default adapter is 'AMD PCNet FAST III'). As for the ACPI (Advanced Configuration and Power Interface) on the VirtualBox, you should enable that, as we shall see later, is useful for shutting down the VM in 'headless' (no display) mode.

    Step 2: Installing and configuring the guest OS in the VM - Installing the Debian into the VM is easier than the 2 other OS that I've tried before this. I used the Debian CD ISO image for i386 for my Mac (Intel). The file name for the ISO is debian-40r4a-i386-kde-CD-1.iso. I used most of the default and standard options during the installation. The installation is quick and painless, as I found out later, because the Debian CD does not have all the required packages. However, most packages (i.e. apache) can be obtained using the 'apt-get install' command.

    After installing the Debian, and starting the VM, the OS should work out of the box with access to the internet too. Just use the KDE (my installation is a KDE version) browser to test the internet connection. Once that passed through, it is a matter of installing the apache (web server) and the ssh. To install the apache, just switch to root (i.e. su -) and type in 'apt-get install apache2', and it will install everything accordingly. Some tutorial for installing apache in Debian. Debian Help, and Debian admin.

    The next thing to do is to enable the SSH service. The SSH is important for the VM as it allows you to log into the VM to perform tasks, and also allows you to trasnfer file in between without using the VM (VirtualBox, in this case) folder sharing feature. To get and install SSH, just use the command 'apt-get install ssh'. If I remember correctly, this will then give you two choices to choose from. And I think the command that actually install the SSH is 'apt-get install OpenSSHxxx' where xxx is some version number. Anyway, this Debian apt-get makes things simple. Once you have both services installed, they ought to be launched and running at the background. For my case, I've also installed mysql and Logwatch (recommended) using the same 'apt-get install' method. I don't recommend Logcheck as it produced way too many logs/alerts and needs to be tweak (some time and Debian log knowledge required) for it to be useful.

    Step 3: Bridge/Link/Connect the VM port to the real world - This steps took me quite a while to do it, reason is that I have choosen to use the Intel network adapter for my VM, thinking that it will probably get recognized easier. However, most of the instructions available from the internet are based on the default settings (i.e. using the AMD PCNet FAST III network adapter).

    To setup the VM-HostMachine connection, you need to first shutdown the VM. If you are using the 'Intel PRO/1000 MT Desktop' for your VM, then you open a terminal (at your host machine - Mac Leopard), and key in the following 3 commands. IMPORTANT: You need to modify the commands below to suit your configuration (i.e. your VM settings). The command 'VBoxManage' should have been installed in '/usr/bin' upon installing VirtualBox.

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/HostPort" 10000

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/GuestPort" 22

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/Protocol" TCP

    For the code above, replace 'DebianVm' with the name you have given to your VM. The value '10000' (you may use any port you want, I choose 10000) is the port in the host machine (Mac), which the VM port will connect to. I have tried choose the host port 22, however, the machine just throws me an error message. I suspect that for any low number port, you may require administrative rights (yes, I have) in any one of the steps or in a particular way. However, using ipfw, the host port use is no longer important, as anyone outside your Mac will see the same result.

    The value '22' (that is the default SSH port. Unless you have modified the SSH port in the guest OS, you should use 22) indicate the port at the VM side. Use the protocol 'TCP' for both webservice and SSH. As for the 'ssh' you see at the commands above, this string value is customizable. It is used as identifier to link these 3 commands together. You replace 'ssh' with 'sshService' if you wish. Now, really important bits on this 3 commands is the 'e1000' word. This 'e1000' indicate the network adapter your VM is using. If you are using the default adapter (AMD PCNet FAST III), you should replace 'e1000' the 3 commands above with 'pcnet'.

    Similarly, you key in the *similar* 3 commands for the apache port 80, to host Mac 10001 port. Note that the word 'apache' in the command line is of preference, not a fix value. However, I would highly recommend you to try the ssh port first before attempting to do the same (similar) to the apache port.

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/apache/HostPort" 10001

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/apache/GuestPort" 80

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/apache/Protocol" TCP

    If you are as curious as me on how to get the value 'e1000' for the commands above (i.e. incase you got a newer version of VirtualBox using differnet network adapter), read on. Or else, just skip to Step 4. -- The value 'e1000' can be seen inside your VM's log file. The log file should be at the directory where VirtualBox keeps its record of all VM, inside the user Library folder. For example, for my case, the log file is in (/Users/xxxx/Library/VirtualBox/Machines/DebianVm/logs/VBox.log), where 'xxxx' is the username. If you open this file, you should see all configuration of your VM in words (confusing one). Look for something that looks like this.

    00:00:00.750 [/Devices/e1000/0/Config/] (level 4)
    00:00:00.750 AdapterType = 0x0000000000000000 (0)
    00:00:00.750 MAC = "01 00 57 1f 87 a3" (cb=6)
    00:00:00.750 CableConnected = 0x0000000000000001 (1)
    00:00:00.750 LineSpeed = 0x0000000000000000 (0)

    Where you have a collection of 'AdapterType' and 'MAC'. Here, you see that the 'e1000' is at the section header. There is where you get the network adapter code 'e1000'.

    Step 4: Check the connected port - Checking the connection of the VM to the host Mac's port is easy, as any mistake made on your 3 commands (for each service port) will cause the VM unable to start, throwing out messages about not being able to find the MAC address. If this happen, it is likely that you have use the 'e1000' or 'pcnet' incorrectly. Please read the section on how to retrieve the correct adapter code for your VM via its log page.

    If you have set everything up correctly, you should be able to start your VM (start using the VirtualBox installed at your 'Application' folder in your host machine). To check that the port is connecting (e.g. checking the SSH on the VM), just open a terminal (or whatever SSH client software you use), and point to 'localhost' using the port you have specified. In my case, I open a terminal window, and key in the value.

    ssh yyyy@localhost -p 10000

    Where 'yyyy' is the username at the VM and '10000' is the port in the host machine (Mac) where I have the VM port 22 connected to. If everything is correctly setup, you should be able to log into the VM.

    However, in the case where things doesn't work out, you will have to delete the settings that you have just added. To delete the settings, just key in the same 3 commands without the last word (i.e. '10000', '22', and 'TCP'). Hence, for the above 3 commands for 'ssh', we use the following commands to clear the settings and start over again (note the value at the end of each command is removed).

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/HostPort"

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/GuestPort"

    VBoxManage setextradata "DebianVm" "VBoxInternal/Devices/e1000/0/LUN#0/Config/ssh/Protocol"

    To verify that you have successfully deleted your settings, just start the VM to see if you have been thrown the same error messages. In case things really get out of hand, you can always create a new VM and point it to the same hardisk file. If the configuration is the same, your VM should start up as usual with the installed OS.

    Step 5: Setting ipfw, forward and blocking the VM port on the host machine - ipfw comes with Mac OSX Leopard. To verify, just do a

    sudo ipfw view

    command, using one of the user in the host machine (Mac) with administrative right. You should see a relatively small list of lines like. Just incase you are not aware of this, Mac does not allow you to 'su' into root as most Linux does. It just allow you to perform task with root privilege using the command 'sudo'. You should be asked to key in your own user's password when you enter the command above.

    33300 deny icmp from any to me in icmptypes 8
    65535 allow ip from any to any

    The above ipfw rule, (taking rule 33300 for example) basically means that, for rule 33300, 'deny' ('icmp') protocol from 'any' host/ip to this computer ('me'), going 'in' of type 'icmptypes 8'. For the rest of this tutorial, we should setup ipfw using the similar grammar.

    If you should able to get VirtualBox to connect the port to the host port 22, then you may skip this step. If you were to able to do it, please let me know how. Anyway, to setup the connection, it is recommended to find a ipfw rule number that is not used. Example, using the command 'sudo ipfw view' to see which rule number (1st column). In Mac OSX Leopard, as the firewall is of the 2nd layer, most of the rule number should not be use. The good thing about using a specific rule number rather than just 'adding' it into the table is that it can be remove safely later if you decided not to use the rule. Now, to use ipfw to perform port forwarding, use the command

    sudo ipfw add 20000 fwd localhost,10000 tcp from any to any 22 in

    The above command grammar is much like Yoda talk, it basically said add rule '20000' which forward 'fwd' *to* the host machine 'localhost', port '10000', for all 'tcp' protocol traffic from any host (external machine) 'any' to any localhost idenfications (127.0.0.1, external, or LAN ip address) 'any' port '22' traffic 'in'. In short, it just said add rule 20000 that forward any traffic from port 22 into port 10000.

    Further from the command above, as we have connected the VM port to our host port 10000, external host (computer) will be able to see that our port 10000 is open. Hence to avoid this, we shall close/block the port 10000. To block port using ipfw, use the following command.

    sudo ipfw add 20010 reset ip from any to any 10000 in

    Similarly, the above rule said, add rule '20010', which 'reset''ip' traffic from 'any' (external) ip to 'any' (host machine) ip, port '10000', 'in' traffic. This will make the host machine port 10000 look as it is closed. Note that, since we are blocking traffic from all ip, even if you try to nmap your own port 10000, you will get a respond as if there is not service opened at the port.

    In cases where you wish to remove the ipfw rules, just use the command below, using the rule number instead of 'xxxxx' you want to delete. Use 'sudo ipfw list' to view the rule number of the rule you want to remove.

    sudo ipfw del xxxxx

    Step 6: Setting ipfw, blocking port such that only host machine may access - the above blocking method deny access from all ip (including yourself) from access the port. However, services such as mysql that you may want to access locally, but not exposed to the outside world. While there is method of blocking mysql from accepting requests from external hosts, it is safer to display to the outside world that you don't even have mysql running, so don't even borther (and also just incase of any new exploitable bugs). To block a port from being accessed, except the localhost, use the following pair of commands

    sudo ipfw add 20020 allow ip from localhost to localhost 3306 in

    sudo ipfw add 20021 reset ip from any to any 3306 in

    The above command pair, adds rule '20020' that 'allow' 'ip' protocol from 'localhost' to 'localhost' at port '3306' 'in' traffic. Rule '20021' will block all other traffic accessing port '3306'. Note: In this example, the blocking rule should come after the allow rule, or else all traffic (including yours)

    Step 7: Setting ipfw, blocking port such that only LAN machine may access - to be continued...