| | spamfilter1 is a Python script that bounces spam which circumvented your firewall or TCP connection rules by coming through an offsite backup mail server. Its intended use is as a qmail filter; hence, it reads the message from stdin and returns 0 when the email is determined to be from a blacklisted sender.
Consider the following scenario:
- example.com uses backup mail services at myalternatehost.com.
- A known spammer attempts to connect to example.com and is refused due to firewall rules, tcpserver's tcprules, etc.
- The spammer then tries to connect to the backup mail server and succeeds; alternatively, the spammer may have simply connected to the backup mail server without even trying the primary MX for example.com.
- The backup mail server accepts the email, detects that the primary MX at example.com is available and redirects the email, completely bypassing the rules designed to deny a connection to the spammer.
As luck would have it, our backup mail service at ZoneEdit adds a well structured Received: header that makes it easy to determine the real IP address of the sending server. This IP address is matched against a list of blacklisted host and/or network addresses. If a match is found, the script returns 0. Otherwise, it returns 1.
We use the script as a bouncesaying command in a dot-qmail file as follows:
bouncesaying "This email address no longer accepts mail" spamfilter.py
To use the script, you will need to perform some minor customization:
- You must customize the getDeniedAddresses function to return a list of strings representing your blacklist. How you implement this function is up to you as long as the listed IP addresses are in one of the following formats:
n.n.n.n
n.n.n.n/nm
where nm is the number of bits allocated to the network (or subnet) portion of the IP address.
For example, 192.168.1.64 blacklists the host 192.168.1.64 while 192.168.1.0/24 blacklists all hosts in the 192.168.1.0 network (192.168.1.0 through 192.168.1.255).
The default implementation is shown below:
def getDeniedAddresses():
return [
'64.248.0.0/13', #korea
'202.0.0.0/8', #apnic
'203.0.0.0/8', #apnic
'205.244.71.0/24', #concentric.net
'209.220.162.138/32', #sweepsclub.com
'211.0.0.0/8', #apnic
'66.151.41.0/24', #opmnetwork.net
'66.151.42.0/24' #opmnetwork.net
]
- You must customize the getSearchString function to return an expression that can be used by string.find to determine whether the email came through your backup mail server. Again, how you implement this function is up to you. If you use ZoneEdit, the default implementation shown below should be correct:
def getSearchString():
return '(HELO ' + 'mx2.zoneedit.com' + ')'
Caveats
- The script assumes that the Received: header written by the local MX (example.com) is immediately followed by a Received: header that will accurately identify the server who sent the email to your backup mail server.
- The script assumes that the IP address of the sending server appears in the header as [n.n.n.n].
Dependencies
The source code for this filter is licensed under The GNU General Public License and is available for download. For more information, see the documentation included at the top of the script.
1 The current version is 1.1 (posted 27 Jun 2003).
|