TLS (formerly SSL) stands for Transport Layer Security. Once this layer is established, it encrypts the communication between two hosts. If we use SMTP AUTH and the mechanisms PLAIN or LOGIN usernames and passwords are sent plaintext over the internet. This means that anyone could sniff the communication and read the passwords. If you don't want this - we bet you don't - you can use TLS to help.
Procedure 8. Process to SMTP AUTH using plaintext passwords and TLS
Connect to your Postfix-server
establish a TLS encrypted communication layer and
only then send our SMTP AUTH PLAIN or LOGIN
Procedure 9. Steps for integration
Check if our Postfix build supports TLS
Build the certificates that are issued when a TLS connection is being established
Add configuration parameters to Postfix main.cf that enable TLS
Advise Postfix only to SMTP AUTH when a TLS connection has successfully been established.
If you built the RPMS you may wonder why we check for TLS support. This section also applies for NON-RPM configuration and people that might just jump in on this HOWTO. Anyway it's a good exercise. You'll find out how to query binaries for the libraries they support.
In our HOWTO the smtpd daemon is in /usr/libexec/postfix/. So we do the following at the command line:
[root@example.com]# ldd /usr/libexec/postfix/smtpd libsasl.so.7 => /usr/lib/libsasl.so.7 (0x4001e000) libssl.so.2 => /lib/libssl.so.2 (0x4002a000) libcrypto.so.2 => /lib/libcrypto.so.2 (0x40057000) libdb-3.2.so => /lib/libdb-3.2.so (0x4011a000) libnsl.so.1 => /lib/libnsl.so.1 (0x401c1000) libresolv.so.2 => /lib/libresolv.so.2 (0x401d7000) libgdbm.so.2 => /usr/lib/libgdbm.so.2 (0x401ea000) libc.so.6 => /lib/i686/libc.so.6 (0x401f1000) libdl.so.2 => /lib/libdl.so.2 (0x4032c000) libcrypt.so.1 => /lib/libcrypt.so.1 (0x40330000) libpam.so.0 => /lib/libpam.so.0 (0x4035d000) libgssapi_krb5.so.2 => /usr/kerberos/lib/libgssapi_krb5.so.2 (0x40365000) libkrb5.so.3 => /usr/kerberos/lib/libkrb5.so.3 (0x40378000) libk5crypto.so.3 => /usr/kerberos/lib/libk5crypto.so.3 (0x403d1000) libcom_err.so.3 => /usr/kerberos/lib/libcom_err.so.3 (0x403e2000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
The smtpd daemon supports TLS. If you cannot find the libssl in the output you either built Postfix with static libraries or building Postfix with TLS didn't work. In this case you'll have to reconfigure your Postfix SOURCE, recompile or rebuild it, backup the data in /etc/postfix/ and reinstall the newly compiled Postfix binaries.
We need a cert from a Cert-Authority that we can refer to when a client wants to validate the cert that we issued from our Postfix-server. There are two possibilities and it all boils down that “It's a matter of trust”.
If you are a private user and simply want to enjoy encrypted communication, but don't want to pay for a cert, you can become your own CA. You'll only will use it for yourself and hey who shouldn't trust yourself more that you. This HOWTO will show you how to do that.
If you will use your server for business purposes (ISP, etc.) you should go and get a valid cert for your server from an official CA. Your customers will appreciate. Meanwhile this should not keep you from reading on and building your own CA authority certificate for testing purposes.
We will need to issue a certificate when we establish the connection. This certificate is the public server.cert.
When a TLS connection is being established the host establishing the connection has to validate itself. This is because someone else could hijack the connection and establish an encrypted connection. The remote host probably wouldn't notice and pass sensible information. Therefore certificates are used to provide unique information that proves that the host encrypting the communication really is the host your client wants to talk to.
You are right when you argue that anyone even a hostile server could issue a certificate if it wasn't for that little detail we left out: Each certificate that is issued provides information about an authority that will validate the cert that is issued when an TLS connection is established. Now that you understand the concept you'll understand what we need:
![]() | Note |
|---|---|
The following information was written for RedHat 7.x users. If you run a different version or distribution your mileage may vary. | |
On RedHat machines OpenSSL has its configuration file for creating certs in /usr/share/ssl. So we go there and edit that file first as it carries the default values that will be offered to us later. You can skip this section, but don't complain when you mistype your values and must start the whole script again. ;-)
[root@example.com]# cd /usr/share/ssl/ [root@example.com]# vi openssl.cnf
edit countryName_default and 0.organizationName_default and provide values that make sense to your setting. This HOWTO will use Germany (DE) and HOWTO as values.
countryName_default = DE 0.organizationName_default = HOWTO
then uncomment organizationalUnitName_default and add a value. We will use Mail server in this HOWTO.
organizationalUnitName_default = Mailserver
add the lines commonName_default (must be the name of your Mail server!) and emailAddress_default and provide values specific to your setting. Our Mail servers hostname is mail.example.com and postmaster@example.com is in charge.
commonName_default = mail.example.com emailAddress_default = postmaster@example.com
That's it and it will save us a lot of typing as we will build not only one cert. Save the file and read on as we will have to edit yet another file.
Consider this: Usually certs are crypted. That's a good idea when you take them along with yourself and the disc you have it on gets lost. It won't be of any use to the finder unless that person also knows your secret passphrase... But then if you don't take it with you, but leave it on a server this feature can become a real problem to the availability of your service. Why?
Any time you restart the server and the server wants to get its hand on the cert, the cert wants to be given the secret passphrase and the server hangs in there waiting to pass that task on its start list. And it waits and waits and waits... until you enter the secret passphrase at the command prompt. The bottom line is: No passphrase, no service.
So we will not create certs with secret passphrases, as we will not always be available when the server needs to be restarted or starts itself, say after a power failure.
In order to have certs that aren't crypted we will have to add a parameter to the script that we run when we create a cert. So let's cd to the directory that holds the script and create a backup first before we edit it.
[root@example.com]# cd misc/ [root@example.com]# cp CA CA_nodes [root@example.com]# edit CA_nodes
![]() | Note |
|---|---|
Either it's CA or CA.pl. This depends on your RedHat distribution. Both scripts will help you generate certs. | |
Search for # create a certificate and add -nodes to the line below that begins with $REQ. When your done with this search for # create a certificate request and do the same again.
When your done it should look like this:
-newcert) # create a certificate $REQ -new -nodes -x509 -keyout newreq.pem -out newreq.pem $DAYS RET=$? echo "Certificate (and private key) is in newreq.pem" ;; -newreq) # create a certificate request $REQ -new -nodes -keyout newreq.pem -out newreq.pem $DAYS RET=$? echo "Request (and private key) is in newreq.pem" ;;
That's it for preparations. Let's create the certs.
The first cert we will create is the Authority cert. We do this by calling the CA script and telling it that we want it to create a new CA:
[root@example.com]# ./CA_nodes -newca CA certificate filename (or enter to create) MAKING CA CERTIFICATE ... Using configuration from /usr/share/ssl/openssl.cnf Generating a 1024 bit RSA private key ................++++++ ......................++++++ writing new private key to './demoCA/private/./cakey.pem' Enter PEM pass phrase: Verifying password - Enter PEM pass phrase: ----- 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) [DE]: State or Province Name (full name) [Germany]: Locality Name (eg, city) []:Munich Organization Name (eg, company) [ExampleOrganisation]: Organizational Unit Name (eg, section) [Mailserver]: Common Name (eg, your name or your server's hostname) [mail.example.com]: Email Address [postmaster@example.com]:
Then we will create the server cert request that will be signed by the CA Authority:
[root@example.com]# ./CA_nodes -newreq Using configuration from /usr/share/ssl/openssl.cnf Generating a 1024 bit RSA private key .........................++++++ .............++++++ writing new private key to 'newreq.pem' ----- 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) [DE]: State or Province Name (full name) [Germany]: Locality Name (eg, city) []:Munich Organization Name (eg, company) [ExampleOrganisation]: Organizational Unit Name (eg, section) [Mailserver]: Common Name (eg, your name or your server's hostname) [mail.example.com]: Email Address [postmaster@example.com]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:certpass An optional company name []: Request (and private key) is in newreq.pem
Finally we sign the server cert request with our own CA cert:
[root@example.com]# ./CA_nodes -sign Using configuration from /usr/share/ssl/openssl.cnf Enter PEM pass phrase: Check that the request matches the signature Signature ok The Subjects Distinguished Name is as follows countryName :PRINTABLE:'DE' stateOrProvinceName :PRINTABLE:'Germany' localityName :PRINTABLE:'Munich' organizationName :PRINTABLE:'ExampleOrganisation' organizationalUnitName:PRINTABLE:'Mailserver' commonName :PRINTABLE:'mail.example.com' emailAddress :IA5STRING:'postmaster@example.com' Certificate is to be certified until Mar 15 07:45:17 2003 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y ... Signed certificate is in newcert.pem
Abstract
Let's review what we have generated:
newreq.pem
This is the private SERVER CERT. We generated it in order to request an CA to sign it. It contains our private key.
newcert.pem
That is your public SERVER CERT. It has been signed by a CA in this case ourselves.
demoCA/cacert.pem
This is the CERT of the CA Authority. We created it when we made ourselves a CA.
We want the certs that we use for TLS support in SMTP to stick closely with our Postfix configuration files. So we copy them to the Postfix CONFIG_DIR.
[root@example.com]# cp newcert.pem /etc/postfix/ [root@example.com]# cp newreq.pem /etc/postfix/ [root@example.com]# cp demoCA/cacert.pem /etc/postfix/
We got the certs. Next we will tell Postfix where they are and that we want it to offer TLS using them.
[root@example.com]# cd /etc/postfix [root@example.com]# vi main.cf
There is no TLS configuration in the main.cf. So we start wherever we want to and add some documentation as we enter the configuration:
## TLS # Transport Layer Security # TLS-Patch by Lutz Jänicke # smtpd_use_tls = yes #smtpd_tls_auth_only = yes smtpd_tls_key_file = /etc/postfix/newreq.pem smtpd_tls_cert_file = /etc/postfix/newcert.pem smtpd_tls_CAfile = /etc/postfix/cacert.pem smtpd_tls_loglevel = 3 smtpd_tls_received_header = yes smtpd_tls_session_cache_timeout = 3600s tls_random_source = dev:/dev/urandom
There's one parameter that we leave commented out for the moment, as we want to check only if we can initiate a TLS session without 'hiding' SMTP AUTH at the moment.
![]() | Note |
|---|---|
If you want to understand what these parameters are for you might want to read Postfix/TLS - Configuring main.cf and master.cf by Lutz Jänicke the creator and maintainer of Postfix/TLS support. | |
So we're done with the configuration. We now need to reload postfix and make it reread the new configuration.
[root@example.com]# postfix reload
Next we will check if we can initiate a TLS session. We telnet to the server and check, if the string STARTTLS shows up when Postfix advertises it's capabilities. Then we simply type in STARTTLS and wait for Postfix to respond that it is ready to start TLS. This is how our successful telnet session should look like:
C: [root@example.com]# telnet mail.example.com 25 S: 220 mail.example.com ESMTP Postfix (1.1.5) C: EHLO example.com S: 250-mail.example.com S: 250-PIPELINING S: 250-SIZE 10240000 S: 250-VRFY S: 250-ETRN S: 250-STARTTLS S: 250-AUTH PLAIN LOGIN DIGEST-MD5 CRAM-MD5 GSSAPI S: 250-AUTH=PLAIN LOGIN DIGEST-MD5 CRAM-MD5 GSSAPI S: 250-XVERP S: 250 8BITMIME C: STARTTLS S: 220 Ready to start TLS
So Postfix advertises TLS and it can start a session. Time to go for the full experience and configure a mail client.
Again we will be using MS Outlook in this HOWTO. Open --> --> and switch to the tab. Then check the box that reads: Server requires secure connection.

TLS configuration: Outlook Express: Properties
That leaves us with one major step to be done. We want to make sure that SMTP AUTH PLAIN will only be available to users who use TLS. So we advise Postfix to issue the SMTP AUTH command only when TLS has been established. This brings us back to the one line we had left commented out in main.cf when we added TLS support.
[root@example.com]# vi main.cf
Search for smtpd_tls_auth_only and uncommented the line. It should read like this:
smtpd_tls_auth_only = yes
We edited main.cf, we must tell Postfix. So we reload it.
[root@example.com]# postfix reload
Now when we send messages to the server SMTP AUTH will only be offered after the TLS layer has been established. You can see that when you telnet to the server. The AUTH announcement is gone and still when you use a mail client you can relay using SMTP AUTH.
C: [root@example.com]# telnet mail.example.com 25 S: 220 mail.example.com ESMTP Postfix (1.1.5) C: EHLO example.com S: 250-mail.example.com S: 250-PIPELINING S: 250-SIZE 10240000 S: 250-VRFY S: 250-ETRN S: 250-STARTTLS S: 250-XVERP S: 250 8BITMIME C: STARTTLS S: 220 Ready to start TLS
That's it. Your done. Have fun.