Calomel.org :: Open Source Research and Reference

OpenSMTPD "how to" (smtpd.conf)



Calomel.org Home Page     RSS Feed


History of OpenSMTPD

OpenSMTPD is a mail daemon currently developed by Gilles Chehade (gilles@), Pierre-Yves Ritschard (pyr@), Jacek Masiulaniec (jacekm@) and 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

It is the hope of the developers that OpenSMTPD will replace Sendmail in OpenBSD 5.1 as the default mailer. If you have a chance please help test smtpd and report and bugs to the openbsd misc mailing list.



Please note that OpenSMTPD 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 works quite well for calomel.org.



The setup of OpenSMTPD

Since OpenSMTPD is included in the default stable build of OpenBSD 5.1 it is incredibly simple to setup and get running. We will be going through a few fully working examples. At the end of this tutorial you will have a functional and very secure mail transfer agent (MTA). Let's take a look at the setup.



Update the /etc/mailer.conf

The mailer.conf is a configuration file for mailwrapper. This tells any program which would like to send mail what program to use. The default /etc/mailer.conf on OpenBSD is setup for sendmail. We need to point all mail functions to the binaries for smtpd. Rename the current mailer.conf in case you ever need it again. Then make a new mailer.conf mapping the mail commands to the opensmtp binaries.

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



Update the /etc/aliases file

The aliases file is used to map email names to local user names. For example, if we accepted mail for susie.summers@example.com we could setup an alias to deliver the mail to the username susan on this system. The setup is easy and the current /etc/aliases file will have examples. Just add the external email address followed by a colon ":" followed by the local user name.

Update the /etc/mail/aliases file by adding any mail aliases to local username you want. When you are done just execute newaliases to make the newaliases.db file.

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

root@machine# ls /etc/mail/aliases*
/etc/mail/aliases
/etc/mail/aliases.db



The smtpd.conf , 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 localhost (ipv4 and ipv6) and port 25 (smtp)
listen on lo0

## the mail aliases database, created with "newaliases"
map "aliases" { source db "/etc/mail/aliases.db" }

## accept local mail and deliver to the user local mbox in /var/mail/
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# newaliases 

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 also accepts remote email for the somehost.com domain. The user or daemons can send mail to the local machine. Mail that is not destined for the local hostnames and sent from a local account will be relayed to gmail over TLS port 587. All mail delivered to the local system will be passed to procmail for delivery.

First, we to make a file which allows the smtpd daemon to send the username and password to the gmail server so we can relay mail. 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 640 so only root can read and write to the file and the smtpd daemon running as _smtpd can read it.

root@machine# cd /etc/mail

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

root@machine# chmod 640 /etc/mail/secrets
root@machine# chown root:_smtpd /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 in the /etc/mail directory and you have a map line in smtpd.conf like the example below. Run the following line to make the secrets.db file.

root@machine# cd /etc/mail
root@machine# makemap /etc/mail/secrets 

Now place the following into /etc/mail/smtpd.conf and start the daemon. We have commented every line so you know what they do.

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

## listen on localhost (ipv4 only) and port 25 (smtp)
listen on 127.0.0.1 port 25

## expire messages in the mail queue after 4 hours. Expired messages will
## be bounced back to the sender after this time.
expire 4h

## the hostname of the mail server shown in the headers. if this
## directive is omitted the hostname of the machine will be shown.
hostname machine.domain.lan

## the mail aliases database, created with "newaliases"
map "aliases" { source db "/etc/mail/aliases.db" }

## the file holding the gmail username and password 
## created with "makemap /etc/mail/secrets"
map "secrets" { source db "/etc/mail/secrets.db" }

## accept mail from the local machine (lo0) to localhost accounts and pass to 
## the recipient's procmail rules. Address mapping is derived from the aliases file.
## This rule is for internal machine mail only.
accept from local for local alias aliases deliver to mda "procmail -f -"

## accept mail from any ip address to the hostname somehost.com and pass to 
## the recipient's procmail rules. Address mapping is derived from the aliases file.
## This rule is for external mail being snt to a local account.
accept from all for domain "somehost.com" alias aliases deliver to mda "procmail -f -"

## outgoing mail is accepted from localhost only and relayed through 
## Google's gmail using TLS authentication on port 587. The user and password 
## from the 'map "secrets"' file is used.
## This rule is for local users _only_ to send mail through gmail. No open relays!
accept from local for all relay via smtp.gmail.com port 587 tls auth "secrets"

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





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"

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



Check smtpd.conf for errors

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 -dv



Start smtpd on boot

As of OpenBSD 5.1 smtpd can be started using the smtpd_flags="" directive in the /etc/rc.conf.local file. For example, we added smtpd so OpenSMTPD starts on boot. You will also want to make sure sendmail does not start by setting sendmail_flags to "no".

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

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


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. One could expect the logs to show the full conversation between client and server.

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. Truthfully, if you are using smtpd you really should be using spamd in front which has support for black lists.

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. The biggest problem with this request is the high cost of dns lookups.

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

This will schedule the immediate delivery of that message. OpenSMTPD will try to deliver that mail right away.

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 or



Calomel.org Home Page :: Open Source Research and Reference
Calomel.org :: Open Source Research and Reference