Nginx mail proxy module - unexpected behavior re: authentication

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

On 24 March 2010 15:38, Maxim Dounin <mdounin at> 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:, 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:, login: "user at domain", ups
tream: yy.yy.yy.yy:143

>> an example telnet session:
>> [root at nginx ~]# telnet localhost 143
>> Trying
>> Connected to
>> 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
>> Connected to
>> Escape character is '^]'.
>> 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.


> 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

> 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!


More information about the nginx mailing list