OpenSMTPD "how to" (smtpd.conf)



Home


OpenSMTPD is a mail daemon currently developed by Gilles Chehade (gilles@), Pierre-Yves Ritschard (pyr@), Jacek Masiulaniec (jacekm@) and many others for the OpenBSD operating system. Its goal is to be a secure mailing daemon without the licensing restrictions of Postfix and without the added complexity of sendmail. It is stable, fast, secure, and easy to configure and use.

OpenSMTPD is a FREE, easy to use implementation of the Simple Mail Transfer Protocol. It provides the ability to send and receive emails, as well as act as a relaying host. It aims to be as reliable as possible and to respect RFC and standard behaviors when they don't reduce the overall security of system. OpenSMTPD



WARNING: OpenSMTPD is _NOT_ quite ready for production use. It is still in development and the code is changing weekly. If you run a server which sends and receives less than 1000 emails per day then OpenSMTPD should work fine for you. It does for us. Also, make sure you use the latest CVS and check the man pages for changes. Please send bug reports, speed tests and successful configurations emails to smtpd-dev@poolp.org



Building and Installing OpenSMTPD on OpenBSD v4.6 from -current cvs

Start with a generic install of OpenBSD v4.6. It is also a good idea to apply any security or kernel patches to avoid known bugs.

Get the latest OpenBSD source tar file and untar it in /usr/src/.

cd /usr/src/
wget ftp://ftp.openbsd.org/pub/OpenBSD/`uname -r`/src.tar.gz
tar zxvf src.tar.gz

Set the CVSROOT environmental variable. This will tell cvs what server to sync to getting the latest OpenSMTPD source code. This line can be used in bash or ksh to set the environmental variable CVSROOT.

### Execute on the command line or put in root's .profile
export CVSROOT=anoncvs@anoncvs3.usa.openbsd.org:/cvs

Update your source tree to -current. This command uses the server in CVSROOT to sync to. The update will be done over a ssh encrypted connection. You may see the standard "yes/no" ssh question to add the key to your known_hosts file. Answer yes to continue. Make sure the CVS update finishes successfully and without errors.

cd /usr/src/
cvs up usr.sbin/smtpd/

OPTIONAL: If you want to update the entire CVS tree execute "cvs up"

Build OpenSMTPD and setup the environment. These lines will build the OpenSMTPD binaries as well as properly symlink makemap and newaliases to mailwrapper.

### This is where the opensmtpd makemap will reside
mkdir /usr/libexec/smtpd/

### Build OpenSMTPD
cd /usr/src/usr.sbin/smtpd && make clean && make && make install

### Make a backup of the sendmail makemap and link to mailwrapper
mv /usr/sbin/makemap /usr/sbin/makemap.orig
ln -sf /usr/sbin/mailwrapper /usr/sbin/makemap

### Make a backup of the sendmail newaliases and link to mailwrapper
mv /usr/bin/newaliases /usr/bin/newaliases.orig
ln -sf /usr/sbin/mailwrapper /usr/bin/newaliases

Update your /etc/mailer.conf . We need to backup the current file in case you need it in the future and make a OpenSMTPD compatible mailer.conf.

root@machine# mv /etc/mailer.conf /etc/mailer.conf.orig
root@machine# vi /etc/mailer.conf
sendmail        /usr/sbin/smtpctl
send-mail       /usr/sbin/smtpctl
mailq           /usr/sbin/smtpctl
makemap         /usr/libexec/smtpd/makemap
newaliases      /usr/libexec/smtpd/makemap

Make a user for OpenSMTPD to run as. This is not currently done during the install.

useradd -u 95 -g =uid -c "SMTP Daemon" -d /var/empty -s /sbin/nologin _smtpd

HELPFUL HINT: If you have run OpenSMTPD in the future and you have updated the binary to the latest CVS then you must clear the mail queue. As changes are made the old queue format may not be compatible with the new format. Not clearing the queue on a new build is a known cause of OpenSMTPD crashing or faulting on start up.

### Clear the mail queue on new CVS builds
rm -rf /var/spool/smtpd/*

Update the /etc/mail/aliases.db file from /etc/mail/aliases. Pick one method...

root@machine# makemap -t aliases -o /etc/mail/aliases.db /etc/mail/aliases

..or..

root@machine# newaliases
/etc/mail/aliases: 3 aliases

Check the validity of your configuration file, /etc/mail/smtpd.conf . Look further down on this page for many working examples. If you see the message, "warning: could not load cert: 127.0.0.1, no SSL/TLS/AUTH support" this is a warning message and is only informational. It will be fixed in later versions.

root@machine# smtpd -n
configuration OK

Start smtpd. Pick one method...

## Start in daemon mode as a background process
smtpd

..or..

## Start in debug mode so you can see error output to the console.
smtpd -d

Edit /etc/rc.conf.local and add the following to start OpenSMTPD on boot.

root@machine# vi /etc/rc.conf.local
smtpd_flags=""

NOTE: You may need to add the following to /etc/rc for Opensmtpd to start on OpenBSD v4.6. Edit /etc/rc and search for sendmail. Place the following lines right after the sendmail lines.

# Start OpenSMTPD
if [ X"${smtpd_flags}" != X"NO" -a -s /etc/mailer.conf ]; then
        echo -n ' opensmtpd';            ( /usr/sbin/smtpd ${smtpd_flags} >/dev/null 2>&1 & )
fi





Lets take a look at some examples configuration files

The following examples should provide a good idea of what you can do with OpenSMTPD. You can combine different options from each example in your config file. For example you may need to use the aliases, secret and virtual db files in your config. Let's take a look at some example configurations and how to set them up.





Example #1: Default smtpd.conf configuration file

This config file will allow local mail delivery only. Mail will go into the recipient's mbox in /var/mail/$USER unless overridden by an entry in the aliases file. No mail will be sent from or accepted to this box from the outside world.

#######################################################
## Calomel.org  OpenSMTPD -- /etc/mail/smtpd.conf

listen on lo0

map "aliases" { source db "/etc/mail/aliases.db" }

accept for local deliver to mbox
accept for all relay

#######################################################





Example #2: Local mail delivery and relay to a central mail server

This configuration is made for a local system which does not accept remote email, but will relay to a central mail server. The user or daemons can send mail to the local machine. Mail that is not destined for the local hostnames will be relayed to the "mailrelay.domain.lan" mail server using standard unencrypted SMTP port 25. For fun, we also want mail that is destined for @somehost.com, i.e. not our domain name, to also be delivered locally. All mail delivered to the local system will be passed to procmail for delivery.

Lets setup an alias file for local mail delivery. An email alias is simply a forwarding e-mail address. Each e-mail alias simply forwards e-mail messages on to each specified e-mail address. Your file may be significantly larger, but as an example we will be aliasing root to calomel. All mail to the user root will be sent to our user calomel.

root@machine# cd /etc/mail

root@machine# vi /etc/mail/aliases
root: calomel

Second, make a db of the aliases file like so.

root@machine# makemap -t aliases -o /etc/mail/aliases.db /etc/mail/aliases 

Then copy the following into /etc/mail/smtpd.conf and start the daemon.

#######################################################
## Calomel.org  OpenSMTPD -- /etc/mail/smtpd.conf
#
## filter rules are evaluated in sequential order, from first to last.

## Interface and port to listen on
 listen on 127.0.0.1 port 25

## Hostname in the ESMTP banner. If omitted the local
## hostname of the system will be used.
 hostname "machine.domain.lan"

## Maps
 map "aliases" { source db "/etc/mail/aliases.db" }

## local mail delivery
 accept for local deliver to mda "procmail -f -"
 accept for domain "somehost.com" deliver to mda "procmail -f -"

## remote delivery mail through a central mail server
 accept for all relay via "mailrelay.domain.lan"

#######################################################





Example #3: Local mail delivery and relay to Google's gmail

This configuration is made for a local system which does not accept remote email. The user or daemons can send mail to the local machine. Mail that is not destined for the local hostnames will be relayed to gmail over TLS port 587. All mail delivered to the local system will be passed to procmail for delivery.

First, make a new file called secrets in /etc/mail/. Add the gmail smtp server you are going to relay to and your gmail username and password. Make sure to set the permission of the file to 600 so only root can read and write to the file.

root@machine# cd /etc/mail

root@machine# vi /etc/mail/secrets
smtp.gmail.com GMAIL_USERNAME@gmail.com:GMAIL_PASSWORD

root@machine# chmod 600 /etc/mail/secrets

Second, make a db of the secrets file. If you received the error, "no credentials for relay through "$myrelay": Undefined error: 0" then the smptd daemon did not find your secrets.db file. Make sure you made the db file and you have a map line in smtpd.conf like the example below. Run the following line to make the secrets.db file. Also, make sure the secrets.db file is group owned by _smtpd and only root and _smtpd can read it.

root@machine# makemap -o /etc/mail/secrets.db /etc/mail/secrets 

root@machine# chmod 640 /etc/mail/secrets.db
root@machine# chgrp _smtpd /etc/mail/secrets.db

Now place the following into /etc/mail/smtpd.conf and start the daemon.

#######################################################
## Calomel.org  OpenSMTPD -- /etc/mail/smtpd.conf
#
## filter rules are evaluated in sequential order, from first to last.

## Interface and port to listen on
 listen on 127.0.0.1 port 25

## Hostname in the ESMTP banner. Otherwise the local
## hostname of the system will be used.
 hostname "machine.domain.lan"

## Maps
 map "aliases" { source db "/etc/mail/aliases.db" }
 map "secrets" { source db "/etc/mail/secrets.db" }

## local mail delivery.
 accept for local deliver to mda "procmail -f -"

## remote delivery mail through a central mail server
 accept for all relay via "smtp.gmail.com" port 587 tls enable auth

#######################################################





Example #4: Local mail delivery, remote mail to our domain and relay to mail server

This configuration is made for a system which will accept remote email from any external ip only for the domain "example.org". OpenSMTPD is listening on localhost as well as the external interface at ip 192.168.5.55 . The user or daemons can send mail to the local machine. Mail that is not destined for the local hostnames and originates from the local machine will be relayed to the "mailrelay.domain.lan" mail server using standard smtp port 25. All mail delivered to the local system will be passed to procmail for delivery.

For the domain "example.org" we might have externally known email addresses that do not match the usernames on the local system. So, we will setup a virtual map file.

# The virtual file will map external addresses to internal usernames
root@machine# vi /etc/mail/virtual
bob_smith@example.org:  robert
support@example.org:    becky
abuse@example.org:      bob

Second, make a db of the virtual file.

root@machine# makemap -t aliases -o /etc/mail/virtual.db /etc/mail/virtual

Finally, put the following in /etc/mail/smtpd.conf and start the daemon.

#######################################################
## Calomel.org  OpenSMTPD -- smtpd.conf
#
## filter rules are evaluated in sequential order, from first to last.

## Interface and port to listen on
 listen on 127.0.0.1    port 25
 listen on 192.168.5.55 port 25

## Hostname in the ESMTP banner. If omitted the local
## hostname of the system will be used.
 hostname "machine.domain.lan"

## Maps
 map "aliases" { source db "/etc/mail/aliases.db" }
 map "virtual" { source db "/etc/mail/virtual.db" }

## local mail delivery
 accept for local deliver to mda "procmail -f -"

## remote mail to our domain from any host
 accept from all for domain "example.org" deliver to mda "procmail -f -"

## remote delivery mail through a central mail server
 accept for all relay via "mailrelay.domain.lan"

#######################################################



HELPFUL HINT: For an added layer of protection again spam you can use a bayesian spam filter. Check out our Bogofilter "how to" Anti-Spam Guide. With a little time and understanding you could easily filter up to 99% of any remaining spam.





What features would you like to see in later versions of OpenSMTPD ?

A few readers have sent mail with some features they would like to see in future updates of OpenSMTPD. This list is just to keep track of them. Remember that OpenSMTPD is still in development and stability is most important right now. Features like the following may come later if the developers see them as useful. Also, look in the "Questions" section below for info on contacting the developers directly.

Verbose Logging: Even if you start the daemon with the "-v" argument verbose logging of the daemon does not increase the output to /var/log/maillog. Also, logging of failed connection attempts do not show up in the mail log.

Filter header output: For security and privacy you may not want the usernames and ip address of your internal network to be included in the header output of sent mail. Postfix has a filter directive using the "header_checks" file that will accomplish this function. For example, "/^Received:.*.domain.lan/ IGNORE" in postfix would omit any header lines with *.domain.lan in it. This option is required in top secret or secure environment.

Blacklists or RTBL: The ability to query a real time black list (RTBL) like zen.spamhaus.org and deny mail on the results. The majority of spam is sent from compromised windows boxes. The zen list has a list of these types of ips, as well as other lists, and mail could be denied from them.

DNS hostname verifications: When a remote mail server connects we could verify that the hostname of the originating ip matches the domain they say they are sending from. We might also want to make sure the HELO statement matches the senders ip. A directive similar to "accept if $CLIENT_HELO equals $SENDER_DOMAIN or error 450" says the HELO header must match the DNS domain name of the client or we send an error 450.

Mail variables: As opensmtpd accepts mail it populates variables for each value. For example the clients ip address in $CLIENT_IP, their hostname in $CLIENT_HOST, and the senders From: in $CLIENT_FROM. This would allow the admin to construct checks on their own to suit their environment. "allow if $CLIENT_HOST != *.adultsite.* else error 500".

Limit acceptable email addresses: Perhaps opensmtpd could look at the Spamd's acceptable email addresses in /etc/mail/spamd.alloweddomains and deny any To: address not on the list.

Work with Spamd: When mail is delivered on its first attempt, the connection goes to opensmtpd if the mail passes the checks. It not it is proxied to spamd. This is probably not going to be developed unless a smtpd proxy is put in front of both daemons.





Questions?

How can I help the project? How do I report to the developers ?

Please send bug reports, speed tests and successful configurations emails to smtpd-dev@poolp.org . Before you ever send an email make sure you are using the latest, up to date CVS checkout and applied the latest OS patches. Reporting a bug which has already been fixed in the committed CVS would be an inefficient use of your time.

When you are ready to report your findings include what version of the OS you are using, OS patches installed and the time you updated you local CVS repository. If you are reporting a bug, make sure you clearly and concisely explain what the bug is as well as the procedure to reproduce it. If you are reporting a speed trial or working configuration then you will probably want to also include information about your hardware. For example a copy of "dmesg" referenced at the end of the email. Take some time to proof read your email so the developers have a good idea of what you are trying to tell them.

Finally, be courteous. The developers are donating their time and energy to the project and they want constructive comments. The purpose of the email is to help them make a better product, thus helping the community as a whole. But, if your email is rude, unjustly argumentative or contains insidious complaining it will probably just be ignored.

How do I flush a single message from the mail queue ?

First, use smtpctl to show all of the messages in your queue:

root@machine# smtpctl show queue
MTA|1244574723.MTwCoXNepGJtbMcJ.441941725|PROCESSING,ENQUEUED|user@our_domain.org|someguy@somedomain.org|1244582934|0

Then schedule the immediate delivery of that message. OpenSMTPD will try to deliver that mail immediately.

root@machine# smtpctl schedule 1244574723.MTwCoXNepGJtbMcJ.441941725
command succeeded

How do I print out statistics on the smtpd process?

root@machine# smtpctl show stats
mta.sessions=16
mta.sessions.active=0
parent.uptime=157948
queue.inserts.local=5
queue.inserts.remote=11
runner.active=0
smtp.errors.delays=0
smtp.errors.linetoolong=0
smtp.errors.read_eof=0
smtp.errors.read_system=0
smtp.errors.read_timeout=0
smtp.errors.tempfail=0
smtp.errors.toofast=0
smtp.errors.write_eof=0
smtp.errors.write_system=0
smtp.errors.write_timeout=0
smtp.sessions=16
smtp.sessions.aborted=0
smtp.sessions.active=0
smtp.sessions.timeout=0
smtp.sessions.smtps=0
smtp.sessions.smtps.active=0
smtp.sessions.starttls=0
smtp.sessions.starttls.active=0

Where can the logs for smtpd be found?

Check in /var/log/maillog for entries similar to this
root@machine# cat /var/log/maillog | grep smtpd
Jan 10 12:30:00 test smtpd[13226]: 1244651996.ZjcewNaiDZhvzdsD: from=<user@our_domain.org>, size=471, nrcpts=1, proto=ESMTP, relay=localhost [IPv6:::1]
Jan 10 12:30:00 test smtpd[20966]: 1244651996.ZjcewNaiDZhvzdsD.2164998912: to=<someguy@somedomain.org>, delay=0, stat=Sent

Does opensmtpd support smtp auth ?

yes, the daemon supports smtp for both incoming and outgoing sessions over ssl (smtps or tls). -gilles@

What is the error, "couldn't enqueue offline message; smtpctl exited abnormally" followed by "sendmail: unknown option -- L" ?

This is a known bug (seen Jun 2009) that will be fixed soon. Make sure to clear out the old mail queue before starting smtpd on a new build.

What is the error, "fatal: queue_load_envelope: fopen: No such file or directory" followed by "lost child: runner exited abnormally" ?

This probably means that the /var/spool/smtpd/ queue directories are out of sync somehow. Opensmptd will not start if this is true. To fix this problem you can just delete all of the files and directories under that path. Like so, "rm -rf /var/spool/smtpd/*". Opesmtpd will remake all of the queue directories when it starts.

What is the error, "error on start warning: could not load cert: lo0, no SSL/TLS/AUTH support" ?

This is a known bug that should be fixed soon (seen Jun 2009). Even though we are not using a SSL cert for mail and it is not configured, this error still shows up. It is an informational message only.

What is the error, "send-mail: write error: Broken pipe" ?

The mail server will return this error if it unexpectedly dies or is killed.





Questions, comments, or suggestions? Contact Calomel.org