cd /
;
apropos
;
To get in charge of your communication tools is a big deal to more freedom and independence. This part will describe how to host an email server at home. No database will be required because it has no benefit on a small server. Let's keep things simple !
Setting up a mail server is often considered difficult. That's why we will split this tutorial in small easy steps: complex, but not complicated.
In order, you will:
Of course, you'll learn how to add new accounts and how to configure a mail client.
You first have to open port 25 (smtp) in your firewall and router.
Some ISP are very restrictive with this port. You can ask them to be more permissive, but make inquiries first to avoid bad surprises. At last resort, we'll discuss how to use external smtp serices.
Read also opensmtpd main developper article about this subject.
https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/
Emails requires specific DNS records. You have add at least two new fields.
First, make sure you have an "A" record (probably):
athome.tld. IN A 192.0.2.2
Of course, use your real IP here.
You must add a MX field pointing to the previous record:
athome.tld. IN MX 1 athome.tld.
Notice ending dots.
"1" describe the weight of the field. This parameter will be used to prioritize mails servers because some of them will be backups if the main server is unavailable. We'll talk about this later.
Some may want to use a specific domain, another A field to organize their mail servers. That is not mandatory, but interesting:
mail1.athome.tld. IN MX 1 mail1.athome.tld. mail1.athome.tld. IN A 192.0.2.2
Below is another example using a different syntax:
$ORIGIN athome.tld [...] @ IN MX 10 mail1.athome.tld. @ IN A 192.0.2.2 mail1 IN A 192.0.2.3
Here, you can see the mail server for this zone is hosted on a different IP.
That's all for now.
To encrypt traffic with your email server, you'll need TLS certificates.
It is explained in the chapter about httpd.
Notice you can use self-signed certificates if you prefer, that is absolutely not an issue. (see man ssl(8))
In the next parts, we'll consider using letsencrypt certificates to keep consistent.
Just remember to have a certificate for the domain of the MX field of your server.
I you're in a hurry, here is a quick setup to have a working email server. It will also be a good starting point to build on later. With the following:
Later, we'll discuss virtual users to go further and achieve more specific tasks. But here, we're in a rush so let's go! π
Edit /etc/mail/smtpd.conf:
# Generic config # Tables table aliases "/etc/mail/aliases" # Certificates pki athome.tld key "/etc/ssl/private/athome.tld.key" pki athome.tld cert "/etc/ssl/athome.tld.crt" # Get messages listen on all tls pki athome.tld # To send with mail client listen on all port submission tls-require pki athome.tld auth # ACTIONS action "sendthismail" relay # System aliases action in_maildir maildir alias <aliases> # Get match for local action in_maildir match from any for domain athome.tld action in_maildir # Sending match for any action "sendthismail" match auth from any for any action "sendthismail"
That's it π
There a almost more comments than reals instructions.
Install dovecot:
# pkg_add dovecot.
In /etc/dovecot/local.conf add:
# listen on IPV4 and IPV6. listen = *, [::] # We use Maildir mail_location = maildir:~/Maildir # only username, not user@domain.tld to auth auth_username_format = %n # imap > pop protocols = imap # Safety. Edit those lines ! ssl = yes ssl_cert = </etc/ssl/athome.tld.crt ssl_key = </etc/ssl/private/athome.tld.key disable_plaintext_auth = yes # auth methods passdb { driver = bsdauth } userdb { driver = passwd }
Reload dovecot:
# rcctl restart dovecot
Here you go, it's done, you can configure your mail client.
"Virtual users" means they are not UNIX system users with a shell. However, they are obviously using your mail server.
New accounts won't be created with adduser but you will edit a file with the username and it's password hash.
Here we'll discuss how to install a SMTP (Opensmtpd) and IMAP (Dovecot) server
We will create an user with the sweet name "_vmail" to manage every emails access. It won't have any shell, it's safer π.
# useradd -m -g =uid -c "Virtual Mail" -d /var/vmail -s /sbin/nologin _vmail
A new directory is created: /var/vmail. Emails will be stored inside, but following a structure with subdirectories for each virtual users. As example:
/var/vmail/athome.tld/batman/Maildir /var/vmail/athome.tld/user/Maildir /var/vmail/athome.tld/ninja/Maildir ...
In this file, we write user's emails, one on each line. Actually, it works like /etc/mail/aliases. (read man aliases(5) π)
heroes@athome.tld batman@athome.tld,superman@athome.tld batman@athome.tld _vmail superman@athome.tld _vmail scoobydoo@athome.tld _vmail
As you can see, every email addresses belongs to user _vmail.
Notice the first line: you see an example showing how to transfer emails sent to "heroes@athome.tld" to "batman@athome.tld" and "superman@athome.tld".
Same as before, one line per passphrase:
batman@athome.tld:$2b$09$lerdFpdQtnu.Bs5EpAsVbeF851GjdD0aza8IDhho38i1DOHk.ujzi superman@athome.tld:$2b$09$VRU/CYJUS3QZHVUFP70xIOURPbiNQeyOEZHoZo6NOY3uO.XSpd2MW
Notice how ":" split email address and the hashed passphrase: <email>:<hash>.
You MUSt have installed opensmtpd-table-passwd port!
# pkg_add opensmtpd-table-passwd
To hash passphrases, use encrypt:
encrypt -b a -p
Or
smtpctl encrypt passphrase
You're prompted to enter the passphrase. Press "Enter" to see the hash of the password and copy it in /etc/mail/passwd.
Previous files shouldn't be readable by everyone. Let's adjust permissions so root and mail daemons -- dovecot and smtpd -- can read passwords. It is not mandatory, but I suggest this part as good habits that can hurt anyone π.
Dovecot and smtpd run as users _dovecot and _smtpd. If one day, one of this process is compromised, it will avoid privilege escalation and threaten the whole system.
Let's create a new group _maildaemons for _dovecot and _smtpd to ease permissions:
# groupadd _maildaemons # usermod -G _maildaemons _smtpd # usermod -G _maildaemons _dovecot
Of course, if you haven't installed dovecot yet since we discuss about it later: "# pkg_add dovecot".
Now we can set owner and group for files storing logins and passwords:
# chown root:_maildaemons /etc/mail/passwd /etc/mail/virtuals
Finally, only root can modify these files and _maildaemons can only read. Others can't do anything:
# chmod 640 /etc/mail/passwd /etc/mail/virtuals
To check everything is as expected:
# ls -l /etc/mail/passwd -rw-r----- 1 root _maildaemons 17226 Nov 12 08:40 /etc/mail/passwd
Opensmtpd or smtpd is the default mail server shipped with OpenBSD. You just have to configure it.
First of all, make sure you opened ports: 25 (smtp), 587 (submission) and 993 (imaps). The latter will be user with dovecot. Do not care about 465 (smtps) since it is deprecated.
To configure smtpd, edit /etc/mail/smtpd.conf. Instructions will be applied in order.
We will split it in 3 parts:
Adjust the example below to your needs:
# Generic configuration # Tables table aliases "/etc/mail/aliases" table passwd "/etc/mail/passwd" table virtuals "/etc/mail/virtuals" # Certificates pki athome.tld key "/etc/ssl/private/athome.tld.key" pki athome.tld cert "/etc/ssl/athome.tld.crt" # Listening ports # Reception listen on all tls pki athome.tld # Sending with a mail client listen on all port submission tls-require pki athome.tld auth <passwd> # ACTIONS action "sendthismail" relay action local_mail maildir alias <aliases> action virtual_maildir maildir "/var/vmail/%{dest.domain:lowercase}/%{dest.user:lowercase}/Maildir" virtual <virtuals> # In/Out # Reception # Message for virtual users match from any for domain athome.tld action virtual_maildir # Message for system users match from any for local action local_mail # Sending match auth from any for any action "sendthismail" match for any action "sendthismail"
There is almost nothing to change in this file, except domain name.
WAIIIIIT a minute! Tell me more!
Take a look at each lines:
First, there are generic instructions
Then, we define actions applied on envelopes.
At last, we apply actions according to envelope criterias.
If not mentioned, the rule match a local mail. In other case, we add "from any".
Finally, in order to label your outgoing messages with the appropriate domain name, add in /etc/mail/mailname your email's domain name. It's the domain mentioned in the MX record.
athome.tld
Now enable and start smtpd:
# rcctl enable smtpd # rcctl restart smtpd
That's all for smtpd π.
We will use Dovecot as IMAP server so you can read mails from a client like Thunderbird.
As usual, install dovecot with pkg_add:
# pkg_add dovecot
Now configure dovecot. Edit /etc/dovecot/local.conf:
# listen IPv4 and IPv6 listen = *, [::] # imap protocols = imap # Encryption. Edit those lines according to your certificates. ssl = yes ssl_cert = </etc/ssl/athome.tld.crt ssl_key = </etc/ssl/private/athome.tld.key disable_plaintext_auth = yes # where mails are stored. %d is domain, %n is username mail_location = maildir:/var/vmail/%d/%n/Maildir # essential since we edited persmission on /etc/mail/passwd service auth { user = $default_internal_user group = _maildaemons } # Auth methodes passdb { args = scheme=blf-crypt /etc/mail/passwd driver = passwd-file } # Mails are /var/vmail , belongs to _vmail userdb { driver = static args = uid=_vmail gid=_vmail home=/var/vmail/%d/%n/ }
I left comments above to help you understand what is done here.
Adjust ssl_cert and ssl_key according to your certificates.
By the way, ssl configuration is already available in /etc/dovecot/conf.d/10-ssl.conf. It is supposed to help us with a script generating a self-signed certificate. However, you probably already have your own. You should comment lines in this file:
# file: /etc/dovecot/conf.d/10-ssl.conf #ssl_cert = </etc/ssl/dovecotcert.pem #ssl_key = </etc/ssl/private/dovecot.pem
Finally, reload mail daemons:
# rcctl enable dovecot # rcctl start dovecot # rcctl restart smtpd
Now you can use a mail client to read your messages.
Add a new line for the new account in /etc/mail/virtuals and /etc/mail/passwd then reload tables for smtpd (dovecot read them on the fly):
smtpctl update table virtuals smtpctl update table passwd
Or # rcctl restart smtpd
You can host an email server and manage multiple domain names.
However, you should organize how you set this up.
Below are a few notes on how to achieve this.
I suggest to create a file containing every hosted domain, one per line. Let's call it /etc/mail/domains:
athome.tld domain.tld other.bar
Now, in /etc/mail/smtpd.conf you can write one line for multiple domains:
table domains "/etc/mail/domains" ... match from any for domain <domains> action virtual_maildir
Take care of used TLS certificates. If you have a certificate for each domain, you can specify each of them in smtpd.conf. Make sure you have a default certificate in the end (*).
pki athome.tld key "/etc/ssl/private/athome.tld.key" pki athome.tld cert "/etc/ssl/athome.tld.crt" pki domain.tld key "/etc/ssl/private/domain.tld.key" pki domain.tld cert "/etc/ssl/domain.tld.crt" pki other.bar key "/etc/ssl/private/other.bar.key" pki other.bar cert "/etc/ssl/other.bar.crt" pki "*" key "/etc/ssl/private/athome.tld.key" pki "*" cert "/etc/ssl/athome.tld.crt" ... listen on all tls ... listen on all port submission tls-require auth <passwd>
HOWEVER, you can use only one certificate matching multiple domains. To do so, use "alternative names" in acme-client configuration. It is absolutely valid and much easier to manage. If so, configure smtpd as if there was only one certificate.
Dovecot will need some care to handle certificates for each domain. Add "local_name" sections in its configuration so it looks like this:
ssl = yes ssl_cert = </etc/ssl/athome.tld.crt ssl_key = </etc/ssl/private/athome.tld.key # no plaintext disable_plaintext_auth = yes local_name domain.tld { ssl_cert = </etc/ssl/domain.tld.crt ssl_key = </etc/ssl/private/domain.tld.key } local_name other.bar { ssl_cert = </etc/ssl/other.bar.crt ssl_key = </etc/ssl/private/other.bar.key }
Here also, a single certificate for multiple domains is much more easier to set up.
As explained in man aliases(5), you can redirect mails to various destination.
As example, you host jwayne@athome.tld and want to redirect every mails received by jwayne to batman@wayne.com.
Edit /etc/mail/virtuals and add:
jwayne.athome.tld: batman@wayne.com
You can set redirections in /etc/mail/aliases too. For system users, you can use their login only:
root: jdoe hostmaster: root postmaster: root webmaster: bruce jdoe: jdoe@domain.tld
Remember to restart smtpd so changes are considered:
# rcctl restart smtpd
Easy. π
To use your mail server with a client such as Thunderbird, use the parameters below:
To help clients finding automatically how to configure parameters to use your mail server, you can add specific DNS records.
_submission._tcp.athome.tld 86400 IN SRV 0 1 587 athome.tld _imap._tcp.athome.tld 86400 IN SRV 0 0 0 . _imaps._tcp.athome.tld 86400 IN SRV 0 1 993 athome.tld
Read rfc6186 about these records.
https://datatracker.ietf.org/doc/html/rfc6186
If, for reasons, your server is offline for a few days or a week, mails could be lost. Normally, senders try again for a while if they couldn't deliver a message.
However, you can plan secondary mail servers to keep your messages if yours is unreachable. You only need:
It will keep messages for your server in queue and will deliver them as soon it gets back online.
On your side, add a new MX field in your DNS zone with a bigger weight. This field points to the secondary server:
@ IN MX 10 athome.tld. @ IN MX 70 mail.friend.eu.
In the above example, your server is ligther (10) than the secondary (70). This means a sending server will try first to deliver on your server, then on the secondary if the first failed to answer.
On his side, your friend just has to add your domain as a backup. If he uses smtpd, then his /etc/mail/smtpd.conf should look like this:
action relaybackup relay backup mx "athome.tld" ... match from any for domain athome.tld action relaybackup
Of course, you should return the favor π.
Some servers could consider your mails as spams. There are a few proofs of good faith you can setup if possible. They are not mandatory. Keep in mind that most spams comes from most well known servers (gmail, I'm looking at you) so don't be too hard on yourselves.
Your ISP might let you configure a reverse DNS. As it suggests, a reverse DNS links your IP to your domain name.
Look in your ISP panel for reverse DNS, or ask them directly. They are responsible for this π.
If you can't and reaaaallly want a rDNS, you could rent a VPN and get a dedicated IP with a rDNS configured by the VPN provider. But in most cases, following next steps should be sufficient.
SPF records show that only YOUR server is allowed to send mails for YOUR domain name. Since it's usually the server's admin who also deals with DNS record, it's a proof of good faith.
Add a DNS record of type SPF in your zone such as:
athome.tld. SPF "v=spf1 a mx ~all"
Or use a TXT field if SPF is not available:
athome.tld. TXT "v=spf1 a mx ~all"
Above is a very simple example that works for most cases. Consider reading about SPF records if you want to fine-tune this record.
With a private key, your server will sign outgoing emails. In DNS records, you will publish a public key to let recipient check if it matches the signature from your server.
Ahem... Say that again?
Here we go. We will generate a private and a public key.
Private key is used to sign mails. It is "private" because you must be the only one able to add a signature to outgoind mails.
Public key displayed in DNS record -- viewable by all -- let one check signature authenticity. You can see it as a unique puzzle piece, the only one that can fit the puzzle.
We'll see two ways to sing outgoing messages: one with an smtpd extension, the other with dkimproxy. You also could to the same with rspamd, it is described later, following the same method to generate keys. Choose the one you prefer π.
Following commands below, you will create a directory for keys, set permissions on this folder and go inside before generating keys with openssl and set permissions on the private part:
# mkdir -p /etc/dkim/ # chmod 770 /etc/dkim/ # cd /etc/dkim/ # openssl genrsa -out private.key 2048 # openssl rsa -in private.key -pubout -out public.key # chmod 400 private.key
Add a DKIM or TXT field so anyone can check signature on your messages match what is published in DNS records.
Mails will receive a flag "dkimpubkey" when signed, it is used to identify the signature in DNS record.
Replace ... by the content of public.key:
# cat /etc/dkim/public.key
The record will look like this:
dkimpubkey._domainkey IN TXT ( "v=DKIM1; k=rsa; t=s;p=v+Fb...vhP/oB")
Since smtpd has filters support, you can sign your messages with port opensmtpd-filter-dkimsign:
# pkg_add opensmtpd-filter-dkimsign
Make sure the script can read keys generated as seen before:
# chown -R _dkimsign:_dkimsign /etc/dkim/
In /etc/mail/smtpd.conf, you add now a new filter with instructions on how to sign messages:
filter "dkimsign" proc-exec "filter-dkimsign \ -d <domain> \ -s <selector> \ -k /etc/dkim/private.key" \ user _dkimsign group _dkimsign
Replace <domain> with your domain name and <selector> by dkimpubkey: that's what we defined in the DNS field earlier.
Now, make sure outgoing mails are processed by this new filter. In /etc/mail/smtpd.conf, the line for outgoing messages now look like this:
listen on all port submission tls-require auth <passwd> filter "dkimsign"
As an alternative, you can use dkimproxy if you prefer to sign mails.
As usual:
# pkg_add dkimproxy
Make sure dkimproxy can read keys:
# chown -R _dkimproxy:_dkimproxy /etc/dkim/
Now configure dkimproxy to match you configuration (domain and DNS selector):
In /etc/dkimproxy_out.conf:
listen 127.0.0.1:10027 relay 127.0.0.1:10028 domain athome.tld signature dkim(c=relaxed) signature domainkeys(c=nofws) keyfile /etc/dkim/private.key selector dkimpubkey
Of course, edit domain and selector according to your DNS record.
Now, tell smtpd to listen for incoming signed and to-send messages on port 10028. They will be tagged "DKIM". Then we can send mails with this tag. On the contrary, they are forwarded to dkimproxy on port 10027.
In /etc/mail/smtpd.conf:
listen on lo0 port 10028 tag DKIM ... match tag DKIM for any action "sendthismail" match auth tag DKIM from any for any action "sendthismail" ... action dkimproxy relay host smtp://127.0.0.1:10027 ... match auth from any for any action dkimproxy match for any action dkimproxy
Finally enable dkimproxy and restart smtpd:
# rcctl enable dkimproxy_out # rcctl start dkimproxy_out # rcctl restart smtpd
Follow instructions on mail-tester.com. You'll send a mail to a randomized recipient and get a score:
You may read about dmarc and other advices if you want to fin tune your configuration. Remember your score is already better than most "big" provider. Last time I checked with a gmail address, I got 6.1/10... π
See also:
https://mxtoolbox.com/deliverability
If your ISP restrict the use of smtp port (25), you can't send any email from your server. To fix this, you may:
However, you need another smtp provider. Put the necessary credentials to access this mail account in /etc/mail/secrets:
# echo "secret_id user:passphrase" > /etc/mail/secrets
Make sure permissions are appropriate, you don't want everyone to know your password:
# chmod 640 /etc/mail/secrets # chown root:_smtpd /etc/mail/secrets
Then, edit /etc/mail/smtpd.conf so outgoing messages go through external mail server:
... table secrets "/etc/mail/secrets" ... listen on all... ... action "relay" relay host smtp+tls://secret_id@smtp.example.com \ auth <secrets> mail-from "@athome.tld" ... match from any for any action "relay"
Some details:
In the end, reload smtpd.
rcctl restart smtpd
Read the example in the end of smtpd manpage to learn more.
https://man.openbsd.org/smtpd.conf
Senderscore keeps a database of mail server reputation.
A moderate reputation doesn't mean much, but a bad one means the server already has sent spams before.
You can use a filter in smtpd to recognize as spam incoming mails according to senderscore.
Install opensmtpd-filter-senderscore port.
Then, edit /etc/mail/smtpd.conf to add a filter:
filter senderscore \ proc-exec "filter-senderscore -junkBelow 70 -slowFactor 2000" ... listen on all tls pki athome.tld filter { senderscore }
spamassassin is a well-known anti-spam. It is used by OpenBSD project with spamd for their mailing lists.
https://spamassassin.apache.org/
You may want to use the filter opensmtpd-filter-spamassassin: install the port then read /usr/local/share/doc/pkg-readmes/opensmtpd-filter-spamassassin.
In a few words:
# pkg_add p5-Mail-SpamAssassin opensmtpd-filter-dkim # rcctl enable spamassassin # rcctl start spamassassin
(no need spampd here)
/etc/mail/smtpd.conf:
filter "spamassassin" proc-exec "filter-spamassassin" [...] listen on all tls pki chezmoi.tld.pki filter { spamassassin senderscore }
Let's see how to use it with smtpd using tags since the setup is interesting if you want to understand how things works.
Install appropriate ports:
# pkg_add p5-Mail-SpamAssassin spampd
Then, run spamassassin daemons. You may add a few flags to make sure it is running as we expect.
# rcctl enable spampd # rcctl set spampd flags "--relayhost=127.0.0.1:10026" # rcctl start spampd # rcctl enable spamassassin # rcctl start spamassassin
Every incoming mails now must be checked by spammassassin, which is listening on port 10025. Once they've been scanned, they will be delivered on port 10026 and tagged "SPAMASSASSIN" so we don't check them twice.
That's how it looks in /etc/mail/smtpd.conf:
... # mails checked by spammassassin listen on lo0 port 10026 tag SPAMASSASSIN ... action spamassassin relay host smtp://127.0.0.1:10025 ... # system mails accept from local for local alias <aliases> deliver to maildir "~/Maildir" # Mails scanned by SPAMASSASSIN match tag SPAMASSASSIN from any for domain "athome.tld" action virtual_maildir # not tagged mails, must be checked by spammassassin match from any for domain "athome.tld" action spamassassin ...
Spams subject are modified by spammassassin.
You can automatically delete them, but it's a risk in case of false positive.
https://wiki.apache.org/spamassassin/DeletingAllMailsMarkedSpam
In order to save spams in a junk folder, modify smtpd's action so it checks for X-spam header:
# /etc/mail/smtpd.conf action virtual_maildir maildir "/var/vmail/%{dest.domain:lowercase}/%{dest.user:lowercase}/Maildir" junk virtual <virtuals>
Rspamd is a very complete mail filter. It is not only an anti-spam, but can handle greylisting, DKIM...
It is also very fast and efficient. If you want to use it, you should read it's official documentation. For now, let's see how to use it with OpenBSD's smtpd as an antispam and for DKIM.
# pkg_add rspamd redis opensmtpd-filter-rspamd # rcctl enable redis rspamd # rcctl start redis rspamd
Then configure rspamd:
# rspamadm configwizard
Finally, consider handling too large logs with newsyslog:
# Add in /etc/newsyslog.conf /var/log/rspamd/rspamd.log 644 5 300 * Z
Just add a new filter named "filter-rspamd" and use it for incoming messages.
filter rspamd proc-exec "filter-rspamd" # filtre en reception listen on all tls pki athome.tld \ filter { rspamd }
Since rspamd can handle DKIM signatures, you won't have to configure dkimproxy or another tool.
Create keys as described before and make sure they belong to _rspamd group.
# chown -R _rspamd:_rspamd /etc/dkim/
Remember to edit your DNS zone π.
Now create /etc/rspamd/local.d/dkim_signing.conf:
# If true, username does not need to contain matching domain allow_username_mismatch = true; path = "/etc/dkim/private.key"; selector = "dkimpubkey";
Then add a few lines in /etc/mail/smtpd.conf to sign outgoing messages:
filter rspamd proc-exec "filter-rspamd" # Send and DKIM sign with rspamd listen on all port submission tls-require pki athome.tld auth \ filter { rspamd }
Rspamd does greylisting by default. If you want to still use spamd instead, disable rspamd greylisting in /etc/rspamd/local.d/actions.conf:
greylist = none;
And /etc/rspamd/local.d/greylist.conf:
enabled = false;
You can use a spamtrap (like what spamd does) using the following lines in /etc/rspamd/local.d/spamtrap.conf:
action = "no action"; learn_spam = true; map = file://$LOCAL_CONFDIR/maps.d/spamtrap.map; enabled = true;
Then fill /etc/rspamd/maps.d/spamtrap.map with regular expressions of fake trap mail addresses:
/^trap@athome.tld$/ /^fake@athome.tld$/
To do so, use multimap module.
https://rspamd.com/doc/modules/multimap.html
Dig a SSH tunnel from your computer and open in a browser http://localhost:9999.
ssh -N -L 9999:127.0.0.1:11334 sshuser@athome.tld
Enjoy wonderfull charts π
You might want to help the anti-spam to learn if it missed spams or got wrong for some messages.
If you use dovecot and a mail client with IMAP protocol, you can move spams in "Junk" folder so the anti-spam recognize them in the future. On the contrary, moving a mail from "Junk" to "INBOX" folder indicates it is legitimate.
No matter if you use rspamd or spammassassin, we explain for both. 3 steps are necessary:
It is described in dovecot documentation (you should read π)
https://wiki2.dovecot.org/HowTo/AntispamWithSieve
First, let's install dovecot pigeonhole plugin:
# pkg_add dovecot-pigeonhole
Add imap_sieve in plugins list to enable it at the end of /etc/dovecot/local.conf:
protocol imap { mail_plugins = $mail_plugins imap_sieve }
Then, still in dovecot's local.conf, configure sieve plugin so it run scripts according to where messages are moved.
plugin { sieve_plugins = sieve_imapsieve sieve_extprograms # When a message is moved in Junk folder; report as spam imapsieve_mailbox1_name = Junk imapsieve_mailbox1_causes = COPY imapsieve_mailbox1_before = file:/usr/local/lib/dovecot/sieve/report-spam.sieve # When a mail is removed from Junk folder: it is nor a spam imapsieve_mailbox2_name = * imapsieve_mailbox2_from = Junk imapsieve_mailbox2_causes = COPY imapsieve_mailbox2_before = file:/usr/local/lib/dovecot/sieve/report-ham.sieve sieve_pipe_bin_dir = /usr/local/lib/dovecot/sieve sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute }
Now create two files in the directory /usr/local/lib/dovecot/sieve/.
The first is report-spam.sieve:
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; if environment :matches "imap.user" "*" { set "username" "${1}"; } pipe :copy "learn-spam.sh" [ "${username}" ];
The second is report-ham.sieve:
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; if environment :matches "imap.mailbox" "*" { set "mailbox" "${1}"; } if string "${mailbox}" "Trash" { stop; } if environment :matches "imap.user" "*" { set "username" "${1}"; } pipe :copy "learn-ham.sh" [ "${username}" ];
Now reload dovecot and compile the above scripts:
# rcctl restart dovecot # sievec /usr/local/lib/dovecot/sieve/report-spam.sieve # sievec /usr/local/lib/dovecot/sieve/report-ham.sieve
As you may have noticed, the above files call learn-spam.sh and learn-ham.sh. Thoses scripts will be different wether you use rspamd or spammassassin since they don't learn spams/hams with the same command. Read the next part π.
Scripts below are stored in /usr/local/lib/dovecot/sieve/.
#!/bin/sh #learn-spam.sh exec /usr/local/bin/spamc -u ${1} -L spam #!/bin/sh # learn-ham.sh exec /usr/local/bin/spamc -u ${1} -L ham
You'll have to set appropriate spamassassin flags to use the above scripts :
# rcctl set spamassassin flags -l
Scripts below are still in /usr/local/lib/dovecot/sieve/.
#!/bin/sh #learn-spam.sh exec /usr/local/bin/rspamc -d "${1}" learn_spam #!/bin/sh # learn-ham.sh exec /usr/local/bin/rspamc -d "${1}" learn_ham
Scripts must be executables:
# chmod +x /usr/local/lib/dovecot/sieve/learn-*.sh
At last, reload dovecot:
# rcctl reload dovecot
Here you go, now your anti-spam will learn when you'll move messages in approriate folders.
Learn more with dovecot official documentation.
https://wiki2.dovecot.org/HowTo
You can sort incoming spams into a Junk folder. But imagine you can annoy spammers π? That's what spamd can do, faking being a mail server and holding spammers so they can't deliver spams while it's talking to them veeery slowly.
You can let somewhere on the web a fake mail address: a spamtrap. Everyone sending a message to this address will be blacklisted and trapped.
In the meantime, new senders are greylisted. They're told to try again later. Every proper email server will try again. Spammers won't, so you don't get the spam. Others who try again correctly are put on a whitelist.
There is also a blacklist-only mode, trapping IPs from lists you already have.
However, this means senders do things correctly. That's is sadly not always true for commercial senders. This said, it is easy to put a server on a whitelist.
To keep track of good and bad senders, the command spamd-setup should be run periodically.
Everything is very well explained in spamd(8) manpage. You must read it since the following are just advices, not a complete howto.
# rcctl enable spamd # rcctl set spamd flags "-v -G 25:4:864" # rcctl start spamd
Also enable spamlogd to keep track of servers already whitelisted and to whitelist servers you write to.
# rcctl enable spamlogd # rcctl start spamlogd
spamd is running in front of smtpd (like a shield, or a janitor π). To do so, edit packet-filter configuration: spamd should redirect mails to smtpd if it is not a spam.
Add in /etc/pf.conf:
table <spamd-white> persist table <nospamd> persist file "/etc/mail/nospamd" pass in on egress proto tcp to any port smtp divert-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
On line order:
Remember to reload pf:
# pfctl -ef /etc/pf.conf
It is necessary to reload spamd blacklist in pf. Edit root's crontab with "# crontab -e" then uncomment the line below:
~ * * * * /usr/libexec/spamd-setup
With ~, spamd-setup is run at a random schedule π.
Let somewhere on the web fake email addresses: spamtraps. Everyone writing to these addresses is a spammer and will be trapped. Of course, those addresses don't really exist!
To keep these spamtraps for bots only, you can add such html snippets on your website so they are invisible for human eyes:
<a href="mailto:trap@athome.tld"></a>
You can copy it on public pastebins too.
To teach spamd what are spamtraps, use:
# spamdb -T -a 'trap@athome.tld'
Some nice people gather IP lists and let everyone download them. To use such lists, edit /etc/mail/spamd.conf.
As example, the default configuration uses nixspam's list:
http://www.heise.de/ix/nixspam
Add in /etc/mail/spamd.conf the following lines:
all:\ :nixspam # Nixspam recent sources list. # Mirrored from http://www.heise.de/ix/nixspam nixspam:\ :black:\ :msg="Your address %A is in the nixspam list\n\ See http://www.heise.de/ix/nixspam/dnsbl_en/ for details":\ :method=http:\ :file=www.openbsd.org/spamd/nixspam.gz
At the beginning, you can read all. Then are written lists you want to use and configured below, separated with ":".
Use an URL to download the list with spamd-setup automatically or a file already on your server.
Peter N.M.Hansteen publish a blacklist, gathered with its own spamtraps.
Avoid to download it too often or you'll be put on a blacklist. Be kind with Peter's bandwidth π.
To get the list every hour past 20 minutes:
20 * * * * /usr/local/sbin/bsdly-spamd
Here is bsdly-spamd script you should copy and make executable:
#!/bin/sh # update bsdly.net traplist into DST URL="https://www.bsdly.net/~peter/bsdly.net.traplist" # alternative URL #URL="https://home.nuug.no/~peter/bsdly.net.traplist" DST=/var/db/bsdly.traplist ftp -o "${DST}" "${URL}"
Then add the new list in /etc/mail/spamd.conf so spamd uses /var/db/bsdly.traplist file:
all:\ :nixspam:bsdlyblack: nixspam:\ :black:\ :msg="Your address %A is in the nixspam list\n\ See http://www.heise.de/ix/nixspam/dnsbl_en/ for details":\ :method=https:\ :file=www.openbsd.org/spamd/nixspam.gz bsdlyblack:\ :black:\ :msg="SPAM. Your address %A has sent spam within the last 24 hours. See http://www.bsdly.net/~peter/traplist.shtml for details.":\ :method=file:\ :file=/var/db/bsdly.traplist
Below we describe how to periodically download lists provided by uceprotect. We will use rsync to reduce bandwidth usage.
http://www.uceprotect.net/en/index.php
Add a new cronjob to call a script downloading lists. Not too often or you'll be blacklisted.
10 * * * * /usr/local/sbin/uceprotect-spamd
/usr/local/sbin/uceprotect-spamd is the script below:
#!/bin/sh RSYNC="/usr/bin/openrsync -a" URLS="rsync-mirrors.uceprotect.net::RBLDNSD-ALL/dnsbl-1.uceprotect.net rsync-mirrors.uceprotect.net::RBLDNSD-ALL/dnsbl-2.uceprotect.net rsync-mirrors.uceprotect.net::RBLDNSD-ALL/ips.whitelisted.org" OUT="/var/db/RBLDNSD-ALL/" mkdir -p "${OUT}" for URL in ${URLS}; do ${RSYNC} "${URL}" "${OUT}" done
Load the lists in /etc/mail/spamd.conf. There are white and blacklists.
all:\ :nixspam:bgp-spamd:bsdlyblack:\ rbldnsd-1:rbldnsd-2:rbldnsd-white: ... rbldnsd-1:\ :black:\ :msg="Your address %A is listed on UCEPROTECT-Level 1\n \ see http://www.uceprotect.net/en":\ :method=file:\ :file=/var/db/RBLDNSD-ALL/dnsbl-1.uceprotect.net rbldnsd-2:\ :black:\ :msg="Your address %A is listed on UCEPROTECT-Level 2\n \ see http://www.uceprotect.net/en":\ :method=file:\ :file=/var/db/RBLDNSD-ALL/dnsbl-2.uceprotect.net rbldnsd-white:\ :white:\ :method=file:\ :file=/var/db/RBLDNSD-ALL/ips.whitelisted.org
Do not hesitate do donate to uceprotect.net for all their work π.
Some big mail provider uses multiple servers to send mails. If you do greylisting, the IP trying to send an email from a provider might change between two delivery attemps. This means spamd can't recognize a legitimate server, never whitelist the IP and you never get the mail.
However, you can whitelists those domains if you want.
Create a file containing domains not to greylist: /etc/mail/nospamd_domains_list.txt.
gmail.com hotmail.com facebookmail.com apple.com microsoft.com lists.openbsd.org linkedin.com freebsd.org twitter.com amazon.com yahoo.com yahoo.fr live.fr mail-out.ovh.net mxb.ovh.net gandi.net laposte.net protonmail.com
Add more domains if you need to.
Now create a script to get sending IP of above domains: /usr/local/sbin/generate-nospamd:
#!/bin/sh # /usr/local/sbin/generate-nospamd DOMAINS=/etc/mail/nospamd_domains_list.txt WHITELIST=/etc/mail/nospamd echo "#$(date)" > "$WHITELIST" smtpctl spf walk < "${DOMAINS}" >> "$WHITELIST" exit 0
Call this script daily with /etc/daily.local and reload nospamd table:
# /etc/daily.local /usr/local/sbin/generate-nospamd pfctl -t nospamd -T replace -f /etc/mail/nospamd
Read "man spamd" at section "BLACKLIST-ONLY MODE" so you can trap spammers from blacklists files without greylisting.
Run "spamdb" to see what's happening:
# spamdb WHITE|62.4.1.33|||1462699174|1462699174|1465809574|1|0 GREY|182.70.43.24|abts-mum-dynamic-024.43.70.182.airtelbroadband.in|<Estella32@thunderguy.co.uk>|<toto@athome.tld>|1473409924|1473424324|1473424324|1|0 GREY|14.183.132.63|static.vnpt.vn|<Abby5@toddelliott.com>|<kiki@athome.tld>|1473410586|1473424986|1473424986|1|0
Read spamdb(8) manpage to learn what it means.
To translate times in human-readable format, run date with -r flag:
$ date -r 1462699174 Sun May 8 11:19:34 CEST 2016
You can put on whitelist an IP with spamdb -a:
# spamdb -a "62.4.1.37"
Remember to keep spamd databases synchroniszd between your server and backups (secondary MX). Read about -Y and -y flags in spamd manpage.
https://man.openbsd.org/spamd#Y
To make sure your mail server works as expected, you can send an email to friends. however, this may be an issue since:
Luckily there are robots that can automatically answer. As example:
Or see the following websites:
https://dkimvalidator.com/results
You should look at smtpctl command to get details about what's happening.
As example, to have generic status:
# smtpctl show stats control.session=1 mda.envelope=0 mda.pending=0 mda.running=0 mda.user=0 mta.connector=1 mta.domain=1 mta.envelope=1 mta.host=2 mta.relay=1 mta.route=1 mta.session=1 mta.source=1 mta.task=1 mta.task.running=0 queue.evpcache.load.hit=1675 queue.evpcache.size=2 queue.evpcache.update.hit=6 scheduler.delivery.ok=826 scheduler.delivery.tempfail=6 scheduler.envelope=2 scheduler.envelope.incoming=0 scheduler.envelope.inflight=1 scheduler.ramqueue.envelope=2 scheduler.ramqueue.message=2 scheduler.ramqueue.update=0 smtp.session=0 smtp.session.inet4=787 smtp.session.local=31 smtp.tls=0 uptime=777861 uptime.human=9d4m21s
To see awaiting envelopes:
# smtpctl show queue 1101f6e60c169eac|inet4|mta||0100015b3a046476-f7d7955a-5842-49af-927c-4fa677f311c6-000000@bounces.duolingo.com|deux@domaine.eu|deux@domaine.eu|1491327053|1491672653|0|5|pending|3154|Network error on destination MXs 1a2123e1c2b3e462|inet4|mta||gitlab@framasoft.org|deux+framagit@domaine.eu|deux+framagit@domaine.eu|1491333449|1491679049|1491333849|1|inflight|50|Network error on destination MXs
To see in real time what's happening:
# smtpctl monitor
And of course; read man smtpctl π.