Full mail server with virtual users
"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
One user to rule them all : _vmail
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 ...
/etc/mail/virtuals
In this file, we write user's emails, one on each line. Actually, it works like the file /etc/mail/aliases. (read man aliases(5) 😉)
heroes@athome.tld batman@athome.tld,superman@athome.tld batman@athome.tld _vmail superman@athome.tld _vmail kiki@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".
Notez que sur la première ligne, on a fait un alias à titre d'exemple pour transférer un mail d'une adresse à une autre.
/etc/mail/passwd
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>.
- L'adresse mail du compte ;
- Le mot de passe chiffré ;
To hash passphrases, use "encrypt" command :
encrypt -p
Or "smtpctl encrypt passphrase".
(Facultative) Fine tuning files permissions
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 (smtpd) config
Opensmtpd or smtpd is the default mail server shipped with OpenBSD. You just have to configure it.
First of all, make sure you opened thos 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 :
- Generic options for smtpd ;
- Actions we will apply on envelopes later;
- Rules matching envelopes and associated action to apply.
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
- "table aliases ..." : This file is a aliases files, to forward envelopes between system users.
- "table passwd ..." : Hashed passwords are stored here
- "table virtuals ..." : Virtual users file. It is also a alias file.
- "pki ..." : Certificate and key location for encrypted traffic.
- "listen on all tls pki athome.tld" : smtpd listen (on port 25) to receive mails from other servers. Here, traffic is tls encrypted if possible with the certificated defined before.
- "listen on all port submission tls-require pki athome.tld auth <passwd>" : The server listen on port "submission" and require tls encryption and authentication matchin tabe <passwd>. It is necessary to send email using a mail client from another device than the server itself.
Then, we define actions applied on envelopes.
- "action "sendthismail" relay" : smtpd send the mail to the smtp server "written on the envelope".
- "action local_mail maildir alias <aliases>" : smtpd deliver the envelope in a maildir directory after matching with the file <aliases>. It is for system users.
- "action virtual_maildir maildir "/var/vmail/%{dest.domain:lowercase}/%{dest.user:lowercase}/Maildir" virtual <virtuals>" : Here, smtpd deliver in a maildir directory located in _vmail's directory. Envelopes are stored according to domain name and user recipient. Everything is lowercased to avoid mistakes. That's here the magic of virtual users.
At last, we apply actions according to envelope criterias.
If not mentioned, the rule is matching for a local mail. In other case, we add "from any".
- "match for local action local_maildir" : deliver local mails.
- "match from any for domain athome.tld action virtual_maildir" : is the message come from the outside, it is saved in the appropriate maildir according to domain name and recipient's name.
- "match auth from any for any action "sendthismail"" : If the envelope comes from a mail client outside after ahtentication, send the message to the recipient's smtp server.
- "match for any action "sendthismail"" : We send every other messages from the inside of the server.
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 😊.
Dovecot
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 up with a script generating a self-signed certificate. However, you probably already have your own. You should comment lines in this 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 mail account
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"