VMWare Server is no more… Long live VirtualBox

Well, it’s been a while since I last posted. There’s a lot been going on (major flat refurb), the results and process of which I shall be blogging about soon. In the interim however, I thought I’d write about an issue I encountered just today.

VMWare has unfortunately decided to end-of-life VMWare Server. This excellent free product allowed me to run multiple VMs on my home server, in a headless configuration, to provide certain resources on my network (DNS server, Radius, IPv6 router). Even better, when I inevitably messed up a kernel, or network config, the product allowed me to open up a console and play with the VM direct rather than relying on ssh.

Unfortunately, it is no more. And what’s worse, I hadn’t realised it was no more until I was part-way through my Gentoo update (up-time 235 days…). I went to recompile the VMWare kernel modules, and emerge informed me it wasn’t aware of any such package as vmware-server. D’oh!

So, what were my options:-

  1. Use VMWare Player or Workstation, in a headless configuration, using the vmrun command line,
  2. Use VMWare ESXi or similar
  3. Use an alternate virtualization technology – KVM, Xen, or VirtualBox

VMWare Player and Workstation are designed to be run with a GUI. Whilst they can be run in a headless configuration, I couldn’t (admittedly after minimal googling) see a way to get a VM console off them for the rare times I need one. So they were out.

ESXi etc are ‘bare-metal’ hypervisors, which would require a full server rebuild. My server is critical for me, and I don’t have any spare HDDs to put in a spare to try installing ESXi on. Plus, it’s a pretty old machine, and I’m not certain it would have the grunt to virtualize all the work I do on it. So they were out (although I like the idea for future reference).

Xen performance appears pretty iffy in most benchmarks I’ve seen.

KVM works well when all the VMs are linux. But they aren’t.

And that leaves VirtualBox. After some experimenting, this seems to work, and is the direction I’ve gone in. This blog details the steps I took to get it working…

So, let’s assume the following:-

  • Running an up-to-date version of Gentoo, with a semi-recent version of VMWare Server
  • Current VMs are stored in /var/lib/vmware/VMs/  with one dir per VM
  • Each VM has a single disk, but that disk is split into multiple files on the host (e.g. Gentoo2010.0-s001.vmdk, Gentoo2010.0.s002.vmdk, etc…)  It is an IDE driver
  • We are going to store all the new VMs in /data/VMs/   one directory per VM
  • You’ll want to get a copy of the MAC addresses of all the interfaces in the VM. We’ll assume de:ad:be:ef:b0:0b for the purpose of this
  • The VM is a Gentoo VM, called wibble

First of all, let’s install virtualbox

echo "app-emulation/virtualbox        -alsa doc extensions headless vboxwebsrv python java" >> /etc/portage/package.use
echo "=app-emulation/virtualbox-extpack-oracle-4.1.4  PUEL" >> /etc/portage/package.license
echo "=app-emulation/virtualbox-additions-4.1.4  PUEL" >> /etc/portage/package.license
emerge -av app-emulation/virtualbox

That should all automagically work. We’re now going to need to (optionally) transcode the VMWare hard drive into a virtualbox one, then create a VirtualBox VM, set up the VM, then run it. Then debug.

First of all, the hard-drive. VirtualBox does apparently now run with VMWare vmdk files natively, however some functionality (namely snapshots) allegedly don’t work. Furthermore, I was following some dated instructions when I did the below, so it may not be necessary. Your mileage may vary with other approaches, but I can tell you this definitely worked for me…

Important: Stop the VMWare VM before you do this to it!!! As soon as you’ve finished the first step, and have a .bin file, you can restart it.

Step 1) Convert VMWare HDD to VirtualBox format (optional)

You will need a qemu tool if you choose to convert the hdd file. So…

emerge -av qemu

Now we can do

# Combine all the <2GB files into one file
vmware-vdiskmanager -r Gentoo2010.0.vmdk -t 0 sda.vmdk
# Now convert it to VirtualBox format, via an intermediate format
qemu-img convert sda.vmdk sda.bin
VBoxManage convertdd sda.bin sda.vdi

Step 2) Set up VirtualBox (optional)

By default, VirtualBox stores VMs at ~/.VirtualBox/  but we want to change that to /data/VMs/

mkdir /data/VMs/
VBoxManage setproperty machinefolder /data/VMs/

Step 3) Create and register VM

Creating and registering a VM is trivial, but note that it is far from all that is needed. When you create a VM, you’re creating an XML file and a directory for it, and optionally registering the VM so the VirtualBox system know about it (allowing you to henceforth refer to it by name). You are not yet populating that VM with anything other than the defaults.

VBoxManage createvm --ostype Gentoo --name wibble --register

That has created a new directory /data/VMs/wibble/ with a configuration wibble.vbox within it. To get a list of supported OS types, try the following:

VBoxManage list ostypes

Step 4) Configuration

We’re first of all going to copy the vdi file in, and then do a load of configuration. I’ll inline notes here. Note that all of the configuration options can be done in a single command if desired.

# Move in the file
mv /var/lib/VMs/wibble/sda.vdi  /data/VMs/wibble/
#Set RAM to 256MB
VBoxManage modifyvm wibble --memory 256
#Disable USB
VBoxManage modifyvm wibble --usb off --usbehci off
#Disable Clipboard
VBoxManage modifyvm wibble --clipboard disabled
#Enable ACPI
VBoxManage modifyvm wibble --acpi on
#Create a single NIC, of the same type as VMWare, and bridge it to eth0. Set the MAC Address so the guest OS doesn't get confused
VBoxManage modifyvm wibble --nic1 bridged --bridgeadapter1 eth0 --nictype1 Am79C970A --macaddress1 deadbeefb00b
#As we still have VMWare installed and running, virtualbox doesn't have exclusive access. We can change this in the future
VBoxManage modifyvm wibble --hwvirtexexcl off
#Create IDE controller
VBoxManage storagectl wibble --name "IDE Controller" --add ide --controller PIIX4
#Attach HDD to controller
 VBoxManage storageattach wibble --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium /data/VMs/wibble/sda.vdi

We’re now almost good to go. The last item is support for a virtual/remote console. VirtualBox provides this through RDP. There has to be one port per running VM, and we’re going to assign it now. Note that I haven’t put any security on here – I strongly recommend you do so… Note that if you start a VM headless, VRDE will automatically be turned on anyway.

VBoxManage modifyvm wibble --vrde on --vrdeport 9999

Step 5) Running, Stopping

To run the VM it’s as simple as:

VBoxHeadless --startvm wibble

Note that this does not daemonize, which is useful for seeing logs, but not perfect for a server. I’ll leave daemonizing it etc as an exercise for the reader (because I haven’t gotten around to doing it myself yet, other than backgrounding it).

And to stop the VM, just do:

VBoxManage controlvm wibble poweroff

Finally, some other useful commands:

# Show the config
VBoxManage showvminfo wibble
# List all available VMs
VBoxManage list vms
#List running VMs
VBoxManage list runningvms

I hope the above proves to be of some use. As stated, your mileage will inevitably vary, but this has definitely worked for me.

Advertisements

Flash media server

I’m a bit of a geek, so I have lots of mobile gadgets. I’m also into Movies and (good) TV shows. I have archived many of my DVDs at home onto a server, so I have a lurvely home cinema setup throughout my flat. The only problem is that I want to watch these movies on my aforementioned gadgets.

Now option 1 is to copy the files over whenever I want them. Unfortunately I never quite know what I’ll want to watch, and I can’t carry all several TB around with me…

For some files I can just browse (via my shiny new VPN) to an Apache service and download/stream them off that. But what about the high quality DVD backups? And I recently moved to mkv as a container, and most mobile toys can’t handle .mkv files. Flash is a nice standardised (well, nice may not quite be the word…) protocol/media format. One option would be to transcode all the files. But that’s just stupid. In order to stream on my 1.5MBps up pipe I’m going to have to transcode the quality down a fair bit, and I don’t want to either lose all my nice high quality files nor have 2 copies of every file.

What I really needed was something which would stream, and transcode on the fly. Unfortunately such a thing didn’t exist, for free, anyway.

But fortunately, as previously stated, I am a geek. And a geek on holiday…

So, I have written FlashServer. The language of choice is C# as that way I get help from .Net for a load of things, and as I’m going to be throwing around a load of strings, I can’t be bothered with C++. Plus, with Mono I can develop on Windows and run on both Windows and Linux – useful as my linux server doesn’t have X…

The result: after around 24 hours of work, I now have a working web server, which allows me to browse specified ‘shares’, and stream movies off them – movies which are transcoded into flash on the fly. Performance seems sufficient for my 1-2 user use-case. There’s no rate limiting, so streaming it will use up a lot of the ‘up’ bandwidth – I may add that at a future date as it will be easy enough. Transcoding is done by ffmpeg, with specific settings set either via a couple of hard-coded profiles, or able to be chosen at start time. There’s no fast-forward or rewind, although you can start your playback from an arbitrary location.

The source is available for download (in MS VS Express 2010 solution format) from here. Note that you will need Inno Setup in order to use the installer (and will need to change paths etc).

Windows users, feel free to try the installer. FFMPEG is bundled with it in exe form. You’ll still want to tweak the conf file before use though. Note that .Net Framework 4.0 is used – install it from: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en

For linux users, and those who don’t want to use the installer, a zip is available. This contains the .exe, a readme, and a sample config file. Please read the README, as you’ll need to point to your installation of ffmpeg. Terrifyingly, the program worked first time with mono, so something will undoubtedly go cataclysmically wrong at some point…

Please let me know (by a comment below, or email: flashserver at ianpeters.net) if you use this, and if you have any feature requests!

Those links again:

VPN on PlayBook

I want to be able to access my files on the move, wherever I am. Whilst cloud services such as dropbox (www.dropbox.com) are fantastic, I have a few too many files to use these exclusively.

Also, many websites don’t use SSL for all their data, only for authentication. Whilst this protects your password, it doesn’t protect your session token after login. Thus anyone can sniff and steal it.

So, I decided to try to get my new toy – a BlackBerry PlayBook – working on my VPN. Until now I have been using my Cisco ASA as a VPN endpoint, but I don’t like how VPNs and ACLs work together on the ASA, and so decided to roll a new VPN in my DMZ. I used strongswan, and it was fantastically easy.

So my network looks like this:-

internet -- ASA -- extranet -- PIX -- dmz
                 |
             internal network

The extranet is a network which allows pretty-much unfettered access through the ASA, whereas the DMZ has a lot of controls put on it by both the PIX and the ASA. Note that the PIX is oriented so the external interface is facing the DMZ. IP address assignments are (all /24 subnets):-

  • ASA: outside=public static IP(outside_ip2), internal=10.1.1.1, extranet=10.1.98.1
  • PIX: extranet=10.1.98.2, dmz=10.1.99.2
  • ipsec server in dmz at: 10.1.99.10
  • pool of virtual IPs for ipsec clients: 10.1.100.0
  • dns server in internal at: 10.1.1.53

The VPN endpoint is on the dmz.

Step 1: Install and setup strongswan
I won’t cover installation, as it’s very distro-specific, however a few pointers:-

  1. Make sure you get the right kernel modules. I had a problem with this for a while. You need the following:-
    • PF_KEY sockets
    • IP: AH transformation
    • IP: ESP transformation
    • IP: IPComp transformation
    • IP: IPsec transport mode
    • IP: IPsec tunnel mode
    • IP: IPsec BEET mode
    • Network packet filtering framework (Netfilter)
      • Advanced netfilter configuration [Note: If you set this to N, you’ll get lots of the below for free – may be an easier way to do things]
      • Core Netfilter Configuration [M]
      • Netfilter connection tracking support [M]
      • (you may want to add all the protocols you’ll want to support) [M]
      • Netfilter Xtables support [M]
      • “esp” match support [M]
      • IPsec “policy” match support [M]
      • “state” match support [M]
    • IP: Netfilter Configuration
      • IPv4 connection tracking support [M]
      • IP tables support [M]
      • Packet filtering [M]
      • REJECT target support [M]
      • LOG target support [M]
  2. Install strongswan. I shall assume the /etc files go in the normal places.
  3. /etc/ipsec.conf
    config setup
    	# Some standard settings. We're not going to use certs, so I don't care about CRLs
    	crlcheckinterval=180
    	strictcrlpolicy=no
    	plutostart=no
    
    conn %default
    	ikelifetime=60m
    	keylife=20m
    	rekeymargin=3m
    	keyingtries=1
    	keyexchange=ikev2
    	dpdaction=clear           #What to do in the event of a dead peer
    	dpddelay=300s
    
    conn rem
    	left=10.1.99.10           #The IP of my IPSec endpoint
    	leftsubnet=0.0.0.0/0    #This will tell the client to send everything through me
    	leftauth=psk               #The server will auth to the client with a PSK
    	#leftfirewall=yes          #This could be set to auto modify iptables rules
    	right=%any
    	rightsourceip=10.1.100.0/24  #A pool of IPs to assign the client
    	rightauth=eap-mschapv2      #The client will auth with EAP-MSCHAPv2
    	righsendcert=never
    	eap_identity=%any
    	auto=start
  4. /etc/strongswan.conf [generally standard, but I added a couple of lines, as shown]
    charon {
    	dns1 = 10.1.1.53
    	dns2 = 87.194.255.154
    ...
  5. /etc/ipsec.secrets The PSK is for the server to auth to the client (but also IIRC needs to be known by the client even if it’s not being used for server auth), the EAP is the plaintext password of the user. They’ll need to supply domain, username, and password. Note: chmod 600 this file to root, as it contains plaintext passwords.
    : PSK longstring1
    domain\user : EAP "longstring2"
  6. A little gotcha here – I tried testing the PB at this point, but there seems to be some issue when it’s sat on the same net as the strongswan, so I moved straight to the next step…
  7. Firewalls. Both the ASA and PIX needed acl changes to allow the IPsec traffic through, and to allow the ipsec clients access to the internet. We are going to nat the ipsec endpoint onto outside_ip2.
    ASA:

    access-list outside_access_in remark Allow IPSec to ipsec server
    access-list outside_access_in extended permit esp any host outside_ip2
    access-list outside_access_in extended permit ah any host outside_ip2
    access-list outside_access_in extended permit udp any eq isakmp host outside_ip2 eq isakmp
    access-list outside_access_in extended permit udp any eq 4500 host outside_ip2
    eq 4500
    ; We want to allow anything from (inside, external) through (outside) to be nat'ed
    ; but traffic between inside and external shouldn't be. nat_exempt has a list of ACEs
    ; which will not be nat'ed
    global (outside) 1 interface
    nat (inside) 0 access-list nat_exempt
    nat (inside) 1 0.0.0.0 0.0.0.0
    nat (external) 0 access-list nat_exempt
    nat (external) 1 0.0.0.0 0.0.0.0
    access-group outside_access_in in interface outside
    ; Both the DMZ and VPN virtual IPs are on the other side of the PIX
    route external 10.1.99.0 255.255.255.0 10.1.98.2 1
    route external 10.1.100.0 255.255.255.0 10.1.98.2 1
    ; Finally, NAT the IPSec server onto outside_ip2
    static (external,outside) outside_ip2 10.1.99.10 netmask 255.255.255.255

    PIX:

    ; acl_int_inbound applies to any traffic going to the DMZ
    access-list acl_int_inbound remark Allow IPSec to ipsec host
    access-list acl_int_inbound permit ah any host 10.1.99.10
    access-list acl_int_inbound permit esp any host 10.1.99.10
    access-list acl_int_inbound permit udp any eq isakmp host 10.1.99.10 eq isakmp
    access-list acl_int_inbound permit udp any eq 4500 host 10.1.99.10 eq 4500
    access-list acl_int_inbound remark Allow remote administration
    access-list acl_int_inbound permit tcp 10.1.1.0 255.255.255.0 any eq ssh
    access-list acl_int_inbound remark Allow inbound useful ICMP
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 echo-reply
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 echo
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 source-quench
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 unreachable
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 time-exceeded
    ; acl_ext_inbound applies to any traffic coming from the DMZ
    access-list acl_ext_inbound remark Allow ipsec back out
    access-list acl_ext_inbound permit ah host 10.1.99.10 any
    access-list acl_ext_inbound permit esp host 10.1.99.10 any
    access-list acl_ext_inbound permit udp host 10.1.99.10 eq isakmp any eq isakmp
    access-list acl_ext_inbound permit udp host 10.1.99.10 eq 4500 any eq 4500
    access-list acl_ext_inbound remark Allow Access to some internal services
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 eq www
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 eq ssh
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 eq https
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 eq 8022
    access-list acl_ext_inbound remark Reserved to allow streaming in future
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 range 6000 6500
    access-list acl_ext_inbound remark Allow DNS
    ; note: this could cause problems for large DNS (e.g. DNSSEC) queries, as tcp will be used
    ;     to fix, just add two more rules to add 53/tcp
    access-list acl_ext_inbound permit udp 10.1.100.0 255.255.255.0 host 10.1.1.53 eq domain
    access-list acl_ext_inbound permit udp 10.1.99.0 255.255.255.0 host 10.1.1.53 eq domain
    ; we want to allow the DMZ unfettered access to the internet, but not to our internal network
    ; the easiest way to do this is explicitly deny access to the internal, and then allow everything else
    access-list acl_ext_inbound remark Deny access to any other internal network
    access-list acl_ext_inbound deny ip any 10.1.0.0 255.255.0.0
    access-list acl_ext_inbound remark But allow browsing of internet from ipsec
    access-list acl_ext_inbound permit ip 10.1.100.0 255.255.255.0 any
    access-list acl_ext_inbound permit ip 10.1.99.0 255.255.255.0 any
    ; PIX firewalls are predisposed to NAT from the internal to external interfaces.
    ; The global() and nat() rules stop that - I just want the PIX as a firewall.
    access-list nat_exempt permit ip any any
    global (outside) 1 interface
    global (inside) 2 interface
    nat (outside) 0 access-list nat_exempt outside
    nat (inside) 0 access-list nat_exempt
    access-group acl_ext_inbound in interface outside
    access-group acl_int_inbound in interface inside
    ; And finally, how to get out
    route inside 0.0.0.0 0.0.0.0 10.1.98.1 1
    route outside 10.1.100.0 255.255.255.0 10.1.99.10 1
  8. Pray. And test. This should be working now, once all the services are started etc. A trick for the debugging is follow the packets through your system. If it’s not working, use a packet capture in the ASA and PIX to see if you’re seeing the IKE traffic in _and_out. If you’re not, then it’s either a firewall or routing issue. To check both, use the packet-tracer command (on the ASA, PIX doesn’t have it). Also set up logging to a syslog server from both firewalls (note: make sure you do a “logging trap warnings” else you won’t see much). Finally, have “tail -f /var/log/messages” going to catch any messages from strongswan as well.
  9. On the PlayBook (and these instructions should generally apply to any client):-
    1. Go to “Options”->”Security”
    2. Scroll down to “VPN”
    3. Press “Add New” at the bottom
    4. Populate the fields:
      • Profile Name: [whatever you want]
      • Server Address: outside_ip2 [external IP of server]
      • Gateway Type: Generic IKEv2 VPN Server
      • Authentication Type: EAP-MSCHAPv2
      • Authentication ID Type: IPv4
      • MSCHAPv2 EAP Identity: [whatever you want]
      • MSCHAPv2 Username: domain\user [from above example (ipsec.secrets)]
      • MSCHAPv2 Password: longstring2 [from above example (ipsec.secrets)]
      • Gateway Auth Type: PSK
      • Gateway Auth ID Type: IPv4
      • Gateway Preshared Key: longstring1 [from above example (ipsec.secrets)]
      • Automatically Determine IP: checked
      • Dynamically Determine DNS: checked
      • Perfect Forward Secrecy: empty
      • Manual Algorithm Selection: empty
    5. Click “Save and Connect”, and cross your fingers…
    6. On the VPN page, you should see your new VPN profile added. If you click on the cog button on the bottom left, you should be able to see the nicely populated VPN details.
  10. And finally, enjoy.

Watching media on Playstation 3

My internal network architecture has a main server with a lot of my movies etc backed up onto, from my extensive DVD library. Previously I played these from the server itself, but keeping HDMI (+Audio), etc working proved to be a pain.

I tried watching the files from my XBox360, using Windows Media Server, but unfortunately I’ve used assorted new formats for the DVD backups (e.g. MKV) which Windows Media Server doesn’t support.

After casting around for alternatives, I found the PS3 Media Server (http://ps3mediaserver.blogspot.com/). This fantastic little utility transcodes and presents a DLNA compliant UPnP interface to your network. This works on my PS3 very very well, and may work on others.

The only pain point I experienced was setting up the (java) program to run nicely on my linux box. So I knocked up the below, completely abusing ‘screen’ as an aside.

#!/sbin/runscript

depend() {
        need net
}

start() {
        ebegin "Starting PS3 Media Server"
        pushd /usr/local/pms-linux-1.10.5 > /dev/null
        /usr/bin/screen -d -m -S PMS ./PMS.sh
        eend $?
        popd > /dev/null
}

stop() {
        ebegin "Stopping PS3 Media Server"
        /usr/bin/screen -r PMS -X quit
        eend $?
}

SSH on a PlayBook / Smartphone

I’ve been using WebShell (http://www-personal.umich.edu/~mressl/webshell/) for a while now. Great little tool, very easy to setup and easy to use.

To use it, download it and stick it somewhere in your filesystem. You’ll need to have python (2.3+) and optionally OpenSSL.

I then (on Gentoo) created the below little script in /etc/init.d/webshell:

#!/sbin/runscript

PID="/var/run/webshell.pid"

depend() {
        need net
        use dns logger
}

checkconfig() {
        return 0
}

start() {
        checkconfig || return 1
        ebegin "Starting ${SVCNAME}"
        start-stop-daemon --start --exec /var/www/WebShell-0.9.6/webshell.py \
                -c nobody \
                -- "-i" "10.1.1.1" "--ssl-disable" "-d"
        eend $?
}

stop() {
        ebegin "Stopping ${SVCNAME}"
        if [ -f ${PID} ]; then
                start-stop-daemon --stop --pidfile ${PID}
        else
                ewarn "Couldn't found ${PID} trying to stop over the process name ${SVCNAME}"
                start-stop-daemon --stop --name ${SVCNAME}
        fi
        eend $?
}

Where 10.1.1.1 is the IP of the host.