While stalking the Internet I have stumbled upon this handy script that collects info about your SASL installation and SMTP auth configuration and display it – I almost haven't used it but it looked pretty nice so I thought I'd share it with you.
It needs bash to run (on my FreeBSD 8 it wasn't installed by default, you can get it from /usr/ports/shells/bash/.
First of all let's remember a strange-sounding config option of Postfix' main.cf file which we saw yesterday when setting it up: it's mynetworks_style. Until today I didn't realy realize what it was for and why have «trusted» and «strangers» when receiving incoming mail. I didn't care and set it to subnet (as it was by default) and everything worked fine.
However, today's morning I got lazy and attempted to send an e-mail using my cell phone – and got a familiar Relay access denied message. Why?
I powered up my brain (not the easiest thing in the morning :P) and remembered that I read something like this in the Postfix' main config file:
The mynetworks parameter specifies the list of «trusted» SMTP clients that have more privileges than «strangers».
In particular, «trusted» SMTP clients are allowed to relay mail through Postfix. See the smtpd_recipient_restrictions parameter in postconf(5).
Than a thought struck me: why, there's actually a difference for Postfix if I'm sending
mails from my home PC (that's inside my server's network) or from anything else? How I'm
supposed to give accounts to other users who are outside my network? List every existing
mail host in the work in relay_domains or all my users in mynetworks? Then what
about their dynamic IPs?
I actually had a hunch like that yesterday but I didn't really believe that it makes senseto restrict sending mail from within host's subnet only.
Then I thought of an easy hack like mynetworks = 0.0.0.0/32 but at this point my mind
finally sobered up and I exclaimed: «Aha!».
Well, the idea seems to be really easy: we can't let anyone use our host to leavecorrespondence to be sent somewhere else – from our machine, usnig our CPU, domain name,
IP and everything else. Spammers would be happy but we probably won't.
«But what's the deal? We can access IMAP, we're authorized already, what's the problem?» – I thought so. However, another brilliant thought struck me and I thought back:
And that was where everything has started.
In fact, if we think about this carefully then no, we're not using any auth mechanism
for SMTP – even if we have Cyrus serving us IMAP our SMTP (handled by Postfix) is gaped
widely to every one willing to use it.
With one small exception: Postfix smartly allows him to send e-mail to a very limitednumber of destinations – by default only the server itself (see relay_domains).
In fact, SMTP is so independent of IMAP or Cyrus that in theory (if we manage to avoid SASL) we can have Postfix with its own SMTP auth with no IMAP4/POP3/whatever.
Configuration process starts from the Postfix' master file – /usr/local/etc/postfix/master.cf. Here Postfix services are defined (similar to system's /etc/services). We need to enable SMTPd and at least one SMTP (I don't know why this is so but without at least one of smtp SMTPd won't start up). I've enabled both smtp's just in case.
confsmtp inet n - n - - smtpd -v
smtp inet n - n - 1 postscreen
smtpd pass - - n - - smtpd -v
The -v flag makes SMTPd run in verbose mode which certainly helps us finding our way around some glitches.
Let's proceed to Postfix' main config file – /usr/local/etc/postfix/main.cf. Append the following lines there:
confsmtpd_sasl_auth_enable = yes # 3 lines below are security/compatibility enhancements. smtpd_sasl_security_options = noanonymous broken_sasl_auth_clients = yes smtpd_sasl_authenticated_header = yes # the rest of lines control how we trust sender and recepient when they talk to us on SMTP. smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, check_relay_domains, reject_non_fqdn_recipient, reject_unauth_destination, check_policy_service inet:127.0.0.1:60000, permit smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit
After this we need to add our realm for SASL but before that let's stop for a little lesson on how SASL works with Postfix.
In a nutshell, SASL tells the calling program if a password matches user name in some specific
database and using some specific auth machanism (called «mech»). One system can have a lot of SASL
clients – even our mail host has IMAP and SMTP servers which can use different SASL user
registries and settings.
Applications that use SASL in addition to user name can also pass arealm – just like in e-mail address where
part after «@» is called domain in SASL's terminology it's called realm.
In addition to that each applciation (called service) can have its own config file.
These config files were a major mess when I was going through all the trials of setting up
SMTP auth.
Nobody seemed to know when they're located on a particular system (Linux, CentOS, FreeBSD,etc.). After some searching I found that what we need is smtpd.conf and it is supposed
to be created by Postfix or Cyrus installer in ports tree. But where?
The answer is: /usr/local/lib/sasl2/smtpd.conf. It looks trivial to me now but you can bet it wasn't just a few hours ago!
By the way, you might have faced a 2 strange groups of Postfix options: smtp_ and smtpd_ – e.g. smtpd_sasl_auth_enable. The first (without d) sets options for Postfix SMTP client – if you want you can use them to make Postfix log into remote SMTP servers when it sends mail. The second group («smtpd_») is about SMTP server – exactly what we need here.
A quick note on other interesting Postfix-SMTP-SASL options:
You can get a complete reference of Postfix options by calling
shman 5 postconf
(search in manual page browser by pressing "/" and repeat by «n»).
So with this new knowledge we create /usr/local/lib/sasl2/smtpd.conf (it probably won't exist yet) and enter the following lines:
confpwcheck_method: auxprop
auxprop_plugin: sasldb
Make sure its permissions are correct:
-r--r--r-- 1 postfix mail 137 Jan 20 12:39 /usr/local/lib/sasl2/smtpd.conf
What we've done is instructed SASL use /usr/local/etc/sasldb2.db – common registry that is also used by Cyrus' SASL. Other option would be using saslauthd which you can install from /usr/ports/security/cyrus-sasl2-saslauthd/. Running a daemon instead of giving direct access to sasldb2.db is somewhat better as a daemon runs as root while its clients have minimal rights, without access to the password DB. In our, though, case we're only using SASL for Cyrus and Postfix so it's simple, easy and relatively secure (they share the same group anyway).
Check the perms of SASL's database:
-rw-r--r-- 1 cyrus mail 16384 Jan 20 12:35 /usr/local/etc/sasldb2.db
Now we need to add a crusial config option to main.cf that tells Postfix which realm to use when talking to SASL. Determine it first:
shell$ sasldblistusers2 cyrroot@example.com: userPassword proger@example.com: userPassword
In our case the realm is my.i-forge.net. Now add it to main.cf:
smtpd_sasl_local_domain = my.i-forge.net
Okay, things seem up to normal now so we proceed to testing – but first tell Postfix
that its config has changed by doing
shpostfix reload
.
shsmtptest
is an extremely handy tool when it comes to testing SMTP server. Remember
shimtest
in previous part of this guide? This is very similar to it.
shell$ smtptest -a cyrroot localhost C: EHLO example.com S: 250-i-forge.net S: 250-PIPELINING S: 250-SIZE 10240000 S: 250-VRFY S: 250-ETRN S: 250-AUTH NTLM LOGIN PLAIN GSSAPI OTP DIGEST-MD5 CRAM-MD5 S: 250-AUTH=NTLM LOGIN PLAIN GSSAPI OTP DIGEST-MD5 CRAM-MD5 S: 250-ENHANCEDSTATUSCODES S: 250-8BITMIME S: 250 DSN Segmentation fault (core dumped)
Come on, another segfault? «Just what's wrong with this box…» – but no panic!
We have already had this issue with
shimtest
– it happens on some systems with some auth
methods – on my FreeBSD 8 it happens when smtp/imtest attempt using NTLM (it doesn't
happen if another client uses NTLM when talking to my Postfix or Cyrus, though).
So we just need to switch to another auth mech.
But first let us examine Postfix-SMTP reply.
We can pick any auth mech we see in any of the AUTH lines and call
shsmtptest
again:
shell$ smtptest -m cram-md5 -a cyrroot localhost ... Please enter your password:
That's the talk – we've got a password prompt. Proceed…
C: cHJvZ2VyIGE3NGUyNzczZGQ3YjY0YjllOWU0YTM5NmUzYjg1Y2M5 S: 235 2.7.0 Authentication successful Authenticated. Security strength factor: 0
Yahoo! Postfix let us in. Great! Exit by pressing Ctrl+D.
«Security strength factor» determines how strong the client-server connection is – the vale of 0 means it's unencrypted, 1 means integrity protection is engaged and the above stends for the encryption strength (in bits) – for example, 256 means we are behind AES-256 or similar provided via a SSL/TLS layer.
If you're getting a message like the following from SMTP:
S: 535 5.7.8 Error: authentication failed: authentication failure Authentication failed. generic failure
…then you did something wrong with SASL – see the Common glitches section.
That's all we had to do – get your favourite e-mail client and make it use some password sending mechanism it has – e.g. NTLM – and spam around as much as you want from any place on the Earth you're currently in :)
These steps are not required but will make our instalation more neat. Remember to refresh
running Postfix with
shpostfix reload
.
As you remember, Postfix has a concept of «trusted» clients which are allowed sending
mails everywhere through it. However, since we're using SMTP authrization now so we can
change «trusted» clients from all the server subnetwork to just the server machine
itself.
Do so by setting: mynetworks_style = host in /usr/local/etc/postfix/main.cf.
Also, many tutorials that I had ran over during my SMTP trial suggested restricting **SASL mechs** to just plain & login for SMTP. I don't know the reason for this (it works fine for me and Thunderbird with full set of mechs and any one of them is better than transmitting plain text password) but if you need it add this line to /usr/local/lib/sasl2/smtpd.conf:
mech_list: plain login
The first thing you need to do when running into troubles with any Postfix service – enable their verbose logging. This is done in /usr/local/etc/postfix/master.cf. Find that service's line and add -v flag (or more for more verbosity: -vv, -vvv) to its executable (specified in the last column):
smtpd pass - - n - - smtpd -v
If the service takes up several lines just add «-v» to the end of the first line. After this
call
shpostfix reload
and produce some activity using
shsmtptest
while checking
/var/log/maillog for new lines – SMTPd produces a lot of debug messages in this mode.
Tip: you can make all log messages be sent to one file (/var/log/all.log) so it's more convenient to see then with one extra terminal by uncommenting (or adding) the following line to /etc/syslog.conf:
conf*.* /var/log/all.log
After this create log file by touching it and setting proper perms:
shell$ touch /var/log/all.log $ chmod 0600 /var/log/all.log
Don't forget to restart syslogd by doing
shkillall -HUP syslogd
.
You can then watch all appearing log messages using tail (-f makes it wait for new
messages and output them as they come in):
shell$ tail -100 -f /var/log/all.log
A most troublesome moment were SASL errors like these:
logJan 20 10:38:10 my postfix/smtpd[40468]: warning: localhost[127.0.0.1]: SASL LOGIN authentication failed: authentication failure Jan 20 12:38:06 my postfix/smtpd[64667]: warning: SASL authentication failure: no user in db Jan 20 13:50:27 my postfix/smtpd[2366]: warning: SASL authentication failure: no secret in database Jan 20 13:50:27 my postfix/smtpd[2366]: warning: unknown[192.168.5.4]: SASL NTLM authentication failed: authentication failure
By deducing and brainstorming I came up with the following reasons for this:
shsaslpasswd2
to manage them.
First off, check that your smtpd.conf is actually read by SASL – do this by adding
some junk text to /usr/local/lib/sasl2/smtpd.conf and tryign connecting to it via
shsmtptest
– if nothing happens (no output from server) then it's read.
Less brutal way of checking this is adding there a line like this:/usr/local/lib/sasl2/smtpd.conf:
mech_list: plain login
…and again trying connect to SMTP via smtptest – examine its output and see if line(s) starting with «S: 250-AUTH» don't ahve anything like CRAM-MD5 or NTLM:
S: 250-AUTH LOGIN PLAIN
Don't forget to do postfix reload after changing any of its configuration files.
If smtpd.conf is correctly parsed by SASL check which means it uses to verify passwords. The first thing is pwcheck_method which among other values (some of which are described here) can be of these:
sasldb will not work for Postfix SMTP authentication directly – i.e. don't specify it as pwcheck_method – SMTP server will fail with errors similar to the ones in the beginning of this section. AFAIK this happens because Postfix expects passwords to be stored in plain text form which isn't the case with sasldb.
saslauthd will work and generally needs the same configuration as auxprop.
auxprop will work too but it needs extra config options. Usually only auxprop_plugin is mandatory. It can have of 3 values:
We'll only discuss auxprop_plugin=sasldb here. Its effect is similar to pwcheck_method=sasldb but, unlike it, it will work even with Postfix – even though SASL stores encrypted passwords there. Just set this option, make sure /usr/local/etc/sasldb2.db is accessible by Postfix and everything should work.
-rw-r--r-- 1 cyrus mail 16384 Jan 20 12:35 /usr/local/etc/sasldb2.db
See also SASL_README page.
If you've followed all instructions above, read zillion of Google pages, scratched
your head and done other things – and SMTP still doesn't work – then you might be
facing the same situation that I did otday.
It's easy to resolve. Just give up.
No, seriously, I have almost given up on this thing and went shopping for foods. After returning I have
decided to give
shsmtptest
just one more try – and it worked! Out of the blue, I didn't
change anything and wasn't doing something different than an hour ago. It just worked like a
charm :)
(No, I wasn't forgetting to reload Postfix.)
So who knows – maybe it's your case as well. Just go do something for an hour and then come back to see if proto-AI self-restorable consciousness of FreeBSD has done the work for you.