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 bymd
, 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
Automation
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 :
[private] 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.