Implementing Upstream SMTP Authentication for Postfix
From RedWall
Contents |
Summary
Postfix, SASL and TLS are all big topics, but these few notes should get most people to where they want to be if they'd like to deliver their mail from a redWall host through their ISP's SMTP server - or *have* to do so for some reason.
About this Howto
More and more remote mail sites are starting to block mail being sent directly from what are considered "Dynamic IP Addresses" (see http://www.dnsbl.org for details), resulting in an inability to reliably send mail directly from many home-based firwalls.
redWall, as of v0.5.5 has support for SASL and TLS built into Postfix, and adding only a few lines to Postfix's main configuration file (main.cf) will allow you to authenticate to your upstream ISP's SMTP server to deliver all your mail.
By default, the SMTP AUTH process initiated by Postfix on the redWall host and going to your ISP's SMTP server will submit your credentials in clear- text. Most ISP's offer the ability to create subordinate email addresses, so if you're willing to submit the id and password credentials of one of those throw- away addresses in clear-text over the Internet, the Postfix configuration is three lines long, and a one-line hash file.
If, on the other hand, you'd like to submit those credentials over TLS, that's also possible, but it's a slightly larger task.
SMTP AUTH in Clear-Text
Postfix needs to know who your upstream relayhost is. In the /etc/postfix/main.cf file look for the "relayhost = " line and enter the hostname of your ISP's SMTP server:
relayhost = smtp.myisp.com
Postfix needs to know how to behave as a SASL client. Add the following lines anywhere you'd like (I put them at the end), again in the /etc/postfix/main.cf file:
smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/saslpw smtp_sasl_security_options =
The first two lines are likely self-explanatory, but the last line left empty is used to support PLAINTEXT passwords - which is *not* SASL's default. If this line were to be left out, you'd likely see a message similar to the following in your /var/log/maillog file:
"Authentication failed: cannot SASL authenticate to server"
You now need to create the Postfix "saslpw" file and hash it. The format of the saslpw file is:
host id:pw
The host portion above must match what you used in the "relayhost" line in main.cf. Something as follows:
smtp.myisp.com myid:mypw
Save the file, and generate the Postfix hash on it:
[root@redwall /etc/postfix] postmap saslpw
Once you restart Postfix, send a test message through it, and you should see a line in /var/log/maillog similar to:
to=< jsmith@example.com >, relay=smtp.myisp.com[1.2.3.4], delay=1, status=sent (250 ok 1234567891 qp 12345)
The header of the received message should include some indicator from your ISP's mail server that the message was submitted with the credentials listed in your saslpw file.
SMTP AUTH over TLS
Considering redWall's role in life, it doesn't seem a terribly bright idea to have an application on it submit valid ISP email credentials in clear-text over the Internet. A much nicer way to submit your credentials to an upstream SMTP server would be do so over an SSL-based connection. redWall v0.5.5 supports this setup by following some basic steps:
Generating OpenSSL Client Cert and copying CA Cert file
I keep all my TLS-related files in /etc/postfix/tls - - you can select whatever write-able directory you'd like.
You first of all need a client cert for the TLS session. This cert needs to be generated without a password. I generated my client cert with:
[root@redwall /etc/postfix/tls] openssl req -new -x509 -nodes -out smtp-client.pem -keyout smtp-client.pem -days 10000
You will also need a CA file in order to know which server certificates to trust. I use the generic CA bundle file supplied by a full OpenSSL install - which on a full-blown Linux distro is usually in /usr/share/ssl/certs in a file called ca-bundle.crt. I copy that file to /etc/postfix/tls and rename it to CAcert.pem.
Setting Postfix to use TLS-based sessions
There are some relatively easy steps you can take to enable the smtpd process on a redWall firewall to enable and accept TLS and/or smtps sessions with clients, but all I'm detailing right here is how to enable Postfix as an SMTP client to use TLS to other SMTP servers - namely your ISP's.
First we enable the SMTP client in Postfix to use TLS:
smtp_use_tls = yes
Then we point Postfix to the client cert we generated above:
smtp_tls_cert_file = /etc/postfix/tls/smtp-client.pem smtp_tls_key_file = $smtp_tls_cert_file
We also point it to the CA file so we know which server certs to trust:
smtp_tls_CAfile = /etc/postfix/tls/CAcert.pem
As noted above in the "SMTP AUTH in Clear Text" section, SASL by default does not allow PLAINTEXT authentication, and we therefore have two more SASL Postfix options to set in order to allow PLAINTEXT authentication when making TLS-based SMTP connections:
smtp_sasl_tls_security_options = $smtp_sasl_security_options smtp_sasl_tls_verified_security_options = $smtp_sasl_security_options
The TLS code in Postfix requires a certain amount of entropy which both the SMTP client and SMTPd server processes use. There are therefore a series of directives specific to that purpose. The Pseudo-Random Number Generator is fed by an external source, the most readily available one on a standard Linux host is: /dev/urandom. I have added the following lines to my main.cf file for the PRNG requirement, and the lines I have commented out simply list those directives' default values:
tls_random_source = dev:/dev/urandom # tls_random_bytes = 32 # tls_random_reseed_period = 3600s # tls_random_upd_period = 60s
Based on how Postfix and AMaViSd work together, you cannot *force* TLS-based SMTP conversations globally within Postfix, so I like to enable the LogLevel of the SMTP TLS code to show me when it has negotiated a TLS- based session with a server.
smtp_tls_loglevel = 2
This will result in lines similar to the following in your /var/log/maillog file whenever a TLS-based session to another SMTP server has occurred:
Apr 8 16:30:00 myhost postfix/smtp[14934]: starting TLS engine Apr 8 16:30:01 myhost postfix/smtp[14934]: CD767FCE5: to=< jsmith@example.com>, relay=smtp.myisp.com[1.2.3.4], delay=1, status=sent (250 ok 1112995865 qp 30349)
If you have a setup where you want to enforce TLS-only SMTP sessions with all remote mail servers, you can tell Postfix to do so with:
smtp_enforce_tls = yes
You can if you'd like, configure Postfix to force TLS-based SMTP conversations only with specific hosts. This is done quite easily in our circumstance where we relay *all* our upstream mail through one host. Postfix's "nexthop" for mail delivery will *always* be your ISP's SMTP server, unless the mail is inbound and destined for the redWall host itself, or some other internal mail server - and it's up to you if you'd like to enforce TLS-based SMTP conversations to those mail servers or not.
I myself deliver upstream mail via TLS and deliver inbound mail with no SMTP AUTH.
The Postfix directive to enable this per-site functionality is:
smtp_tls_per_site = hash:/etc/postfix/tls/tls_sites
That Postfix hash file will likely contain something similar to below:
internal-mailserver.mydomain.com NONE smtp.myisp.com MUST_NOPEERMATCH
Your choices for the right-hand side are:
- NONE - don't bother making any TLS attempt
- MAY - attempt a STARTTLS, but still continue if not
- MUST - force STARTTLS and validate that the FQDN of the host matches the CommonName in the server cert
- MUST_NOPEERMATCH - force STARTTLS but continue if the FQDN of the host doesn't match the CommonName value in the server's cert
Run a postmap on that file:
[root@redwall /etc/postfix/tls] postmap tls_sites
then restart Postfix, and Postfix should now know with whom to make a TLS SMTP connection, and those hosts about which it needn't care.

