The goal is to automatically synchronize files between several hosts without compromising the integrity of the separate machines. A nice tool for 2-way sync is unison. To sync files between different machines The Right Way (TM) is to tunnel the unison protocol over ssh. This is well supported by unison.
To run sync automatically (e.g. via cron), you need to create an SSH keypair without passphrase, so unison can log into the other machine without human interaction. This is where the problems start, since anyone who got access to the private key (e.g. by compromising or stealing the machine the private key was on) can log into the other host.
Now ssh has a nice way to restrict what you can do with a specific key, so you
can e.g. use the following in the remote hosts
command="/usr/bin/unison -server" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA8K2cd0yemw...
That way someone who has the private key can't execute arbitrary commands, but
just unison in server mode. However it's still possible to tell the unison
server to overwrite arbitrary files (which the user has write access to). This
is a major problem, since also files like
~/.bashrc can be
overwritten, so the next time the user logs in, arbitrary commands will be
A possible solution
One solution is to simply create a new user on the remote host with a disabled
password, and let unison run as that user (via adding the appropriate line to
$HOME/.ssh/authorized_keys, and telling the local unison to use
That's possible, but the
.bashrc trick still works, it's just less
likely that the code there is ever executed (root would have to use
su to become that user).
For me this solution didn't work out since I wanted to sync my maildir, and it was hard to ensure that file permissions were set in a way that both allowed me to read my mail and allowed unison (running under user unison-sync) to sync the files.
The Right Solution (TM)
All the problems vanish as soon as you run unison under the user you'd normally use, but in a chroot. Now a full-blown chroot takes up a lot of space, and there's once again the danger that someone might enter the chroot and run some kind of shell (though the risk is even lower).
It's best to use a chroot which only contains the bare minimum of files
necessary to run
You get numerous advantages:
- No problems with file permissions
- No shell inside the chroot that would read startup files from
- Hardly any space wasted. The whole chroot is about 4Mb in size
- Since the chroot is pretty much empty, many common exploits (well, shell codes) won't work
How to do it
greek0@orest:/home/chroots/unichroot$ cat ~/.ssh/authorized_keys command="/usr/bin/dchroot -q -c unison -- /usr/bin/unison -server" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA8K2cd0..... greek0@orest:/home/chroots/unichroot$ grep unison /etc/dchroot.conf unison /home/chroots/unichroot greek0@orest:/home/chroots/unichroot$ find . -maxdepth 3 | xargs ls -ld drwxr-xr-x 2 root root 4096 2006-08-04 16:39 ./bin -rwxr-xr-x 1 root root 576100 2006-08-04 15:06 ./bin/sash lrwxrwxrwx 1 root root 4 2006-08-04 16:39 ./bin/zsh -> sash drwxr-xr-x 3 root root 4096 2006-08-04 15:10 ./home drwx------ 4 greek0 greek0 4096 2006-08-04 15:18 ./home/greek0 drwx------ 31 greek0 greek0 4096 2006-08-04 13:47 ./home/greek0/Maildir drwx------ 2 greek0 greek0 4096 2006-08-04 15:47 ./home/greek0/.unison drwxr-xr-x 2 root root 4096 2006-08-04 15:07 ./lib -rwxr-xr-x 1 root root 88164 2006-08-04 14:58 ./lib/ld-linux.so.2 -rwxr-xr-x 1 root root 1151644 2006-08-04 14:56 ./lib/libc.so.6 -rw-r--r-- 1 root root 9592 2006-08-04 14:56 ./lib/libdl.so.2 -rw-r--r-- 1 root root 141040 2006-08-04 14:55 ./lib/libm.so.6 -rw-r--r-- 1 root root 9656 2006-08-04 14:55 ./lib/libutil.so.1 drwxr-xr-x 3 root root 4096 2006-08-04 14:53 ./usr drwxr-xr-x 2 root root 4096 2006-08-04 14:55 ./usr/bin lrwxrwxrwx 1 root root 14 2006-08-04 15:12 ./usr/bin/unison -> unison-2.13.16 -rwxr-xr-x 1 root root 955784 2006-08-04 14:54 ./usr/bin/unison-2.13.16
zsh symlink is there because I have
my shell in
/etc/passwd, and dchroot also wants to use it in the
chroot (for launching unison).
/home/greek0/Maildir is bind-mounted from outside the chroot,
bind-mounting is done at boot-time via
The chroot was created manually, simply by copying the files from the host. You
/usr/bin/unison plus all the libraries it depends
on. You can find those via
readelf -d /usr/bin/unison | grep NEEDED.
Additionally you need the dynamic linker
readelf -l /usr/bin/unison | grep INTERP -A 1).
One thing to pay attention to is that most of the files copied from
/lib are symlinks. Be sure to either use
arguments, or use
cp -a and copy the link targets too.