OpenBSD Email Server
This Wiki page will walk through the setup of an OpenBSD Email Server.
The server will be built with:
OpenSMTPD ,
LibreSSL ,
spamd ,
Dovecot ,and
DKIMproxy
OpenSMTPD will be configured to:
- Receive mail for Local User Accounts
- Receive mail for Virtual Domains
- Provide Virtual Domain aatch-all aliases for local user accounts
- Use SSL Cert Signed by a Personal Certificate Authority for SMTPS
- Use SSL Cert Signed by a Public Certificate Authority for STARTTLS
- Require STARTTLS for MTA-to-MTA Connections on Port 25
- Send Un-Signed email through
dkimproxy_out Before Relay
Table of Contents
- Install Packages
- Create Maildir
- Configure PF Firewall
/etc/pf.conf
- Configure Daemons
/etc/rc.conf.local
- Configure OpenSMTPD
/etc/mail/smtpd.conf
- OpenSMTPD Tables
/etc/mail/domains
/etc/mail/users
/etc/mail/blacklist-recipients
- DKIM and DomainKey
- Create DKIM DomainKey
- Make DNS Record
/var/dkimproxy/default.txt
- Configure Outbound Mail Signing
/etc/dkimproxy_out.conf
- Configure Dovecot for IMAP
/etc/dovecot/dovecot.conf
/etc/dovecot/conf.d/10-auth.conf
/etc/dovecot/conf.d/10-mail.conf
/etc/dovecot/conf.d/10-ssl.conf
1 Install Packages
In this setup we will not use dkim-milter , but we install it anyway because it brings with some useful programs.
pkg_add dkim-milter dkimproxy dovecot
2 Create Maildir
rm /var/mail/{root,thomas}
mkdir -p /var/mail/{root,thomas}/{Inbox,Drafts,Sent,Trash,Spam}/{new,cur,tmp}
chown -R thomas:thomas /var/mail/thomas
chmod 700 /var/mail/{root,thomas}
3 Configure PF Firewall
The following OpenBSD 5.6 PF firewall configuration will:
- Reassemble Fragmented Packets
- Return ICMP for dropped packets
- Enable logging on egress interfaces
- Allow everything on loopback interfaces
- Scrub Packets of weirdness
- Define tables
<bruteforce> , <spamd>
- Set Default policy for in to Drop and Log
- Drop
urpf-failed packets add label uRPF
- Drop packets from IPs in
<bruteforce> table
- Randomize TCP Sequence Numbers
- Respond to ICMPv4 Echo-Requests and Destination-Unreachable
- Allow SSH connections
- Limit 15 connections from a Source IP
- Limit 15 Connection Attempts in 5 minute window
- Violating IPs are added to
<bruteforce> table and associated states flushed
- Allow HTTP, HTTPS connections
- Limit 100 connections from a Source IP
- Limit 25 Connection Attempts in 5 minute window
- Violating IPs are added to
<bruteforce> table and associated states flushed
- Allow IMAPS connections
- Limit 50 connections from a Source IP
- Limit 15 Connection Attempts in 5 minute window
- Violating IPs are added to
<bruteforce> table and associated states flushed
- Tarpit SMTP, SMTPS packets from IPs found in
<spamd> table to spamd on localhost
- Allow IMAPS connections
- Limit 50 connections from a Source IP
- Limit 15 Connection Attempts in 5 minute window
- Violating IPs are added to
<bruteforce> table and associated states flushed
3.1 /etc/pf.conf
File Permissions: -rw------- 1 root wheel
set reassemble yes
set block-policy return
set loginterface egress
set skip on lo
match in all scrub (no-df random-id max-mss 1440)
table <bruteforce> persist
table <spamd> persist
block in log
block in quick from urpf-failed label uRPF
block quick from <bruteforce>
pass out all modulate state
pass in quick inet proto icmp icmp-type { echoreq, unreach }
pass in quick proto tcp from any \
to (egress) port ssh \
flags S/SA modulate state \
(max-src-conn 15, max-src-conn-rate 15/5, overload <bruteforce> flush global)
pass in quick proto tcp from any \
to (egress) port { http, https } \
flags S/SA modulate state \
(max-src-conn 100, max-src-conn-rate 25/5, overload <bruteforce> flush global)
pass in quick proto tcp from any \
to (egress) port imaps \
flags S/SA modulate state \
(max-src-conn 50, max-src-conn-rate 15/5, overload <bruteforce> flush global)
pass in on egress inet proto tcp from <spamd> \
to (egress) port { smtp, smtps } \
rdr-to 127.0.0.1 port spamd
pass in proto tcp from any \
to (egress) port { smtp, smtps } \
flags S/SA modulate state \
(max-src-conn 50, max-src-conn-rate 25/5, overload <bruteforce> flush global)
4 Configure Daemons
Configure your system to start the daemons spamd, Dovecot, and dkimproxy to start at boot.
4.1 /etc/rc.conf.local
File Permissions: -rw-r--r-- 1 root wheel
spamd_flags="-v -b"
spamd_black=YES
pkg_scripts="dovecot dkimproxy_in dkimproxy_out"
5 Configure OpenSMTPD
The following OpenSMTPD /etc/mail/smtpd.conf configuration will:
- Enable Queue Compression
- Enable Queue Encryption
- Create a key with the following command
openssl rand -hex 16
- Define table aliases as Berkly DB
/etc/mail/aliases.db
- Define table domains as File
/etc/mail/domains
- Define table users as File
/etc/mail/users
- Define table blacklist-recipients as File
/etc/mail/blacklist-recipients
- Define SSL Cert/Key comodo.puffysecurity.com.pki
- Certificate
/etc/ssl/comodo/full.comodo.puffysecurity.com.crt
- Key
/etc/ssl/private/comodo.puffysecurity.com.pem
- Define SSL Cert/Key puffysecurity.com.pki
- Certificate
/etc/ssl/puffysecurity.com.crt
- Key
/etc/ssl/private/puffysecurity.com.pem
- Listen on SMTP, STARTTLS in on egress interface
- Use comodo.puffysecurity.com.pki SSL Cert/Key
- Require STARTTLS
- Server Hostname puffysecurity.com
- Listen on SMTPS in on egress interface
- Use puffyssl_ca01.puffysecurity.com.pki SSL Cert/Key
- Require Authentication
- Server Hostname puffysecurity.com
- Accept mail from any
- For recipient not found in
<blacklist-recipients>
- For domain found in
<domains>
- For Virtual User found in
<users>
- Deliver to Maildir
/var/mail/%{user.username}/Inbox
- Accept mail from any
- For recipient not found in
<blacklist-recipients>
- For local domain
- Lookup alias in
<aliases>
- Deliver to Maildir
/var/mail/%{user.username}/Inbox
- Listen on SMTP in on loopback interface
- Server Hostname puffysecurity.com
- Listen in on loopback interface
- Port 10028
- tag DKIM
- Server Hostname puffysecurity.com
- Accept mail tagged DKIM
- For any
- Relay
- Server source
$wan_ip
- Server Hostname puffysecurity.com
- Accept mail from local
- For any
- Relay via
smtp://127.0.0.1:10027
5.1 /etc/mail/smtpd.conf
File Permissions: -rw-r--r-- 1 root wheel
egress_int="bnx0"
wan_ip="91.209.12.222"
queue compression
# Create Unique Queue Key `openssl rand -hex 16`
queue encryption key 400e0bb7ac8c0368b2150a29e65d3de5
table aliases db:/etc/mail/aliases.db
table domains file:/etc/mail/domains
table users file:/etc/mail/users
table blacklist-recipients file:/etc/mail/blacklist-recipients
pki comodo.puffysecurity.com.pki certificate "/etc/ssl/comodo/full.comodo.puffysecurity.com.crt"
pki comodo.puffysecurity.com.pki key "/etc/ssl/private/comodo.puffysecurity.com.pem"
pki puffyssl_ca01.puffysecurity.com.pki certificate "/etc/ssl/puffysecurity.com.crt"
pki puffyssl_ca01.puffysecurity.com.pki key "/etc/ssl/private/puffysecurity.com.pem"
listen on $egress_int pki comodo.puffysecurity.com.pki tls-require hostname puffysecurity.com
listen on $egress_int pki puffyssl_ca01.puffysecurity.com.pki smtps auth hostname puffysecurity.com
accept from any \
recipient !<blacklist-recipients> \
for domain <domains> \
virtual <users> \
deliver to maildir "/var/mail/%{user.username}/Inbox"
accept \
recipient !<blacklist-recipients> \
for local alias <aliases> \
deliver to maildir "/var/mail/%{user.username}/Inbox"
listen on lo0 hostname puffysecurity.com
listen on lo0 port 10028 tag DKIM hostname puffysecurity.com
accept tagged DKIM \
for any \
relay \
source $wan_ip \
hostname puffysecurity.com
accept from local \
for any \
relay via smtp://127.0.0.1:10027
5.2 OpenSMTPD Tables
-
Add domains you want to receive mail for to table domains file: one-per-line
-
Add /(recipient)([[:space:]])(user)/ mappings to table users
file: one-per-line. The recipient may be a complete email addresses
or apply to an entire domain if prefixed with '@'.
-
Add recipient to table blacklist-recipients file: one-per-line
5.2.1 /etc/mail/domains
File Permissions: -rw-r--r-- 1 root wheel
puffysecurity.com
tomd.tel
venona.nl
5.2.2 /etc/mail/users
File Permissions: -rw-r--r-- 1 root wheel
thomas@puffysecurity.com thomas
@puffysecurity.com thomas
thomas@tomd.tel thomas
@tomd.tel thomas
thomas@venona.nl thomas
@venona.nl thomas
5.2.3 /etc/mail/blacklist-recipients
File Permissions: -rw-r--r-- 1 root wheel
troll@puffysecurity.com
igetspam@tomd.tel
ticketsite@venona.nl
6 DKIM and DomainKey
This setup will sign out-going mail with DKIM DomainKey via dkimproxy_out .
6.1 Create DKIM DomainKey
Use dkim-genkey to create a 2048 RSA key in /var/dkimproxy .
dkim-genkey -D /var/dkimproxy -r -b 2048 -d $HOSTNAME
6.2 Make DNS Record
The file /var/dkimproxy/default.txt will contain a valid
Domainkey TXT record that you need to add to your DNS.
Create a new TXT record for default._domainkey and copy
everything in-between the double-quotes into the value field
of the TXT record.
6.3 /etc/dkimproxy_out.conf
File Permissions: -rw-r--r-- 1 root wheel
listen 127.0.0.1:10027
relay 127.0.0.1:10028
domain puffysecurity.com,venona.nl
signature dkim(c=relaxed)
signature domainkeys(c=nofws)
keyfile /var/dkimproxy/default.private
selector default
7 Configure Dovecot for IMAP
7.1 /etc/dovecot/dovecot.conf
File Permissions: -rw-r--r-- 1 root wheel
protocols = imap lmtp
listen = *, ::
base_dir = /var/dovecot/
login_greeting = IMAP Server Ready.
dict {
#quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
#expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext
}
!include conf.d/*.conf
!include_try local.conf
7.2 /etc/dovecot/conf.d/10-auth.conf
File Permissions: -rw-r--r-- 1 root wheel
disable_plaintext_auth = yes
auth_cache_size = 10M
auth_cache_ttl = 1 hour
auth_cache_negative_ttl = 1 hour
auth_mechanisms = plain
!include auth-system.conf.ext
7.3 /etc/dovecot/conf.d/10-mail.conf
File Permissions: -rw-r--r-- 1 root wheel
mail_location = maildir:/var/mail/%u/Inbox
namespace inbox {
inbox = yes
}
mmap_disable = yes
first_valid_uid = 1000
mail_plugin_dir = /usr/local/lib/dovecot
mbox_write_locks = fcntl
7.4 /etc/dovecot/conf.d/10-ssl.conf
File Permissions: -rw-r--r-- 1 root wheel
ssl_cert = </etc/ssl/puffysecurity.com.crt
ssl_key = </etc/ssl/private/puffysecurity.com.pem
ssl_dh_parameters_length = 4096
# vim: set ts=4 sw=4 tw=80 et : |