Thursday, February 5, 2015

OpenBSD Mail Server - Part 2, OpenSMTPD and spamd

1. Read the man page for smtpd and smtpd.conf and review the configuration files.

2. Set up virtual users and virtual domains:

# cat /etc/mail/vusers
joe@example.com joe
@example.com joe
joe@example.net joe
@example.net joe

# cat /etc/mail/vdomains
example.com
example.net

3. Create SSL certificates as described in man 5 smtpd.conf:

# openssl genrsa -out /etc/ssl/private/mail.example.com.key 4096
# openssl req -new -x509 -key /etc/ssl/private/mail.example.com.key \
        -out /etc/ssl/mail.example.com.crt -days 365
# chmod 600 /etc/ssl/mail.example.com.crt
# chmod 600 /etc/ssl/private/mail.example.com.key

4. Create ~/Maildir for user ("joe" in this example).

5. Edit /etc/mail/smtpd.conf so it listens on egress with tls (for incoming mail) and egress port 587 (submission) with tls and authentication (for outgoing mail), accepts mail for virtual users and virtual domains, and delivers this mail to Maildir. Note that the smtpd.conf man page clearly says: "For each message processed by the daemon, the filter rules are evaluated in sequential order, from first to last. The first matching rule decides what action is taken." Therefore, the order of the rules in smtpd.conf is very important and will become more important as additional bits are added (e.g. for clamsmtp, spampd, and dkimproxy).

# cat /etc/mail/smtpd.conf
pki mail.example.com certificate "/etc/ssl/mail.example.com.crt"
pki mail.example.com key "/etc/ssl/private/mail.example.com.key"

listen on lo0
listen on egress tls pki mail.example.com auth-optional
listen on egress port submission tls-require pki mail.example.com auth

table aliases db:/etc/mail/aliases.db
table vusers file:/etc/mail/vusers
table vdomains file:/etc/mail/vdomains

accept for local alias <aliases> deliver to maildir

accept from any for domain <vdomains> virtual <vusers> deliver to maildir
accept from local for any relay

6. Edit pf.conf to allow connections on smtp port 25 and port 587, such as:

# cat /etc/pf.conf
...
pass in on egress proto tcp to any port smtp
pass in on egress proto tcp to any port submission
...

7. Reload pf and start /etc/rc.d/smtpd.

8. Test sending mail to/from the user's account.  Since there is no imap client yet, might want to install mutt or something similar and point to the user's ~/Maildir to check incoming mail.  The user should be able to connect to OpenSMTPD on port 587 from an outside client to send mail through OpenSMTPD to another party.  Sending outbound mail from the command line should also work.  Perhaps telnet into the server or run a couple of SMTP checks against the server like this one to verify things are working correctly.  The session transcript should look something like this:

Connecting to 123.456.789.000

220 mail.example.com ESMTP OpenSMTPD [624 ms]
EHLO MXTB-PWS3.mxtoolbox.com
250-mail.example.com Hello MXTB-PWS3.mxtoolbox.com [64.20.227.133], pleased to meet you
250-8BITMIME
250-ENHANCEDSTATUSCODES
250-SIZE 36700160
250-DSN
250-STARTTLS
250 HELP [640 ms]
MAIL FROM: <supertool@mxtoolbox.com>
250 2.0.0: Ok [640 ms]
RCPT TO: <test@example.com>
550 Invalid recipient [640 ms]

MXTB-PWS3v2 3260ms

9. If that works, set up spamd.  This is a very simple and standard setup and there are lots of resources out there on how to do this, but here is the shorthand:  Add spamd_flags=”-v” to /etc/rc.conf.local. Edit /etc/mail/spamd.conf to add override/whitelist if desired (file /etc/mail/nospamd in sample pf rules). Add spamd pf rules from example /etc/pf.conf and comment out prior rule that passed smtp on egress (because now we want incoming mail to be redirected to spamd running on localhost port 8025):

# cat /etc/pf.conf
...
#pass in on egress proto tcp to any port smtp
pass in on egress proto tcp to any port submission
# rules for spamd(8)
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
...

Reload pf and start /etc/rc.d/spamd.  Check netstat to see if spamd is listening on port 8025:

# netstat -na -f inet

10. Send test emails again and check logs and 'spamdb' to see if email is getting greylisted.  Once spamd is working, those third-party SMTP checks won't work because spamd is intercepting incoming mail.  Same with telnet, if you can stand waiting for the stuttering. ;-) Anyway, now the session transcript should look something like this:

Connecting to 123.456.789.000

220 mail.example.com ESMTP spamd IP-based SPAM blocker; Sat Jan 31 11:33:21 2015 [11716 ms]
EHLO MXTB-PWS3.mxtoolbox.com
250 Hello, spam sender. Pleased to be wasting your time. [640 ms]
MAIL FROM: <supertool@mxtoolbox.com>
250 You are about to try to deliver spam. Your time will be spent, for nothing. [640 ms]
RCPT TO: <test@example.com>
250 This is hurting you more than it is hurting me. [640 ms]

MXTB-PWS3v2 14602ms

Haha.  Love spamd.

11. So here is what's happening:

Incoming mail:

pf -> relay to spamd -> send to opensmtpd on lo0 -> deliver to maildir

Outoing mail:

opensmtpd on lo0 -> relay out

2 comments:

  1. Throughout the post you are using service names in the '/etc/pf.conf' examples, apart from '587' (where you use the port number). For consistency you may want to use the service name instead - 'submission'.

    ReplyDelete
  2. Thanks, rjc. Changed 587 to submission and removed bit about enabling pf in the other post. Noted both in the 'updates' section in the Intro section. Cheers!

    ReplyDelete