Postfix certificate verify howto

Version: 0.8
Author: maxigas*anargeek.net
Update:2010.03.15

Warning: Beta version, needs peer review and further testing. It seems to work for me, nontheless.

How to connect two Postfix servers running on Debian systems to send mails between themselves through SSL with verifying the certificates that were issues by a certificate authority (here cacert.org)?

Note: you need to know basic unix commands and get around a text editor like nano / emacs / vi (I use emacs but I wrote nano in the instructions below because that is the most user friendly).

  1. Documentation:

The basis of this howto is the postfix and cacert IRC channels, Postfix documentation, forums and lists. Special thanks to Dan.

  1. Check DNS records:

MX records have to be set, for example mail.example1.org mail.example2.org

  1. Install and configure postfix:
apt-get install postfix
nano /etc/postfix/main.cf

Follow Basic Configuration guide of the Postfix documentation.

Send mail from test@example1.org to test@example2.org, and vica versa. Save mail headers for future reference. The certificate part is similar to this:

Received: from example1.org
(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
(No client certificate requested)
  1. Get certificates from cacert.org:
cd ~
wget http://svn.cacert.org/CAcert/Software/CSRGenerator/csr
sh csr

It will ask you a few questions. Here is one example for configuring mail.example1.org:

Private Key and Certificate Signing Request Generator
This script was designed to suit the request format needed by
the CAcert Certificate Authority. www.CAcert.org
Short Hostname (ie. imap big_srv www2): example1
FQDN/CommonName (ie. www.example1.tld) : example1.tld
Type SubjectAltNames for the certificate, one per line. Enter a blank line to finish
SubjectAltName: DNS:mail.example1.org
SubjectAltName: DNS:
Running OpenSSL...
Generating a 2048 bit RSA private key
........................................................+++
................................................+++
writing new private key to '/root/example1_privatekey.pem'
-----
Copy the following Certificate Request and paste into CAcert website to obtain a Certificate.
When you receive your certificate, you 'should' name it something like example1_server.pem
-----BEGIN CERTIFICATE REQUEST-----
MIIDBjCCAe4CAQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQClsXcoj86dyYlIe96khbZqYtyV03ak+teyClv5
80I46irKcYQx4CFiirTCuusiAwsDfnDyZvnrwoxaUkc5nkw4Tlmb1j/y91U8rusX
Zu43rep8s0zs7aMx/q34TTCc5Mru8UQjbnj9aCX1DF+8cA0ayQMm1BOFv8nTFcjK
SnI5NdxRKDyqeH3KUgfxgGkBVU4VFVRU9XKD/zprzj+hWFT+fsjF7yQm0ZXDXaJ+
0Yr9mDQjfzdLP3GObc7y7rwz8a5ozATwfpqZiWYjM34oKFPSj7kwLdA+otx0glGG
e+P7G/E2uE+lbzi41CSFgKAjw3E0l1x47NoVD6DADS5mYIatAgMBAAGggaowgacG
CSqGSIb3DQEJDjGBmTCBljCBkwYDVR0RBIGLMIGIggtleGFtcGxlLm9yZ4IPd3d3
LmV4YW1wbGUub3Jngg9mb28uZXhhbXBsZS5vcmeCE3d3dy5mb28uZXhhbXBsZS5v
cmeCD2Jhci5leGFtcGxlLm9yZ4ITd3d3LmJhci5leGFtcGxlLm9yZ4ILZXhhbXBs
ZS5iYXKCD3d3dy5leGFtcGxlLmJhcjANBgkqhkiG9w0BAQQFAAOCAQEAHFiUDgVc
lDGoq+2kLmQxKtYagc37sugw4OoutILxrXF0zJUSplF4Aco/KhBcSLQUpsW5u11Q
tcxj4DqXrxsoZuawATKTGQXDaAxL/ud2FsXyhe2FC1h0id2cH12GsnDSziuFCM+t
rz05dqnW6mZR5OHILlYPoIPNqk3tbkIyOs4GplL9PZLNjSKJ3oeXJXn1iSI6oegB
dBJQMByDZsh7Xd/d1OFJMQq3TFMqmLEXErkXQnOmzBN375AHGYGZwozhVPjhfFZ1
74AvmxOe17+OLm1j10EA9J/5jLzIgK0vs7HgK0131S/JAV4Ik9JccAWByGlxeuVb
4Kf5vAucZZVe7g==
-----END CERTIFICATE REQUEST-----
The Certificate request is also available in /root/example1_csr.pem
The Private Key is stored in /root/example1_privatekey.pem
-----BEGIN CERTIFICATE REQUEST-----
MIIDBjCCAe4CAQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQClsXcoj86dyYlIe96khbZqYtyV03ak+teyClv5
80I46irKcYQx4CFiirTCuusiAwsDfnDyZvnrwoxaUkc5nkw4Tlmb1j/y91U8rusX
Zu43rep8s0zs7aMx/q34TTCc5Mru8UQjbnj9aCX1DF+8cA0ayQMm1BOFv8nTFcjK
SnI5NdxRKDyqeH3KUgfxgGkBVU4VFVRU9XKD/zprzj+hWFT+fsjF7yQm0ZXDXaJ+
0Yr9mDQjfzdLP3GObc7y7rwz8a5ozATwfpqZiWYjM34oKFPSj7kwLdA+otx0glGG
e+P7G/E2uE+lbzi41CSFgKAjw3E0l1x47NoVD6DADS5mYIatAgMBAAGggaowgacG
CSqGSIb3DQEJDjGBmTCBljCBkwYDVR0RBIGLMIGIggtleGFtcGxlLm9yZ4IPd3d3
LmV4YW1wbGUub3Jngg9mb28uZXhhbXBsZS5vcmeCE3d3dy5mb28uZXhhbXBsZS5v
cmeCD2Jhci5leGFtcGxlLm9yZ4ITd3d3LmJhci5leGFtcGxlLm9yZ4ILZXhhbXBs
ZS5iYXKCD3d3dy5leGFtcGxlLmJhcjANBgkqhkiG9w0BAQQFAAOCAQEAHFiUDgVc
lDGoq+2kLmQxKtYagc37sugw4OoutILxrXF0zJUSplF4Aco/KhBcSLQUpsW5u11Q
tcxj4DqXrxsoZuawATKTGQXDaAxL/ud2FsXyhe2FC1h0id2cH12GsnDSziuFCM+t
rz05dqnW6mZR5OHILlYPoIPNqk3tbkIyOs4GplL9PZLNjSKJ3oeXJXn1iSI6oegB
dBJQMByDZsh7Xd/d1OFJMQq3TFMqmLEXErkXQnOmzBN375AHGYGZwozhVPjhfFZ1
74AvmxOe17+OLm1j10EA9J/5jLzIgK0vs7HgK0131S/JAV4Ik9JccAWByGlxeuVb
4Kf5vAucZZVe7g==
-----END CERTIFICATE REQUEST-----
nano ~/example1_server.pem
  1. Put the certificates in some suitable directories:
cp -v ~/example1_privatekey.pem /etc/ssl/private/
cp -v ~/example1_server.pem /etc/ssl/certs/

Of course there are other options as well, some are even better than this, but for me that worked fine.

  1. Install CAcert root certificate:
apt-get install ca-certificates
  1. Configure Postfix:

Trying to create a certificate authority verified SMTP connection between two servers of course means that you have to configure both servers. If you want them both to send and receive mail from each other then the configuration is symmetric, so only one is described here, but don't forget to configure both servers. The snippets below refer to the configuration of server example1 to exchange mails with server example2.:

nano /etc/postfix/main.cf
  1. Add section for TLS configuration:
### Transport Layer Security ###

# Server side TLS
smtpd_tls_security_level = may
smtpd_tls_key_file = /etc/ssl/private/example1_privatekey.pem
smtpd_tls_cert_file = /etc/ssl/certs/example1_server.pem
smtpd_tls_CAfile = /usr/share/ca-certificates/cacert.org/root.crt
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
smtpd_tls_ask_ccert = yes

# Client side TLS
smtp_tls_security_level = may
smtp_tls_key_file = $smtpd_tls_key_file
smtp_tls_cert_file = $smtpd_tls_cert_file
smtp_tls_CAfile = $smtpd_tls_CAfile

# Misc TLS
tls_random_source = dev:/dev/urandom
  1. Create a policy map. Policy maps only work in Postfix 2.2 and above, so check version:
postconf | grep version

Lower versions use another system, check the Postfix documentation or rather update your software base!

Create / edit a file with the policy and hash it for quicker processing:

echo "example2.tld verify" >> /etc/postfix/tls_policy
echo ".example2.tld verify" >> /etc/postfix/tls_policy
postmap /etc/postfix/tls_policy

Run postmap on the file each time you edit it. Add the policy map to the postfix configuration:

echo "smtp_tls_policy_maps = hash:/etc/postfix/tls_policy" >> /etc/postfix/main.cf

Now reload the postfix configuration:

/etc/init.d/postfix reload
  1. Test configuration:
openssl s_client -connect mail.example1.hu:25 -starttls smtp | openssl x509 -noout -text
openssl s_client -connect mail.example2.hu:25 -starttls smtp | openssl x509 -noout -text

These commands are useful for debugging, for example to see what certificates the servers offer (if any).

Finally, try to send a mail from test@example1.org to test@example2.org. Headers should have similar:

Received: from example1.org
(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
(Client CN "example1.org", Issuer "CA Cert Signing Authority" (verified OK))

Note: only the hops between the two servers should have these lines.

  1. Debug Postfix configuration:

Send mail from test@example1.org to test@example2.org and vica versa:

tail -f /var/log/mail.log

Not sure if it is a simple TLS problem or a certificate problem? Temporarily change "verify" to "encrypt" in your policy map, rehash, reload and try again:

rpl verify encrypt /etc/postfix/tls_policy
postmap /etc/postfix/tls_policy
/etc/init.d/postfix reload

Now the certificate verification is turned off and you can test your configuration without it.

PostFixVerify (last edited 2010-03-12 06:21:20 by maxigas)