Encrypted share with GELI

After my file storage on a NAS, I wished to add a specific share for sensitive information. That’s why I created a encrypted volume with md and geli, then shared via the usual way.

Choice of the encryption system

Three encryption systems got my attention :

  • EncFS, can be used with FUSE and encrypts each file separatly with OpenSSL, available in FreeBSD ports.
  • TrueCrypt, multiplatform without FreeBSD support, client-side installation only (one installation per client).
  • GELI, volume-based encryption, based on the kernel crypto API, available by default on FreeBSD. GELI is designed to work with full disks, but it can be used with a memory disk created by md, in order to create a encrypted volume within a regular file.

Disk initialization

First of all, load the corresponding kernel module with kldload geom_eli (and by adding  geom_eli_load="YES" in /boot/loader.conf to load it on boot).
The first step is the virtual disk file creation (5 GB) :

# dd if=/dev/zero of=/data/private/container bs=1M count=5120

Which can be mounted with mdconfig :

# mdconfig -a -t vnode -f /data/private/container -u 0

Here, the -a option forces the disk mounting, -t vnode is used for opening a regular file, and the path of this file is specified after -f. The -u 0 option set the virtual disk identifier to use, in this case /dev/md0.

Then the encrypted disk can be created :

# geli init -s 4096 -e AES -l 256 -a HMAC/SHA256 /dev/md0

The option -s 4096 specifies the block size to use, -e AES the encryption algorithm, -l 256 the keylength an -a HMAC/SHA256 the algorithms used for integrity verification.
By default a password is asked for data encryption, but an encryption key can also be specified during disk creation, with option -k. For more details about key management with geli, see the Magic Garden wiki.

At this point, the disk can be mounted, and this operation create a new /dev/md0.eli device containing the plaintext data :

# geli attach -d /dev/md0

The option -d forces the plaintext device unmount when the source fileystem is unmounted. A new filesystem is required :

# newfs -U /dev/md0.eli

It may be required to fill the virtual device with empty data using dd, or newfs may fail to initialize the disk (more explanation available here).

At last, the device can be mounted :

# mount /dev/md0.eli /data/private/plain

Metadata backup and cleanup

By default, a metadata copy is written in /var/backups and this file provides the capability to restore the default configuration for geli, including password changes. For this reason, it is recommended to backup this file in a safe place, and delete it from the data storage host. That’s why I encrypted this file :

# openssl enc -bf-cbc -salt -in md0.eli -out md0.eli.bf

Then the output can be stored elsewhere, and all previous files can be completely deleted, for example with gshred (included in the sysutils/coreutils port) :

# gshred -u md0.eli

Disk mount / unmount

For each disk mount, it is required to recreate the virtual disk :

# mdconfig -a -t vnode -f /data/private/container -u 0

So the encrypted data can be read from this virtual disk :

# geli attach -d /dev/md0

Then the plaintext disk can be mounted :

 # mount /dev/md0.eli /data/private/plain

Unmouting only involves a umount :

# umount /data/private/plain

Followed by the virtual disk removal :

# mdconfig -d -u 0


All the required steps for mount / unmount have been in this script, which can be used after modifying the following variables :

container="/data/private/container" # Path of the encrypted data container
clear="/data/private/plain" # Path to mount plain data

This script can be used via sudo (included in FreeBSD ports) in order to allow encrypted disks operations from standard users. For such needs, sudoers file can be edited with visudo :

mount_user ALL= NOPASSWD: /home/mount_user/mount.sh

Of course, the scipt owner must be root, and it must be the only user with write access to this file.

Then the script can be run with :

$ sudo /home/mount_user/mount.sh

Samba share

If the volume is shared via SSHFS, no more steps are required.

If Samba is used, a proper share must be configured :

   path = /data/private
   valid users = your_user
   public = no
   writable = yes
   printable = no
   browsable = no
   case sensitive = yes
   default case = lower
   preserve case = yes
   short preserve case = yes

This way, the private share will not be listed in the available shares according to option browsable = no. Once the share is mounted, the files stored in /data/private will be accessible, as the /data/private/plain repertory. However, no file will be shown in the /data/private/plain repertory until the encrypted volume is mounted.