# SMTP Load Balancing With Exchange 2013

**URL:** <https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946>\
**Category:** Help!\
**Created:** [January 21, 2017, 1:50am UTC](https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946 "2017-01-21T01:50:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Emalacar](https://avatars.discourse-cdn.com/v4/letter/e/ecccb3/32.png) [@Emalacar](https://discourse.haproxy.org/u/Emalacar)\
**Post date:** [January 21, 2017, 1:50am UTC](https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946/1 "2017-01-21T01:50:29Z")

</div>

Hello,

I’ve set up a test environment with Exchange 2013 and Haproxy loadbalancing services at layer 7. I believe I have the exchange urls setup correctly and my Outlook and ActiveSync clients connect ok. My problem is with loadbalancing SMTP connections to the server…

I am unable to connect over port 25 with putty to the exchange servers. The port is open in firewalld, iptables is off, checking what’s listening the haproxy service is listening on port 25. However, when I connect with putty the connection just times out. Likewise, if I try to send an email over smtp I receive the following error…

said: 250 2.1.5 Recipient OK - then a bounce back is sent.

I don’t believe that the issue is with exchange as I can connect with putty directly to the CAS servers and send emails that way. Below is my Haproxy configuration, any insight or corrections would be greatly appreciated!

global  
log 127.0.0.1 local0 info  
maxconn 10000  
daemon quiet  
tune.ssl.default-dh-param 2048

defaults  
log global  
mode http  
option httplog  
option dontlognull  
timeout connect 60000ms  
timeout client 30000ms  
timeout server 60000ms  
timeout check 60000ms  
stats enable  
stats hide-version  
stats show-node  
stats auth admin:PASSWORD  
stats uri /stats

frontend unsecured 192.168.1.1:80  
redirect location [https://mail.domain.com/owa](https://mail.domain.com/owa)

frontend fe\_ex2013\_smtp  
mode tcp  
bind \*:25 name smtp  
log global  
option tcplog  
option dontlognull  
option contstats  
timeout client 300s  
default\_backend bk\_exchange\_2013\_smtp

frontend fe\_ex2013  
mode http  
bind \*:443 ssl crt /etc/ssl/certs/exchange\_certificate  
acl autodiscover url\_beg /Autodiscover  
acl mapi url\_beg /mapi  
acl rpc url\_beg /rpc  
acl owa url\_beg /owa  
acl eas url\_beg /microsoft-server-activesync  
acl ecp url\_beg /ecp  
acl ews url\_beg /ews  
acl oab url\_beg /oab  
use\_backend be\_ex2013\_autodiscover if autodiscover  
use\_backend be\_ex2013\_mapi if mapi  
use\_backend be\_ex2013\_rpc if rpc  
use\_backend be\_ex2013\_owa if owa  
use\_backend be\_ex2013\_eas if eas  
use\_backend be\_ex2013\_ecp if ecp  
use\_backend be\_ex2013\_ews if ews  
use\_backend be\_ex2013\_oab if oab  
default\_backend be\_ex2013

backend be\_ex2013\_autodiscover  
mode http  
balance leastconn  
option httpchk GET /autodiscover/healthcheck.htm  
option log-health-checks  
http-check expect status 200  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend be\_ex2013\_mapi  
mode http  
balance leastconn  
option httpchk GET /mapi/healthcheck.htm  
option log-health-checks  
http-check expect status 200  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend be\_ex2013\_rpc  
mode http  
balance leastconn  
option httpchk GET /rpc/healthcheck.htm  
option log-health-checks  
http-check expect status 200  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend be\_ex2013\_owa  
mode http  
balance leastconn  
option httpchk GET /owa/healthcheck.htm  
option log-health-checks  
http-check expect status 200  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend be\_ex2013\_eas  
mode http  
balance leastconn  
option httpchk GET /microsoft-server-activesync/healthcheck.htm  
option log-health-checks  
http-check expect status 200  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend be\_ex2013\_ecp  
mode http  
balance leastconn  
option httpchk GET /ecp/healthcheck.htm  
option log-health-checks  
http-check expect status 200  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend be\_ex2013\_ews  
mode http  
balance leastconn  
option httpchk GET /ews/healthcheck.htm  
option log-health-checks  
http-check expect status 200  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend be\_ex2013\_oab  
mode http  
balance leastconn  
option httpchk GET /oab/healthcheck.htm  
option log-health-checks  
http-check expect status 200  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend be\_ex2013  
mode http  
balance leastconn  
server Server1 10.1.1.1:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt  
server Server2 10.1.1.2:443 check ssl inter 15s verify required ca-file /etc/ssl/certs/ca-bundle.crt

backend bk\_exchange\_2013\_smtp  
mode tcp  
balance leastconn  
option tcplog  
log global  
option redispatch  
retries 3  
source 0.0.0.0 usesrc clientip  
option smtpchk HELO [mail.domain.com](http://mail.domain.com)  
server Server1 10.1.1.1:25 send-proxy check  
server Server2 10.1.1.2:25 send-proxy check

---

<div class="post-metadata">

**Author:** ![AaronWest](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.haproxy.org/aaronwest/32/164_2.png) [@AaronWest](https://discourse.haproxy.org/u/AaronWest)\
**Post date:** [January 26, 2017, 10:55pm UTC](https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946/2 "2017-01-26T22:55:35Z")

</div>

In your backend you appear to be sending proxy protocol on the real server lines:

server Server1 10.1.1.1:25 send-proxy check  
server Server2 10.1.1.2:25 send-proxy check

I’m not aware of Exchange 2013 supporting proxy protocol at all so it could well be interfering with the connection.

You also have “source 0.0.0.0 usesrc clientip” which would normally need a 2 arm tproxy setup like this: [http://www.loadbalancer.org/eu/blog/configure-haproxy-with-tproxy-kernel-for-full-transparent-proxy](http://www.loadbalancer.org/eu/blog/configure-haproxy-with-tproxy-kernel-for-full-transparent-proxy)

You can almost certainly ignore the bit about compiling it into the Kernel as it’s been in there for ages now in most kernel’s I’ve used. However do you really need these options? Are you trying to make it source IP transparent? If not then remove those options and it will work but non transparently so you may need to lock down access to port 25 on the server running HAproxy rather than at the Exchange server.

---

<div class="post-metadata">

**Author:** ![Emalacar](https://avatars.discourse-cdn.com/v4/letter/e/ecccb3/32.png) [@Emalacar](https://discourse.haproxy.org/u/Emalacar)\
**Post date:** [January 27, 2017, 9:42pm UTC](https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946/3 "2017-01-27T21:42:28Z")

</div>

Thank you for your response! I’ll take a look at the article.

---

<div class="post-metadata">

**Author:** ![kshitij\_M](https://avatars.discourse-cdn.com/v4/letter/k/e5b9ba/32.png) [@kshitij\_M](https://discourse.haproxy.org/u/kshitij_M)\
**Post date:** [June 15, 2017, 11:52pm UTC](https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946/4 "2017-06-15T23:52:04Z")

</div>

This was really helpful. I ran into something similar. Slightly off topic, but i noticed you used leastconn instead of round robin for load balancing. According to your experience and general popularity in SMTP world, what do you recommend using. I am aware of the high level difference between those two, but would like to know any real world feedback.

---

<div class="post-metadata">

**Author:** ![Emalacar](https://avatars.discourse-cdn.com/v4/letter/e/ecccb3/32.png) [@Emalacar](https://discourse.haproxy.org/u/Emalacar)\
**Post date:** [June 16, 2017, 3:41pm UTC](https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946/5 "2017-06-16T15:41:26Z")

</div>

As an update, my final SMTP config looks like the following.

listen smtp \*:25

```
mode tcp

option tcplog

balance leastconn

server Cas1 10.10.10.31:25 check

server Cas2 10.10.10.28:25 check

```

I have 2 backend exchange servers, each listening on 25 for inbound mail. I removed the “send-proxy” entries and all works; ended up locking down inbound connections on the frewall and in the send connector scope properties of exchange.

As for the performance of leastconn vs roundrobin… I’ve had no issues with leastconn. I’m using it across 3 different load balanced exchange environments. IMO, if one of the exchange servers is queued up or taking it’s time completing smtp transactions, it allows the other servers to pick up the slack, instead of continuing to add new sessions to the server that’s taking longer. This also keeps the number of concurrent transactions on each server lower.

---

<div class="post-metadata">

**Author:** ![kshitij\_M](https://avatars.discourse-cdn.com/v4/letter/k/e5b9ba/32.png) [@kshitij\_M](https://discourse.haproxy.org/u/kshitij_M)\
**Post date:** [June 23, 2017, 9:33pm UTC](https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946/6 "2017-06-23T21:33:45Z")

</div>

Thanks for the Reply Emalacar. That was helpful.

---

<div class="post-metadata">

**Author:** ![rannick](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@rannick](https://discourse.haproxy.org/u/rannick)\
**Post date:** [April 1, 2020, 11:55am UTC](https://discourse.haproxy.org/t/smtp-load-balancing-with-exchange-2013/946/7 "2020-04-01T11:55:57Z")

</div>

What about option smtpchk? It causing some errors in smtpserver log file like: ERROR smtpserver: Socket to Hostname (IP) closed remotely.
