“stealth” encrypted home directory filesystem using encfs on GNU/Linux

September 8th, 2006

This article will show you how to protect your privacy by encrypting and hiding your home directory under GNU/Linux, using established technology and a quick hack.

You will be able to safeguard personal files, e-mail messages and address books, web browsing data such as history, cookies and cached files from visited sites, PIM data such as appointments and to-dos, instant messaging conversation logs, stored passwords and other sensitive bits.

skip the introduction and go to Setup ]

Introduction

Several months ago I decided to do something to fight the long-standing feeling of unease I had with my notebook's setup.

Doing the job I do and being quite on the paranoid side (whichever comes first, the chicken or the egg), I've been keeping all of my sensitive documents in an encrypted portion of my storage space since long ago, using techniques that have evolved in time, following both availability of better software and change of my usage patterns.

As a rule, I always consider the content of my home directory as expendable (with the notable exception of my e-mail folder), even if I keep regular backups of it (there is specific reasoning behind this, but I think it goes beyond the scope of this document). Anyway, it's easy to underestimate how many things are kept into your home directory in a modern un*x environment. e-mail, IM logs, PIM data, browser history, cache, cookies, account information, program preferences, whatnot. A whole lot of stuff.

So I decided that it was time for me to have an encrypted home directory space, and stop worrying about what it would take me to sleep again if someone stole my notebook.

skip the rest of this introduction and go to Setup ]

The first step was investigating the choice of software available to accomplish the goal. I started by coming up with a list of requisites.

  • It did not need to be a cross-platform solution (though that may have been a bonus). My primary work environment is GNU/Linux, and likely to stay so for the foreseeable future;
  • I wanted the solution to be manually activated at my need, meaning that I wanted the system to be (or, at the very least, to appear) fully functional without my encrypted home being mounted. Of course the common un*x mechanism of layered filesystem branches and self-containedness of the $HOME played nice with this requisite;
  • I wanted the solution to be as "stealthy" as possible, as in impossible or at least difficult to discover;
  • I wanted the solution to rely on Free Software components only;
  • I was very determined (though willing to loosen up a little bit, if really needed) to rely on components which were stock parts of my distribution of choice, Debian GNU/Linux at the time.

The search reported three results: dm-crypt, loop-aes and encfs.

A quick comparation of the features and strong points of each software pointed to encfs. I knew loop-aes was probably the fastest runner, as someone I know and trust told me during my research, but it needed a kernel patch. Encfs also needed kernel patching, was somehow weaker in strict theoretical terms and, being based on FUSE, it was surely going to perform worse than the other solutions, but also had the significant advantage of allowing encrypted backups at file level. This feature is referred to as "Layering / Separation of Trust" in this introduction to encfs. That was not one of my requisites, but I thought of it as a nice bonus, so I decided to start evaluating encfs first.

Encfs was also the only software in the lot I'd never used before. I knew loop-aes from it being used in Knoppix, and was (and still am) using dm-crypt for other purposes. So I needed a couple more hours of fiddling with encfs to get to know its basics.

Well, after some trial-and-error and a short testing period, I was very satisfied with my solution. The performance impact was negligible for my purposes, the level of security was, in my opinion, up to the task, and the ability to do incremental encrypted backups via rsync was a real life saver.

I've since been running under this setup, with only a few refinements needed and without a single minor hassle.

Recently I've come to think that my setup might be of interest to other people, and is probably non-trivial enough that I may write a little technical report (with a lengthy introduction :) ) about it. So here it is.

This document is by no means complete and thorough, but I think it may be up to its task. If someone shows interest and constructive criticism, I may turn it into a mini-HOWTO or something like that, with improved structure and accessibility, and planned maintainance.

Let me end this introduction by saying that encfs is an awesome piece of software and once again thanking the excellent Valient Gough for writing it. I've been using it for different purposes and it redefined some of my working habits in ways I couldn't have imagined.

Playing with encfs also gave me the opportunity to deepen my shallow knowledge of FUSE. Now I think it is nothing short of one of the strongest "selling points" of Linux (I hear it's been ported to FreeBSD, though). There are very interesting and useful filesystems based on FUSE and I strongly advise you to check them out. I also was very happy to see FUSE merged into the main Linux source tree starting from 2.6.14.

I still pay a lot of attention not to have my notebook stolen when I carry it around (the other part of the problem being the money I'd need to buy a new one, though heaven knows how much I'd like to test my setup on a shiny new MacBook :) ); but I don't keep it under my pillow at night anymore. Remember the sense of unease I was telling you about at the start; I guess that's what you call an uneasy pillow. :)

Come on now.

The Setup

Before we start

I will assume a certain acquaintance with the Unix shell commands. Please leave a comment to this post if you think that something really important is being left out.

Another thing worth mentioning now is that this tutorial is based on Ubuntu GNU/Linux 6.06 (Dapper Drake). There shouldn't be many differences with other distributions, though. I will try and point out when something is relevant to Ubuntu only.

Installing encfs kernel module and userspace utilities

The first thing you are going to need is the FUSE kernel module. As I was saying, FUSE was merged into the main Linux kernel tree as of 2.6.14, but several distros (including Ubuntu, IIRC) were shipping with it before. If this is not your case, check the FUSE docs on how to compile and install it.

Anyway, load the module (as root):

root@bambino:/home/myuser# modprobe fuse

You may instruct your machine to load the module at boot time by adding it to the /etc/modules file:

root@bambino:/home/myuser# echo fuse >> /etc/modules

You also need FUSE userspace utilities (namely the fusermount command, as far as I can tell) and the encfs userspace library and utilities. With Ubuntu, you just need to install the fuse-utils and encfs packages, both included in the Universe repository. I'm sure you won't have many difficulties mapping this to your other distro of choice.

root@bambino:/home/myuser# apt-get update
root@bambino:/home/myuser# apt-get install encfs fuse-utils

Speaking of Ubuntu Dapper Drake, I had to add my user to the fuse group, that is because the fusermount command is suid and set up to be executable only to members of that group:

root@bambino:/home/myuser# ls -la $(which fusermount)
-rwsr-xr-- 1 root fuse 18328 2006-05-11 19:45 /usr/bin/fusermount

Of course, this is achieved by adding your username to the relevant line in /etc/group (or using your preferred graphical tool).

After adding your user to the fuse group, you will need to log out then back in. If you are running a graphical session, closing your terminal window and opening a new one will not do, you will have to exit X altogether. You may check by issuing the id command; if you don't see the fuse group listed in the output, you won't be able to run fusermount. If you're unsure, reboot your machine. :)

NB: he who knows a way around this (as if in how to "refresh" the gid/egid list in the current shell process), please let me know.

Creating your encrypted filesystem

Now may be a good time to know more about encfs. A good way of doing it may be reading this introduction, if you haven't done it already.

Now that you know everything about encfs, you understand that it will write encrypted files to an underlying filesystem, so we need to find a proper place for them. Since I have a dedicated /home partition, this is the obvious place in my case (and that is why I need to do this as the root user). Of course your mileage may vary.

Anyway, your user needs to have write permission to this directory, so maybe it's not a bad idea to create it and check/set the proper permissions in advance:

root@bambino:/home/myuser# mkdir /home/.myuser-c
root@bambino:/home/myuser# chown myuser /home/.myuser-c
root@bambino:/home/myuser# chgrp myuser /home/.myuser-c
root@bambino:/home/myuser# chmod 770 /home/.myuser-c
root@bambino:/home/myuser# ls -lad /home/.myuser-c
drwxrwx--- 2 myuser myuser 4096 2006-07-22 15:31 /home/.myuser-c

Then we're going to create the encrypted filesystem. The same command used to mount the filesystem will also trigger its creation if it's not already there.

Also, we won't be mounting the new filesystem as our home yet; we still need access to the current home directory, so we don't want to overlay it for the moment, we will mount it as /tmp/test. As a side note, this time we don't need to create the mount point; encfs will do this for us (providing the user you're working with has write permission there; no issues here since it's under /tmp).

myuser@bambino:~$ encfs /home/.myuser-c /tmp/test
The directory "/tmp/test" does not exist. Should it be created? (y,n) y
Sto creando una nuovo volume cifrato
Please choose from one of the following options:
enter "x" for expert configuration mode,
enter "p" for pre-configured paranoia mode,
anything else, or an empty line will select standard mode.
? >

Selezionato configurazione standard

Configuration finished. The filesystem to be created has
the following properties:
Filesystem cipher: "ssl/blowfish", version 2:1:1
Filename encoding: "nameio/block", version 3:0:1
Key Size: 160 bits
Block Size: 512 bytes
Each file contains 8 byte header with unique IV data.
Filenames enblockquoted using IV chaining mode.

Now you will need to enter a password for your filesystem.
You will need to remember this password, as there is absolutely
no recovery mechanism. However, the password can be changed
later using encfsctl.

Nuova password di Encfs:
Verifica password di Encfs:
myuser@bambino:~$

(please excuse the mixing of locales)

We used exactly two parameters with encfs, the first being the directory where we want the actual, encrypted files stored, the second being the mount point for the virtual, unencrypted filesystem. Each file we will be writing in /tmp/test will be physically stored in /home/.myuser-c, with its name and contents encrypted. Of course, the file will be also available in /tmp/test, name and contents clear, but only as long as the virtual filesystem is mounted.

As you probably have noticed, when asked for a set of options for the new filesystem, I chose to go with the default. My little paranoid friends (I know you're there! And they're out to get us!!!) may be tempted to do as I did during my first tests, that is of course to choose pre-configured paranoia mode instead. Too bad this is going to give you problems later, since paranoia mode does not support hard links, and some programs that rely on them will fail. For instance, I haven't been able to run X with my $HOME in paranoia mode. If you wish to know more about this issue, please refer to this message from the encfs-users mailing list archive.

If everything went OK, your df output should look like this:

myuser@bambino:~$ df
Filesystem blocchi di 1K Usati Disponib. Uso% Montato su
[...]
/dev/hda10 4324728 2711400 1393644 67% /home
[...]
encfs 4324728 2711400 1393644 67% /tmp/test

You have a new filesystem under /tmp/test that's ready for use.

Obviously the statistics for the new filesystem are exactly the same as the filesystem hosting the actual storage of the files, /home in my example.

Creating your new home directory

This new filesystem is going to be your home directory, so most probably what you want to do is copy the contents of your current home directory to it:

myuser@bambino:~$ cp -a /home/myuser/* /tmp/test/

Maybe you'd like to copy your dot files as well (UPDATED: thanks to Davide Canova for kindly suggesting an elegant solution in place of my horrible kludge):

myuser@bambino:~$ cp -a /home/myuser/.??* /home/myuser/.[!.] /tmp/test/

Of course, if you prefer starting with a clean slate, you may just copy in the contents of /etc/skel or whatever else you see fit.

When you're done preparing your new environment, you may unmount your encrypted volume from the temporary location:

myuser@bambino:~$ fusermount -u /tmp/test

Let's take a look at what's in the container filesystem, just out of curiosity:

myuser@bambino:~$ ls -la /home/.myuser-c/
totale 212
drwxrwx--- 14 myuser myuser 4096 2006-07-22 16:08 .
drwxr-xr-x 23 root root 4096 2006-07-22 15:31 ..
drwx------ 3 myuser myuser 4096 2006-07-22 15:39 0q3j645h74IvfmFwBXYtNyLo
drwx------ 2 myuser myuser 4096 2006-07-22 15:28 2U6OLASpOQQcP,
-rw-r--r-- 1 myuser myuser 82492 2006-07-22 15:54 4uYoJqAF97QaBF5qgem5gXl07xsjGqe12H5
drwxr-xr-x 2 myuser myuser 4096 2006-07-22 15:28 96GPD1f-h0Nd2-
-rw------- 1 myuser myuser 433 2006-07-22 15:51 B6BINkspsycUr1DH7G4yggK,
-rw------- 1 myuser myuser 169 2006-07-22 15:51 cibL79W7jUT-BqRPH50p9Vum
lrwxrwxrwx 1 myuser myuser 47 2006-07-22 16:03
cXLN0cpMR0hRXTRY7WBBPJ0i -> +U7tUrUNLI8,ORga4KRGsFoRKNlp9,ZWE77ELPunIXo,al,
-rw-r----- 1 myuser myuser 224 2006-07-22 15:56 .encfs5
[...]

What you see is several files and dirs, each corresponding to files and dirs of your encrypted volume. Both the names and the contents of these files have been encrypted. The file named .encfs5 is the filesystem's control file you have read about in the introduction (you read it, didn't you? :) ).

Mounting your new home directory

Now you're ready to mount your home directory over your old one.

encfs /home/.myuser-c /home/myuser -- -o nonempty,use_ino,allow_root

Set the mount point as to overlay your current directory with the new virtual filesystem. We also needed to provide some extra options (the options are actually for FUSE and the "-- -o" switches tell encfs to pass them down):

  • nonempty is needed if the mount point directory is not empty (as is the case for this example);
  • use_ino is to instruct FUSE to use inodes, since some programs need that. If your version of encfs is 1.2.2 or later, you do not need to specify this option since it's been made the default;
  • allow_root is to allow the root user to access your files. This is not default with FUSE. You may think, as I did, that there's no need for the root user to access your home directory. I found that if you don't allow the root user you won't be able to log in correctly using graphical login managers like xdm/gdm/kdm. I still haven't had the time to look better, maybe there's a way to circumvent this, and I'd like to know it, but for the time being I'll just stick with this option. This is the only good reason I found for allow_root, so if you don't use a graphical login manager (and you don't need root access to your home for other reasons), you may leave it out.

If everything went good, your new home filesystem is mounted.

What you need to do now is log out immediately. The programs you're currently running are probably still referencing to files in your old home directory, so you need to start over. Log out then back in. Do it now.

Enjoying your new home directory

You should now be inside your new, stealthy environment! Start enjoying it.

Reverting to your "old" environment

Going back to your "regular" home is actually a little tricky. You won't be able to unmount your home filesystem while in use, so what you need to do is:

  • log out
  • log in with a different user
  • open a shell and switch to your original user with su
  • unmount the filesystem: fusermount -u /home/myuser
  • log out from this user and log back in with the original user

I don't really care about this process, since I never do it but just switch off the PC when I'm done. Of course this may not be the case for people with different usage patterns.

Doing it over and over

After your next boot, you just need to repeat the last step of the process to get back to your encrypted environment:

encfs /home/.myuser-c /home/myuser -- -o nonempty,use_ino,allow_root

You may put this command in a shell script or leave it in your shell history, trading convenience for a little security. You'll be leaving a just a little evidence, but I think it's definitely worth it.

Anyway, you always need to log out then back in before you can use the new environment.

Points of style

You may want to change the contents of your former home directory, since the files are now better off protected in their new location, or simply just to avoid confusion between the two.

I have a completely different setup into each of the two homes. The "actual" home is a default GNOME environment, while the "stealthy" home features my usual, heavily customized KDE environment.

I even activated autologin; after the boot process, the system is perfectly functional without my private profile being exposed at all, which I find convenient on several occasions:

  • when I don't need my full environment, for instance when I just need a quick browse, to watch a movie, listen to some music, and so on;
  • when I don't want my full environment, for instance when temporarily lending my notebook to a friend or a coworker.

8 responses

  1. fullo comments:

    bel tutorial :)
    adesso fanne le slide perchè sei stato reclutato per il security day come ogni anno ;)

  2. Simon comments:

    Hi,
    I also use EncFS to protect my laptop data whilst powered off… once it’s on and encrypted data is mounted the it’s as secure as any other filesystem.

    There is a ‘Pam_Encfs’ module which can automatically mount/unmount as user(s) log in and out.

    Another thing to consider is that you should always use in conjunction with an encrypted swap file and think about whether ’suspending’ will leave important data in a file/partition on the disk.

    For light amusment I have the encrypted ‘partition’ mount over the top of a default home directory with a desktop background of ‘dogs playing poker’ (Thomas Crown Affair [remake] reference) :o).

    Simon

  3. Sy Ali comments:

    This step can be simplified.

    myuser@bambino:~$ cp -a /home/myuser/* /tmp/test/
    myuser@bambino:~$ cp -a /home/myuser/.??* /tmp/test/

    =>

    myuser@bambino:~$ cp -a /home/myuser /tmp/test

  4. andrew comments:

    Simon: thanks for your comments. I will include them if this document gets revised.

    Sy: I see I haven’t made it clear that I wanted a command to copy dotfiles only. My fault. I have updated the document to reflect that.

  5. Nathan comments:

    Would like to note that in addition to swap, it is also important to encrypt your /tmp to prevent from leaking private data. You can obviate some of the need for encrypted /tmp by setting environment variables to point temporary files to ~/tmp, but some broken software won’t follow this. Remember that when written to disk in clear, you can never trust this data to be private again. It’s hard to ensure at a user level that even the same logical sector is overwritten after a file is deleted, and with modern drives it may be impossible to ensure wiping the same physical sector. Not to mention hardware recovery techniques that can sometimes retrieve data that has been magnetically rewritten.

  6. Upayavira comments:

    For the sake of being able to do your encfs mount in the same session after you have just added your user to the fuse group, you can just do su - . That’ll create a new login shell in which your user will be a member of the requisite group.

  7. andrew comments:

    @Upayavira: interesting. Many thanks.

Leave a comment