Back to the sea ; the mail server (SMTP, IMAP, GreyList, RBL...), episode X

       1414 words, 7 minutes

Like I did with NetBSD, this is how to build an almost complete Mail Server with OpenBSD.

We’re gonna use a Dovecot IMAP server and a Postfix SMTP server. Postfix will use Dovecot as a SASL service. Both will use LDAP to identify valid users and e-mail aliases. Mail sanitization will be provided by RBL, from Postfix, and by the spamd shipped with OpenBSD.

Prerequisites

You’ll need an OpenBSD server and a few depending services:

The previous articles from the series explain how to implement those services.

Installation

Start with installing Postfix and Dovecot from the binary packages:

# pkg_add http://ftp.fr.openbsd.org/pub/OpenBSD/4.8/packages/amd64/postfix-2.7.1-ldap.tgz
# pkg_add http://ftp.fr.openbsd.org/pub/OpenBSD/4.8/packages/amd64/dovecot-1.2.13p0-ldap.tgz

The server certificate should already be installed from the previous articles steps ; I use the same DNS/CN name as I only have one publically known certificate:

# file /etc/ssl/server.crt /etc/ssl/private/server.key  
/etc/ssl/server.crt: ASCII text  
/etc/ssl/private/server.key: ASCII text 

Create the virtual mail storage space:

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

Configure the system to allow services to trust my private CA ; this is required for LDAPS connection:

# cat >> /etc/openldap/ldap.conf
TLS_CACERT /etc/ssl/TMFCA/cacert.pem

Configuration

We’ll first configure the IMAP server, then the SMTP server.
This is because Postfix needs a socket from Dovecot to authenticate users.

The IMAP server (Dovecot)

Modify the main configuration file:

# diff /usr/local/share/examples/dovecot/dovecot-example.conf /etc/dovecot.conf
23c23
< #protocols = imap imaps
---
> protocols = imaps
98,99c98,99
< ssl_cert_file = /etc/ssl/dovecotcert.pem
< #ssl_key_file = /etc/ssl/private/dovecot.pem
---
> ssl_cert_file = /etc/ssl/server.crt
> ssl_key_file = /etc/ssl/private/server.key
146c146
< #login_chroot = yes
---
> login_chroot = yes
302,303c302,303
< #mail_uid =
< #mail_gid =
---
> mail_uid = vmail
> mail_gid = vmail
376c376
< #verbose_proctitle = no
---
> verbose_proctitle = yes
619c619
< protocol pop3 {
---
> #protocol pop3 {
699,700c699,700
<   pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
< }
---
> #  pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
> #}
844c844
< #auth_verbose = no
---
> auth_verbose = yes
968c968
<   passdb bsdauth {
---
>   #passdb bsdauth {
971c971
<   }
---
>   #}
996c996
<   #passdb ldap {
---
>   passdb ldap {
998,999c998,999
<     #args =
<   #}
---
>     args = /etc/dovecot-ldap.conf
>   }
1027c1027
<   userdb passwd {
---
>   #userdb passwd {
1034c1034
<   }
---
>   #}
1074c1074
<   #userdb ldap {
---
>   userdb ldap {
1076,1077c1076,1077
<     #args =
<   #}
---
>     args = /etc/dovecot-ldap.conf
>   }
1089c1089
<   user = root
---
>   user = nobody
1108c1108
<   #socket listen {
---
>   socket listen {
1119c1119
<     #client {
---
>     client {
1123,1126c1123,1128
<       #path = /var/run/dovecot/auth-client
<       #mode = 0660
<     #}
<   #}
---
>       path = /var/spool/postfix/private/auth
>       mode = 0660
>       user = _postfix
>       group = _postfix
>     }
>   }

Create the LDAP authentication configuration file:

# install -o _dovecot -g _dovecot -m 0640 /usr/local/share/examples/dovecot/dovecot-ldap-example.conf /etc/dovecot-ldap.conf
# diff /usr/local/share/examples/dovecot/dovecot-ldap-example.conf /etc/dovecot-ldap.conf
21c21
< #uris =
---
> uris = ldaps://ldap.tumfatig.net
25c25
< #dn =
---
> dn = cn=email,dc=tumfatig,dc=net
28c28
< #dnpass =
---
> dnpass = password
66c66
< #auth_bind = no
---
> auth_bind = yes
82c82
< #auth_bind_userdn =
---
> auth_bind_userdn = uid=%u,ou=users,dc=tumfatig,dc=net
85c85
< #ldap_version = 3
---
> ldap_version = 3
89c89
< base =
---
> base = ou=users,dc=tumfatig,dc=net
106c106
< #user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid
---
> user_attrs = homeDirectory=home,mailbox=mail
113c113
< #user_filter = (&#038;(objectClass=posixAccount)(uid=%u))
---
> user_filter = (&(objectClass=CourierMailAccount)(uid=%u))
121c121
< #pass_attrs = uid=user,userPassword=password
---
> pass_attrs = uid=user,userPassword=password
131c131
< #pass_filter = (&#038;(objectClass=posixAccount)(uid=%u))
---
> pass_filter = (&(objectClass=CourierMailAccount)(uid=%u))

Configure the system to start Dovecot at boot ime:

# cat >> /etc/login.conf
dovecot:
        :openfiles-cur=1024:
        :openfiles-max=2048:
        :tc=daemon:
# cat >> /etc/rc.local
if [ -x /usr/local/sbin/dovecot ]; then
        echo -n ' dovecot';
        su -c dovecot root -c '/usr/local/sbin/dovecot'
fi

Start Dovecot and check the logs.

The SMTP server (Postfix)

OpenBSD ships with Sendmail by default. But it can be replaced with Postfix, from the binary packages.

Enable Postfix:

# /usr/local/sbin/postfix-enable
# cat >> /etc/rc.conf.local
sendmail_flags="-bd"
# vi /etc/syslog-ng/syslog-ng.conf
(...)
unix-dgram ("/var/spool/postfix/dev/log");
(...)
# crontab -e
(...)
# sendmail clientmqueue runner
#*/30   *       *       *       *       /usr/sbin/sendmail -L sm-msp-queue -Ac -q

Edit the main configuration file:

# diff /usr/local/share/examples/postfix/main.cf /etc/postfix/main.cf
76c76
< #myhostname = virtual.domain.tld
---
> myhostname = cherie.tumfatig.net
99c99
< #myorigin = $mydomain
---
> myorigin = $mydomain
163c163
< #mydestination = $myhostname, localhost.$mydomain, localhost
---
> mydestination = localhost
263c263
< #mynetworks = 168.100.189.0/28, 127.0.0.0/8
---
> mynetworks = 10.0.0.0/24, 127.0.0.0/8
295c295,296
< #relay_domains = $mydestination
---
> relay_domains = hash:/etc/postfix/relay_transport
> relay_transport = $relay_domains
314c315
< #relayhost = [mailserver.isp.tld]
---
> relayhost = smtp.free.fr
330c331
< #relay_recipient_maps = hash:/etc/postfix/relay_recipients
---
> relay_recipient_maps = hash:/etc/postfix/relay_recipients
358a360,361
> virtual_mailbox_domains = $transport_maps
> virtual_mailbox_base = /home/vmail
359a363,369
> 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
>
366a377
> transport_maps = hash:/etc/postfix/transport
511a523,526
> disable_vrfy_command = yes
> smtpd_delay_reject = yes
> smtpd_helo_required = yes
> strict_rfc821_envelopes = yes
512a528,560
> 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,
>       permit
>
654a703,725
>
> # TLS configuration
> #
> smtpd_tls_cert_file = /etc/ssl/server.crt
> smtpd_tls_key_file = /etc/ssl/private/server.key
>
> smtpd_tls_loglevel = 1
> smtpd_tls_security_level = may
>
> smtpd_tls_auth_only = yes
>
> smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache
> smtpd_tls_session_cache_timeout = 3600s
>
> # 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

Create the LDAP configuration files:

# cat /etc/postfix/ldap_accounts
server_host = ldaps://ldap.tumfatig.net
search_base = ou=users,dc=tumfatig,dc=net
query_filter = (&(mail=%s)(objectClass=CourierMailAccount))
result_attribute = mailbox
version = 3
bind = yes
bind_dn = cn=email,dc=tumfatig,dc=net
bind_pw = password
# cat /etc/postfix/ldap_aliases
server_host = ldaps://ldap.tumfatig.net
search_base = ou=alias,dc=tumfatig,dc=net
query_filter = (&(mail=%s)(objectClass=CourierMailAlias))
result_attribute = maildrop
version = 3
bind = yes
bind_dn = cn=email,dc=tumfatig,dc=net
bind_pw = password
# chgrp _postfix /etc/postfix/ldap_a*
# chmod 0640 /etc/postfix/ldap_a*
# postmap /etc/postfix/ldap_accounts /etc/postfix/ldap_aliases

Create the other external references:

# cat > /etc/postfix/relay_transport
other.tld     smtp:10.15.5.12
# cat > /etc/postfix/relay_recipients
friend@other.tld  OK
abuse@other.tld       OK
postmaster@other.tld  OK
webmaster@other.tld   OK
# cat > /etc/postfix/transport
tumfatig.net            virtual:
carnat.net              virtual:
# cat > /etc/postfix/access_client
# cat > /etc/postfix/access_helo
funky.smtp.server.tld  OK
# postmap /etc/postfix/relay_transport /etc/postfix/relay_recipients /etc/postfix/transport /etc/postfix/access_client /etc/postfix/access_helo

In OpenBSD, Postfix is chrooted and requires access to files from within its jail:

# tar cpf - /etc/openldap/ldap.conf /etc/ssl/TMFCA/cacert.pem | tar xpf - -C /var/spool/postfix/

Reboot and check that everything loaded OK.

The SPAM Deferral daemon (spamd)

I used to use Postgrey with Postfix to greylist e-mails. This works quite well for direct connections. OpenBSD ships with a daemon that does greylisting. It’s a bit different in the way it works.

Configure pf to redirect SMTP traffic to spamd:

# vi /etc/pf.conf
table <spamd-white> persist
table <nospamd> persist file "/etc/mail/nospamd"
pass in on egress proto tcp from any to any port smtp 
        rdr-to 127.0.0.1 port spamd
pass in on egress proto tcp from <nospamd> to any port smtp
pass in log on egress proto tcp from <spamd-white> to any port smtp
pass out log on egress proto tcp to any port smtp
# touch /etc/mail/nospamd

Have to daemons start at boot time:

# vi /etc/rc.conf.local
spamd_flags=""
spamlogd_flags=""

Reboot to ensure everything starts correctly.

The submission feature

One problem with spamd is that without having previously whitelisted a triple (source, from, to), the SMTP connexion would have a change to get to the AUTH phase. This isn’t a nice feature for mobile users that must authenticate to the SMTP server to be allowed to relay. According to OpenBSD’s mailing list, the right way to deal with mobile users is either use authpf or dedicate a submission port on the SMTP server.

Configure the “authenticate and allow relay port”:

# vi /etc/postfix/master.cf
(...)
submission inet n       -       -       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
(...)
# postfix reload

The configuration is quite straight forward as we already configured the authentication stuff on the normal SMTP port ;-)

That’s All Chicks!