Why run Postfix behind an ELB instead of doing DNS round-robin? Lots of reasons. It’s a lot easier to autoscale, for one. You get increased control over load distribution, you don’t have to wait for DNS propagation. But wait, won’t I lose the source IP since we’ll have to do TCP load balancing? No, of course not - that was a rhetorical question. Here’s how it’s done.
Amazon ELB supports Proxy Protocol. This will write a TCP header that can later be read by applications which support it. Luckily for us, Postfix supports Proxy Protocol in versions 2.10 and above.
Unfortunately, the AWS web console doesn’t have an easy way to enable Proxy Protocol, but it’s pretty easy to accomplish with the AWS CLI tools. First, we need to create a policy:
aws elb create-load-balancer-policy --load-balancer-name YOUR-ELB-HERE --policy-name EnableProxyProtocol --policy-type-name ProxyProtocolPolicyType --policy-attributes AttributeName=ProxyProtocol,AttributeValue=True
Then, apply the policy:
aws elb set-load-balancer-policies-for-backend-server --load-balancer-name YOUR-ELB-HERE --instance-port 25 --policy-names EnableProxyProtocol
We can check to make sure our changes were applied:
aws elb describe-load-balancers --load-balancer-name YOUR-ELB-HERE
You should see EnableProxyProtocol listed under policies. That’s it for the ELB side, now you just need to enable Proxy Protocol on Postfix. In your /etc/postfix/main.cf you’ll need to add the line:
postscreen_upstream_proxy_protocol = haproxy
And then your service configuration in /etc/postfix.master.cf should look something like this:
smtp inet n — — — 1 postscreen
smtpd pass — — — — — smtpd
Restart Postfix and you’re done! You should immediately see proper source IP start to show up in your mail.log.