In my last blog post I have highlighted how HAProxy can be used to distribute client connections to two or more servers with Exchange 2013 CAS role. But there is another common use case for load balancers in a Exchange environment: SMTP. Let’s take a look at this drawing:
The inbound SMTP connections are distributed to two Mail Transfer Agents (often a cluster of appliances, like Cisco IronPort or Symantec Messaging Gateway) and the MTAs forward the e-mails to the Exchange servers. Sometimes the e-mails are not directly forwarded to the Exchange servers, but to mail security appliances instead (like Zertificon Z1 SecureMail Gateway). After the e-mails have been processed by the mail security appliances, they are forwarded to the Exchange backend. Such setups are quite common. If a load balancer isn’t used, the MX records often point to the public IP address of a specific MTA. In this case, two or more MX records have to be set to ensure that e-mails can be received, even if a MTA fails.
A setup with a load balancers allows you to have a single MX record in your DNS, but two or more servers that can handle inbound SMTP connections. This makes maintenance easier und allows you to scale without having to fumble on the DNS. It’s without saying that your Load Balancer should be highly available, if you decide to realize such a setup.
It’s not hard to persuade HAProxy to distribute inbound SMTP connections. All you have to do is to add this to your haproxy.conf. To get the full config, check my last blog post about HAProxy.
mode tcp no option http-server-close balance roundrobin option smtpchk HELO mail.terlisten-consulting.de server mail1 192.168.200.107:25 send-proxy check server mail2 192.168.200.108:25 send-proxy check
The “send-proxy” parameter ensures, that the incoming IP address is forwarded to the servers behind the load balancer. This is important if you use Greylisting or real-time blacklists on your MTA or mail server. When running Postfix 2.10 or later, please make sure that you add this line to your main.cf:
smtpd_upstream_proxy_protocol = haproxy
This option add support for the PROXY protocol. Incoming requests are distributed alternating to the servers behind the load balancer. The “balance roundrobin” parameter ensures this. Please make sure that the MTA, that is running on your Linux host, doesn’t listen on the external IP. In my case, Postfix listens only on 127.0.0.1.
[root@haproxy haproxy]# netstat -tulpen Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name tcp 0 0 192.168.200.103:25 0.0.0.0:* LISTEN 0 228433 22876/haproxy tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 0 15431 1309/master
The statistics page can be used to verify the success of the configuration (click the picture to enlarge).
Alternatively you can use Telnet to connect to the load balancer on port 25/tcp. As you can see in the screenshot, using the FQDN mailin.vcloudlab.local resulted in an alternating connection to the backend servers.
- Failed to connect to IKEv2 VPN using iPhone USB tethering - June 26, 2023
- Why you should change your KRBTGT password prior disabling RC4 - July 28, 2022
- Use app-only authentication with the Microsoft Graph PowerShell SDK - July 22, 2022
It doesnt work for me, i receive an error in the smtp gateway:
500 Command unrecognized “PROXY TCP4 192.168.0.31 192.16”
Where do you get this error message?
Hi thanks for your howto,
Im facing a problem with my postfix-dovecot HA with haproxy.
dovecot : 2:2.2.19
haproxy : 1.5.14
postfix : 2.11.2-1
I ‘ve followed these links :
– http://wiki2.dovecot.org/HAProxy
– http://blog.haproxy.com/2012/06/30/efficient-smtp-relay-infrastructure-with-postfix-and-load-balancers/
this is my haproxy configuration
#postfix
listen smtp
bind mail.xx.xx:465
balance roundrobin
timeout client 1m
timeout connect 5s
no option http-server-close
mode tcp
option smtpchk
option tcplog
server tst tst.xxx:10465 send-proxy
server tst2 tst2.xxx:10465 send-proxy
server tst3 tst3.xxx:10465 send-proxy
#dovecot
listen imap
bind mail.xxx.xx:993
timeout client 1m
no option http-server-close
balance leastconn
stick store-request src
stick-table type ip size 200k expire 30m
mode tcp
option tcplog
server tst tst.xxx:10993 send-proxy-v2
server tst2tst2.xxx:10993 send-proxy-v2
server tst3 tst3.xxx:10993 send-proxy-v2
postix main.cf
#Haproxy proxy protocol
postscreen_upstream_proxy_protocol = haproxy
postfix master.cf
#haproxy
10465 inet n – n – 1 postscreen
smtpd pass – – n – – smtpd
dovecot dovecot.conf
#trust haproxy requests
haproxy_trusted_networks = 172.20.1.3
haproxy_timeout = 5
inet_listener imap_haproxy {
port = 10993
haproxy = yes
}
test with thunderbird client
imap logs, don’t know why user is empty …
dovecot: imap-login: Disconnected: Too many invalid commands (no auth attempts in 0 secs): user=, rip=my public ip, lip=haproxy public ip, session=
smtp logs, i get a timeout …
postfix/postscreen[16654]: CONNECT from [my public ip]:49942 to [my haproxy public ip]:465
postfix/postscreen[16654]: PREGREET 166 after 0 from [my public ip ]:49942: 2231161115733+0Eb213131177173>r/213177i223k”FjA#144145153vP\155HL190
Do you have an idea ? Thanks
Kind regards !
Hi thanks for your howto,
Im facing a problem with my postfix-dovecot HA with haproxy.
dovecot : 2:2.2.19
haproxy : 1.5.14
postfix : 2.11.2-1
I ‘ve followed these links :
– http://wiki2.dovecot.org/HAProxy
– http://blog.haproxy.com/2012/06/30/efficient-smtp-relay-infrastructure-with-postfix-and-load-balancers/
this is my haproxy configuration
#postfix
listen smtp
bind mail.xx.xx:465
balance roundrobin
timeout client 1m
timeout connect 5s
no option http-server-close
mode tcp
option smtpchk
option tcplog
server tst tst.xxx:10465 send-proxy
server tst2 tst2.xxx:10465 send-proxy
server tst3 tst3.xxx:10465 send-proxy
#dovecot
listen imap
bind mail.xxx.xx:993
timeout client 1m
no option http-server-close
balance leastconn
stick store-request src
stick-table type ip size 200k expire 30m
mode tcp
option tcplog
server tst tst.xxx:10993 send-proxy-v2
server tst2tst2.xxx:10993 send-proxy-v2
server tst3 tst3.xxx:10993 send-proxy-v2
postix main.cf
#Haproxy proxy protocol
postscreen_upstream_proxy_protocol = haproxy
postfix master.cf
#haproxy
10465 inet n – n – 1 postscreen
smtpd pass – – n – – smtpd
dovecot dovecot.conf
#trust haproxy requests
haproxy_trusted_networks = haproxy private ip
haproxy_timeout = 5
inet_listener imap_haproxy {
port = 10993
haproxy = yes
}
test with thunderbird client
imap logs, don’t know why user is empty …
dovecot: imap-login: Disconnected: Too many invalid commands (no auth attempts in 0 secs): user=, rip=public ip, lip=haproxy public ip, session=
smtp logs, i get a timeout …
postfix/postscreen[16654]: CONNECT from [my public ip]:49942 to [my haproxy public ip]:465
postfix/postscreen[16654]: PREGREET 166 after 0 from [159.180.255.62]:49942: 2231161115733+0Eb213131177173>r/213177i223k”FjA#144145153vP\155HL190
Do you have an idea ? Thanks
Kind regards !
Hi Michael,
sorry, no idea. But I’m sure the HAProxy developers can help you.
Regards,
Patrick
I would not recommend this approach when the backend SMTP servers are Exchange, as Exchange ESMTP does not support the PROXY command (send-proxy in HAProxy).
Using send-proxy with default Exchange SMTP (receive connectors) will result in tarpitting, possibly causing the HAProxy check to timeout, though this could be avoided by disabling tarpitting on the receive connectors, it could cause other problems as Exchange will respond with “500 Unknown command” to the initial check.
Safest approach is just to skip the “send-proxy”, and it will work just fine.