FreeBSD Geli encrypted container
FreeBSD geli encrypted container with zfs, truecrypt replacement
Code on Github
Support for geli is available as a loadable kernel module. To configure the system to automatically load the module at boot time, add the following line to /boot/loader.conf:
Create container with dd
create a 2 gig container with dd on the Desktop called disk.img
Mount the image with mdconfig
use mdconfig to mount the disk image
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.
Generate the masterkey
create the director to store the geli key
Now we want to create a key for GELI to encrypt with, and attach it to our disk image device:
replace username with your username
Enter the passphrase
Create the ZFS file system
Next, format the device with the ZFS file system and mount it on an existing mount point:
create the ZFS mount point
Finally, when you want to unmount, we also want to detach from GELI and detach from md:
Mounting and umounting
Mount
Umount
Bash script to mount and umount the container
Change the container, gelikey and poolname variables to match your own set up
ossuary shell script version
FreeBSD geli encrypted container with zfs, truecrypt replacement
Code on Github
Support for geli is available as a loadable kernel module. To configure the system to automatically load the module at boot time, add the following line to /boot/loader.conf:
Code:
geom_eli_load="YES"
Create container with dd
create a 2 gig container with dd on the Desktop called disk.img
- change directory to the Desktop
cd ~/Desktop
- switch to root
sudo su
- use dd to create a 2 gig disk image
dd if=/dev/random of=disk.img bs=1M count=2048
Mount the image with mdconfig
use mdconfig to mount the disk image
mdconfig -a -t vnode -f disk.img -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.
Generate the masterkey
create the director to store the geli key
mkdir -p ~/.ossuary
Now we want to create a key for GELI to encrypt with, and attach it to our disk image device:
replace username with your username
Code:
dd if=/dev/random of=/usr/home/username/.ossuary/ossuary.key bs=256 count=1
geli init -e aes -l 256 -s 4096 -K /usr/home/username/.ossuary/ossuary.key /dev/md0
geli attach -k /usr/home/username/.ossuary/ossuary.key /dev/md0
Enter the passphrase
Create the ZFS file system
Next, format the device with the ZFS file system and mount it on an existing mount point:
- use dd to write random data to geli container before adding file system
dd if=/dev/random of=/dev/md0.eli bs=1M
- To create a simple, non-redundant pool using a single disk device:
zpool create crypt /dev/md0.eli
- add compression and duplication to the zfs pool
zfs set compression=lz4 crypt
- set the ZFS mount point
mkdir -p ~/mnt
create the ZFS mount point
zfs set mountpoint=/usr/home/username/mnt crypt
- change the permission on the container, replace username with your username
sudo chown -R username:username ~/mnt
Finally, when you want to unmount, we also want to detach from GELI and detach from md:
- ZFS umount
zfs umount crypt
- zpool export
zpool export crypt
- Geli detach
geli detach md0.eli
- mdconfig free loop device
mdconfig -d -u 0
Mounting and umounting
Mount
- use mdconfig to mount the encrypted container to /dev/md0
mdconfig -a -t vnode -f disk.img -u 0
- use geli with the path to the key and device
geli attach -k /usr/home/username/.ossuary/ossuary.key /dev/md0
- we need to import the zpool which will also mount the container
zpool import crypt
Umount
- umount the zfs pool
zfs umount crypt
- export the ZFS pool before we use geli detach, otherwise geli thinks the device is busy
zpool export crypt
- use geli to detach the encrypted device
geli detach md0.eli
- free the loop device
mdconfig -d -u 0
Bash script to mount and umount the container
Change the container, gelikey and poolname variables to match your own set up
Code:
#!/usr/bin/env bash
# geli container mount and umount script
#=======================================
# check to see if script was run as root
if [[ $UID -ne 0 ]]; then
echo "$0 must be run as root using sudo, make your own sandwich"
exit 1
fi
# Create the prompt
PS3="Enter your choice: "
options=("mount" "umount" "quit")
OLD_IFS=${IFS}; #ifs space seperator
IFS=$'\t\n' #change ifs seperator from spaces to new line
# container variables
loop="/dev/md0"
loopcrypt="/dev/md0.eli"
container="/usr/home/username/documents/disk.img"
gelikey="/usr/home/username/.ossuary/ossuary.key"
poolname="crypt"
# select and case statement
select opt in "${options[@]}"; do
case $opt in
mount)
mdconfig -a -t vnode -f "$container" -u 0
geli attach -k "$gelikey" "$loop"
zpool import "$poolname"
break;;
umount)
zfs umount "$poolname"
zpool export "$poolname"
sleep 1
geli detach "$loopcrypt"
mdconfig -d -u 0
break;;
quit)
echo "Quitting"
IFS=${OLD_IFS}
break;;
*) echo "Usage: ossuary [ mount | umount | quit ]";;
esac
done
ossuary shell script version
Bash:
#!/bin/sh
# script usage
script_usage () {
echo "\
mount: $(basename "$0") mount -f container -k gelikey
umount: $(basename "$0") umount -f container"
}
# check to see if script was run as root
if [ "$(id -u)" != "0" ]; then
echo "$0 must be run as root" && script_usage
exit 1
fi
# mount function
mount () {
# group commands
{
# container
container="$1" && \
# gelikey
gelikey="$2" && \
# mdconfig loopname from container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//')
# eli filepath
loopcrypt="/dev/${loopdevice}.eli"
# mdconfig create vnode from container
echo "+ mdconfig creating vnode for '$container'" && \
loop=$(mdconfig -a -t vnode -f "$container") && \
# geli attach key to vnode
echo "+ geli attaching '$gelikey' key to '$container' file" && \
geli attach -k "$gelikey" "$loop" && \
# mdconfig loop device for container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//') && \
# path to mdconfig eli file
loopcrypt="/dev/${loopdevice}.eli" && \
# zpool name from mdconfig eli file
poolname=$(zdb -l "$loopcrypt" | awk -F\' '/[[:blank:]]name/ {print $2; exit;}') && \
# zpool import pool
echo "+ zpool importing '$poolname'" && \
zpool import "$poolname" && \
# mount point from zpool
mountpoint=$(zfs get -H -o value mountpoint "$poolname") && \
echo "+ '$poolname' mounted to '$mountpoint'";
} || { mdconfig -du "$loopdevice" && exit; }
}
# umount function
umount () {
# group commands
{
# container
container="$1" && \
# mdconfig loopname from container
loopdevice=$(mdconfig -lf "$container" | sed 's/[ \t]*$//') && \
# eli filepath
loopcrypt="/dev/${loopdevice}.eli" && \
# zpool name from eli file
poolname=$(zdb -l "$loopcrypt" | awk -F\' '/[[:blank:]]name/ {print $2; exit;}') && \
# zfs umount poolname
echo "zfs unmounting $poolname" && \
zfs umount "$poolname" && \
# zpool export poolname
echo "zpool exporting '$poolname'" && \
zpool export "$poolname" && \
sleep 1 && \
# geli detach
echo "geli detaching '$loopcrypt'" && \
geli detach "$loopcrypt" && \
# mdconfig remove md file
echo "mdconfig clearing '$loopdevice'" && \
mdconfig -du "$loopdevice" && \
echo "unmounted device";
} || { echo 'container not mounted' && exit; }
}
# check if mount is first argument
# + 2nd argument shuld be -f for the file to mount
# + 3rd argument should be the path to the file to mount
# + 4th argunent should be -k for key
# + 5th argument should be the path to the keyfile
# check if umount is first argument
# + 2nd argument shuld be -f for the file to unmount
# + 3rd argument should be the path to the file to unmount
# check arguments
if [ "$1" = mount ] && [ $# -eq 5 ]; then
# group commands
{
[ "$2" = '-f' ] && \
[ -f "$3" ] && \
[ "$4" = '-k' ] && \
[ -f "$5" ];
} || { script_usage && exit; }
# mount function pass conatainer and key to function
mount "$3" "$5"
elif [ "$1" = umount ] && [ $# -eq 3 ]; then
# group commands
{
[ "$2" = '-f' ] && \
[ -f "$3" ];
} || { script_usage && exit; }
# umount function pass container to function
umount "$3"
else
script_usage
fi
Last edited: