Extended Brain Storage

OpenBSD: Mail Server

Posted on February 28, 2018

Installing, running and managing own e-mail server is interesting and it is fun. It is not a simple and easy task, though. This is yet another tutorial of how to deal with it in the realm of OpenBSD


When sending electronic mail (e-mail) became an unpaid service, new possibilities of selling products emerged. Ever since, treacherous methods have been developed in order to deceive e-mail recipients and to steal their assets. Therefore, various mechanisms (such as SPF, DKIM, DMARC and ARC) were designed to help dealing with e-mail forgery and spam.

OpenBSD comes with a built-in e-mail server named OpenSMTPD, which is a FREE implementation of the server-side SMTP protocol. However, it currently lacks milter support (page #68), which is an essential feature in order to perform Authenticated Received Chain (ARC) checks. Therefore, the good old Postfix was selected as the mail transfer agent (MTA).

Dealing with spam has always been a tough job. Various software has been developed, but some of them became obsolete or abandoned during time. The notoriously known is SpamAssassin, which is not a bad software, but it can become very resource-hungry and its setup may be clumsy for some. Therefore, Rspamd was selected to filter e-mails. Furthermore, is is:

Finally, Clam AntiVirus (ClamAV) was selected in order to make sure that e-mails do not carry malicious code or viruses.

Mail Server Principle

Mail Server Principle

Installation of Plain OpenBSD

This process is fully covered in OpenBSD: Full Disk Encryption. The disk encryption (esp. on a server) has its pros & cons and it is up to everyone to decide for themselves.

Some post installation steps including several tips and tricks can be found in OpenBSD: Post Installation Steps.

The packet filtering topic is covered in OpenBSD: Packet Filtering.

Finally, the Domain Name System (DNS) resolver setup including DNSSEC and DNSCRYPT options is discussed in OpenBSD: Validating and Caching DNS Resolver.

X.509 Certificates for TLS using ACME

The process of obtaining free Transport Layer Security (TLS) certificates from Let’s Encrypt is thoroughly described in OpenBSD: HTTPD with TLS Support Using ACME.

User Management

The reasons to utilise Lightweight Directory Access Protocol (LDAP) services for user management purposes are discussed in: OpenBSD: LDAP User Management.

Mail Server

The reasons to utilise Postfix instead of OpenSMTPD have been clarified earlier. The installation and configuration steps are outlined in OpenBSD: Postfix and its integration with Dovecot is described in OpenBSD: Dovecot.

The principles and configuration of Sieve and ManageSieve protocols as well as quotas setup are recounted in OpenBSD: Dovecot with Sieve, ManageSieve and Quota.

Mail Content Filtering

The reasons to leverage Rspamd and ClamAV for the purpose of mail content filtering, signature and policies verification (incl. signing), and statistics have been made clear earlier. The installation and configuration process are presented in OpenBSD: Rspamd and ClamAV.

Running a Mail Server

If I was being cynical, I could say that there exist interested parties, who provide penetration testing and security assessment services for free. Though indeed free as a beer, they are not doing it with honourable intentions. Based on analysis of log files, every system administrator will soon get the idea, what is the real price involved.

A simple solution to deal with “connection bruteforces” was described in OpenBSD: Packet Filtering. However, there are more ways to contribute to the bruteforce table. Attack attempts (mostly made by automated bots) can be found in:

The most simple way is to create a shell script, which will analyse the log files and which will be run by cron on a regular basis:

$ vi /root/logcheck.sh
ETCFILE="/etc/bruteforce" # from which bruteforcers are loaded into pf
# No GNU-date in OpenBSD. So, the following GNU-coreutils syntax does not work:
#date -d "yesterday now" '+%b %d %H:%M:%S'
# Instead, the following workaround needs to be executed:
YDAY=$(date -r `expr $(date +%s) - 86400` '+%b %d %H:%M:%S')
TDAY=$(date -r `expr $(date +%s)` '+%b %d %H:%M:%S')
# Furthermore, the log date format does not include a leading zero in day,
# so instead of "Apr 01", log contains "Apr  1" and that needs to be corrected:
YDAY=$(echo "$YDAY" | sed "s/ 0/  /")
TDAY=$(echo "$TDAY" | sed "s/ 0/  /")
# In order to print a log range between two dates, awk can be used as follows:
#awk '$0>=from&&$0<=to' from="$YDAY" to="$TDAY" /path/to/log/file

# backup of "bruteforce" table in TMPFILE
pfctl -t bruteforce -T show | awk '{print $1}' > "$TMPFILE"
# backup of current "bruteforce" file in TMPFILE
cat "$ETCFILE" >> "$TMPFILE"
# IPs grepped from MAILLOG file saved in TMPFILE
awk '$0>=from&&$0<=to' from="$YDAY" to="$TDAY" "$MAILLOG" \
 | grep "disconnect from unknown" \
 | grep -v auth=1 \
 | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}" \
 | sort | uniq >> "$TMPFILE"
# IPs grepped from AUTHLOG file saved in TMPFILE
awk '$0>=from&&$0<=to' from="$YDAY" to="$TDAY" "$AUTHLOG" \
 | grep -E "root|invalid|by [0-9]|identification" \
 | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}" \
 | sort | uniq)
# sorting out possible duplicates, numeric sort of IPs into ETCFILE
grep -v "^$" "$TMPFILE" \
 | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 \
 | uniq > "$ETCFILE"
# cleaning TMPFILE file
rm -f "$TMPFILE"
# pf reload
pfctl -f /etc/pf.conf

The script “greps” the last-day content from defined log files. Since crontab executes /etc/daily.local every day at 01:30AM by default, the script can be automated by running the following command:

$ echo "/root/logcheck.sh" >> /etc/daily.local

More tricks can be done further. For instance, sending an e-mail to the postmaster, that the particular IP addresses were added to the bruteforce table and so on…

Tags: #OpenBSD #security #privacy #Postfix #OpenSMTPD #Dovecot #Rspamd #SPF #DKIM #DMARC #ARC #DNS

⏴ Previous Post Next Post ⏵