Nginx as reverse proxy mail server host

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Nginx as reverse proxy mail server host

vergil
Hi,

I am trying to proxy a SMTP server on Nginx using the below configuration. I
want all the client calls to hit the SMTP server via my proxy host. I want
the SSL termination on nginx for the client calls to the SMTP Server.

When I do the connection getting below exception even before the SSL
handshake.. Please correct me if I am wrong anywhere.

Without SSL directive & Properties in nginx.conf, it works fine and able to
do SSL handshake as well. Not sure how it would be a SSL connection, without
the SSL directive and SSL properties.

Java Error
########
javax.mail.MessagingException: Could not connect to SMTP host: localhost,
port: 3001, response: -1
        at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2197)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:740)
        at javax.mail.Service.connect(Service.java:388)
        at javax.mail.Service.connect(Service.java:246)
        at javax.mail.Service.connect(Service.java:195)
        at javax.mail.Transport.send0(Transport.java:254)
        at javax.mail.Transport.send(Transport.java:124)
        at com.att.client.smtp.SMTPTestClient.main(SMTPTestClient.java:50)

nginx.conf
########
stream{
    upstream smtp_backend {
                least_conn;
                server smtp.gmail.com:587;
         }
       
        server {
        listen        3001 ssl;
        proxy_pass    smtp_backend;
               
        ssl_certificate       C:/nginx-selfsigned.crt;
        ssl_certificate_key   C:/nginx-selfsigned.key;
        ssl_protocols         SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers           ALL;
        #ssl_ciphers           HIGH:!aNULL:!MD5;
        ssl_session_cache     shared:SSL:20m;
        ssl_session_timeout   4h;
        ssl_handshake_timeout 30s;
    }
}

Java client code
#############
..
..
        Properties prop = new Properties();
        //prop.put("mail.smtp.host", "smtp.gmail.com");
        prop.put("mail.smtp.host", "localhost");
  //prop.put("mail.smtp.port", "587");
        prop.put("mail.smtp.port", "3001");
        prop.put("mail.smtp.auth", "true");
        prop.put("mail.smtp.starttls.enable", "true"); //TLS
        //prop.put("mail.smtp.starttls.required", "true");
       
        Session session = Session.getInstance(prop,
                new javax.mail.Authenticator() {
                    protected PasswordAuthentication
getPasswordAuthentication() {
                        return new PasswordAuthentication(username,
password);
                    }
                });

        try {

            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("[hidden email]"));
            message.setRecipients(
                    Message.RecipientType.TO,
                    InternetAddress.parse("[hidden email]")
            );
            message.setSubject("Testing Gmail TLS from nginx");
            message.setText("Dear Mail Crawler,"
                    + "\n\n Please do not spam my email!");

            Transport.send(message);

            System.out.println("Done");
...
....

Posted at Nginx Forum: https://forum.nginx.org/read.php?2,288532,288532#msg-288532

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: Nginx as reverse proxy mail server host

Francis Daly
On Thu, Jul 02, 2020 at 02:20:59PM -0400, siva.pannier wrote:

Hi there,

> I am trying to proxy a SMTP server on Nginx using the below configuration. I
> want all the client calls to hit the SMTP server via my proxy host. I want
> the SSL termination on nginx for the client calls to the SMTP Server.

Your config has nginx as an ssl-termination point, and nginx just sends
the decrypted traffic to its upstream.

The simplest way to prove that this works is probably to use a well-known
working client, such as "openssl s_client -connect".

> When I do the connection getting below exception even before the SSL
> handshake.. Please correct me if I am wrong anywhere.

There are two ways of doing ssl with smtp. One is to establish a ssl
session, and then "speak" smtp through that -- that is what you have
configured your nginx server to expect here. The other is to establish
a smtp session, and then use the smtp command "starttls" to establish a
ssl session -- that is what you have configured your client to do.

Things fail because nginx is expecting to see a ssl session being
established, but the client is expecting to see a smtp session being
established.

> Without SSL directive & Properties in nginx.conf, it works fine and able to
> do SSL handshake as well. Not sure how it would be a SSL connection, without
> the SSL directive and SSL properties.

In this case, nginx is acting as a plain tcp forwarder; it does not know
or care what is in the packet, it just copies it.

Now your client connects to nginx, and nginx sends the content to your
upstream. Your client says "starttls" and negotiates the ssl session
with your upstream, not with nginx.

What you have can work; but you must make sure that your design has the
client and the server speaking the same protocol with each other.

An alternative way of proxying smtp is described at
https://docs.nginx.com/nginx/admin-guide/mail-proxy/mail-proxy/

Good luck with it,

        f
--
Francis Daly        [hidden email]
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: Nginx as reverse proxy mail server host

vergil
Thank you for your suggestions!

My understanding from your suggestions is that you do not want me to make
any corrections on the client code. I just need to make corrections on the
Nginx configuration as per the blog link.

I am trying to understand that blog, going through again and again. so far I
understand that it creates a SSL layer first through which it accepts the
client request. Client should point to my proxy host and one of the ports
listed under "mail{... }". Proxy server identifies the upstream host based
on the username came from the client request. Then the call is routed to
actual upstream host based on the port. Please correct me if I am wrong
anywhere.

My questions are
1) Significance of this line "auth_http  
localhost:9000/cgi-bin/nginxauth.cgi;" is just to have my own authorization
logic and return the valid upstream server host based on the username. Is it
correct?
2) I want to know what does this mean "smtp_auth  login plain cram-md5;".
Does the connection to actual upstream happen here?

Please help me on this and also share links supporting the above
configuration.

Posted at Nginx Forum: https://forum.nginx.org/read.php?2,288532,288539#msg-288539

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: Nginx as reverse proxy mail server host

Francis Daly
On Fri, Jul 03, 2020 at 08:38:09AM -0400, siva.pannier wrote:

Hi there,

> My understanding from your suggestions is that you do not want me to make
> any corrections on the client code. I just need to make corrections on the
> Nginx configuration as per the blog link.

Not quite, no.

You need to know which of the smtp-involving-ssl protocols you want your
client to speak.

You need to know which of the smtp-involving-ssl protocols your upstream
server speaks.

Then you decide how (and whether) to configure nginx to translate between
the two.

From your report, your client already works with nginx using stream{}
and no ssl, because your client uses smtp+starttls and your upstream
server uses smtp+starttls.

So maybe there is nothing that you need to change.

> I am trying to understand that blog, going through again and again. so far I
> understand that it creates a SSL layer first through which it accepts the
> client request.

Maybe.

That document describes multiple possible ways of configuring things.

You will want to use exactly one way.

If you use the nginx mail{} with "ssl on", then what you suggest is
correct.

If you do not use "ssl on", then it is not correct.

> Client should point to my proxy host and one of the ports
> listed under "mail{... }". Proxy server identifies the upstream host based
> on the username came from the client request. Then the call is routed to
> actual upstream host based on the port. Please correct me if I am wrong
> anywhere.

When nginx is configured to proxy a message to an upstream server,
it needs to know which upstream server to talk to.

If you use nginx stream{}, you configure the upstream using proxy_pass. If
you use nginx mail{}, as this document does, you configure the upstream
indirectly using auth_http. auth_http refers to a http url that is
expected to return an indication of which server:port the connection
should be proxied to. How it does that is up to you to write -- maybe
it differs per user and per port; maybe it always gives the same response.

> My questions are
> 1) Significance of this line "auth_http  
> localhost:9000/cgi-bin/nginxauth.cgi;" is just to have my own authorization
> logic and return the valid upstream server host based on the username. Is it
> correct?

http://nginx.org/r/auth_http

> 2) I want to know what does this mean "smtp_auth  login plain cram-md5;".
> Does the connection to actual upstream happen here?

http://nginx.org/r/smtp_auth

The connection to upstream cannot happen until after nginx knows which
upstream to connect to. And that comes from the auth_http response. The
auth_http request includes the details provided by the client in response
to the smtp_auth "challenge".

> Please help me on this and also share links supporting the above
> configuration.

There is a lot of information at http://nginx.org/en/docs/

The "ngx_mail_*" modules are grouped together.

For a lot of this, if the documentation is unclear, you may be better
off building a test system and seeing what happens when you try things.

If that results in the unclear documentation being made clear, that
is good.

Good luck with it,

        f
--
Francis Daly        [hidden email]
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: Nginx as reverse proxy mail server host

vergil
Thanks for your inputs.. let me try those..

Posted at Nginx Forum: https://forum.nginx.org/read.php?2,288532,288566#msg-288566

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx