SMTP AUTH with XCLIENT - impossible or just difficult?

Karl Kraft karl at karlkraft.com
Wed Aug 4 17:02:29 MSD 2010


I have been successful at using nginx as a front end to POP and IMAP servers to keep mailboxes spread across multiple machines.   It also provided the added benefit of enabling SSL for privacy. I wrote a custom HTTP based authentication agent to direct to the proper mailbox, and everything seems to work great. Now I would like to do the same for SMTP connections, using nginx as both an SSL front end and director to my SMTP daemons.

However, after implementing XCLIENT in the SMTP daemon, and adding a simple configuration to nginx, all is not well. After working my way through the mailing list and trying several configurations, I am left thinking that XCLIENT with authentication simply does not work.  Has anyone ever managed to get this to work?

Very simple sample configuration:

....
smtp_auth plain cram-md5;

server {
listen     10.10.10.104:1466;
server_name veyron.karlkraft.com;
protocol   smtp;
proxy      on;
}
....

This is an example of a session:

CN - client to nginx
NC  - nginx to client
NS - nginx to smtp server
SN - smtp server to nginx


NC: 220 veyron.karlkraft.com ESMTP ready
CN: EHLO client.karlkraft.com
NC: 250 AUTH PLAIN CRAM-MD5
CN: AUTH PLAIN xxxxxxxxxxxxxxxxxxxxxxx

At this point, nginx contacts the authentication agent over HTTP, and is told to contact explorer on port 1125 as the actual SMTP back end daemon.    Once the connection is successful, it passes back the 235 code for passing authentication:

NS: [Connects to back end SMTP server]

NC: 235 2.0.0 OK

And then nginx proceeds to negotiate with the back end server:

SN: 220 explorer.karlkraft.com. - explorer.karlkraft.com (NFSmtp/2006q2.1) Authorized network 10.10.0.0/255.255.0.0
NS: EHLO veyron.karlkraft.com
SN: 250-/10.10.10.104
SN: 250-EXPN
SN: 250-NAME ADDR PROTO HELO
SN: 250-SIZE
SN: 250-AUTH CRAM-MD5 PLAIN
SN: 250 HELP

nginx then sends the XCLIENT command.  The back end server needs the information in order to be able to provide the proper routing and QOS based on the login, as well as performing SPF and DNSBL checks against the original IP.

NS: XCLIENT ADDR=10.10.10.2 LOGIN=karl at karlkraft.com NAME=[UNAVAILABLE]
SN: 220 Authenticated via XCLIENT

And here is where it all falls apart, because the response to XCLIENT is then passed back to the original client, which confuses the client because it hand't sent any commands yet. 

NC: 220 Authenticated via XCLIENT

Nginx then sends the second EHLO to the server:

NS: EHLO client

The server then responds, and nginx forwards all this response to the original client as well, leaving the client even more confused:

SN: 250-/10.10.10.104
SN: 250-EXPN
SN: 250-NAME ADDR PROTO HELO
SN: 250-SIZE
SN: 250-AUTH CRAM-MD5 PLAIN
SN: 250 HELP

NC: 250-/10.10.10.104
NC: 250-EXPN
NC: 250-NAME ADDR PROTO HELO
NC: 250-SIZE
NC: 250-AUTH CRAM-MD5 PLAIN
NC: 250 HELP

Since the client has no idea about XCLIENT and the second EHLO, it is horribly confused. The session from the clients perspective looks like this:

NC: 220 veyron.karlkraft.com ESMTP ready
CN: EHLO client.karlkraft.com
NC: 250 AUTH PLAIN CRAM-MD5
CN: AUTH PLAIN xxxxxxxxxxxxxxxxxxxxxxx
NC: 235 2.0.0 OK
NC: 220 Authenticated via XCLIENT
NC: 250-/10.10.10.104
NC: 250-EXPN
NC: 250-NAME ADDR PROTO HELO
NC: 250-SIZE
NC: 250-AUTH CRAM-MD5 PLAIN
NC: 250 HELP


The only way I am able to get close to a working connection is with the following two conditions:

Turn XCLIENT off - this of course makes it impossible for the back end server to know the authenticated username or source IP address. 

Client must send HELO instead of EHLO - controlling all the clients is out of the question.

--
Karl Kraft



More information about the nginx mailing list