SMTP relay control through SNAT using F5 BIG-IP iRules

When building an email solution it is absolutely critical to avoid becoming an open SMTP relay. Aside from contributing to the spam problem, it can take a long time to get off blacklists (such as DNSBLs) and be a serious disruption to your business.

Relay control is a topic that seems to come up reasonably often in the context of load balancers such as F5 BIG-IP Local Traffic Manager. The quickest way to set up load balancing is usually to use SNAT, which rewrites the client IP address. This breaks the most common method of relay control, which is to have the SMTP server compare the client IP address against its own list of relay-allowed addresses or subnets. Turn on SNAT-based load balancing and now all the server sees is the load balancer’s SNAT address.  All relaying is denied or – worse – the administrator adds the SNAT address to the relay allow list and your site becomes an open relay.

A few solutions tend to be offered for this:

  • Use routing instead of SNAT. This is the best solution, and requires reconfiguration of the servers to use the BIG-IP as their route back to clients. The servers can now see the real client IP, and the old methods keep working. Usually this means the BIG-IP becomes default route for the backend servers. This is not an option in many cases – most obviously when the SMTP servers are not on the same subnet as the BIG-IP. The servers may not even be on the same subnet as each other, as may be the case with most DR sites.
  • Use inline bridging. This is not a good solution in my view. Bridging is something you might do when you need to retrofit load balancing to an existing environment without reconfiguring servers or clients. The solution is complex and non-obvious, and still suffers from the subnetting problem of the routed solution above. You need layer 2 between the BIG-IP and all your servers. This is just not an option in many cases.
  • Use an SMTP Proxy iRule to intercept the session, performing just enough SMTP with the client to determine whether it is relaying, and make a decision whether to allow it through. In my view this is excessively complex. By getting too involved in the session, the BIG-IP becomes another point to diagnose when there are mail reception problems. There are a lot of quirks in SMTP client implementations, and I prefer the mail server engineers at the likes of Microsoft be left to handle them. Furthermore, it is likely that your SMTP server is a mail security/spam solution (such as Ironport or MailMarshal). To get the best value from those platforms you want them to see every stage of the real client SMTP  session (if not the real client IP address).
SMTP relay control using a SNAT address

Here is my solution, which I believe is much simpler than the SMTP Proxy iRule.

Essentially what we will do is move the relay control list from your SMTP servers into your F5 BIG-IP, and identify this to the server by selecting a different SNAT address.

SMTP SNAT address selection by iRule

Define a SNAT on a new IP address that can reach your SMTP servers. (It doesn’t need to be on the subnet, just needs a route.)  Continue using SNAT Automap in your Virtual Server definition so that – by default – client addresses are rewritten to any appropriate self IP.

Add a Data Group List of Address type to contain your whitelist of relay-allowed client IP addresses or even whole subnets. Add an iRule to your Virtual Server to test the client IP against the Data Group List and explicitly select the SNAT IP address if it is on the whitelist.

Screenshot of datagroup list

Datagroup list to control SMTP relay, including both IP address and subnet examples

Then all you need to do is configure your backend servers to only allow relay from that SNAT address.

The iRule code is very simple:

	set accepted_snat ""

	if { [ class exists smtp_relay_allowed ] }
		if { [ class match [IP::client_addr]
		           equals smtp_relay_allowed ] }
			snat $accepted_snat
		} else {
			snat automap
	} else {
		snat automap


Change the accepted_snat variable to your SNAT address for whitelisted clients.  If you are running a very large site where you anticipate over 65000 connections, you will need a SNAT pool instead of a single SNAT address.  The command in that case is snatpool. You’ll probably want two SNAT pools and stop using automap.

I hope this example gives you another option for achieving secure, fast, and available SMTP service through F5 BIG-IP Local Traffic Manager.