Can I load balance SMTP / mail servers?
Short answer
Yes, with an L7 TCP vService. Ports 25 and 587 are forwarded as they are with the TCP protocol on the frontend; STARTTLS takes place on the mail server. If required, SMTPS on port 465 is terminated on TR7 with TCP + TLS in a separate vService. The most important point is the client IP: since relay restrictions, SPF and spam checks rely on the real IP, it is ensured that the server sees the client's IP, not TR7's. There are two ways to do this: SNAT → Use Client IP on the Backend Service or, if the mail server supports it, Proxy Protocol.
Problem: Why Should the Mail Server See the Client IP?
Since the L7 TCP vService accepts the connection on TR7, the mail server by default sees all connections as if they came from TR7's IP. Mail servers, on the other hand, make their decisions on which addresses can relay mail, on the SPF check and on the blacklist check by looking at the client IP. If all traffic appears to come from a single internal IP, these checks do not work; if the relay rules allow the internal network, the server can start relaying mail coming from outside as well.
Solution: Two Methods
In both methods, the SMTP ports are published with an L7 TCP vService; the difference is how the client IP is carried to the mail server.
| Your situation | Suitable method |
|---|---|
| The server's return traffic can be routed through TR7 (gateway or Spoofing) | Method 1: SNAT → Use Client IP |
| The mail server supports Proxy Protocol (e.g. Postfix); the network will not change | Method 2: Proxy Protocol |
Method 1: SNAT → Use Client IP Recommended
- How it works TR7 distributes the SMTP connections to the servers; with the SNAT setting on the Backend Service, it establishes the connection it opens to the server with the client's IP.
- Where it is opened vService → Type: L7 TCP → Frontend 25 / 587 → Protocol: TCP; Backend Service → SNAT → Use Client IP
- Requirement The mail server's return traffic passing through TR7 (the server's gateway being TR7, or Spoofing)
- vService type L7 TCP
- Backend Service side If the gateway is to be set to TR7, it is changed on the server; if Spoofing is used, no change is required on the server. Since the server now sees the real client IPs, the relay permissions (e.g. Postfix
mynetworks) are reviewed so that they contain only the networks that are to be allowed to relay mail.
Step-by-Step Configuration
On the Load Balancer → Profiles → Health Checks screen, the Add button is clicked (how to add).
Name is entered and SMTP is selected as the Check Type; if the server requires STARTTLS, Use STARTTLS is turned on.
The Add button at the bottom of the form is clicked.
On the Load Balancer → Backend Services screen, the Add button is clicked (How is a Backend Service added; which information is required?).
Backend Service Name and Address (e.g. 192.0.2.80:25) are entered; in the Health Check field, the profile created in steps 1–3 is selected.
In the Details section of the same form, Use Frontend Port is turned on; since more than one port is published in a single vService, each connection goes to the same port on the server.
In the SNAT field, Use Client IP is selected. If the server's default gateway is not TR7, the Spoofing switch that appears is turned on; in a cluster, the VIP that determines the device on which spoofing will work is selected in the Spoofing IP VIP Condition field.
The Add button (Edit for an existing Backend Service) at the bottom of the form is clicked. Steps 4–8 are repeated for each mail server.
The Load Balancer → Load Balancer vService List → Add steps are followed; Name is entered and L7 TCP is selected as the Type.
The 25 / TCP and 587 / TCP rows with the same IP are added to the Frontend table. If TLS for 465 (SMTPS) is to stay on the server, a third row is added as 465 / TCP; if SMTPS must be terminated on TR7, 465 is published in a separate vService with TCP + TLS and a certificate. If the IP is not in the list, it is first added with Network → Interfaces → Actions → Add IP (Why can't I type the Frontend IP manually; what should I do to use an IP that is not in the list (e.g. IPv6) on a vService?).
In the Default Backend Services table, the Backend Services added in steps 4–8 are selected.
The Save button is clicked. In a cluster setup, the change is also transferred to the peer device with the default auto-sync; if Manual Sync Mode is on, it is sent manually with Synchronize.
Verification
openssl s_client -starttls smtp -connect 203.0.113.70:587The mail server's certificate and the 250 responseThe source address of the incoming connection is checked in the connection log of the mail server.
connect from [198.51.100.25] (the client's IP)Method 2: Proxy Protocol
- How it works At the beginning of each connection it opens to the mail server, TR7 sends the client's IP with the Proxy Protocol header; the server uses this address in the relay and spam checks.
- Where it is opened Backend Service → Proxy → Proxy (v1) or Proxy v2
- Requirement The mail server supporting Proxy Protocol and being configured to expect this header on connections coming from TR7
- vService type L7 TCP
- Backend Service side Required: the server is configured to expect the Proxy Protocol header (the Postfix example is in the panel below). No change is required in the network and on the gateway.
Step-by-Step Configuration
The server is configured to expect the Proxy Protocol header on connections coming from TR7 (the panel below). If Proxy is turned on in TR7 before the server is prepared, the connections fail.
On the Load Balancer → Profiles → Health Checks screen, the Add button is clicked.
Name is entered and TCP is selected as the Check Type. TR7's health checks do not send the Proxy Protocol header; on a port that expects the header, the SMTP health check is rejected. Instead of TCP, a separate port that does not expect Proxy Protocol can also be checked with Use Different IP for Health Check on the Backend Service.
The Add button at the bottom of the form is clicked.
On the Load Balancer → Backend Services screen, the Add button is clicked.
Backend Service Name and Address are entered; in the Health Check field, the profile created in steps 2–4 is selected.
In the Details section of the form, Use Frontend Port is turned on.
In the Proxy field, the version the server expects (Proxy or Proxy v2) is selected; the default is No Proxy. SNAT stays Default.
The Add button (Edit for an existing Backend Service) at the bottom of the form is clicked. Steps 5–9 are repeated for each mail server.
Steps 9–11 of Method 1 are applied: Type L7 TCP, the 25 / TCP and 587 / TCP (and 465 / TCP, if any) rows with the same IP, and the Backend Services.
The Save button is clicked. In a cluster setup, the change is also transferred to the peer device with the default auto-sync.
The setting is written to Postfix's main.cf file and Postfix is reloaded; the haproxy value accepts Proxy Protocol v1 and v2 headers (Postfix · smtpd_upstream_proxy_protocol).
# main.cf
smtpd_upstream_proxy_protocol = haproxyOnly connections coming from TR7
It is ensured that only TR7 can connect to the port on which this setting is on; a client that can send the Proxy Protocol header directly can make itself appear to come from another IP.
Verification
A connection is made from the client with openssl s_client -starttls smtp -connect 203.0.113.70:587 and the connection log of the mail server is checked.
connect from [198.51.100.25] (the client's IP)Common Mistakes
- Not turning on Use Frontend Port. While 25, 587 and 465 are in the same vService, the single port in the Address of the Backend Service is used; all connections go to the same port.
- Leaving SNAT at the default. The server sees all connections as coming from TR7's IP; if the relay rules allow the internal network, the server can also relay mail coming from outside.
- Turning on Use Client IP without preparing the return path. If the server's responses bypass TR7, the SMTP connections are not completed; the gateway is set to TR7 or Spoofing is turned on.
- Selecting TCP + TLS on 25 or 587. STARTTLS starts later within the connection; it cannot be terminated on TR7.
- Turning on Proxy Protocol on a server that does not support it. A server that does not support it takes the header for an SMTP command, and the connections break.
How it is done in the documentation
