OpenSMTPD Building a Mail Server [FAQ Index]


This example will show you how to turn your OpenBSD installation into a full-fledged mail server for medium-sized environments. However, keep in mind that everyone has different requirements and this example makes some very specific assumptions. It only shows a very small subset of what is possible with smtpd(8). The mail server will be doing the following things:

A standard OpenBSD installation as well as a recent installation of OpenSMTPD-extras including: table-passwd, filter-pause, filter-regex, filter-dnsbl, filter-spamassassin, filter-clamav, and tool-stats is assumed. SpamAssassin, ClamAV and Dovecot will be used and should be installed.

The following is not a copy and paste guide. You should know what you are doing and read the man pages.

smtpd Setup

The configuration below is for a medium-size mail server which handles multiple domains with multiple virtual users and is based on several assumptions. One is that a single system user named vmail is used for all virtual users. This user needs to be created:
# useradd -g =uid -c "Virtual Mail" -d /var/vmail -s /sbin/nologin vmail
# mkdir /var/vmail
# chown vmail:vmail /var/vmail
Afterwards, the /etc/passwd file will contain an entry like this:
vmail:*:1000:1000:Virtual Mail:/var/vmail:/sbin/nologin
The home directory /var/vmail is used to store virtual users maildir folders, and is entirely managed by the IMAP server (Dovecot). Mail is delivered to Dovecot via LMTP, using the rcpt-to keyword.

The configuration below assumes that virtual users submit mails via the submission port. Virtual users sending mail are authenticated via the /etc/mail/passwd file, which is shared with Dovecot for the IMAP authentication.

The full content of the /etc/mail/smtpd.conf file is shown below:

# filters and filter chains setup
filter filter-pause pause
filter filter-regex regex
filter filter-dnsbl-sorbs dnsbl
filter filter-dnsbl-spamcop dnsbl "-h"
filter filter-dnsbl-spamhaus dnsbl "-h"
filter filter-spamassassin spamassassin "-s reject"
filter filter-clamav clamav
filter all chain filter-pause filter-regex filter-dnsbl-sorbs filter-dnsbl-spamcop filter-dnsbl-spamhaus filter-spamassassin filter-clamav
filter sub chain filter-pause filter-spamassassin filter-clamav

# pki setup
pki certificate "/etc/ssl/"
pki key "/etc/ssl/private/"

# tables setup
table aliases file:/etc/mail/aliases
table domains file:/etc/mail/domains
table passwd passwd:/etc/mail/passwd
table virtuals file:/etc/mail/virtuals

# listen ports setup
listen on lo0 filter sub
listen on egress port 25 filter all tls pki
listen on egress port 587 filter sub tls-require pki auth <passwd>

# special case for gmail to avoid ipv6 here
#limit mta for domain inet4

# allow local messages
accept from local for local alias <aliases> deliver to lmtp "/var/dovecot/lmtp" rcpt-to
# allow virtual domains
accept from any for domain <domains> virtual <virtuals> deliver to lmtp "/var/dovecot/lmtp" rcpt-to
# allow outgoing mails
accept from local for any relay
The first lines in the configuration above set up several filters in filter chains. The used filters can be installed using the package system:
# export PKG_PATH=http://your.local.mirror/pub/OpenBSD/%c/packages/%a
# pkg_add opensmtpd-extras opensmtpd-extras-spamassassin opensmtpd-extras-clamav
filter-spamassassin and filter-clamav are used to detect spam and viruses, which are both rejected. In addition, filter-dnsbl, filter-regex, and filter-pause are used to keep spammers away. In particular, filter-regex is used to reject invalid HELO arguments. The associated /etc/mail/filter-regex.conf file content is shown below:
# reject helo with leading or trailing dot, and without dots (non-FQDN)
# skipping address literals
helo ! ^\[
helo ^\.
helo \.$
helo ^[^\.]*$
Besides the filters, several table(5) directives are specified in the configuration shown above. The aliases table is set up from the /etc/mail/aliases file and contains aliases for local system users. Below the system user john has an alias to the virtual user
vmail:    /dev/null
root:     john
The domains table is set up from the /etc/mail/domains and contains a list of accepted virtual domains:
In addition, table-passwd is used to set up shared authentication for the virtual users between smtpd(8) and Dovecot. The /etc/mail/passwd file contains (at least) the virtual user names and the encrypted passwords:$2b$...encrypted...password...::::::$2b$...encrypted...password...::::::userdb_quota_rule=*:storage=1G
Finally, the actual virtual users setup is in the /etc/mail/virtuals file as shown below:          vmail          vmail
Note that all virtual users which are supposed to receive mail into a maildir folder are mapped to the single system user vmail.

Antispam Filter

In this example, SpamAssassin and ClamAV are used as spam and virus filters and might be installed using the package system.
# export PKG_PATH=http://your.local.mirror/pub/OpenBSD/%c/packages/%a
# pkg_add p5-Mail-SpamAssassin clamav
# rcctl enable spamassassin clamd
SpamAssassin and ClamAV are assumed to be running on the same host as smtpd(8). The ClamAV configuration needs to be adjusted to listen on localhost. Change at least the lines shown below in /etc/clamd.conf:

LogSyslog yes
LogFacility LOG_MAIL

TCPSocket 3310

User _clamav
The /etc/freshclam.conf file also needs to be adjusted:

LogSyslog yes
LogFacility LOG_MAIL
Manually run freshclam once and start ClamAV and SpamAssassin:
# rcctl start spamassassin clamd
Finally, test your setup with the GTUBE test spam string. You may also want to look into installing and configuring Razor and Pyzor to improve the SpamAssassin detection.

IMAP Server

In this example, Dovecot is used as an IMAP server.
# export PKG_PATH=http://your.local.mirror/pub/OpenBSD/%c/packages/%a
# pkg_add dovecot
# rcctl enable dovecot
Virtual users access and read their mails via IMAP. Dovecot listens on a LMTP socket in /var/dovecot/lmtp for mail delivery from smtpd(8). Passwords are shared with smtpd(8) in the /etc/mail/passwd file and mails are delivered to /var/vmail subfolders. Thus the Dovecot configuration should contain something like the lines below:
passdb {
    args = scheme=blf-crypt /etc/mail/passwd
    driver = passwd-file

userdb {
    args = uid=vmail gid=vmail home=/var/vmail/%d/%n
    driver = static

Bonus: Log Statistics

A simple weekly crontab(5) entry can be set up to parse the mail logs and send statistics, using mail(1) and tool-stats:
/usr/bin/zcat /var/log/maillog.*.gz \
    | /usr/local/bin/tool-stats \
    | /usr/bin/mail -s " smtpd log report" root