Note

The Funtoo Linux project has transitioned to "Hobby Mode" and this wiki is now read-only.

Mail Server

From Funtoo
Revision as of 04:42, December 14, 2016 by Shamus397 (talk | contribs) (Still needs work, but that's enough for tonight)
Jump to navigation Jump to search

How to set up a simple, secure, lightweight email server using Postfix and Dovecot

Running one's own email server doesn't have to be mystical and impenetrable; using a simple MTA like Postfix along with an LDA like Dovecot makes the task relatively easy. Regrettably, good information on how to do this is hard to come by. What this guide will help you do is install a mail server which uses a database backend to manage domains and users, and features mail delivery via POP3 and/or IMAP.

__

Prerequisites

If you intend to run your own email server, you will need to have DNS with at least one MX record on a DNS server that can be seen by the Internet at large. It is also essential for reliable mail delivery to have properly-configured reverse DNS as many mail servers will use reverse DNS and will expect your IP address to resolve to your advertised hostname. Setting up such a thing is beyond the scope of this document.

Preparation

The following packages need to be installed first, before we can do anything: mail-mta/postfix, net-mail/dovecot, and dev-db/mariadb. Before we emerge these, however, we must ensure some USE flags are properly set first:

   /etc/portage/package.use/mail-server - USE flags
mail-mta/postfix dovecot-sasl pam ssl
net-mail/dovecot bzip2 maildir pam ssl zlib

With USE flags properly set, we can emerge our packages:

root # emerge -avq postfix mariadb

Setting the dovecot-sasl USE flag should pull in net-mail/dovecot. If it does not, emerge this way:

root # emerge -avq postfix dovecot mariadb

Next, we need to set up the location on the server where email will be delivered:

root # mkdir /mailstore
root # chgrp mail /mailstore
root # chmod -R g+rw /mailstore

Configuration

Now we come to the meat of the project. First we will have to set up the mail user/domain database, then we will have to configure Postfix, then finally, configure Dovecot. At the end of this procedure, we should have a fully functioning mail server.

Setting up the Database

First step is to set up the database for the virtual domain/user tracking. We need to set up the database's root user and get the database up and running (be sure to replace <strong-password> with a real, strong password):

root # mysqladmin -u root password '<strong-password>'
root # rc-update add mysql default
root # rc

Next, we need to login to MySQL (you will have to enter the <strong-password> you set above):

root # mysql -p

Now, we create the database and its tables (again, replace <mailuserpass> with a real password):

mysql> CREATE DATABASE mailserver;
mysql> USE mailserver;
mysql> GRANT SELECT ON mailserver.* TO 'mailuser'@'127.0.0.1' IDENTIFIED BY '<mailuserpass>';
mysql> FLUSH PRIVILEGES;
mysql> CREATE TABLE virtual_domains (id INT(11) NOT NULL AUTO_INCREMENT,
root ##i##       name VARCHAR(50) NOT NULL, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
mysql> CREATE TABLE virtual_users (id INT(11) NOT NULL AUTO_INCREMENT,
root ##i##       domain_id INT(11) NOT NULL, password VARCHAR(106) NOT NULL, email VARCHAR(100) NOT NULL,
root ##i##       PRIMARY KEY (id), UNIQUE KEY email (email), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id)
root ##i##       ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8;
mysql> CREATE TABLE virtual_aliases (id INT(11) NOT NULL AUTO_INCREMENT,
root ##i##       domain_id INT(11) NOT NULL, source VARCHAR(100) NOT NULL, destination VARCHAR(100) NOT NULL,
root ##i##       PRIMARY KEY (id), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE)
root ##i##       ENGINE=InnoDB DEFAULT CHARSET=utf8;

Now that we've created our database and tables, we need to put our domain into it. Replace <my.fqdn.com> with the FQDN of that will go to the right of the '@' sign in email addresses on your mail domain:

mysql> INSERT INTO virtual_domains VALUES (DEFAULT, '<my.fqdn.com>');
   Note

If you're planning on receiving mail for more than one domain, you can add them by reusing the previous query and changing <my.fqdn.com> to the other domain(s); you will have to enter one query for each extra domain.

Next, we need to populate that database with users (the part that goes on the left side of the '@' sign). Again, these need to be added one at a time. For each entry in the database, we will need a username and a password; since we want these passwords to be strong, we will use doveadm to generate them:

root # doveadm pw -s SHA512-CRYPT
Enter new password: 
Retype new password: 
{SHA512-CRYPT}$6$dMNWSDK.CYzDfADO$LLSqttmYD/3WDBIEwxLjzae1s0G.eQw6EU8U7cjysPDK/z3Pntz8gxabfrYmLzpdc.L3gMyxaoI4V9ci4zruM.

You will be prompted to enter the password twice before it gives back the hash. The part that comes after {SHA512-CRYPT} is the password that will need to go into the database (it will always start with $6$).

   Note

The password you will distribute to your users is the one you typed into doveadm; the hash that it outputs is what will go into the virtual_users table.

Replace <pw_hash> with the output of doveadm (starting with $6$), and <user@my.fqdn.com> with the email address for the user you're creating:

mysql> INSERT INTO virtual_users VALUES (DEFAULT, 1, '<pw_hash>', '<user@my.fqdn.com>');
   Note

The second field in the query above (the '1') is the ID of the entry in the virtual_domains table. If you're only using one domain, you don't have to worry about changing it; otherwise, you will have to change it to correspond to the domain for that user. You can find out what IDs they have with the following query:

mysql> SELECT * FROM virtual_domains;

Once you are done entering users you can leave MySQL:

mysql> quit

Configuring Postfix

Now we have to configure Postfix. Pull up your favorite text editor and add the following lines to the bottom:

   /etc/postfix/main.cf - Postfix configuration
# SASL config
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

# TLS config
smtpd_tls_cert_file = /etc/ssl/certs/dovecot.pem
smtpd_tls_key_file = /etc/ssl/private/dovecot.pem
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtp_tls_loglevel = 2
smtpd_tls_received_header = yes

# Authentication config
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf
local_recipient_maps = $virtual_mailbox_maps

Next, we have to change a few items in the same config file (change the defaults in the file to what's listed here):

   /etc/postfix/main.cf - More Postfix configuration
compatibility_level = 2
myhostname = <my.fqdn.com> # Replace <my.fqdn.com> with your mail server's FQDN
mydomain = <fqdn.com> # Replace <fqdn.com> with your mail server's domain
mydestination = localhost # This MUST be set to localhost
mynetworks = 192.168.0.0/24, 127.0.0.0/8 # Replace 192.168.0.0/24 with your LAN's IP/mask

Next, we have to create the files referenced above as part of the 'Authentication config'. First, we have to create /etc/postfix/mysql-virtual-mailbox-domains.cf:

   /etc/postfix/mysql-virtual-mailbox-domains.cf - MySQL/virtual domains Postfix configuration
user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_domains WHERE name='%s'

Next, we have to create /etc/postfix/mysql-virtual-mailbox-maps.cf:

   /etc/postfix/mysql-virtual-mailbox-maps.cf - MySQL/virtual maps Postfix configuration
user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM virtual_users WHERE email='%s'

And finally, we have to create /etc/postfix/mysql-virtual-alias-maps.cf:

   /etc/postfix/mysql-virtual-alias-maps.cf - MySQL/virtual alias maps Postfix configuration
user = mailuser
password = mailuserpass
hosts = 127.0.0.1
dbname = mailserver
query = SELECT destination FROM virtual_aliases WHERE source='%s'

Now lets start Postfix and make sure that our authentication queries are working:

root # /etc/init.d/postfix start
root # postmap -q <my.fqdn.com> mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
1
root # postmap -q <user>@<my.fqdn.com> mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
1

Assuming both postmap commands returned 1, we can go on to configuring Dovecot.

Configuring Dovecot

Now that Postfix is properly configured, it's time to tackle Dovecot. The first file we want to look at is /etc/dovecot/dovecot.conf. In particular, we want to make sure the protocols line has imap, pop3, and lmtp enabled:

   /etc/dovecot/dovecot.conf - Dovecot configuration
protocols = imap pop3 lmtp

Next we need to look at /etc/dovecot/conf.d/10-mail.conf:

   /etc/dovecot/conf.d/10-mail.conf - Dovecot configuration
mail_location = maildir:/decrypted-mail/%d/%n
mail_privileged_group = mail
first_valid_uid = 0

On to /etc/dovecot/conf.d/10-auth.conf:

   /etc/dovecot/conf.d/10-auth.conf - Dovecot authorization config
disable_plaintext_auth = yes
auth_mechanisms = plain login
#INSERT a hashtag in front of the following import.  This separates your mail server's login from UNIX logins.
#!include auth-system.conf.ext
#REMOVE the hashtag in front of the following import.  This points it at mysql for authentication.
!include auth-sql.conf.ext

On to /etc/dovecot/conf.d/auth-sql.conf.ext:

   /etc/dovecot/conf.d/auth-sql.conf.ext - Dovecot SQL config
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
  driver = static
  args = uid=mail gid=mail home=/decrypted-mail/%d/%n
}

On to /etc/dovecot/dovecot-sql.conf.ext:

   /etc/dovecot/dovecot-sql.conf.ext - More Dovecot SQL config
driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mailuser password=mailuserpass
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';

Next up is /etc/dovecot/conf.d/10-master.conf:

   /etc/dovecot/conf.d/10-master.conf - Dovecot master config file
service imap-login {
  inet_listener imap {
    port = 0
  }
…
service pop3-login {
  inet_listener pop3 {
    port = 0
  }
…
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0666
    group = postfix
    user = postfix
  }
  # Create inet listener only if you can't use the above UNIX socket
  #inet_listener lmtp {
    # Avoid making LMTP visible for the entire internet
    #address =
    #port =
  #}
  user=mail
}

service auth {
  # auth_socket_path points to this userdb socket by default. It's typically
  # used by dovecot-lda, doveadm, possibly imap process, etc. Its default
  # permissions make it readable only by root, but you may need to relax these
  # permissions. Users that have access to this socket are able to get a list
  # of all usernames and get results of everyone's userdb lookups.
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  unix_listener auth-userdb {
    mode = 0600
    user = mail
    #group =
  }
  # Postfix smtp-auth
  #unix_listener /var/spool/postfix/private/auth {
  #  mode = 0666
  #}
  # Auth process is run as this user.
  user = dovecot
}
service auth-worker {
  # Auth worker process is run as root by default, so that it can access
  # /etc/shadow. If this isn't necessary, the user should be changed to
  # $default_internal_user.
  user = mail
}

And last, but not least, /etc/dovecot/conf.d/10-ssl.conf:

   /etc/dovecot/conf.d/10-ssl.conf - Dovecot SSL config
ssl_cert = </etc/ssl/certs/dovecot.pem
ssl_key = </etc/ssl/private/dovecot.pem
ssl = required

We now need to generate the SSL certificates that Postfix and Dovecot are looking for. When it asks for a FQDN for the certificate, make sure to put in the FQDN of the mail server:

root # openssl req -new -x509 -days 1000 -nodes -out "/etc/ssl/certs/dovecot.pem" -keyout "/etc/ssl/private/dovecot.pem"

Yes, they are self-signed certificates; if that bothers you feel free to buy one from GoDaddy or some other CA. It won't make things more secure (self-signed certificates have an undeserved bad reputation), but it will make you slightly poorer and the CA slightly richer.

Finally, we set the permissions on the Dovecot config files so they belong to mail:dovecot and nobody else:

root # chown -R mail:dovecot /etc/dovecot
root # chmod -R o-rwx /etc/dovecot

Final Steps

We want Postfix and Dovecot to come up when our server boots up, so we need to add them to the server's startup; once that's done, we'll start Postfix and Dovecot with the rc command:

root # rc-update add postfix default
root # rc-update add dovecot default
root # rc

With that, the mail server should be configured correctly to send and receive email. If it doesn't work, you will probably want to snoop around /var/log/messages and look for lines that have postfix or dovecot in them for clues.

Client Configuration

This configuration is for Thunderbird, but it should be applicable to any other client. When setting up a new account, it will ask for your name, email address, and password. Clicking on the Continue button will then have Thunderbird attempt to autodetect your mail server settings automagically; this should normally fail (if not, then you're done!). If you look in /var/log/messages on the mail server, you should see something similar to this:

   /var/log/messages - System log file
postfix/smtpd[]: improper command pipelining after EHLO from <client FQDN>[<client IP>]: QUIT\r\n

The solution then is to select port 993 from the Port: combobox on the Incoming: line. Hitting the Re-test button should allow Thunderbird to properly detect the settings at this point, assuming that the following is true:

  • The server hostname fields contain the FQDN of your mail server
  • The Incoming: and Outgoing: username fields contain the user's full email address
  • The password given for the user's email address is correct.

If all else fails, you can try the following settings:

ProtocolServerPortSSLAuthentication
Incoming:IMAPmail server's FQDN993SSL/TLSNormal password
Outgoing:SMTPmail server's FQDN25STARTTLSNormal password
   Note

Once the settings are correct in Thunderbird, the first time you send or receive an email message, Thunderbird will ask you to confirm the certificates coming from your email server if they are self-signed.

A Few Words on Security, Spam & Blacklists

The email server you have just set up should be reasonably secure from attackers; it won't relay messages outside of your LAN and it won't talk to unencrypted peers. As long as you and your users have chosen good, strong passwords for each link of the chain, you shouldn't have to worry too much about such as bad actors, or being put on spam blacklists. As long as you keep an eye on your mail server and investigate suspicious activity, it should serve you well and work well in the wider Internet environment.

But Wait, There's More!

But only a bit more. Those are the basics, but if you want you can also set up SPF, DKIM, PTR records; unfortunately those are beyond the scope of this article. Other possibilities are spam filtering, push support, and full text-search; these are left as an exercise for the reader.