Tim's Blog

Information, Technology, Security, and other stuff.

Secure and Free Disk Imaging Solution for Windows and Linux

Published 2015-07-27

I'm now running 7(!) active machines in my home network (a mixture of Windows 8.1, Server 2012 R2, CentOS 7 and Raspbian), and I've been hunting for a backup solution that satisfies the following requirements:

  • The Backups are Compressed,
  • The Backups are Encrypted,
  • The Windows Backups are full "bare metal" recovery backups,
  • The Backup Storage isn't "managed" by the backup tool, and finally
  • It's free (or really cheap).

Now there are heaps of tools that can meet most of those requirements, but they either refuse to install on Windows Server (making you purchase an Enterprise/Server licence) or they want to manage the backup storage and freak out if something changes there by outside influence. I can't afford to fork out $1k or more for a piece of software just to back up my home machines. They aren't exactly critical infrastructure.

Windows Server, and especially with the Essentials feature enabled, offers a completely automated backup product out-of-the-box, but I got frustrated by the lack of control you get over it. It'll run daily backups whether you like it or not, and it'll quickly fill the storage location if you don't have much space to spare.

Compression is really important to me for keeping storage requirements down, and Encryption is critical for preventing data compromise. I have full disk encryption enabled on all of my machines, but full disk images don't get that same protection. Why bother attacking a network to get data if all I need to do is snatch a copy of the backups?

So I run all my backups to a network share (samba), which is just a single 1TB USB drive connected to my server. Once the drive is full, it gets swapped out for an empty identical drive. The full drive is stored offsite, and I just cycle between those two drives. It works out to be roughly every 60 days I have to swap them over, which is a comfortable backup age for me. And it meets one of the key tenants of backup, to have a copy offsite.

What I Tried

This is everything I tried that failed:

  • UrBackup: A great free product that meets every requirement on my list, but I just couldn't get it working on CentOS. I suspect with a little more time it'll be on my radar again.
  • EaseUS Todo Backup: Meets most of the Windows requirements, but has its own proprietary file format and a strange restriction on the length of the password for the encryption keys.
  • Amanda: Easy tool to install, but doesn't do full disk imaging of Windows machines.
  • Bacula: Easy like Amanda, and worked really well with Linux, but can't do full disk imaging of Windows machines. Also doesn't do encryption.
  • Bareos: Couldn't get it running and working correctly at all.
  • Running Disk2VHD to create a VHD of the OS drive, and then encrypting that with 7zip. I found though that 7zip couldn't encrypt the Disk2VHD file though, as the OS would still hold a lock on it for some unknown period of time.

So on to what actually worked...

The Windows Solution

wbadmin is the tool of choice here, as it comes with Windows as the standard backup tool. I created a PowerShell script to run as a Scheduled Task on a weekly basis, at 2am:

$date = Get-Date -Format "yyyy-MM-dd"
$backupWorkingDir = 'G:' # note: You can't specify a subdirectory. Only the root drive directory works.
$computerName = {computer_name}
$backupDirectory = $backupWorkingDir + '\WindowsImageBackup'
$backupStorageDirectory = '\\{server_name}\Backups\'
$logfile = $backupWorkingDir + '\' + $computerName + '-Backup-' + $date + '.log'
$backupFilename = $backupStorageDirectory + $computerName + '-Backup-' + $date + '.7z'

Start-Transcript -path $logfile -append
wbadmin start backup -backupTarget:$backupWorkingDir -allCritical -quiet -vssFull
7z a -t7z -mx2 $backupFilename $backupDirectory -p{complex_password}
Remove-Item -Recurse -Force $backupDirectory
Stop-Transcript

wbadmin, with the -allCritical switch, will run as bare metal backup backing up whatever drives the OS is installed on and dependent on. 7zip, with the -mx2 switch, will compress at level '2' compression, which isn't too high, but it doesn't really need to be very high for this task. And 7zip can encrypt using an AES key generated by a password you provide it (with the -p switch). I've also enabled logging with the Start-Transcript cmdlet, as we want some history to be able to troubleshoot if it fails in the future.

Now I could just direct the backup itself to the network share and then encrypt it there, but then there's a period of time where it's "exposed" as an unencrypted backup. Instead I've opted to just backup to an internal local drive, then send that backup encrypted up to the server, and finally just delete the original backup files.

This script will work on both Windows 8.1 and Server 2012 R2 machines. I would test on others, but I don't have any other OS's running in my environment. I don't see why it wouldn't work on Windows 7/Server 2008 either as wbadmin was bundled with them and PowerShell is there too.

The Linux Solution

Linux offers far more simple and elegant backup solutions. It frustrates me it isn't as easy on Windows, but we just have to deal with what we have available. I've opted for the most simple solution by just tarballing the whole machine and encrypting it with OpenSSL. GnuPG is also a viable alternative, but I got frustrated and gave up trying to stop it prompting for the passphrase. I could also use 7zip, just like the Windows backups, but then I have to install yet another package.

To protect against malware like cryptolocker I don't permanently mount the backup directory, only keeping it open whilst we run the backup. The same applies with the Windows backup, as I point to the network share but don't mount it (from what I remember cryptolocker just runs through any mounted network shares).

These instructions are for CentOS, but it'll most likely apply as-is to any of the other distros (with adjustments to the package installation part):

# elevate
sudo su

# install prerequisites
yum install cifs-utils -y

# create samba credentials (you'll need these domain credentials already made in the domain, and have them allowed to access the backups share)
useradd -u 5000 serveruser
groupadd -g 6000 serveruser
touch /root/smb-credentials
echo "username=domainuser" >> /root/smb-credentials
echo "password=CoMpLeXpAsSwOrD" >> /root/smb-credentials
chmod 0600 /root/smb-credentials

# create the bash script
mkdir /scripts
touch /scripts/weekly-backup.sh

Fill the script with the following, replacing {computer_name} and {server_name} with their respective names:

#/bin/sh
# mount the backup directory
mkdir /mnt/backups
mount -t cifs -o uid=5000,gid=6000,rw,credentials=/root/smb-credentials,file_mode=0775,dir_mode=0775 //{server_name}/Backups /mnt/backups

# tar the filesystem (excluding the backup file we're creating)
tar -cpzf /{computer_name}-Backup-$(date '+%Y-%m-%d').tar.gz --exclude=/proc --exclude=/sys --exclude=/mnt --exclude=/media --exclude=/run --exclude=/tmp --exclude=/dev --exclude=/{computer_name}-Backup-$(date '+%Y-%m-%d').tar.gz /

# encrypt the backup and store on the samba share
openssl aes-256-cbc -salt -in /{computer_name}-Backup-$(date '+%Y-%m-%d').tar.gz -out /mnt/backups/{computer_name}-Backup-$(date '+%Y-%m-%d').tar.gz.enc -pass pass:CoMpLeXpAsSwOrD

# unmount the backup directory:
umount /mnt/backups
rm -rf /mnt/backups

exit 0

And then finally:

# set the permissions for the script
chmod 500 /scripts/weekly-backup.sh

# create the cron job to run the script
echo "0 2 * * 3 root /scripts/weekly-backup.sh" >> /etc/crontab

This cron job will run at 0200 on the 3rd day of the week (Wednesday), and only the root account has the ability to view and execute it.

Everything else

So those scripts above cover weekly "Image" backups, but I have other files that require backup on as frequent as a daily basis or as infrequent as a monthly. For those I just use robocopy (Windows) and tar (Linux) to perform those backups. I won't include them here (I can happily on request) as they're simple file copy operations, but with the same encryption methods employed as above to protect the data at rest.

Things that fall into the daily backup category include:

  • My DokuWiki data
  • My Mail Server mailboxes
  • My Password Manager Databases

Things that fall into the monthly backup category include:

  • My Photos (I don't take many photos to justify more frequent backups)
  • My Music collection (doesn't get updated much now I've stopped buying music and started streaming)
  • My Google Drive data (already stored in multiple places, this is just to have monthly snapshots of the state)

It's not perfect

There are still some open problems with this solution:

  1. The passwords for encrypting the data are stored in the scripts. I'm satisfied to live with this risk for now, as I'll have a much more severe problem if I have an intruder able to read the script files directly.
  2. Incremental backups aren't covered yet.

I also hope to find a way in the future to integrate the success and failure of these backups into Nagios in some form, so I can monitor their results from there. But for now I'm quite satisfied with this setup. Recovery just constitutes decrypting the relevant backup I need to use, and for Windows pointing a recovery disk to the directory, and for Linux just extracting the tar to the root directory (overwriting whatever is already there).