Chrooting sendmail on FreeBSD

Brian M. Clapper, bmc @ clapper . org
$Id: sendmail-chroot.html 6964 2007-08-12 15:24:39Z bmc $

Introduction

This document outlines a procedure for running the open source sendmail SMTP server in a chroot'd area on FreeBSD. It is specific to sendmail version 8.12. I developed this document while chrooting sendmail on a FreeBSD 4.8 system. With minor modifications, these procedures should work with other configurations; as usual, of course, YMMV.

Before attempting to follow these instructions, you should read all pertinent documentation for sendmail. Start with the README file in the top-level directory of the unpacked sendmail sources.

Feel free to send any suggestions, corrections, or enhancements to this document directly to me, at the above email address.

Chrooting Sendmail

  1. Log in as, or su(8) to, root.

  2. Decide where you're going to create the chroot directory structure. This document assumes you'll be using /usr/local/chroot/sendmail, but you're obviously free to substitute some other directory.

  3. Create the directory tree. You'll need the following directories, with the following permissions. Note: If you're using the sendmail "runAsUser" feature, to run sendmail as a non-root user, some of the directories must be owned by that user, rather than by root. Those directories are marked with an asterisk ("*") in the table below. (The "runAsUser" feature is controlled by sendmail configuration option "O RunAsUser=user". See the sendmail configuration README file, located in sendmail-source/cf/README, for details.)

    Directory Permission Mode Owner Group
    /usr/local/chroot/sendmail/bin 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/etc 0755 (drwxr-xr-x) root wheel
    * /usr/local/chroot/sendmail/etc/mail 0755 (drwxr-xr-x) root (or the "run-as" user) wheel
    /usr/local/chroot/sendmail/usr 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/usr/lib 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/usr/sbin 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/usr/bin 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/usr/libexec 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/tmp 01777 (drwxrwxrwt) root wheel
    /usr/local/chroot/sendmail/var 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/var/run 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/var/spool 0755 (drwxr-xr-x) root wheel
    /usr/local/chroot/sendmail/var/spool/clientmqueue 0770 (drwxrwx---) smmsp smmsp
    * /usr/local/chroot/sendmail/var/spool/mqueue 0755 (drwxr-xr-x) root (or the "run-as" user) daemon
    /usr/local/chroot/sendmail/dev 0755 (drwxr-xr-x) root wheel

  4. Copy /bin/sh and /bin/ls (which are statically linked) to the /usr/local/chroot/sendmail/bin directory. Note: This is temporary. Having a shell and the ls(1) command in the chrooted area can be helpful for debugging. You'll delete these files later.

  5. Copy /etc/master.passwd, /etc/passwd and /etc/group to the /usr/local/chroot/sendmail/etc directory.

  6. With your favorite text editor, pare down master.passwd and passwd so they contain only the following users:
    root
    daemon
    smmsp
    mailnull
    nobody

  7. Move the edited /usr/local/chroot/sendmail/etc/master.passwd to a temporary file. (I'll use "/tmp/foo"). It'll be rebuilt in the next step.

  8. Update the password database in your chroot'd area by running the pwd_mkdb(8) command, as shown below:
    # pwd_mkdb -d /usr/local/chroot/sendmail/etc /tmp/foo

  9. Edit /usr/local/chroot/sendmail/etc/group, paring it down to the following groups:
    wheel
    daemon
    mail
    smmsp
    mailnull
    nogroup
    nobody

  10. Copy /etc/services, /etc/resolv.conf and /etc/localtime to directory /usr/local/chroot/sendmail/etc/

  11. Copy /etc/hosts to directory /usr/local/chroot/sendmail/etc/. Make sure there's an entry for each of the local IP addresses, plus 127.0.0.1. If your sendmail configuration also refers to other IP addresses, then you'll need entries for those, as well. For example:
    127.0.0.1        localhost localhost.example.org
    192.168.1.1      inside-ip inside-ip.example.org
    192.168.1.2      inside-mail-relay inside-mail-relay.example.org
    

  12. Copy /etc/host.conf to directory /usr/local/chroot/sendmail/etc/. It should look like this:
    hosts
    bind

  13. Create /usr/local/chroot/sendmail/dev/null, using the mknod(8) command. First, take a look at the existing /dev/null, and be sure to match the major and minor numbers.
    # ls -l /dev/null
    crw-rw-rw-  1 root  wheel    2,   2 Apr 11 10:11 /dev/null
    # mknod /usr/local/chroot/sendmail/dev/null 2 2 root:wheel

  14. Copy /usr/lib/libc.so.4 and /usr/lib/libutil.so.3 to directory /usr/local/chroot/sendmail/usr/lib.

  15. Copy /usr/libexec/ld-elf.so.1 to directory /usr/local/chroot/sendmail/usr/libexec.

  16. Verify that the chroot area is set up properly by firing up a chroot'd shell:
    # chroot /usr/local/chroot/sendmail /bin/sh
    -r-xr-sr-x  1 root  smmsp  516944 Apr  9 13:17 /usr/local/chroot/sendmail/usr/sbin/sendmail

  17. Copy /usr/libexec/sendmail/sendmail to directory /usr/local/chroot/sendmail/usr/sbin. Make sure it has the following permissions:
    # ls -l /usr/local/chroot/sendmail/usr/sbin/sendmail
    -r-xr-sr-x  1 root  smmsp  516944 Apr  9 13:17 /usr/local/chroot/sendmail/usr/sbin/sendmail

  18. Copy /usr/sbin/mailstats and /usr/sbin/makemap to /usr/local/chroot/sendmail/usr/sbin. Both should be owned by root, have group wheel, and mode 0755.

  19. In directory /usr/local/chroot/sendmail/usr/bin, create two symlinks:
    # cd /usr/local/chroot/sendmail/usr/bin
    # ln -s ../sbin/sendmail mailq
    # ln -s ../sbin/sendmail newaliases
    (This step probably isn't strictly necessary, but it doesn't hurt.)

  20. Copy the contents of your existing /etc/mail directory to /usr/local/chroot/sendmail/etc/mail. Note: If you're using the "run-as" feature, you must ensure that the various "*.db" files are owned by that user.

  21. In the real file system (not the chroot'd area), replace /etc/mail, /var/spool/mqueue, and /var/spool/clientmqueue with symlinks to their counterparts in the chroot'd area. This step isn't required, but it allows you to use commands like mailq(1) without being in the chroot'd area.

  22. Next, you need to edit /etc/rc.conf, to:

    To do that, make sure /etc/rc.conf contains these entries:
    SENDMAIL_TOP=/usr/local/chroot/sendmail
    sendmail_program="chroot $SENDMAIL_TOP /usr/sbin/sendmail"
    sendmail_pidfile=$SENDMAIL_TOP/var/run/sendmail.pid
    sendmail_mspq_pidfile=$SENDMAIL_TOP/var/spool/clientmqueue/sm-client.pid
    sendmail_flags="-bd -q15m"
    
    syslogd_flags="-s -l $SENDMAIL_TOP/var/run/log"
  23. At this point, you should be ready to try your chroot'd sendmail. Run this command:
    # sh /etc/rc.sendmail restart

  24. Examine /var/log/maillog, and use ps(1), to verify that sendmail has come up properly. Send some test email messages. Once you're sure sendmail is running fine, remove /usr/local/chroot/sendmail/bin/sh

$Id: sendmail-chroot.html 6964 2007-08-12 15:24:39Z bmc $