Installing a mailserver is a quite complex matter because several components are involved. Since there are many different operational scenarios, there are many different possible configurations, thus lots of different howtos around the internet. In this howto I’m going to describe the basic configuration of a mail server which has the following characteristics:
- Everything runs on Ubuntu 14.04 LTS x64
- All software packages are taken from the repository (no compiling necessary)
- The server is directly connected to the internet using a static IP address
- Users don’t have system accounts on the Unix machine
- User accounts are virtual accounts stored in an LDAP
- Users with a valid LDAP account can …
- Send and receive mail via POP3/IMAP
- Send and receive mail via Web Interface
Spam and virus protection (amavis, clamav, spamassasin) is not covered by this howto.
Graphical overview of the set-up:
These are the necessary components:
- Postfix as MTA (Mail Transfer Agent) –> This is the SMTP server. It accepts incoming mail (after a successful LDAP lookup of the recipient address) and passes it to Dovecot. It forwards outgoing mail (after the user successfully authenticated) to the next responsible SMTP server.
- Dovecot as LDA (Local Delivery Agent) –> This is the POP3 and IMAP server. It accepts incoming mail from Postfix and stores it in virtual mailboxes. It is connected to the LDAP for user authentication and lookups.
- Cyrus SASL –> Provides authentication for the SMTP server (since users are only allowed to send mail after they authenticated). User and password verification is done via LDAP.
- LDAP –> This is the directory service that stores the (virtual) user accounts for the mail server. It uses the postfix-book scheme. [UPDATE 2017-11-17: The original postfix-book scheme seems to be no longer available, but there is one on Github]
- Roundcube –> This is a web interface that lets users access their mail via web browser instead of a mail client (Mail User Agent). In addition to a webserver (i.e. Apache) Roundcube requires a database to store user settings (i.e. MySQL).
As for this howto, everything is running on a single machine. In real life (especially when you have to deal with a lot of users), it might be better to have dedicated machines for certain services. If you use dedicated machines, however, you have to make sure that the communication between these is secure!
Basic Prerequisites
1. Connectivity
The server must be connected to the internet and should be accessible through the following ports:
- 25 (SMTP)
- 80 (HTTP)
- 110 (POP3)
- 143 (IMAP)
- 443 (HTTPS)
If you have any firewalls, don’t forget to open the necessary ports.
2. System Time
The server should have an accurate system time, i.e. by using NTP.
3. Hostname
The server needs a fully-qualified hostname (i.e. mail.example.com), because otherwise foreign mail servers might not accept mails from it. This can be checked with the following command: hostname -f
The hostname can be configured in the following config files:
- /etc/hostname
- /etc/hosts
4. DNS Resolution
The server must be configured to use a working DNS server. Traditionally, DNS servers have to be added to /etc/resolv.conf, but on Ubuntu these are configured via the Network Manager. Preferably by using the GUI, or by manually editing the config file in /etc/NetworkManager/system-connections.
5. DNS Records
The hostname needs to be resolvable in both directions (hostname –> ip & ip –> hostname), so your provider needs to set the following DNS Records for you:
- A Record (forward lookup, resolvs a hostname to an IPv4 address)
- AAAA Record (forward lookup, resolvs a hostname to an IPv6 address)
- PTR Record (reverse lookup, resolvs an IP address to a hostname)
- MX Record (provides the hostname of a domain’s mail server)
This can be checked with the following commands:
1 2 3 4 |
dig mail.example.com A +short # should return your server's IPv4 address dig mail.example.com AAAA +short # should return your server's IPv6 address, if configured dig -x <ip address> +short # should return your fully-qualified hostname dig example.com MX +short # should return your mail server's fully-qualified hostname |
6. Logging
For troubleshooting it is important that the logging service is working. This is rsyslogd by default, the configuration can be found in /etc/rsyslog.d. By default, mail-related log will go to /var/log/mail.log.
LDAP
A basic LDAP guide can be found here: basic-openldap-installation-configuration
The BaseDN for this howto is “dc=example,dc=com” and it contains two organizationalUnits:
- “ou=people,dc=example,dc=com” for user accounts (RDN = uniqueIdentifier)
- “ou=services,dc=example,dc=com” for service accounts (RDN = uid)
- You’ll need accounts for postfix, dovecot, saslauthd and roundcube
The following screenshots show the LDAP structure, the necessary objectClasses and attributes:
For testing purposes it might be a good idea to create an “allow everything” ACL ( {0}to * by * write) — see the LDAP guide for that — but keep in mind that everyone who has access to the LDAP server will be able to read and edit the whole directory. So don’t forget to create appropiate ACLs before you put the server into productive operation!
Postfix
1. Installation
Install Postfix and the extensions for Pearl Compatible Regular Expressions and LDAP Connections. During installation select the “No Configuration” option:
1 |
apt-get install postfix postfix-pcre postfix-ldap |
Optionally, you can install extra tools for managing mailboxes (mutt) and sending testmails (swaks):
1 |
apt-get install mutt swaks |
2. Configuration
Before Postfix can be started, some configuration files need to be created in /etc/postfix:
- main.cf –> This is the main configuration file for Postfix (parameter documentation)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181###################################################################################################### Base Settings ######################### Listen on all interfacesinet_interfaces = all# Use TCP IPv4inet_protocols = ipv4# Greet connecting clients with this bannersmtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)# Fully-qualified hostnamemyhostname = mail.example.com# Do not append domain part to incomplete addresses (this is the MUA's job)append_dot_mydomain = no# Trusted networks/hosts (these are allowed to relay without authentication)mynetworks =# Local127.0.0.0/8# External1.2.3.4/32###################################################################################################### Local Transport ########################### Disable local transport (so that system accounts can't receive mail)local_transport = error:Local Transport Disabled# Don't use local alias mapsalias_maps =# Local domain (could be omitted, since it is automatically derived from $myhostname)mydomain = example.com# Mails for these domains will be transported locallymydestination =$myhostnamelocalhost.$mydomainlocalhost###################################################################################################### Virtual Transport ############################# Deliver mail for virtual recipients to Dovecotvirtual_transport = dovecot# Process one mail at one timedovecot_destination_recipient_limit = 1# Valid virtual domainsvirtual_mailbox_domains = hash:/etc/postfix/virtual_domains# Valid virtual recipientsvirtual_mailbox_maps = proxy:ldap:/etc/postfix/ldap_virtual_recipients.cf# Virtual aliasesvirtual_alias_maps = proxy:ldap:/etc/postfix/ldap_virtual_aliases.cf###################################################################################################### ESMTP Settings ############################ SASL #### Enable SASL (required for SMTP authentication)smtpd_sasl_auth_enable = yes# Enable SASL for Outlook-Clients as wellbroken_sasl_auth_clients = yes### TLS #### Enable TLS (required to encrypt the plaintext SASL authentication)smtpd_tls_security_level = may# Only offer SASL in a TLS sessionsmtpd_tls_auth_only = yes# Certification Authoritysmtpd_tls_CAfile = /etc/postfix/certs/example-cacert.pem# Public Certificatesmtpd_tls_cert_file = /etc/postfix/certs/mail_public_cert.pem# Private Key (without passphrase)smtpd_tls_key_file = /etc/postfix/certs/mail_private_key.pem# Randomizer for key creationtls_random_source = dev:/dev/urandom# TLS related logging (set to 2 for debugging)smtpd_tls_loglevel = 0# Avoid Denial-Of-Service-Attackssmtpd_client_new_tls_session_rate_limit = 10# Activate TLS Session Cachesmtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_session_cache# Deny some TLS-Cipherssmtpd_tls_exclude_ciphers =EXPEDH-RSA-DES-CBC-SHAADH-DES-CBC-SHADES-CBC-SHASEED-SHA# Diffie-Hellman Parameters for Perfect Forward Secrecy# Can be created with:# openssl dhparam -2 -out dh_512.pem 512# openssl dhparam -2 -out dh_1024.pem 1024smtpd_tls_dh512_param_file = ${config_directory}/certs/dh_512.pemsmtpd_tls_dh1024_param_file = ${config_directory}/certs/dh_1024.pem###################################################################################################### Connection Policies ############################### Reject Early Talkerspostscreen_greet_action = enforce###################################################################################################### Session Policies ############################ Recipient Restrictions (RCPT TO related)smtpd_recipient_restrictions =reject_non_fqdn_recipientreject_unknown_recipient_domain# Allow relaying for SASL authenticated clients and trusted hosts/networks# This can be put to smtpd_relay_restrictions in Postfix 2.10 and laterpermit_sasl_authenticatedpermit_mynetworks# If not authenticated or on mynetworks, reject mailing to external addressesreject_unauth_destination# Reject the following hostscheck_sender_ns_access cidr:/etc/postfix/drop.cidrcheck_sender_mx_access cidr:/etc/postfix/drop.cidr# Additional blacklistreject_rbl_client ix.dnsbl.manitu.net# Finally permit (relaying still requires SASL auth)# WARNING: Due to this permit, everyone will be able to send emails to internal addresses without authentication. If this is set to reject though, the server does not receive emails from external addresses. Unfortunately I do not have a solution for this.permit# Reject the request if the sender is the null address and there are multiple recipientssmtpd_data_restrictions = reject_multi_recipient_bounce# Sender Restrictionssmtpd_sender_restrictions =reject_non_fqdn_senderreject_unknown_sender_domain# HELO/EHLO Restrictionssmtpd_helo_restrictions =permit_mynetworkscheck_helo_access pcre:/etc/postfix/identitycheck.pcre#reject_non_fqdn_helo_hostnamereject_invalid_hostname# Deny VRFY recipient checksdisable_vrfy_command = yes# Require HELOsmtpd_helo_required = yes# Reject instantly if a restriction applies (do not wait until RCPT TO)smtpd_delay_reject = no# Client Restrictions (IP Blacklist)smtpd_client_restrictions = check_client_access cidr:/etc/postfix/drop.cidr - virtual_domains –> Contains the domains the server takes mails for
123# Domain Anythingexample.com OK - ldap_virtual_recipients.cf –> LDAP query for recipient validation
12345678bind = yesbind_dn = uid=postfix,ou=services,dc=example,dc=combind_pw = secretserver_host = ldap://127.0.0.1:389search_base = ou=people,dc=example,dc=comdomain = example.comquery_filter = (&(mail=%s)(mailEnabled=TRUE))result_attribute = mail - ldap_virtual_aliases.cf –> LDAP query to get aliases and forwarding addresses (mail forwarding can be achieved by putting the external address into the “email” field in the LDAP-Account and copying the main address from the “mail” field into a “mailAlias” field.)
12345678bind = yesbind_dn = uid=postfix,ou=services,dc=example,dc=combind_pw = secretserver_host = ldap://127.0.0.1:389search_base = ou=people,dc=example,dc=comdomain = example.comquery_filter = (&(mailAlias=%s)(mailEnabled=TRUE))result_attribute = mail, email - identitycheck.pcre –> Regular expression to block clients that use your hostname
12345# Identity (RegEx) Action/^(mail\.example\.com)$/ REJECT Hostname Abuse: $1/^(1\.2\.3\.4)$/ REJECT Hostname Abuse: $1/^(\[1\.2\.3\.4\])$/ REJECT Hostname Abuse: $1 - drop.cidr –> Contains blacklisted IP addresses
123# IP/CIDR Action1.2.3.0/24 REJECT Blacklisted
Since Dovecot and TLS are not configured yet, temporarily comment out the following lines in main.cf:
- dovecot_destination_recipient_limit = 1
- smtpd_tls_security_level = may
- smtpd_tls_auth_only = yes
- smtpd_tls_CAfile = /etc/postfix/certs/example-cacert.pem
- smtpd_tls_cert_file = /etc/postfix/certs/mail_public_cert.pem
- smtpd_tls_key_file = /etc/postfix/certs/mail_private_key.pem
3. Hashmap Creation
Certain maps (i.e. hashmaps) need to be converted to .db files before they can be used by Postfix. In main.cf the virtual_domains file is called as a hashmap, so it needs to be converted:
1 |
postmap hash:/etc/postfix/virtual_domains |
4. Starting Postfix
Start Postfix with the following command: service postfix start
Check if it is running: lsof -Pni :25
Have a look at /var/log/mail.log to see if there are any errors.
5. SMTP Connection Test
Use Telnet to connect to the SMTP server: telnet 127.0.0.1 25. When you are connected, send an EHLO client. You should get the following response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. 220 mail.example.com ESMTP Postfix (Ubuntu) EHLO client 250-mail.example.com 250-PIPELINING 250-SIZE 10240000 250-ETRN 250-AUTH DIGEST-MD5 NTLM CRAM-MD5 LOGIN PLAIN 250-AUTH=DIGEST-MD5 NTLM CRAM-MD5 LOGIN PLAIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN QUIT 221 2.0.0 Bye |
6. LDAP Lookup Test
With this test you can find out if Postfix is able to query the LDAP server:
1 2 |
postmap -q alice@example.com ldap:/etc/postfix/ldap_virtual_recipients.cf postmap -q postmaster@example.com ldap:/etc/postfix/ldap_virtual_aliases.cf |
Both of the above commands should return “alice@example.com”, because …
- there is an LDAP entry with “mail = alice@example.com”, so it is a valid recipient and
- there is an LDAP entry with “mailAlias = postmaster@example.com”, which is an alias address for “alice@example.com”.
7. Useful Commands
Config-related:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Show all Postfix parameters and their effective values postconf # Show value for the given parameter postconf smtpd_tls_security_level # Show all parameters that have been explicitly set in main.cf postconf -n # Show all default values postconf -d # Show default value of the given parameter postconf -d alias_maps |
Queue-related:
1 2 3 4 5 6 7 8 9 10 11 |
# Show mails that are currently queued postqueue -p # Flush the queue (try to send) postqueue -f # Delete a mail from the queue (ids can be found in mail.log) postsuper -d <id> # Delete all mails from the queue postsuper -d ALL |
Dovecot
1. Installation
Install Dovecot and the necessary extensions. During installation, you will be asked if a certificate should be created. If you skip this, you can add your own certificate later.
1 |
apt-get install dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-ldap |
2. Configuration
Disable unwanted protocols (IMAPS and POP3S) by setting the ports to 0 in /etc/dovecot/conf.d/10-master.conf. Also, set the permissions, user and group for the authentication-userdb:
1 2 3 4 5 |
inet_listener imaps { port = 0 #port = 993 #ssl = yes } |
1 2 3 4 5 |
inet_listener pop3s { port = 0 #port = 995 #ssl = yes } |
1 2 3 4 5 |
unix_listener auth-userdb { mode = 0600 user = vmail group = vmail } |
Define the desired authentication mechanisms in /etc/dovecot/conf.d/10-auth.conf, disable system-based authentication and enable LDAP-based authentication instead:
1 2 3 |
auth_mechanisms = plain login #!include auth-system.conf.ext !include auth-ldap.conf.ext |
Set the LDAP-related parameters in /etc/dovecot/dovecot-ldap.conf.ext:
1 2 3 4 5 6 7 8 9 10 |
hosts = 127.0.0.1 dn = uid=dovecot,ou=services,dc=example,dc=com dnpass = secret ldap_version = 3 base = ou=people,dc=example,dc=com user_attrs = mailHomeDirectory=home,mailUidNumber=uid,mailGidNumber=gid,mailStorageDirectory=mail user_filter = (&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n)) pass_attrs = uniqueIdentifier=user,userPassword=password pass_filter = (&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n)) default_pass_scheme = CRYPT |
Activate logging in /etc/dovecot/conf.d/10-logging.conf:
1 2 3 |
log_path = syslog syslog_facility = mail auth_debug = yes |
Set the path to your certificates in /etc/dovecot/conf.d/10-ssl.conf:
1 2 |
ssl_cert = </etc/dovecot/mail_public_cert.pem ssl_key = </etc/dovecot/private/mail_private_key.pem |
Add a system user and group named vmail with uid and gid 5000:
1 2 |
addgroup --system --gid 5000 vmail adduser --system --home /srv/vmail --uid 5000 --gid 5000 --disabled-password --disabled-login vmail |
Make sure that /srv/vmail has been created.
4. Starting Dovecot
Start Dovecot with service dovecot start and check if it is running with lsof -Pni — port 110 and 143 should be open. If it isn’t running, check the logfiles (mail.log and syslog). If there are no errors in the log, start Dovecot in foreground mode to have the errors printed to the console: dovecot -F.
5. IMAP Connection & Authentication Test
Use Telnet to connect to Dovecot’s IMAP Server: telnet 127.0.0.1 143. Then send a login request ( 1 login alice@example.com secret) to see if authentication (plain) is working:
1 2 3 4 5 6 7 8 |
Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS AUTH=PLAIN AUTH=LOGIN] Dovecot (Ubuntu) ready. 1 login alice@example.com secret 1 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE] Logged in 2 logout * BYE Logging out |
6. Postfix Integration
Activate Dovecot Deliver in Postfix by adding these lines to /etc/postfix/master.cf:
1 2 |
dovecot unix - n n - - pipe flags=ODRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -e -f ${sender} -d ${recipient} |
Set the postmaster address in /etc/dovecot/conf.d/15-lda.conf:
1 |
postmaster_address = postmaster@example.com |
Restart Dovecot and Postfix:
1 2 |
service dovecot restart service postfix restart |
7. Dovecot Deliver Test
Send a testmail to alice@example.com using one of the following methods:
1 |
echo Testmail | sendmail -f bob@example.com alice@example.com |
1 |
swaks --from bob@example.com --to alice@example.com --server 127.0.0.1:25 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
telnet 127.0.0.1 25 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 mail.example.com ESMTP Postfix (Ubuntu) EHLO test.local 250-mail.example.com 250-PIPELINING 250-SIZE 10240000 250-ETRN 250-AUTH DIGEST-MD5 NTLM CRAM-MD5 LOGIN PLAIN 250-AUTH=DIGEST-MD5 NTLM CRAM-MD5 LOGIN PLAIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN MAIL FROM:<bob@example.com> 250 2.1.0 Ok RCPT TO:<alice@example.com> 250 2.1.5 Ok DATA 354 End data with <CR><LF>.<CR><LF> Testmail . 250 2.0.0 Ok: queued as 51586A1146 QUIT 221 2.0.0 Bye |
Check the log (/var/log/mail.log) and Alice’s mailbox: mutt -f /srv/vmail/alice@example.com/Maildir/
SASL (Cyrus)
1. Installation
1 |
apt-get install libsasl2-2 sasl2-bin |
2. Configuration
Create an “smtpd.conf” in /etc/postfix/sasl/ with the following content:
1 2 3 |
log_level: 3 pwcheck_method: saslauthd mech_list: PLAIN LOGIN |
Enable autostart, set the mechanism to LDAP and set the options for a chrooted Postfix in /etc/default/saslauthd:
1 2 3 |
START=yes MECHANISMS="ldap" OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd" |
Create the LDAP configuration for SASL in /etc/saslauthd.conf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
ldap_servers: ldap://127.0.0.1/ ldap_bind_dn: uid=saslauthd,ou=services,dc=example,dc=com ldap_bind_pw: secret ldap_timeout: 10 ldap_time_limit: 10 ldap_scope: sub ldap_search_base: ou=people,dc=example,dc=com ldap_auth_method: bind ldap_filter: (&(uniqueIdentifier=%u)(mailEnabled=TRUE)) ldap_debug: 0 ldap_verbose: off ldap_ssl: no ldap_starttls: no ldap_referrals: yes |
Set permissions for the config file:
1 2 |
chown root:sasl /etc/saslauthd.conf chmod 640 /etc/saslauthd.conf |
Add the postfix user to the sasl group: adduser postfix sasl
And start the daemon: service saslauthd start
3. SASL Authentication Test
Use the following command to test if SASL is working:
1 |
testsaslauthd -u alice -p secret -f /var/spool/postfix/var/run/saslauthd/mux |
It should return 0: OK “Success.”
4. SMTP Authentication Test
To test if SASL works with SMTP, we first need the username and password in Base64 format. Use this command to convert it (@ needs to be escaped with a backslash):
1 2 |
perl -MMIME::Base64 -e 'print encode_base64("alice\@example.com");' perl -MMIME::Base64 -e 'print encode_base64("secret");' |
Open up a Telnet session, send an EHLO test.local, followed by an AUTH LOGIN. The server will ask for the username by sending “334 VXNlcm5hbWU6”. Just paste your encoded username now. Then the server will ask for the password (“334 UGFzc3dvcmQ6”):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
telnet localhost 25 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 mail.example.com ESMTP Postfix (Ubuntu) EHLO test.local 250-mail.example.com 250-PIPELINING 250-SIZE 10240000 250-ETRN 250-STARTTLS 250-AUTH PLAIN LOGIN 250-AUTH=PLAIN LOGIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN AUTH LOGIN 334 VXNlcm5hbWU6 YWxpY2VAZXhhbXBsZS5jb20= 334 UGFzc3dvcmQ6 c2VjcmV0 235 2.7.0 Authentication successful QUIT 221 2.0.0 Bye |
If everything went well, the server should return 235 2.7.0 Authentication successful. If it did not work, check /var/log/auth.log for any errors. If that file doesn’t help, activate extended logging in the SMTP server by adding a “-v” to the smtpd command in master.cf:
1 |
smtp inet n - - - - smtpd -v |
5. Comfortably Send Test Mails (with Authentication)
1 |
swaks --from alice@example.com --to bob@example.com --server 127.0.0.1:25 --auth plain --auth-user=alice@example.com |
TLS (Postfix)
With the current configuration, the mail server only offers plaintext (and login) authentication. This is good, because all clients support this and the passwords can be stored encrypted in the LDAP. Other authentication methods would require storing the passwords in plaintext. To make the authentication process secure (and not have the passwords trasferred in plaintext) the session needs to be encrypted — this is done with TLS.
1. Certificate Files & Permissions
Save your certificate and key files in /etc/postfix/certs (see main.cf for filenames). Also save the Diffie-Hellman files (for perfect forward secrecy) in this folder. These can be created as follows:
1 2 |
openssl dhparam -2 -out dh_512.pem 512 openssl dhparam -2 -out dh_1024.pem 1024 |
Set the permissions to:
1 2 |
chown -R root:root /etc/postfix/certs/ chmod -R 600 /etc/postfix/certs/ |
2. Activate TLS
In main.cf uncomment the six parameters that have been commented out in step 2 of the Postfix chapter, restart Postfix and check the log for any errors. If everything went well, the server should no longer offer AUTH PLAIN LOGIN, but STARTTLS instead. You can check this by looking at the EHLO response (see step 5 of the Postfix chapter).
3. TLS Test
With the following command you can connect to the server using STARTTLS:
1 |
openssl s_client -CAfile certs/example-cacert.pem -starttls smtp -connect localhost:25 |
Then you can talk to the server like in a Telnet session, but do not type a capital “R” since this will trigger a Renegotiation. If you want to send a mail, use “rcpt to:” instead of “RCPT TO:”.
This also works from external hosts (just change the -connect value to your mail server name). The -CAfile parameter is optional and can be omitted for a quick test.
Roundcube
1. Installation
Download the Roundcube archive (v1.0.1 at this time) from http://roundcube.net/download/ and extract it to your webroot (/var/www/html on Ubuntu 14.04, /var/www on previous versions). See the INSTALL file for installation instructions. These are the essential steps:
Install the necessary software:
1 |
apt-get install apache2 php5 mysql-server php5-mysql php5-mcrypt php5-intl php-pear php5-ldap |
Set permissions of the webdir:
1 2 3 4 |
cd /var/www/html chown -R root:www-data roundcube chmod -R 750 roundcube chmod -R 720 roundcube/temp roundcube/logs |
Configure your timezone in /etc/php5/apache2/php.ini:
1 |
date.timezone = Europe/Berlin |
Activate mcrypt:
1 2 |
php5enmod mcrypt service apache2 restart |
2. Database Setup
Connect to the database:
1 |
mysql -u root -p |
Create a database for Roundcube:
1 2 3 |
CREATE DATABASE roundcubemail CHARACTER SET utf8 COLLATE utf8_general_ci; GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost IDENTIFIED BY 'password'; QUIT; |
3. Config File Creation
Open Firefox and go to http://127.0.0.1/roundcube/installer to start the Roundcube installer, which will perform some system checks, initialize the database and create a config file for you. Two notes:
- Set tls://localhost as smtp_server
- Check “Use the current IMAP username and password for SMTP authentication”
Save the generated config file to /var/www/html/roundcube/config/config.inc.php and set the permissions like above. You might have to call the installer again to get the “Initialize Database” option.
Delete (or chmod -R 000) the installer directory.
Add the Override option for the Roundcube directory in /etc/apache2/sites-enabled/000-default.conf so that its .htaccess file will be loaded (this will also deactivate Indexes):
1 2 3 |
<Directory /var/www/html/roundcube> AllowOverride All </Directory> |
4. Roundcube Test
Go to http://127.0.0.1/roundcube and try to log in as “alice@example.com” with password “secret”.
Before any real users log in, HTTPS should be enabled on the webserver!
5. Enable The Password Change Plugin
Add it to the plugin array in /var/www/html/roundcube/config/config.inc.php:
1 |
$config['plugins'] = array('password'); |
Copy the necessary options from /var/www/html/roundcube/plugins/password/config.inc.php.dist to /var/www/html/roundcube/config/config.inc.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// Password Plugin options // ----------------------- $config['password_driver'] = 'ldap_simple'; $config['password_confirm_current'] = true; $config['password_minimum_length'] = 6; $config['password_require_nonalpha'] = false; $config['password_log'] = false; $config['password_login_exceptions'] = null; $config['password_hosts'] = null; $config['password_force_save'] = false; // LDAP and LDAP_SIMPLE Driver options // ----------------------------------- $config['password_ldap_host'] = '127.0.0.1'; $config['password_ldap_port'] = '389'; $config['password_ldap_starttls'] = false; $config['password_ldap_version'] = '3'; $config['password_ldap_basedn'] = 'dc=example,dc=com'; $config['password_ldap_method'] = 'user'; $config['password_ldap_searchDN'] = 'uid=roundcube,ou=services,dc=example,dc=com'; $config['password_ldap_searchPW'] = 'secret'; $config['password_ldap_search_base'] = 'ou=people,dc=example,dc=com'; $config['password_ldap_search_filter'] = '(uniqueIdentifier=%name)'; $config['password_ldap_encodage'] = 'crypt'; $config['password_ldap_pwattr'] = 'userPassword'; $config['password_ldap_force_replace'] = true; |
Users should now be able to change their LDAP password in the Roundcube Settings.
Closing Words
This was an attempt to create an as short as possible mailserver howto. It only addresses the most essential parts. Depending on your environment things might have to be different, though.
Please consider: in this howto LDAP and Apache communication is completely unencrypted. On a real server you should do something about that! Also, don’t forget to keep your private keys and password files safe by chown- and chmod-ing them properly!
Files and folders containing passwords:
- /etc/postfix/ldap_virtual_aliases.cf
- /etc/postfix/ldap_virtual_recipients.cf
- /etc/dovecot/dovecot-ldap.conf.ext
- /etc/saslauthd.conf
- /var/www/html/roundcube/config/config.inc.php
Folders containing private keys:
- /etc/postfix/certs
- /etc/dovecot/private
- /etc/ssl/private (possibly for your Apache key)
Hello,
Thanks for this very detailed tutorial. I was looking for one up to date for Ubuntu for a while.
However, I’m stuck at the IMAP log in step. I followed every step carefully, I think.
Here the logs:
In ldap
Oct 27 17:17:50 ldap slapd[4656]: conn=1011 op=1 SRCH base=”ou=people,dc=,dc=fr” scope=2 deref=0 filter=”(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=clement))”
Oct 27 17:17:50 ldap slapd[4656]: conn=1011 op=1 SRCH attr=uniqueIdentifier userPassword
Oct 27 17:17:50 ldap slapd[4656]: <= bdb_equality_candidates: (uniqueIdentifier) not indexed
Oct 27 17:17:50 ldap slapd[4656]: conn=1011 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
In dovecot
Oct 27 17:16:15 mail dovecot: auth: Debug: client in: AUTH#0111#011PLAIN#011service=imap#011secured#011session=ZTaZ2WkGKQB/AAAB#011lip=127.0.0.1#011rip=127.0.0.1#011lport=143#011rport=48425#011resp=
Oct 27 17:16:15 mail dovecot: auth: Debug: ldap(clement@.fr,127.0.0.1,): pass search: base=ou=people,dc=,dc=fr scope=subtree filter=(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=clement)) fields=uniqueIdentifier,userPassword
Oct 27 17:16:15 mail dovecot: auth: Debug: ldap(clement@.fr,127.0.0.1,): result: uniqueIdentifier=clement; uniqueIdentifier unused
Oct 27 17:16:15 mail dovecot: auth: Debug: auth(clement@.fr,127.0.0.1,): username changed clement@.fr -> clement
Oct 27 17:16:15 mail dovecot: auth: Debug: ldap(clement,127.0.0.1,): result: uniqueIdentifier=clement; userPassword missing
Oct 27 17:16:15 mail dovecot: auth: ldap(clement,127.0.0.1,): No password returned (and no nopassword)
Oct 27 17:16:17 mail dovecot: auth: Debug: client passdb out: FAIL#0111#011user=clement
Is someone has a clue about what’s wrong?
Thank you 🙂
Hi, in your log it says “ou=people,dc=,dc=fr”. Did you remove the domain name on purpose or does it really look like that in the log?
I removed the domain on purpose.
Ok 😉 Can you post the content of your /etc/dovecot/dovecot-ldap.conf.ext file?
Sure. I removed all commented lines and change the domain and dnspass variable :
hosts = 192.168.1.12
dn = uid=dovecot,ou=services,dc=mydomain,dc=fr
dnpass = mypassword
ldap_version = 3
base = ou=people,dc=mydomain,dc=fr
user_attrs = mailHomeDirectory=home,mailUidNumber=uid,mailGidNumber=gid,mailStorageDirectory=mail
user_filter = (&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))
pass_attrs = uniqueIdentifier=user,userPassword=password
pass_filter = (&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))
default_pass_scheme = CRYPT
Well, that config file looks fine, but for some reason the query doesn’t return the password. I checked my logs and it also says “uniqueIdentifier unused” so that doesn’t seem to be a problem.
In your LDAP, the “userPassword”-attribute for the account “uniqueIdentifier=clement,ou=people,dc=yourdomain,dc=fr” is existent and set?
What’s the result for this manual query?
ldapsearch -x -W -D uid=dovecot,ou=services,dc=yourdomain,dc=fr -b ou=people,dc=yourdomain,dc=fr -LLL ‘uniqueIdentifier=clement’
Yes, it’s set with a value {ssha}n…..
# ldapsearch -x -W -D uid=dovecot,ou=services,dc=mydomain,dc=fr -b ou=people,dc=mydomain,dc=fr -LLL ‘uniqueIdentifier=clement’
Enter LDAP Password:
dn: uniqueIdentifier=clement,ou=people,dc=mydomain,dc=fr
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: PostfixBookMailAccount
objectClass: extensibleObject
cn: Clement
givenName: Clement
mail: clement@…
mailEnabled: TRUE
mailGidNumber: 5000
mailHomeDirectory: /home/clement
mailQuota: 0
mailStorageDirectory: maildir:/home/clement/Maildir
mailUidNumber: 5000
uniqueIdentifier: clement
sn: Clement
mailAlias: postmaster@…
//edited by admin: real domain name changed to ‘mydomain’
The userPassword is missing in that result, which means that the problem is within your LDAP configuration / ACL (olcAccess)
Thank you! Actually, I had two problems. First I configured the ACL, then, I tried to use a remote disk connected with sshfs (not a good idea ^^).
So I followed the rest of the tutorial until the TLS part (included). But I can’t send emails although it works if I send an email to the same domain. I configured thunderbird with starttls on port 25.
Nov 1 18:33:55 mail postfix/smtpd[811]: connect from myclient.tld[192.168.1.1]
Nov 1 18:33:55 mail postfix/smtpd[811]: NOQUEUE: reject: RCPT from myclient.tld[192.168.1.1]: 554 5.7.1 : Relay access denied; from= to= proto=ESMTP helo=
Nov 1 18:34:00 mail postfix/smtpd[811]: disconnect from myclient.tld[192.168.1.1]
Do I need to enable something in postfix?
Relay access denied means that you’re not allowed to send mail. Maybe SMTP authentication didn’t work? Are the two tests in the SASL chapter successful?
Yes, it was. But now, I can’t connect with telnet (but I think it’s the normal behavior):
# telnet localhost 25
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.
220 mail.forumanalogue.fr ESMTP Postfix (Ubuntu)
ehlo client
250-mail.mydomain.fr
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
Now with tls:
% openssl s_client -starttls smtp -connect mail.mydomain.fr:25
[…]
—
250 DSN
ehlo client
250-mail.mydomain.fr
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth login
334 VXNlcm5hbWU6
Y2xlbWVudEBmb3J1bWFuYWxvZ3VlLmZy
334 UGFzc3dvcmQ6
Q2xlbWVudDAx
DONE
%
I think I found what’s wrong in my configuration. It’s the parameter reject_unauth_destination in smtpd_recipient_restrictions. If I understood, it forbids to send email to another domain.
‘reject_unauth_destination’ prevents the mailserver from being an open relay, so I think it is better to keep that parameter. Clients that do not authenticate will only be able to send mail to your domain. ‘permit_sasl_authenticated’ ensures that authenticated clients will be able to send mail to any domain.
I probably miss something because since there is ‘reject_unauth_destination’, I can’t send email to other domains.
As for the last log you posted: It is correct, that the server doesn’t offer authentication when you connect with Telnet. Authentication is only offered when the connection is established using TLS, so that part seems to be fine.
It still looks like a SASL problem to me. If you do an “AUTH LOGIN” and enter your base64 encoded credentials, does the server repsond with “DONE”? I think it should respond with “Authentication successful” – unless it has been changed in newer versions..
Thanks for a great tutorial.
Could you tell me what modifications I would need to make to this setup if I wanted to connect from say a Thunderbird (Windows) or K9 (Android) client?
There are no modifications necessary. It should be possible to connect with any email client. SMTP port is 25, IMAP port is 143 and POP3 port is 110. Authentication method is PLAIN and TLS needs to be checked.
it’s possible use more than one virtual user mapping, for example ldap and mysql at same time????
I don’t know, sorry.
Excellent howto – very grateful for your effort – saved a lot of time here. HINTS: For anyone attemting RHEL/CentOS setup, may require remove ‘MECH=pam’ and replace with MECH=ldap in /etc/sysconfig/saslauthd – Also note CentOS path to socketdir is /var/run/saslauthd and may require edit/modify the smtpd_sasl_path ‘smtpd_sasl_path = private/auth’ in main.cf
Hi, I am getting the exact same no password error with Clement. However when I do:
ldapsearch -x -W -D uid=dovecot,ou=services,dc=mydomain,dc=com -b ou=people,dc=mydomain,dc=com -LLL ‘uniqueIdentifier=jon.saral’
It says, Bad search filter (-7). My output from ldapsearch -x -W -D cn=admin,dc=mydomain,dc=com -b dc=mydomain,dc=com -LLL
is:
dn: dc=mydomain,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: mydomain
dc: mydomain
dn: cn=admin,dc=mydomain,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: passwordhashed
dn: ou=people,dc=mydomain,dc=com
objectClass: organizationalUnit
objectClass: top
ou: people
dn: ou=services,dc=procekts,dc=com
objectClass: organizationalUnit
objectClass: top
ou: services
dn: uid=postfix,ou=services,dc=procekts,dc=com
objectClass: account
objectClass: simpleSecurityObject
objectClass: top
uid: postfix
userPassword:: hashedpassword
dn: uid=dovecot,ou=services,dc=mydomain,dc=com
objectClass: account
objectClass: simpleSecurityObject
objectClass: top
uid: dovecot
userPassword:: hashedpswd
dn: uid=saslauthd,ou=services,dc=mydomain,dc=com
objectClass: account
objectClass: simpleSecurityObject
objectClass: top
uid: saslauthd
userPassword:: hashed password
dn: uid=roundcube,ou=services,dc=mydomain,dc=com
objectClass: account
objectClass: simpleSecurityObject
objectClass: top
uid: roundcube
userPassword:: hashed password
dn: uniqueIdentifier=jon.saral,ou=people,dc=mydomain,dc=com
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: PostfixBookMailAccount
objectClass: extensibleObject
cn: Jon Saral
givenName: Jon
mail: jon.saral@procekts.com
mailAlias: postmaster@procekts.com
mailEnabled: TRUE
mailGidNumber: 5000
mailHomeDirectory: /srv/vmail/jon.saral@procekts.com
mailQuota: 10240
mailStorageDirectory: maildir:/srv/vmail/jon.saral@procekts.com/Maildir
mailUidNumber: 5000
sn: Saral
uniqueIdentifier: jon.saral
userPassword:: hashed password
I would appreciate any help. Thanks!
The bad search filter error is probably due to wrong quotation marks. This blog unfortunately converts these to typographical quotation marks, so if you copy and paste from here, you have to remove and re-type the quotation marks.
THX for the great tutorial!
is it possible to create virtual adresses for users to receive emails in their default postbox?
Example: The default address gunnar@example also receives postmaster@example.de emails.
Thanks.
Yes, that’s already implemented in this solution. See main.cf and ldap_virtual_aliases.cf in chapter [Postfix -> 2. Configuration]. In chapter [LDAP] see the first screenshot (alice will also receive messages for postmaster and abuse).
Hi,
first of all thanks for a great tutorial!
I was having Clément’s problem too and I fixed it moving ‘reject_unauth_destination’ line under ‘permit_sasl_authenticated’ one.
Hope it helps.
Hello! Thanks you for this excellent tutorial. It’s really helping me out. But I’ve got stuck when loging in dovecot:
root@mail-server:~# telnet localhost 143
Trying ::1…
Connected to localhost.
Escape character is ‘^]’.
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
1 login test2@alex.com test2
1 NO [UNAVAILABLE] Temporary authentication failure. [mail-server:2014-12-29 13:13:50]
Then I checked the log…
Error: ldap(test2@alex.com,::1,): ldap_search(base= filter=(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=test2))) failed: No such object
…
auth-worker(11792): pam(test2@alex.com,::1): pam_authenticate() failed: Authentication failure (password mismatch?)
So I thought it may be because dovecot’s user at LDAP has no rights to view user passwords, but this is how my slapd.conf looks like (according to dovecot-ldap.conf.ext, access to passwords by dovecot must be enabled in order to check them):
…
access to attrs=userPassword,shadowLastChange
by dn=”@ADMIN@” write
by dn=”uid=dovecot,ou=services,dc=mydomain,dc=com” read
by anonymous auth
by self write
by * none
…
And still not works.
Mail users in my LDAP are in an OU named mail-users; all of them looks like the ones you create in this tutorial (I used postfix book schema).
I tried to create RootDN cn=config with your other howto but I can’t connect; it says invalid credentials.
I hope you can help me.
Thanks you.
Hi & sry for the delayed answer. Try to run the following command (with your corresponding data):
ldapsearch -x -W -D uid=dovecot,ou=services,dc=example,dc=com -b ou=people,dc=example,dc=com -LLL uniqueIdentifier=alice
It should return all information of the user including the encrypted password. If that doesn’t work, check if the contents of the following files are correct:
/etc/dovecot/conf.d/10-auth.conf
/etc/dovecot/dovecot-ldap.conf.ext
Thanks for your excellent tutorial. This is one of the few that cover ldap integration.
However, since I’m a complete noob on ldap, I am struggeling with creating ACLs for the postfix,dovecot,roundcube and saslauthd users. I understand that these user need at least read access to the ou=people subtree to find users, but I have no idea how to add this to the LDAP configuration.
Thanks again,
Wim
Hello,
Please ignore my previous message regarding the ldap configuration. I solved it by using your ldap tutorial.
I am installing on a Fedora 21 machine (just for testing purposes), and I had to make a slight modification to the ldap_virtual_recipients.cf and ldap_virtual_aliases.cf files. I had to add the line: ‘version = 3’. Otherwise I would get a protocol error.
The SASL bit is still a bit unclear to me. I got it working by using dovecot for authentication by using the line ‘smtpd_sasl_type=dovecot’. It is quite clearly described in the postfix manual.
Anyway, thanks again for this guide. It has been fun configuring this. Before long I will do an install on a FreeBSD machine based on my current test environment.
Regards,
Wim
Hello Wim, glad that you figured it out. And thanks for the feedback!
Gracias, todo me salio perfecto.
Hi, thanks for this great tutorial.
I am facing a issue with ldap while running following command:
# postmap -v -q testuser1@mydomain.com ldap:/etc/postfix/ldap_virtual_recipients.cf
postmap: name_mask: ipv4
postmap: inet_addr_comal: configured 2 IPv4 addresses
postmap: dict_ldap_open: Using LDAP source /etc/postfix/ldap_virtual_recipients.cf
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: server_host = ldap://ldap.mydomain.com:389
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: server_port = 389
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: version = 2
postmap: dict_ldap_open: /etc/postfix/ldap_virtual_recipients.cf server_host URL is ldap://ldap.mydomain.com:389
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: scope = sub
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: search_base = ou=Users,dc=mydomain,dc=com
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: timeout = 10
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: query_filter = (&(mail=%s)(mailEnabled=TRUE))
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: result_format =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: result_filter = %s
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: domain = mydomain.com
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: terminal_result_attribute =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: leaf_result_attribute =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: result_attribute = mail
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: special_result_attribute =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: bind = yes
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: bind_dn = uid=postfix,ou=Services,dc=mydomain,dc=com
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: bind_pw = postfix
postmap: cfg_get_bool: /etc/postfix/ldap_virtual_recipients.cf: cache = off
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: cache_expiry = -1
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: cache_size = -1
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: recursion_limit = 1000
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: expansion_limit = 0
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: size_limit = 0
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: dereference = 0
postmap: cfg_get_bool: /etc/postfix/ldap_virtual_recipients.cf: chase_referrals = off
postmap: cfg_get_bool: /etc/postfix/ldap_virtual_recipients.cf: start_tls = off
postmap: cfg_get_bool: /etc/postfix/ldap_virtual_recipients.cf: tls_require_cert = off
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: tls_ca_cert_file =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: tls_ca_cert_dir =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: tls_cert =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: tls_key =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: tls_random_file =
postmap: cfg_get_str: /etc/postfix/ldap_virtual_recipients.cf: tls_cipher_suite =
postmap: cfg_get_int: /etc/postfix/ldap_virtual_recipients.cf: debuglevel = 0
postmap: dict_open: ldap:/etc/postfix/ldap_virtual_recipients.cf
postmap: dict_ldap_lookup: In dict_ldap_lookup
postmap: match_string: mydomain.com ~? mydomain.com
postmap: dict_ldap_lookup: No existing connection for LDAP source /etc/postfix/ldap_virtual_recipients.cf, reopening
postmap: dict_ldap_connect: Connecting to server ldap://ldap.mydomain.com:389
postmap: dict_ldap_connect: Actual Protocol version used is 2.
postmap: dict_ldap_connect: Binding to server ldap://ldap.mydomain.com:389 with dn uid=postfix,ou=Services,dc=mydomain,dc=com
postmap: warning: dict_ldap_connect: Unable to bind to server ldap://ldap.mydomain.com:389 with dn uid=postfix,ou=Services,dc=mydomain,dc=com: 2 (Protocol error)
postmap: fatal: table ldap:/etc/postfix/ldap_virtual_recipients.cf: query error: Success
Could you please tell me if I need to configure anything in ldap.
Thanks
Hello,
Thanks a lot for this awesome tutorial! It was very helpfull 😀
I was wondering if it is possible to make a Multi domain setup with this configuration.
I’m guessing if i’d add another domain to LDAP (same content as your example) and add the new search criteria in the config files it should work.
Am I right, or am I missing something here?
Thanks in advance
Regards,
André
@Tim:
The problem might be that protocol version 2 is used instead of 3. Check /etc/dovecot/dovecot-ldap.conf.ext and make sure to add ldap_version = 3.
@Andre:
It might work like that, but I can’t tell since I haven’t tried it.
Very Good Tutorial!
I’ve applied on CentOS 7 setup successfully with minimal modification!
Thanks you!
Thanks for the feedback @ bernardi
I ran into a problem in the step SASL under ubuntu 12. The testsaslauth command worked, that is accepted valid logins and rejected invalid usernames and/or passwords. However trying to connect to smtp with telnet just froze the telnet client, trying to send a test email would connect but then freeze. The error log showed the following “SASL: per-process initialization failed”. After I executed “apt-get install libsasl2-modules-ldap” everything worked as intended. I don’t really understand why. “testsaslauth” obviously did perform ldap queries even without that additional module, otherwise it could not distinguish valid from invalid credentials. It seems that in order for the postfix-sasl-ldap integration to work however the sasl-ldap module is required. Since the sasl test-command worked it didn’t even occur to me for a long time that a required module could be missing. I thought I note that here to maybe safe other people some time. I should point out that I use virtualmin which preconfigures the mailing-system and might have modified the mail-settings in a way that caused that issue.
Great starter tutorial. One of the only one’s I’ve seen that actually work 🙂
Thanks !
Thanks a lot for the tutorial! It’s awesome, saved me a lot of time.
Regarding the email forwarding: I would like to keep a copy in the original address to. Is this possible? Which changes to the Postfix configuration should be done? I’ve been searching but I couldn’t find any tutorial that works for me, so I wondered if someone here could help.
Thanks,
F.
I can’t test this right now, but aren’t emails sent to both addresses, the original one and the forward address?
Email forwarding is only described very briefly in my howto (section “Postfix”, “2. Configuration”, “ldap_virtual_aliases.cf”). In the LDAP account of a user the original email address must also be saved to a “mailAlias” field, which will result in “ldap_virtual_aliases.cf” being executed if the server receives an email for the user. The forwarding address must be saved to an “email” field. Since the result_attribute in the .cf file is set to mail,email the server should send the email to the original address (mail) and the forward address (email). At least that how I thought it would work 😉
:pleeeeeeeeeease when Use Telnet to connect to Dovecot’s IMAP Server: telnet 127.0.0.1 143. Then send a login request ( 1 login alice@example.com secret) to see if authentication (plain) is working I got athantication failed and when I look /var/log/mail.log I got password mismatch?
In that case I’d try to re-set the password of alice in LDAP. See my LDAP guide (chapter 12c) on how to do that.
Hi admin, I will further test email forwarding and I will let you know if I find out something.
However, I have a more important problem first…:
Sending and receiving emails from @mydomain addresses to @mydomain addresses works (I tested it from roundcube, thunderbird and using swaks). Also, I can send emails from a @gmail account to @mydomain and they are correctly delivered.
However, when I try to send from @mydomain to another domain such as @gmail.com, I get a Relay access denied error.
I checked the logs and there seems to be a problem in the postfix checks:
—————-
…
Dec 28 11:14:21 postfix/smtpd[25707]: START Helo command RESTRICTIONS
Dec 28 11:14:21 postfix/smtpd[25707]: generic_checks: name=permit_mynetworks
Dec 28 11:14:21 postfix/smtpd[25707]: permit_mynetworks: mydomain.net 127.0.0.1
Dec 28 11:14:21 postfix/smtpd[25707]: match_hostname: mydomain.net ~? 127.0.0.0/8
Dec 28 11:14:21 postfix/smtpd[25707]: match_hostaddr: 127.0.0.1 ~? 127.0.0.0/8
Dec 28 11:14:21 postfix/smtpd[25707]: match_list_match: permit_mynetworks: no match
Dec 28 11:14:21 postfix/smtpd[25707]: generic_checks: name=permit_mynetworks status=1
Dec 28 11:14:21 postfix/smtpd[25707]: END Helo command RESTRICTIONS
…
Dec 28 11:14:21 postfix/smtpd[25707]: START Recipient address RESTRICTIONS
Dec 28 11:14:21 postfix/smtpd[25707]: generic_checks: name=permit_mynetworks
Dec 28 11:14:21 postfix/smtpd[25707]: permit_mynetworks: mydomain.net 127.0.0.1
Dec 28 11:14:21 postfix/smtpd[25707]: match_hostname: mydomain.net ~? 127.0.0.0/8
Dec 28 11:14:21 postfix/smtpd[25707]: match_hostaddr: 127.0.0.1 ~? 127.0.0.0/8
Dec 28 11:14:21 postfix/smtpd[25707]: match_list_match: permit_mynetworks: no match
Dec 28 11:14:21 postfix/smtpd[25707]: generic_checks: name=permit_mynetworks status=1
Dec 28 11:14:21 postfix/smtpd[25707]: END Recipient address RESTRICTIONS
…
—————-
The rest of the generic_checks give status=0 (which I assume is successful), and authentication doesn’t seem to be the issue:
Dec 28 11:14:21 postfix/smtpd[25707]: xsasl_cyrus_server_first: decoded initial response
Dec 28 11:14:21 postfix/smtpd[25707]: mydomain.net[127.0.0.1]: 235 2.7.0 Authentication successful
Dec 28 11:14:21 postfix/smtpd[25707]: < mydomain.net[127.0.0.1]: MAIL FROM:
My /etc/postfix/main.cf config file, the value of mynetworks is:
mynetworks = 127.0.0.0/8
and the restrictions parameters are exactly as in the tutorial.
Also, my /etc/hosts file:
127.0.0.1 mydomain.net mydomain alias1 alias2
I don’t understand what is happening, and why I can’t relay messages to other domains… Does someone have a clue?
Thanks a lot,
F.
Yes, you were right about the email forwarding. If I want both original address and forwarding address to receive a copy of the email, I must set:
– email field: forwarding address and original address
– mailAlias: original address
Thanks a lot! 🙂
F.
Since permit_mynetworks doesn’t seem to work (I’m not sure about the reason) you can’t relay without authentication. Roundcube however should do SMTP authentication. What happens if you use Roundcube to send an email to an @gmail address?
My bad… I should have read ALL the previous comments in the first place.
The problem was the order of the smtpd_recipient_restrictions: reject_unauth_destination should always be AFTER permit_mynetworks and permit_sasl_authenticated. So the correct configuration in the /etc/postfix/main.cf should be:
—————-
# Recipient Restrictions (RCPT TO related)
smtpd_recipient_restrictions =
reject_non_fqdn_recipient
reject_unknown_recipient_domain
# Allow relaying for SASL authenticated clients and trusted hosts/networks
# This can be put to smtpd_relay_restrictions in Postfix 2.10 and later
permit_sasl_authenticated
permit_mynetworks
reject_unauth_destination
# Reject the following hosts
check_sender_ns_access cidr:/etc/postfix/drop.cidr
check_sender_mx_access cidr:/etc/postfix/drop.cidr
# Additional blacklist
reject_rbl_client ix.dnsbl.manitu.net
# Finally permit (relaying still requires SASL auth)
permit
—————-
🙂
That makes sense. With reject_unauth_destination before permit_sasl_authenticated and permit_mynetworks the mail got rejected before you even had the chance to authenticate.
Actually this was my bad since I didn’t update the config file after ßingen posted the solution :-/ Thanks for the reminder and thanks to ßingen for the original comment. I have updated it now.
I have also changed the final permit to reject since it turned out that it was possible to send emails to local addresses without authentication using telnet.
Is there a way to extend the great tutotial working with multiple domains?
Thank you!
/Btw: Had to change the final reject back to permit, because the server stopped to receive emails from external addresses.
@Gunnar: Sry, I can’t try that since I don’t have an opportunity to test that kind of setup.
hi,
when i try login mathias@mydomain.com i have NO [AUTHENTICATIONFAILED] Authentication failed.
Hi, just a dumb question but how to create the certs such as mail_public_cert.pem, etc…
Thanks for this very nice tutoriel…
Hi, to create and sign own certificates, a certification authority needs to be set up. This can be done manually on command-line or with a graphical tool like TinyCA. This might help: http://acidx.net/wordpress/2012/09/creating-a-certification-authority-and-a-server-certificate-on-ubuntu/
Thank you for very good tutorial,,,
This saves lot of time of my life
Hi!
How with this setup would someone configure a Mailman+Postfix so that newly created mailing lists accept emails?
Imagine I created a new mailing list newlist@domain.com, how can I integrate the new aliase newlist so that emails are received and sent to mailman?
Sorry if the question goes too much out of the scope of this tutorial. I would also appreciate some references/links.
Cheers!
I’m having the same issue that mathi-b is. I have followed the rest of the steps and can run the “3. SASL Authentication Test” works fine, but I’m not able to login in via Imap or roundcube.
Is it possible to use ldap uid and gid for mail folders instead of the system vmail account
For my version of dovecot (Debian Jessie) I needed to add ‘auth_bind = yes’ to
/etc/dovecot/dovecot-ldap.conf.ext
Hello,
Thank you very much for this great tutorial.
I am able to send e-mail to my gmail account.
But I am not receiving an e-mail from my gmail account to my virtual e-mail address.
I don’t receive an error response from Gmail.
The log below shows the message was received from Gmail and delivered to my Maildir box apparently, but I don’t see it on my client email software:
Below is the log I got when I refresh my client email:
Any help or tip, please?
Hello,
I solved my own issues.
It’s working fine now.
Thanks again.
Hi, I am having an issue,
I copied most of it and funnily it works even transfered to my server, however I decided to use “uid” for dovecot lookup via lda and it works fine on virtual aliases, but looking up the virtual recipient return value doesnt work.
e.g. mail = firstname.lastname@whatever.com
mailAlias = firstname@whatever.com
now when i write to the latter address it is properly translated into uid=mrfirstname and dovecot delivers, when i write to the firstname.lastname address postfix looks up uid=mrfirstname through virtual recipients (i can see the smtpd log), then logs out to use mrfirstname (firstname.lastname@whatever.com -> mrfirstname) and then ignores it and gives lda firstname.lastname which of course will fail.
My question is: Why does this happen, and what is that virtual_mailbox for then?
Should I just expand the alias filter to also look up mail=%s?
Hi, great tutorial!
I was wondering if you had any guides for how to implement starttls for ldap.
Hi, unfortunately I haven’t continued to further enhance the mail server / ldap configuration, so I’m not able to help, sry.
i have error when run testsaslauthd -> connect() : No such file or directory
can you help me?
Hi, tanks for your greate tutorial.
I’m beginner in ldap. I should install a mail server on FreeBSD. THe link for schema file doesn’t open.
Would you please send the schema content and the ldif file?
Thank you.
DG might help if you post your filters.
rian more information? Show your command line.
DG show your filters.
[…] installing-a-mailserver-with-postfix-dovecot-sasl-ldap-roundc)ube […]
wow. You solved my life. Thank you.
hope someone can help..
I go thru the guide and it fails on the testing email after I setup dovecot.
The email is bounced.
#echo helloworld | sendmail user3@domain.com user4@domain.com
Apr 13 16:40:28 domain postfix/pickup[7774]: 391EA3F514: uid=1000 from=
Apr 13 16:40:28 domain postfix/cleanup[8053]: 391EA3F514: message-id=
Apr 13 16:40:28 domain postfix/qmgr[7775]: 391EA3F514: from=, size=351, nrcpt=1 (queue active)
Apr 13 16:40:28 domain postfix/local[8056]: 391EA3F514: to=, relay=local, delay=0.05, delays=0.03/0/0/0.02, dsn=5.1.1, status=bounced (unknown user: “user5”)
Apr 13 16:40:28 domain postfix/cleanup[8053]: 417B244B56: message-id=
Apr 13 16:40:28 domain postfix/qmgr[7775]: 417B244B56: from=, size=2100, nrcpt=1 (queue active)
Apr 13 16:40:28 domain postfix/bounce[8057]: 391EA3F514: sender non-delivery notification: 417B244B56
Apr 13 16:40:28 domain postfix/qmgr[7775]: 391EA3F514: removed
Apr 13 16:40:28 domain postfix/local[8056]: 417B244B56: to=, relay=local, delay=0.02, delays=0.01/0/0/0.01, dsn=2.0.0, status=sent (delivered to mailbox)
Apr 13 16:40:28 domain postfix/qmgr[7775]: 417B244B56: removed
i have already test postfix can talk with ldap.
#ldapsearch -x -W -D cn=admin,dc=domain,dc=com -b dc=domain,dc=com -LLL uniqueIdentifier=user4
user4@domain.com
can anyone give a hint to troubleshoot?
Your Postfix is not configured correctly. It looks like your virtual LDAP DB mapping is messed up. Check your Postfix files containing your LDAP table configuration for mailboxes, aliases, etc
http://www.postfix.org/ldap_table.5.html
Derrick,
you tested LDAP with user4 and the postfix msg says “unknown user: user5” 🙂
I bet that there is no user5 in the LDAP