I recently configured smptd to replace a postfix-based solution.
smtpd(8) is a joy to work with. In ~four rules I had a working email
server!

My next goals was to get content filtering in place. I decided on
amavisd-new with clamav and spamassassin.

I couldn't find any tutorials for using amavisd with smtpd(8) so I
worked out my own solution based on some postfix tutorials and the
excellent smtpd.conf(5) doc.

Following are the steps and missteps that got me to the working
smtpd.conf included at the bottom.

I have also have one question for the smtpd(8) developers at the end.

The goal was to have smtpd deliver via lmtp to amavisd. Fortunately
smtpd in 5.4 (shipping) supports lmtp via the deliver and relay
keywords. That’s important as we’ll see in a minute.

Installing amavisd is easy. Configuration is another story. For now I'm
assuming the user can handle pkg_add -i amavisd-new and starting the
relevant daemons.

The first step is to create a rule to send inbound email to amavisd
rather than procmail.

accept tagged default from any for domain <domains>               \
  relay via lmtp://127.0.0.1:10024

The reason for "relay via" will make sense shortly.

Once I had mail delivering to amavisd I had to arrange for smtpd to
listen on another port to receive the content-filtered email.

The default in the amavis world is to listen on port 10024 and re-inject
on 10025. I initially tried writing to rules to “accept from if:port”.
That failed miserably. Tagging is the solution. Each “listen on” command
can tag client sessions that are later used via “accept tagged <tag>”.
With that problem solved I was able to define 3 production listeners and
one for testing:

listen on lo0  port 10025 tag amavis  hostname amavis # re-injection
listen on lo0  port 1587  tag test    hostname test   # testing
listen on msk0 port 25    tag default                 # external
listen on lo0             tag default                 # internal

It was at this point I discovered the need for "relay via" rather than
"delivery to". Initially I sent mail to amavisd with this rule:

accept tagged test from any for domain <domains> virtual <vmap> \
  deliver to lmtp 127.0.0.1:10024

That failed. What would happen is "virtual <vmap>" was forwarding the
emails to amavisd for delivery to the user’s system account. 
 "To: <user-t...@example.com>" effectively became "To: <user>".

When amavisd re-injected the email it was rejected by smtpd because "To:
<user>" is an invalid recipient. The solution, then, was to defer the
"virtual <vmap" lookup until re-injection. The way to do do that was to
use "relay via":

accept tagged default from any for domain <domains>             \
  relay via lmtp://127.0.0.1:10024

With those change in place content filtering began working and has
continued to do so. smtpd(8) + spamd(1) + content-filtering = very
little spam.

The question I have for Gilles et al.: Is there a better way to send the
emails to amavisd? It would be more efficient if emails went through
"virtual <vmap>" first so invalid recipients were rejected before
content filtering.

Regardless, I'm happy with the results I'm seeing.

Cheers,

--Aaron
Aaron Poffenberger

#       $OpenBSD: smtpd.conf,v 1.6 2013/01/26 09:38:25 gilles Exp $

# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.
  
# To accept external mail, replace with: listen on all
#
listen on lo0  port 10025 tag amavis  hostname amavis # re-injection
listen on lo0  port 1587  tag test    hostname test   # testing
listen on msk0 port 25    tag default                 # external
listen on lo0             tag default                 # internal

table vmap    db:/etc/mail/virtusertable.db
table domains db:/etc/mail/domains.db

# public emails before content filtering
accept tagged default from any for domain <domains>               \
  relay via lmtp://127.0.0.1:10024

# re-injection from amavis
accept tagged amavis from any for domain <domains> virtual <vmap> \
  deliver to mda "/usr/local/bin/procmail -f -"

# local delivery
accept tagged default from any for local           virtual <vmap> \
  deliver to mda "/usr/local/bin/procmail -f -"

# outbound relay for local users
accept tagged default          for any                            \
  relay

# Easy way to test content-filtering
accept tagged test            for domain <domains>                \
  relay via lmtp://127.0.0.1:10024

Reply via email to