Complete (almost) Mail Server with NetBSD

       1179 words, 6 minutes

Those are the directions I used to setup an almost complete OpenSource Mail server running NetBSD and pkgsrc.
The Mail server will feature:

Prerequisites

Install a NetBSD server ; I used a Xen3 domU.
I’ll mostly use prebuilt packages ; except for Dovecot that doesn’t have LDAP support by default.

Edit the system-wide LDAP configuration file to enable slapd/ssl certificate validation:

# cat /etc/openldap/ldap.conf  
TLS_CACERT /etc/openssl/certs/ca.tumfatig.local.pem 

Install the SSL public certificate (PEM with private key) that will be used by Postfix and Dovecot:

# chown root:wheel /etc/postfix/www.tumfatig.net.pem  
# chmod 640 /etc/postfix/www.tumfatig.net.pem 

Create the user, group and storage space that’ll be used by the mail daemons:

# groupadd -g 3000 vmail  
# useradd -m -u 3000 -g vmail -c "Virtual Mail user" -d /home/vmail -s /sbin/nologin vmail  
# rm -rf /home/vmail/.??*  
# chmod 750 /home/vmail 

Of course, you have to have a Lightweight Directory Access Protocol (LDAP) server filled with your e-mail users and aliases. I expanded my OpenLDAP with the Courier IMAP schema(authldap.schema).

Don’t forget to properly configure the Domain Name System (DNS) server too!

IMAP server

The Internet Message Access Protocol (IMAP) server I choose is Dovecot .
I choose it for historical reasons. I first used Courier-IMAP ; about 2003. Then, I began to store the e-mails on a remote NFS server. I read that Courier may not deal with this very well (at the time of switching). There were informations that claimed Dovecot would and might even be faster (thanks to index caching). So I tried it and kept it :-D

Another reason to keep it is that the NetBSD’s default Postfix instance does support Simple Authentication and Security Layer (SASL) through Dovecot.

The Dovecot server will provide an authentication socket to Postfix and wil offer imaps access only.

Install Dovecot

In pkgsrc, Dovecot doesn’t enable LDAP support by default. So I had to compile it:

# cd /usr/pkgsrc/mail/dovecot  
# env PKG_OPTIONS.dovecot="dovecot-managesieve dovecot-sieve ldap" make install clean-depends 

Configure LDAP Authentication

Create and edit the backend configuration file:

# cp -p /usr/pkg/share/examples/dovecot/dovecot-ldap-example.conf /usr/pkg/etc/dovecot-ldap.conf
# chmod 600 /usr/pkg/etc/dovecot-ldap.conf
# vi /usr/pkg/etc/dovecot-ldap.conf
uris = ldaps://ldap.tumfatig.local
dn = cn=email,dc=tumfatig,dc=local
dnpass = password
auth_bind = yes
auth_bind_userdn = uid=%u,ou=users,dc=tumfatig,dc=local
ldap_version = 3
base = ou=users,dc=tumfatig,dc=local
user_attrs = homeDirectory=home,mailbox=mail
user_filter = (&(objectClass=CourierMailAccount)(uid=%u))
pass_attrs = uid=user,userPassword=password
pass_filter = (&(objectClass=CourierMailAccount)(uid=%u))

Create and edit the main configuration file:

# vi /usr/pkg/etc/dovecot.conf
protocols = imaps
listen = *

disable_plaintext_auth = yes

ssl_cert_file = /etc/postfix/www.tumfatig.net.pem
ssl_key_file = /etc/postfix/www.tumfatig.net.pem

login_chroot = yes
login_user = dovecot

mail_location = /home/vmail/%u
mail_uid = vmail
mail_gid = vmail

verbose_proctitle = no

protocol imap {
  imap_client_workarounds = delay-newmail
}

auth_verbose = yes
auth_debug = no
auth default {
  mechanisms = plain
  passdb ldap {
    args = /usr/pkg/etc/dovecot-ldap.conf
  }
  userdb ldap {
    args = /usr/pkg/etc/dovecot-ldap.conf
  }
  user = vmail
  socket listen {
    client {
      path = /var/spool/postfix/private/auth
      mode = 0660
      user = postfix
      group = wheel
    }
  }
}
dict {
}
plugin {
}

Configure automatic launch at boot time:

# cat >> /etc/rc.conf
dovecot=YES
# cat >> /etc/rc.local
[ -x /usr/pkg/share/examples/rc.d/dovecot ] &&
        /usr/pkg/share/examples/rc.d/dovecot start

Test your installation:

# openssl s_client -connect localhost:imaps  
CONNECTED(00000004)  
(...)  
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE AUTH=PLAIN] Dovecot ready.  
. login someusername somepassword  
. OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT IDLE CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS] Logged in  
. logout  
* BYE Logging out  
. OK Logout completed.  
closed 

SMTP server

The Simple Mail Transfer Protocol (SMTP) server that ships with NetBSD (at the time of writing) is Postfix 2.6.x.

Uncomment the smtp line from the /etc/postfix/master.cf so that Postfix listens to connections on port 25.

Edit the main configuration file:

# vi /etc/postfix/main.cf  
myhostname = cherie.tumfatig.net  
mydomain = tumfatig.local  
myorigin = tumfatig.net

mydestination = localhost  
mynetworks = 10.0.0.0/24, 127.0.0.0/8

local\_recipient\_maps = $virtual\_mailbox\_maps $virtual\_alias\_maps

unknown\_local\_recipient\_reject\_code = 550

transport_maps = hash:/etc/postfix/transport

virtual\_mailbox\_domains = $transport_maps  
virtual\_mailbox\_base = /home/vmail  
virtual\_minimum\_uid = 3000  
virtual\_uid\_maps = static:3000  
virtual\_gid\_maps = static:3000  
virtual\_mailbox\_maps = ldap:/etc/postfix/ldap_accounts  
virtual\_alias\_maps = ldap:/etc/postfix/ldap_aliases 

Create and edit the accounts configuration file:

# vi /etc/postfix/ldap_accounts  
server_host = ldaps://ldap.tumfatig.local  
search_base = ou=users,dc=tumfatig,dc=local  
query_filter = (&(mail=%s)(objectClass=CourierMailAccount))  
result_attribute = mailbox  
version = 3  
bind = yes  
bind_dn = cn=email,dc=tumfatig,dc=local  
bind_pw = password  
# chown root:postfix /etc/postfix/ldap_accounts  
# chmod 640 /etc/postfix/ldap_accounts 

Create and edit the aliases configuration file:

# vi /etc/postfix/ldap_aliases  
server_host = ldaps://ldap.tumfatig.local  
search_base = ou=alias,dc=tumfatig,dc=local  
query_filter = (&(mail=%s)(objectClass=CourierMailAlias))  
result_attribute = maildrop  
version = 3  
bind = yes  
bind_dn = cn=email,dc=tumfatig,dc=local  
bind_pw = password  
# chown root:postfix /etc/postfix/ldap_aliases  
# chmod 640 /etc/postfix/ldap_aliases 

Create and edit the transport configuration file:

# vi /etc/postfix/transport  
tumfatig.local virtual:  
tumfatig.net virtual:  
carnat.net virtual:  
truttet.net smtp:network.truttet.net. 

Final touch and run the road:

# set -o braceexpand  
# postmap /etc/postfix/{ldap\_accounts,ldap\_aliases,transport}  
# cat >> /etc/rc.conf  
postfix=YES  
# /etc/rc.d/postfix restart 

Enable TLS on Postfix

Enabling TLS in quite straight forward:

# vi /etc/postfix/main.cf  
# TLS configuration  
#  
smtpd_tls_cert_file = /etc/postfix/www.tumfatig.net.pem  
smtpd_tls_key_file = $smtpd_tls_cert_file  
smtpd_tls_loglevel = 1  
smtpd_tls_security_level = may

smtpd_tls_auth_only = yes

smtpd_tls_session_cache_database = btree:/var/db/postfix/smtpd_scache  
smtpd_tls_session_cache_timeout = 3600s 

Test the STARTTLS connexion:

# openssl s_client -starttls smtp -connect localhost:25  
CONNECTED(00000004)  
(...)  
250 DSN  
EHLO localhost  
250-cherie.tumfatig.net  
250-PIPELINING  
250-SIZE 10240000  
250-ETRN  
250-AUTH PLAIN  
250-ENHANCEDSTATUSCODES  
250-8BITMIME  
250 DSN 

Enable SASL on Postfix

Check the available SASL server plug-in types:

# postconf -a  
dovecot 

Enable SASL in Postfix (the previous section restricts SASL to TLS connexions):

# vi /etc/postfix/main.cf
# SASL configuration
#
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth

smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous

Allow mail relay when authenticated:

# vi /etc/postfix/main.cf
smtpd_recipient_restrictions =
  permit_mynetworks,
  permit_sasl_authenticated,
  reject_unauth_destination

Implement greylisting on Postfix

Install Postgrey:

# pkg_add http://nyftp.netbsd.org/pub/pkgsrc/packages/NetBSD/i386/5.0/All/postgrey-1.33nb1.tgz  
# pkg_add http://nyftp.netbsd.org/pub/pkgsrc/packages/NetBSD/i386/5.0/All/p5-Digest-SHA1-2.13nb1.tgz 

Configure automatic start at boot time:

# cat >> /etc/rc.conf
postgrey=YES
postgrey_flags="-i localhost:8025 --delay=120 --privacy"
# cat >> /etc/rc.local
[ -x /usr/pkg/share/examples/rc.d/postgrey ] &&
        /usr/pkg/share/examples/rc.d/postgrey start
# /usr/pkg/share/examples/rc.d/postgrey start

Configure Postfix to use Postgrey:

# vi /etc/postfix/main.cf
smtpd_recipient_restrictions =
  permit_mynetworks,
  reject_non_fqdn_recipient,
  reject_unknown_recipient_domain,
  permit_sasl_authenticated,
  check_policy_service inet:127.0.0.1:8025,
  reject_unauth_destination
# postfix reload

Test that it works properly:

# telnet 192.168.12.143 25  
Trying 192.168.12.143...  
Connected to 192.168.12.143.  
Escape character is '^]'.  
220 cherie.tumfatig.net ESMTP Postfix  
HELO localhost  
250 cherie.tumfatig.net  
MAIL FROM: jdoe@tumfatig.net  
250 2.1.0 Ok  
RCPT TO: joel@carnat.net  
450 4.2.0 <joel@carnat.net>: Recipient address rejected: Greylisted, see http://postgrey.schweikert.ch/help/carnat.net.html  
RSET  
250 2.0.0 Ok  
QUIT  
221 2.0.0 Bye  
Connection closed by foreign host. 

Tune Postfix to help blocking as many UCE as possible

Configure Postfix to conform to various basics RFC and use external RBL to reject unwanted e-mails:

# vi /etc/postfix/main.cf
disable_vrfy_command = yes
smtpd_delay_reject = no
smtpd_helo_required = yes
strict_rfc821_envelopes = yes

smtpd_client_restrictions =
        permit_mynetworks,
        check_client_access hash:/etc/postfix/access_client,
        permit_sasl_authenticated,
        reject_unauth_pipelining,
        reject_rbl_client bl.spamcop.net,
        reject_rbl_client zen.spamhaus.org,
        reject_rbl_client cbl.abuseat.org,
        permit

smtpd_helo_restrictions =
        permit_mynetworks,
        check_helo_access hash:/etc/postfix/access_helo,
        reject_invalid_helo_hostname,
        reject_non_fqdn_helo_hostname,
        reject_unknown_helo_hostname,
        permit

smtpd_sender_restrictions =
        permit_mynetworks,
        reject_non_fqdn_sender,
        reject_unknown_sender_domain,
        reject_rhsbl_sender dsn.rfc-ignorant.org,
        permit

smtpd_recipient_restrictions =
        permit_mynetworks,
        reject_non_fqdn_recipient,
        reject_unknown_recipient_domain,
        reject_unauth_destination,
        permit_sasl_authenticated,
        check_policy_service inet:127.0.0.1:8025,
        permit

# touch /etc/postfix/access_client
# postmap /etc/postfix/access_client

# touch /etc/postfix/access_helo
# postmap /etc/postfix/access_helo

# postfix reload

Sources

http://wiki.dovecot.org/HowTo/DovecotOpenLdap
http://www.postfix.org/TLS_README.html
http://www.postfix.org/SASL _README.html#server_dovecot