cifs-to-cloud bridge with enhanced privacy using samba, davfs2 and encfs

In this post I document how to use some cloud storage (“davfs2”) with enhanced privacy (“encfs”) and share this within my LAN (read: samba).

With plenty of online storage (ca. 1TB, 1&1 SmartDrive) and up-to-date internet connectivity at home (1&1 VDSL 100, with 40MBit uplink) it is reasonable to just use this.

As many germans I pay attention to my privacy. So just copying my (private) data on some cloud storage is not an option for me. I will use encfs for this part.

But dealing with davfs2, encfs-stuff and general fuse stuff is nothing I want to set up on every box at home but just on my local server (Debian wheezy) and export everything just using my (existing) samba setup.

Basic setup

Dealing with encfs-on-davfs2 is not very pleasant so I create a dedicated system account namend “cloud” with a group “cloud”, with /home/cloud for home directory and /cloud as the root directory for any mountpoints.

## example, you may want to change this according to your needs
# groupadd --gid 999 --system cloud
# useradd --comment "Cloud Management" --create-home --home-dir /home/cloud --system --shell /bin/bash --gid 999  --uid 2000 cloud

This user should be able to mount some stuff with enhanced options, so we need sudo here. I created a /etc/sudoers.d/cloud for some tasks:

Cmnd_Alias C_DAVFS = /usr/sbin/mount.davfs, /usr/sbin/umount.davfs, /sbin/mount.davfs, /sbin/umount.davfs, /bin/mount /cloud/1und1, /bin/umount /cloud/1und1
Cmnd_Alias C_ENCFS = /bin/mount /cloud/1und1_secure , /bin/umount /cloud/1und1_secure
Runas_Alias R_ROOT = root
%cloud ALL=(R_ROOT) NOPASSWD: C_DAVFS, C_ENCFS

Set up davfs2 with 1&1 smartdrive

At first we need to install and configure davfs2 then set up directories and mountpoints and /etc/fstab:

# apt-get update
# apt-get install davfs2
# adduser cloud fuse
# adduser cloud davfs2
# echo 'use_locks 0' >> /etc/davfs2/davfs2.conf
# mkdir -pv /cloud/1und1
# chmod 750 /cloud
# chown -R cloud:cloud /cloud
# touch /etc/davfs2/secrets                # if not exist
# chown root:root /etc/davfs2/secrets      # be sure
# chmod 600 /etc/davfs2/secrets            # be sure
# echo '/cloud/1und1  cloud@mydomain.name mY53cr37P455W0rD' >> /etc/davfs2/secrets
# echo 'https://sd2dav.1und1.de/ /cloud/1und1 davfs noauto,user,rw,uid=2000,gid=999,dir_mode=0750,file_mode=0640' >> /etc/fstab

After that root and user cloud should be able to mount and umount the online storage:

# su - cloud
$ sudo mount /cloud/1und1
$ mkdir /cloud/1und1/secure # we will need this later
$ ls -la /cloud/1und1
insgesamt 1
drwxr-x--- 8 cloud cloud 240 Aug 19  2014 .
drwx------ 2 cloud cloud   0 Apr  2 16:16 lost+found
drwxr-x--- 3 cloud cloud   0 Aug 19  2014 Papierkorb
drwxr-x--- 2 cloud cloud   0 Apr  2 16:27 secure

We are now ready to use the cloud storage.

Set up samba

This post isn’t about samba so I’d like just to show you the config for our share.
I assume you already have working samba.

1
2
3
4
5
6
7
8
9
[cloud]
        comment         = Cloud Storage
        path            = /cloud
        read only       = no
        valid users     = me,wife,kids,cat
        create mask     = 0660
        directory mask  = 0770
        force user      = cloud
        force group     = cloud

You may need to reload samba

# service samba reload

Check access to the share using smbclient from another box in my lan

$ smbclient -A ~/.smbcredentials //server.local/cloud/ -c dir
Domain=[MYDOMAIN] OS=[Unix] Server=[Samba 3.6.6]
  .                                   D        0  Sun Apr  2 16:27:21 2017
  ..                                  D        0  Sun Apr  2 14:37:25 2017
  1und1                               D        0  Tue Aug 19 01:30:18 2014
  1und1_secure                        D        0  Sun Apr  2 16:31:50 2017

If you see this samba is just fine, we’re done with samba. Now we can access our /cloud/1und1 within our LAN using CIFS.

Privacy hurts, encfs sucks

If you want to have some “encrypted file system” you may put in on a secured block device. But we don’t have block device here, so we need some “overlay” file system implementing security.

But encfs sucks in some ways as it needs passwords instead of keyfiles and this passwords have to be typed in every time. There is an –extpass option where you can use ssh-askpass for example or some strange –stdinpass where you need to “type” in the password in stdin.

For clean setup we want to be able to mount encfs by /etc/fstab but it seems there is no option for encfs to grab the key/password by parameter.

Since encfs is a fuse driver we have some options to get this into /etc/fstab.

First, we need a basic wrapper script stored in /home/cloud/bin/encfs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/sh
#
# $* contains fields from /etc/fstab:
 
if [ ! -d "${1}" ]; then
        echo "ERROR: SRC=${1} not a directory" >&2
        exit 1
fi
 
if [ ! -d "${2}" ]; then
        echo "ERROR: DST=${2} not a directory" >&2
        exit 1
fi
 
logger --tag cloud::encfs "$*"
exec /usr/bin/encfs --extpass="cat /home/cloud/.encfs/pw_1und1_secure" $*

Then we create mountpoints and entry in /etc/fstab:

# mkdir /cloud/1und1_secure
# chown cloud:cloud /cloud/1und1_secure
# chmod 750 /cloud/1und1_secure
# echo '/home/cloud/bin/encfs#/cloud/1und1/secure /cloud/1und1_secure fuse noauto,user,rw,uid=2000,gid=999,allow_other' >> /etc/fstab

Then we need to set up a fresh encfs filesystem:

# su - cloud
$ mkdir /home/cloud/.encfs/
$ chmod 700 /home/cloud/.encfs/
$ pwgen -s 16 > /home/cloud/.encfs/pw_1und1_secure
$ LANG=C ~/bin/encfs /cloud/1und1/secure /cloud/1und1_secure
Creating new encrypted volume.
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.
?>

Standard configuration selected.

Configuration finished.  The filesystem to be created has
the following properties:
Filesystem cipher: "ssl/aes", version 3:0:2
Filename encoding: "nameio/block", version 3:0:1
Key Size: 192 bits
Block Size: 1024 bytes
Each file contains 8 byte header with unique IV data.
Filenames encoded using IV chaining mode.
File holes passed through to ciphertext.

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.

encfs will init on first invocation and mount it then.

Let’s test:

$ echo "Test" > /cloud/1und1_secure/test.txt
$ ls -la /cloud/1und1/secure /cloud/1und1_secure
/cloud/1und1_secure:
total 16
drwxr-xr-x 2 cloud cloud   55 Apr  3 00:54 .
drwxrwxrwt 6 root  root  8192 Apr  3 00:57 ..
-rw-r--r-- 1 cloud cloud    5 Apr  3 00:54 test.txt

/cloud/1und1/secure:
total 20
drwxr-xr-x 2 cloud cloud   55 Apr  3 00:54 .
drwxrwxrwt 6 root  root  8192 Apr  3 00:57 ..
-rw-r--r-- 1 cloud cloud 1077 Apr  3 00:53 .encfs6.xml
-rw-r--r-- 1 cloud cloud   13 Apr  3 00:54 lItfxxyyzz123aKaabbcc6-u

Let’s test our /etc/fstab and sudo rules, if everything works, you won’t see any prompt for passwords (encfs, sudo):

# su - cloud
$ sudo umount /cloud/1und1_secure
$ sudo mount /cloud/1und1_secure

$ LANG=C ls -la /cloud/1und1_secure
total 16
drwxr-xr-x 2 cloud cloud   55 Apr  3 00:54 .
drwxrwxrwt 6 root  root  8192 Apr  3 01:01 ..
-rw-r--r-- 1 cloud cloud    5 Apr  3 00:54 test.txt

Testing access through samba:

$ smbclient -A ~/.smbcredentials ///cloud/  -c "cd 1und1_secure; dir"
Domain=[MYDOMAIN] OS=[Unix] Server=[Samba 3.6.6]
  .                                   D        0  Sun Apr  2 16:27:07 2017
  ..                                  D        0  Sun Apr  2 16:27:21 2017
  test.txt                            N        0  Sun Apr  3 00:23:42 2017

Works!

Important notes

There is somethig important to say about noauto,user,rw,uid=2000,gid=999,allow_other: since encfs is a fuse filesystem and we put our cloud user into the “fuse” group we should be able to mount/umount without(!) sudo.

But as we want to share /cloud through samba we need the “allow_root” or “allow_other” option, because even root has no access to /cloud/1und1_secure/ if it is mounted by the unprivileged cloud user using fuse.

As samba operates with root rights and drop its privileges after entering a directory to the “force user = cloud”, it will fail accessing /cloud/1und1_secure/ while operating as root (before dropping rights to “cloud”).

Because of this reason we need “allow_other” when mounting the encfs (but use the wrapper owned by cloud user) and this fuse option is only available to root user therefore we need sudo here

ToDo

the file systems are not mounted on boot. We’ll need some cronjob for our cloud-user, which continously maintains the availability of davfs2 (/cloud/1und1/secure) and encfs (/cloud/1und1_secure).

Security

We have some security now but encfs still needs to operate with plain passwords stored somewhere. But we have it in our own wrapper and there we defined just some --extpass="cat /home/cloud/.encfs/pw_1und1_secure".

You may replace “cat” by “rot13” or “base64 -d”, gpg or whatever you want.

You also may also recreate this password on demand using a static seed:

$ dd if=/dev/urandom bs=1 count=256 of=keyfile
$ pwgen -s 16 1 --sha1=keyfile
PVWkFNqVGDT5g5cp
$ pwgen -s 16 1 --sha1=keyfile
PVWkFNqVGDT5g5cp

The password is created by pwgen but is static for same key and same options, so if we re-create the key we will get another staitc password with the same options

$ dd if=/dev/urandom bs=1 count=256 of=keyfile
$ pwgen -s 16 1 --sha1=keyfile
NBuHVSdcl6jep5HO
$ pwgen -s 16 1 --sha1=keyfile
NBuHVSdcl6jep5HO

… so pwgen is able to create safe and human readable passwords using (the sha1 checksum of) some inputfile as random seed.

Leave a Reply