Nginx mail proxy module - unexpected behavior re: authentication

Naresh V nareshov at gmail.com
Wed Mar 24 13:45:18 MSK 2010


On 24 March 2010 15:38, Maxim Dounin <mdounin at mdounin.ru> wrote:
> Hello!
>
> On Wed, Mar 24, 2010 at 12:45:13PM +0530, Naresh V wrote:
>
>> I have a setup with me where I'm using nginx to talk to a redirector
>> (embedded perl script) which redirects IMAP/POP communication to the
>> appropriate IMAP/POP server based on a simple DB query that says "this
>> user's emails are on that IMAP server".
>> I'm not doing any authentication at this level since according to
>> this[1] request-timeline diagram, the authentication request/response
>> is done again with the actual IMAP server anyway.
>>
>> When my IMAP client is trying to authenticate with legitimate username
>> and password, nginx - as expected according to the diagram - delegates
>> the ". login username at domain password" to the real IMAP server whose
>> ". OK" is relayed back to the IMAP client by nginx.
>> The problem I'm facing right now is when I provide the wrong password,
>> IMAP server returns AUTHENTICATIONFAILED, but nginx thinks it's an
>> invalid response and cuts off the session with the IMAP client.
>>
>> In nginx error log:
>>
>> > 2010/03/23 14:43:53 [info] 12550#0: *29 upstream sent invalid response: "* BAD internal server error" while reading response from upstream, client: xx.xx.xx.xx, server: 0.0.0.0:143, login: "username at domain", upstream: yy.yy.yy.yy:143
>
> Well, you didn't check password as auth_http was expected to do,
> and this resulted in nginx complaining about internal error.
> Looks like expected behaviour for me.

True. It was my mistake. I should've checked everything again. The
"which IMAP server should this user be redirected to" check was
failing because, unbeknownst to me, the DB where this query was
running was modified (which I wasn't aware of and wasn't expecting).

Previously, I was getting:

2010/03/24 10:26:03 [info] 13356#0: *14 upstream sent invalid
response: "NO [AUTHENTICATIONFAILED] Authentication failed."
while reading response from upstream, client: xx.xx.xx.xx, server:
0.0.0.0:143, login: "user at domain", ups
tream: yy.yy.yy.yy:143


>> an example telnet session:
>>
>> [root at nginx ~]# telnet localhost 143
>> Trying 127.0.0.1...
>> Connected to 127.0.0.1.
>> Escape character is '^]'.
>> * OK IMAP4 ready
>> + login username at domain wrongpassword
>> * BAD internal server error
>> Connection closed by foreign host.
>> [root at nginx ~]#
>>
>> The behaviour I expect is:
>>
>> [root at nginx ~]# telnet localhost 143
>> Trying 127.0.0.1...
>> Connected to 127.0.0.1.
>> Escape character is '^]'.
>> * OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE
>> AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
>> + login username at domain wrongpassword
>> + NO [AUTHENTICATIONFAILED] Authentication failed.
>> <telnet session doesn't close>
>>
>> How do I go about configuring nginx to support this?
>> 'proxy_pass_error_message on' didn't help.
>> Where exactly do I look in the source to make the appropriate changes?
>
> In the scenario you suggest nginx does 2 "internal requests" to
> authenticate user: the one to find out it's backend and one to
> check it's password.  As username client will use after failed
> authentication isn't known it has to close backend connection
> anyway on failed authentication.

Yep, with the present architecture I think that's to be expected.

( http://nginx.org/pipermail/nginx/attachments/20090905/685e1310/attachment.png
)

> Moreover, in this mode it would be trivial to find out valid
> usernames via timing attack (even if you make sure that messages
> returned by auth_http and backend match).

True. Also, this way nginx wouldn't hold open connections for too long
if this is the redirect imap-proxy for _many_ backend imapds.
The telnet session with nginx closes on providing the wrong password
after passing the right error message to me. Which seems like a good
thing.

> Not even talking about the fact that in this scenario you won't be
> able to use CRAM-MD5/APOP authentication at all.
>
> I believe checking password in auth_http is fairy trivial and this
> is what should be done instead of an attempt to change the way how
> it works.

Since this problem I came here with is solved for now, I'll stick to
not doing any authentication at all at the nginx level for now.

Thanks a lot!

-Naresh



More information about the nginx mailing list