Chroot with sSMTP

Introduction

This tutorial describes how to create a working chroot for "sendmail" (we use sSMTP as a "gateway" to our real MTA). I used ssmtp_2.61.orig.tar.gz. This setup is often used for a chrooted webserver setup. A chroot is quite easy, but when it comes to sending mail from a chroot, it then becomes a lot more "complicated", unless you know how.

I have taken the simplest setup possible, and while I'm sure there are more advanced ways of configuring it all, this way works for me.

For my example I will be using the following directory structure (as seen below). In the rest of the tutorial I refer to my base directory (where my chroot will be) as ${CHROOT} (you can replace all commands with your own path). You are welcome to place your chroot wherever you want, as long as the drive it resides on is mounted at boot time. You will need to create these directories yourself.

$ export CHROOT="/home/chroot"	# choose this path yourself
$ mkdir -p ${CHROOT}/bin
$ mkdir -p ${CHROOT}/dev
$ mkdir -p ${CHROOT}/etc/ssmtp
$ mkdir -p ${CHROOT}/lib

Create /dev/(log/urandom) devices

sSMTP required a few basic things to be able to run and connect to your actual postfix (or whichever mailserver), including 2 devices, urandom and log ${CHROOT}/dev/urandom we can easily create:

$ mknod ${CHROOT}/dev/urandom c  1 9

${CHROOT}/dev/log is slightly more complicated, as this device is designed to "listen" in order to write to the system log. The simple solution to this is to edit /etc/syslog-ng/syslog-ng.conf to contain also the line (replace ${CHROOT} with the value you chose above)

source jail1 { unix-stream("${CHROOT}dev/log"); };

below the standard one. Syslog-ng can listen on different devices, so with a restart of this service the new log device should be created. Note : If you do not use systlog-ng, please refer to the documentation of the one you do use regarding creation of other listening devices.

Compile sSMTP for your chroot

We need to compile sSMTP to be able to be used in our chroot, and copy the needed config, binary and dependency files to their appropriate location. Download sSMTP, unpack it, and compile it with:

$ ./configure --prefix=/ ; make

Do not make install it though. We will copy it by hand. First we copy the config files to ${CHROOT}/etc/ssmtp

$ cp ssmtp.conf revaliases ${CHROOT}/etc/ssmtp

Now copy the ssmtp to the bin directory, and symlink the ssmtp to sendmail

$ cp ssmtp ${CHROOT}/bin
$ cd ${CHROOT}/bin
$ ln -s ssmtp sendmail

sSMTP has dependencies too, and these need to be copied to ${CHROOT}/lib:

$ ldd ${CHROOT}/bin/ssmtp
linux-gate.so.1 => (0xffffe000)
libnsl.so.1 => /lib/libnsl.so.1 (0xb7f45000)
libc.so.6 => /lib/libc.so.6 (0xb7e2c000)
/lib/ld-linux.so.2 (0xb7f5e000)

You will need to copy /lib/libnsl.so.1 /lib/libc.so.6 & /lib/ld-linux.so.2 to ${CHROOT}/lib/

$ cp /lib/libnsl.so.1 /lib/libc.so.6 /lib/ld-linux.so.2 ${CHROOT}/lib/

NOTE!!! : I also had to copy the following files to ${CHROOT}/lib/ in order to get it working:

/lib/libnss_compat.so.2
/lib/libnss_dns.so.2
/lib/libnss_files.so.2
/lib/libnss_nis.so.2
/lib/libpam.so.0
/lib/libpam_misc.so.0

I am not sure why these dependencies are not shown (or where they are coming from), but they are required. Thankfully strace helped me out here to detect them. This was in order to fix the :

sendmail: Could not find password entry for UID 0

Extra /etc files & edits

In order for ssmtp to work in it's chrooted environment it requires /etc/localtime and /etc/passwd copied to ${CHROOT}/etc and edited to contain only the user which will be chrooted and using "sendmail" (sSMTP). For testing purposes I suggest leaving the user root in the new passwd file until we have it all working. Add a "description" containing some "no-reply" name:

root:x:0:0:No-Reply:/:/bin/sh

sSMTP also needs to be configured to deliver it's mail to the mailserver you use. Normally you configure sSMTP to use the hostname of this machine, however I use it's IP (127.0.0.1) in my config because name-resolving requires quite a few other things. In ${CHROOT}/etc/ssmtp/ssmtp.conf

root=postmaster
mailhub=127.0.0.1
hostname=localhost
FromLineOverride=YES # Allow setting of From:

This tells sSMTP to deliver all mail to 127.0.0.1 (on default port 25, if you need another port use <ip>:<port>).

Extra binaries & dependencies

In order to run commands (like sendmail) from within your chroot, you need ${CHROOT}/bin/sh, and it's dependencies.

$ cp /bin/sh ${CHROOT}/bin

To get a list of it's dependencies:

$ ldd /bin/sh
linux-gate.so.1 => (0xffffe000)
libdl.so.2 => /lib/libdl.so.2 (0xb7fdf000)
libc.so.6 => /lib/libc.so.6 (0xb7ec6000)
/lib/ld-linux.so.2 (0xb7fe7000)

So you will have to copy /lib/libdl.so.2 /lib/libc.so.6 and /lib/ld-linux.so.2 to ${CHROOT}/lib/

Testing

A very simple test is to chroot yourself in your new path, and run sendmail. In my example I will echo some data to sendmail and send a mail to a user. Please note that this echoed text will not come through, it just allows me to bypass all the commands to send a mail ;-)

$ chroot ${CHROOT} /bin/sh
$ echo "empty"|sendmail username@server.com
$

If all goes well it should just go to the next line. Check your actual logs (and email) and you should have a blank email ;-)

Conclusion

Yes I know this is a simple (very) setup, but I wrote this to create a chrooted environment for lighttpd, where I require the mail() function. It works, and quite well.

website software by Techno Joy // New Zealand Web Developers