Normally, the Halon platform operates in a traditional store-and-forward MTA fashion. In some cases however, such as providing outbound filtering for a network of computers, it's desired to run the software in a more proxy-like setup.
One aspect of proxying is being more transparent. Please keep in mind that many of the recommended methods for dealing with spam and blacklisting is hampered as you move towards a more transparent mode of operation.
When delivering email out from the gateway, the source address can be changed using the SetSourceIP() function. By enabling the system_nonlocal_source system setting, any (such as the connecting/sending client's IP) address can be used
SetSourceIP($senderip, ["nonlocal_source" => true]);
Please keep in mind that your routers/firewalls needs to be configured in such a way so that the returning traffic is routed back to the Halon system.
We argue that "forcing" the email to be sent to the $recipientdomain's (RCPT TO) MX by simply relying on the normal behaviour of a "lookup-mx" transport is a powerful security/anti-spam feature. However, in some cases it might be necessary to send the message to the original destination IP address that the sending client connected to. This requires a load balancer in front of the Halon system, that can append the destination IP as a header to the message. If you don't have a load balancer, you can setup a simple SMTP proxy on for example Linux, using the SO_ORIGINAL_DST socket option. The header can be read from the DATA script
SetMetaData(["orig_dest" => GetHeader("x-orig-dest")]);
and used in the pre-delivery script when sending the message
$meta = GetMetaData();
You could in theory even forward authentication information from the AUTH script to the pre-delivery script's SetSASL() function, although that seems like a poor idea from a security perspective.
Fully transparent mode
If the semi-transparent method described in the previous chapter isn't suitable, one can use an external proxy that handles all communication between client and server with the Halon system on "the side" (inspecting the messages, and coming up with an verdict).
Using Halon's modified version
For high performance systems, we recommend that you use our ProxSMTP version https://github.com/halonsecurity/proxsmtp which enables direct communication from ProxSMTP to Halon nodes without invoking an external program. It is configured like
FilterType: smtp FilterCommand: IP-OF-HALON ...
Using ProxSMTP with a Halon cluster
ProxSMTP does not have built-in support for load balancing traffic against a cluster of Halon nodes but this can be easily accomplished by installing a separate load balancer (for example HAProxy) and using a configuration similar to this:
listen smtp 127.0.0.1:25 mode tcp option tcplog option smtpchk balance roundrobin server halon1 10.2.0.30:25 check server halon2 10.2.0.31:25 check
and then using the listener for the load balancer as the FilterCommand in ProxSMTP.
Using pre-compiled versions with a script
It is possible to use a stock (packaged) ProxSMTP with Halon using a FilterCommand script, although this isn't recommended. The proof-of-concept Python code below can be used for lower traffic volumes.
#!/usr/bin/env python # Proof-of-concept proxy-to-Halon FilterCommand script for ProxSMTP import os, smtplib, sys try: cn = smtplib.SMTP() cn.connect('10.2.0.30', 25) cn.sendmail( os.environ['SENDER'], os.environ['RECIPIENTS'].split('\n'), open(os.environ['EMAIL'], 'r').read()) cn.quit() except smtplib.SMTPDataError as e: sys.stderr.write(str(e) + ' ' + e + '\r\n') exit(1) except Exception: pass exit(0)
Although the system operates more efficiently in queued mode (because the system can schedule more freely), sometimes you want queue-less, in-line delivery using DirectDeliver(). It's also possible to combine queued delivery in the Halon and in-line delivery for a client, using an external SMTP proxy which reacts to callbacks from a post-delivery script such as
http("https://smtp-proxy/callback", , , ["code" => $errorcode, "msg" => $errormsg, "id" => $messageid]);
Delete(); // no more retries
While developing such a proxy might seem like a daunting task; we have customers who have done so in reasonable short time using high-level frameworks such as Twisted.