A CentOS 5 Virtual Mail Server using Postfix, Dovecot, and MySQL
Enable the centosplus repository
# vi /etc/yum.repos.d/CentOS-Base.repo
Under the [centosplus] section, change enabled=0 to enabled=1. The centosplus repository has an RPM with Postfix+MySQL support.
Remove Sendmail
# yum erase sendmail
Make sure that apache and MySQL are installed and running
# yum install dovecot httpd postfix mysql-server php php-mysql php-mbstring
I like to edit /etc/my.cnf first, and make mysql listen just on localhost by adding this to the top [mysqld] section:
bind=127.0.0.1
Then start up apache and mysql
# /etc/init.d/httpd start # /etc/init.d/mysqld start # chkconfig httpd on # chkconfig mysqld on
If you don’t have a root password for mysql, you should do that now:
/usr/bin/mysqladmin -u root password 'new-password' /usr/bin/mysqladmin -u root -h <YOUR_IP_ADDRESS> password 'new-password'
Install postfixadmin
Postfixadmin is a pretty simple web-based frontend for managing your mail domains and accounts (Screenshots)
Download and extract it
You may want to check The download page to make sure you are getting the latest version
cd /usr/local/src wget http://superb-west.dl.sourceforge.net/sourceforge/postfixadmin/postfixadmin-2.2.0.tgz tar -xvzf postfixadmin-2.2.0.tgz
Move it into the DocumentRoot
mv postfixadmin-2.2.0 /var/www/html/mailadmin
Alternatively, you can check out the code from the subversion repository:
# svn co https://postfixadmin.svn.sourceforge.net/svnroot/postfixadmin/tags/postfixadmin-2.2.0 .
Create a database user
Run the following mysql commands:
CREATE DATABASE postfix; GRANT ALL on postfix.* to 'postfix'@'localhost' IDENTIFIED BY 'password';
Create the config file
cp config.inc.php.sample config.inc.php replace "change-this-to-your.domain.tld" "<YOURDOMAIN.TLD>" -- config.inc.php
Now edit config.inc.php and make these changes to the defaults:
configured: | true |
postfix_admin_url: | http://YOUR_IP_ADDRESS/mailadmin/ |
postfix_admin_path: | /var/www/html/mailadmin/ |
database_user: | postfix (change it from postfixadmin) |
database_password: | Make up a random password. You’ll need it in several config files, so be ready to copy/paste it often |
encrypt: | cleartext – The needs to be clear text for SMTP Authentication to work |
page_size: | 25 |
default_aliases | Remove the hostmaster line |
The next two settings will put your mail accounts directories in the format of /home/vmail/<DOMAIN>/<USERNAME> | |
domain_path: | YES |
domain_in_mailbox: | NO |
aliases: | 25 |
mailboxes: | 25 |
quota: | 100 |
Create the Database
Hit http://YOUR_IP_ADDRESS/mailadmin/setup.php in your web browser. This will verify that your system meets the requirements, set up the database tables, and allow you to create an administrator account.
Remove setup.php
This file bypasses all authentication and can be used to create a new administrator, so it is extermely important that you delete it! Postfixadmin requires that setup.php doesn’t exist before allowing you to log in. I noticed, however, that the instructions say to rename it to setup.php.disabled, and I was able to hit setup.php.disabled in my browser and it still worked! Better to be safe and wipe it out completely rather than renaming it.
cd /var/www/mailadmin rm setup.php
Check your setup
Now hit postfixadmin in your web browser:
http://YOUR_IP_ADDRESS/mailadmin/
You should be able to log in using the administrator account you created in the last step.
Configuring Postfix
Now that we have postfixadmin installed and saving all of our mail account information to the database, we need to tell postfix how to access that database
cd /etc/postfix
Edit main.cf
Change inet_interfaces to this so that the server listens on the public IP address:
inet_interfaces = $myhostname, localhost
And add this to the bottom:
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf virtual_gid_maps = static:89 virtual_mailbox_base = /home/vmail virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_mailbox_domains.cf virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf virtual_minimum_uid = 89 virtual_transport = virtual virtual_uid_maps = static:89 broken_sasl_auth_clients = yes smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_hostname, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_hostname smtpd_sasl_auth_enable = yes smtpd_sasl_local_domain = $myhostname smtpd_sasl_security_options = noanonymous
Create /etc/postfix/mysql_virtual_alias_maps.cf with this content:
user = postfix password = <YOUR_DATABASE_PASSWORD_HERE> hosts = localhost dbname = postfix query = SELECT goto FROM alias WHERE address = '%s'
Create /etc/postfix/mysql_virtual_mailbox_domains.cf with this content:
user = postfix password = <YOUR_DATABASE_PASSWORD_HERE> hosts = localhost dbname = postfix query = SELECT domain FROM domain WHERE domain = '%s' AND backupmx = '0' AND active = '1'
Create /etc/postfix/mysql_virtual_mailbox_maps.cf with this content:
user = postfix password = <YOUR_DATABASE_PASSWORD_HERE> hosts = localhost dbname = postfix query = SELECT maildir FROM mailbox WHERE username = '%s'
SMTP Authentication with SASL
SMTP Authentication will allow you to use this mail server as your outgoing mail server. The password is required so that spammers aren’t able to relay mail through it
Install some packages that this will require
yum install cyrus-sasl cyrus-sasl-sql
Edit your smtpd.conf file and replace it with these contents. The location of smtpd.conf is probably /usr/lib/sasl2/smtpd.conf on 32-bit systems or /usr/lib64/sasl2/smtpd.conf on 64-bit systems. Other distros might put this in /etc/sasl2/ or /etc/postfix/sasl/.
pwcheck_method: auxprop mech_list: PLAIN LOGIN auxprop_plugin: sql sql_verbose: yes sql_engine: mysql sql_hostnames: localhost sql_user: postfix sql_passwd: <YOUR_DATABASE_PASSWORD_HERE> sql_database: postfix sql_select: SELECT password FROM mailbox WHERE username = '%u@%r'
Configure TLS
TLS/SSL encryption is useful when using this server as an outgoing mail server. Basic SMTP authentication transmits your username and password in a Base64 encoded string which is easy to intercept and decode. If the session is encrypted, that will prevent the possibility that somebody may be able to sniff your password. It also encrypts the contents of mail that you send, so it adds an extra layer of protection if you are using unencrypted (or poorly encrypted) wifi or something where your traffic is easily captured.
In this example, we will create a self-signed certificate that expires in 10 years. The first time your mail client sees this certificate, it will warn you that it isn’t signed by a recognized certificate authority. You can usually tell your mail client to accept the certificate, and it will trust it from then on.
First we have to create some certificates. In the following steps replace <YOURDOMAIN.TLD> with the exact name that you want the certificate to be for. (ie mail.yourdomain.com).
Create a private key
mkdir /etc/postfix/ssl cd /etc/postfix/ssl openssl genrsa -out <YOURDOMAIN.TLD>.key 1024
Create the certificate request. Answer the questions appropriately.
[root@www ssl]# openssl req -new -key <YOURDOMAIN.TLD>.key -out <YOURDOMAIN.TLD>.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [GB]:<YOUR_COUNTRY> State or Province Name (full name) [Berkshire]:<YOUR_STATE> Locality Name (eg, city) [Newbury]:<YOUR_CITY> Organization Name (eg, company) [My Company Ltd]:<YOUR_COMPANY> Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []:<YOURDOMAIN.TLD> Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
Sign the certificate yourself. If you are running a server that will be accessible to other users, you may want to purchase a commercially signed SSL certificate to avoid having your users get a warning that the certificate isn’t signed by a recognized certificate authority.
# openssl x509 -req -days 3650 -in <YOURDOMAIN.TLD>.csr -signkey <YOURDOMAIN.TLD>.key -out <YOURDOMAIN.TLD>.crt Signature ok subject=/C=US/ST=State/L=City/O=CompanyName/CN=<YOURDOMAIN.TLD> Getting Private key
And create a cacert.pem. Answer the questions the same way as above. This certificate does require a password, so make sure you document that somewhere if you ever need it again.
openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -days 3650
Now, tell postfix about the certificates by adding this to the bottom of /etc/postfix/main.cf:
## Enable TLS smtp_use_tls = yes smtpd_use_tls = yes smtp_tls_note_starttls_offer = yes smtpd_tls_key_file = /etc/postfix/ssl/<YOUR.DOMAIN.TLD>.key smtpd_tls_cert_file = /etc/postfix/ssl/<YOUR.DOMAIN.TLD>.crt smtpd_tls_CAfile = /etc/postfix/ssl/cacert.pem smtpd_tls_loglevel = 1 smtpd_tls_received_header = yes smtpd_tls_session_cache_timeout = 3600s tls_random_source = dev:/dev/urandom
And tell postfix to listen on the SMTP Submission port (587), and the SMTP/SSL port (465). Edit /etc/postfix/master.cf and uncomment these respective lines:
## Enable SMTP on port 587 only for authenticated/TLS clients submission inet n - n - - smtpd -o smtpd_enforce_tls=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject ## Enable SMTP on port 465 only for authenticated/SSL clients smtps inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject
File Permissions
Make it so that postfix can write to the directory where all mail will be delivered
mkdir -p /home/vmail chown postfix:postfix /home/vmail chmod 770 /home/vmail
Restart postfix, and it should be ready to accept mail
/etc/init.d/postfix restart
If you get an error about the mysql dictionary not being supported, try to remove then reinstall postfix (make a copy of your config files first). I believe this happens when you install postfix prior to enabling the centosplus repository.
Install and Configure Dovecot
Install it from yum. This RPM was compiled with MySQL support
yum install dovecot
Create /etc/dovecot-mysql.conf with this content
driver = mysql connect = host=127.0.0.1 dbname=postfix user=postfix password=<YOUR_DATABASE_PASSWORD> default_pass_scheme = PLAIN password_query = SELECT password FROM mailbox WHERE username = '%u' user_query = SELECT maildir, 89 AS uid, 89 AS gid FROM mailbox WHERE username = '%u'
And now edit the main dovecot configuration file in /etc/dovecot.conf, and tell it to use the /etc/dovecot.mysql.conf file for the auth and password databases.
Under the ‘auth default’ section, uncomment the passdb sql section so that it looks like this (Line 831 in a default dovecot.conf file):
passdb sql {ldelim} # Path for SQL configuration file, see doc/dovecot-sql.conf for example args = /etc/dovecot-mysql.conf {rdelim}
And same thing with the userdb sql section on line 885:
userdb sql {ldelim} # Path for SQL configuration file, see doc/dovecot-sql.conf for example args = /etc/dovecot-mysql.conf {rdelim}
If you want to use SSL/TLS for your incoming mail, you can configure dovecot to use the same certificates as postfix:
ssl_cert_file = /etc/postfix/ssl/<YOUR.DOMAIN.TLD>.crt ssl_key_file = /etc/postfix/ssl/<YOUR.DOMAIN.TLD>.key ssl_ca_file = /etc/postfix/ssl/cacert.pem
And add this to the bottom of the file (still in /etc/dovecot.conf):
first_valid_uid = 89 mail_location = maildir:/home/vmail/%d/%n
Finally, list the protocols/ports that you want to listen on (still in /etc/dovecot.conf). Here are what ports each protocol is on:
Cleartext protocols: | POP3(110), IMAP(143) (both can do TLS) |
Encrypted protocols: | POP3/SSL(993) and IMAP/SSL(995) |
protocols = imap imaps pop3 pop3s
Now start up dovecot
/etc/init.d/dovecot start
Testing Everything
Here are some things you should test to ensure that everything is working correctly
Postfix Tests
All of these can be tested through a telnet session or with OpenSSL
- Send mail from an external host and an external account to a valid account
- Send mail from an external host and an external account to an invalid account (make sure it fails)
- Send mail from an external host from aa valid account to an external account (without authentication) and make sure it fails
- Authenticate with SMTP Authentication, make sure you can send to an external domain
- Send mail from localhost, everything should be accepted
- Test SMTP with TLS
(Use my SMTP authtool to get your encoded password)
openssl -starttls smtp s_client -connect <YOUR_IP_ADDRESS>:587
openssl s_client -connect <YOUR_IP_ADDRESS>:465
Dovecot Tests
All of these can be tested through a telnet session or with OpenSSL
- Test a simple POP3 session
- Test a simple IMAP session
- Test both of those with TLS
openssl -starttls pop3 s_client -connect <YOUR_IP_ADDRESS>:110
openssl s_client -connect <YOUR_IP_ADDRESS>:993
Sample Sessions
Here is a basic SMTP Session through telnet
[root@host ~]# telnet <YOUR_IP_ADDRESS> 25 Trying 22.33.44.55... Connected to mail.yourdomain.com (22.33.44.55). Escape character is '^]'. 220 mail.yourdomain.com ESMTP Postfix ehlo my.host.name.com 250-mail.yourdomain.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-STARTTLS 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN PLAIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN mail from:<[email protected]> 250 2.1.0 Ok rcpt to:<[email protected]> 250 2.1.5 Ok data 354 End data with <CR><LF>.<CR><LF> Subject:test test . 250 2.0.0 Ok: queued as EC2273130099 quit 221 2.0.0 Bye Connection closed by foreign host.
Sample POP3 Session:
[root@host ~]# telnet <YOUR_IP_ADDRESS> 110 Trying 22.33.44.55... Connected to mail.yourdomain.com (22.33.44.55). Escape character is '^]'. +OK Dovecot ready. user [email protected] +OK pass password +OK Logged in. list +OK 4 messages: 1 551 2 541 3 530 4 505 . quit +OK Logging out.
Troubleshooting
- Both postfix and dovecot log to /var/log/maillog. Often, they tell you exactly what is long if you know where to look.
- If troubleshooting postfix lookups, you can use postmap directly:
[root@mail postfix]# postmap -q [email protected] mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf somedomain.com/someuser
smtp inet n - n - 500 smtpd -v
Leave a Reply