A dial-up-list (DUL) is simply a list of network ranges that is assigned to dial-up users. In a previous post I discussed building such a DUL purely from whois information. This turned out to be a horrific failure as there is no common, usable, standard with regards to the information in the information returned by whois.
Whilst browsing the mail logs looking for where the newest spam flood was coming from another idea presented itself …
Each mail server (or host) on the internet is supposed to HELO with a unique string, the host’s FQDN – and this should in fact be the first stop sign for most incoming mail if it wasn’t for the hordes of legit but misconfigured mail servers out there. For the sake of getting the DUL concept going I’m going to assume that each host at least has a unique helo string (I’ll later show that this is probably incorrect – yes Google and Facebook – I’m looking at you). Now, since a host on a static IP will never connect from differing IP addresses, this means that any helo string that we see on different IPs identifies a dynamic block – the size of which we can (reliably enough) obtain from whois.
So the idea is to troll the mail logs in arrears (unfortunately) and list the ranges that showed the same HELO string from different IPs.
First things first, my mail logs is about a GB for the last three days, and I really don’t feel like copying that whole thing down, so we first write a script that will at least limit the information to that which we need:
# sed -nre ’s/.* <= .* H=\(?([^ \)]+)\)? (\(([^\)]+)\)( ))?[[]([^]]+)[]] .*/\1 \3\4\5/p’ < /var/log/exim/exim_main.log | sed -re ’s/[^ ]+ ([^ ]+ [^ ]+)/\1/’ > ~/helos.txt
This nasty little expression will troll your exim main log for all incoming mail that came in from an SMTP host and in helos.txt write a line for each one in the format “helo_string ip” – which is exactly what we need. On my system this takes quite a while to complete, so don’t get impatient.
Now we want to find all duplicate helo strings that came from different IP addresses. The easiest way to do this is to actually just sort the data in helos.txt and to then pipe it through uniq -c (just so we can get an idea of how often this IP/helo string matched in the past):
sort < helos.txt | uniq -c > helo_sorted_counted.txt
And now any offending helo strings will appear twice in the file above, and as a bonus, on successive lines, which makes it even simpler to rip out the offenders:
$ awk ‘BEGIN{ pl=”"; ph=”"; pp=0 }{ if (ph==$2) { if (!pp) { print pl }; print; pp=1 } else { pp= 0 }; pl=$0; ph=$2; }’ helo_sorted_counted.txt > helo_offenders.txt
The only real work happening here is that the second field of each line gets compared with the second field of the previous line, and if it matches, it prints the entire previous line if it hasn’t already been printed, as well as the entire of this line.
On my system so far I’ve reduced the initial 120690 helo/ip strings from helos.txt to 13229 unique helo/ip pairs, and then after the above I’m left with 1442 offending helo/ip pairs. This will be reduced even further as we continue working.
The next step is to look up the IPs in whois to find the blocks they belong to. This is a rather lengthy process, and part of the reason why the above had to be reduced as far as possible. The efficiency of this can be improved by caching the blocks and first checking a local cache, but for proof of concept I’ll be looking up each IP in the whois database simply because it’s faster to implement. We’re looking for at least one bit of information regarding the block – the “inetnum” (Also labeled NetRange) and then preferably some description. The majority of the blocks I’ve looked up has some reasonable information as the first line labeled descr (or OrgName) and since this information isn’t the end all be all it’ll suffice:
$ cat helo_offenders.txt | while read CNT HELO IP; do whois $IP | awk -F’: +’ ‘BEGIN{ hd=0 } { if($1==”inetnum” || $1==”NetRange”) inetnum=$2; if (!hd && ($1==”descr” || $1==”OrgName”)) { hd=1; descr=$2;} }’”END{ print inetnum\” ${IP} ${HELO} ${CNT} \”descr }”; done > offender_blocks.txt
Unfortunately this still misses on some IP blocks which use yet another different whois format, so we need to cover the cases where the above gives us yet another different format rule, and sometimes we’re unable to obtain the blocks (a script with caching should avoid this since the majority of cases here seem to be rate limit protection) and so instead we need to use something like this:
$ cat helo_offenders.txt | while read CNT HELO IP; do whois $IP | awk -F’: +’ ‘{ if(inetnum==”" && ($1==”inetnum” || $1==”NetRange”)) inetnum=$2; if (descr==”" && ($1==”descr” || $1==”OrgName”)) descr=$2; if (NF==2) hadtwo=1; if (!hadtwo && NF==1) { if ($1 ~ “^ *[#%].*”) {} else if ($1 ~ “^ *[0-9]“) { inetnum=$1; } else { descr=$1; }}}’”END{ if (inetnum==\”\”) inetnum=\”-\”; print inetnum\” ${IP} ${HELO} ${CNT} \”descr }”; done > offender_blocks.txt
The best thing to try and understand that is to actually put it in a text file and properly indent and newline it. Not the simplest of pieces of code to grok, but essentially it takes the IP from helo_offenders, and determines the block it belongs to from the global whois database. It takes a while. We end up with lines such as:
1.2.3.4 – 1.2.3.5 1.2.3.3 helo count name
and
1.2.3/20 1.2.3.3 helo count name
Depending on the provider who listed the stuff in whois (And that we don’t hit protection traps like “% Query rate limit exceeded”, or other problems like “connect: Address family not supported by protocol”). I want the entire range as $1, and I always want it in 1.2.3.4-1.2.3.5 format. So for the first one I’m going to use sed to clear out the ” – ” to be just ” ” permitting it’s in the initial fields (as well as strip out some unwanted leading spaces):
$ sed -re ’s/^ *([0-9.]+) *- *([0-9])/\1 \2/’
This leaves us with a more script-friendly format. The next thing to do is convert the CIDR notation to the above as well. sed isn’t particularly well suited for this task, and the first thing that popped into my head is yet another ugly bash+ask hack:
$ cat offender_blocks.txt | while read BLOCK REST; do if [[ $BLOCK = */* ]]; then echo $BLOCK | awk -F[./] ‘{ blsz=$NF; ip=0; for(i=1; i < NF; i++) { ip += $i * 2 ^ (32 – 8 * i) }; printf(“%d.%d.%d.%d-”, ip / (2 ^ 24), (ip / (2 ^ 16)) % 256, (ip / (2 ^ 8)) % 256, ip % 256); ip += 2 ^ (32 – blsz) – 1; printf(“%d.%d.%d.%d”, ip / (2 ^ 24), (ip / (2 ^ 16)) % 256, (ip / (2 ^ 8)) % 256, ip % 256); }’; else echo -n $BLOCK; fi; echo ” $REST”; done > offender_blocks_cleaned.txt
From this we can get a list of all the hopefully DUL blocks:
$ awk ‘$1 ~ “.-.” { print $1 }’ offender_blocks_cleaned.txt | sort -u
An initial run of the unrefined scripts resulted in 521 IPs for which I wasn’t able to obtain whois information (caching should reduce this number significantly), and a unique block count of 345. Out of an initial 120690 incoming mails 27756 would have been rejected off the bat without even asking spamassassin for help. The question of accuracy remains open.
I mentioned earlier that Facebook and Google are unfriendly. Well, my reasoning is simple, they have hordes of offending helo strings:
$ grep -E ‘google|facebook’ helo_offenders.txt
11 an-out-0708.google.com 209.85.132.240
14 an-out-0708.google.com 209.85.132.241
…
1 fallbackmx-out.facebook.com 204.15.20.130
3 fallbackmx-out.facebook.com 204.15.20.131
…
19 fallbackmx-out.facebook.com 69.63.184.102
22 fallbackmx-out.facebook.com 69.63.184.103
And so forth. These problems needs to be avoided before the concept as a whole can go into production.
I’ve decided I need to verify the accuracy of those 345 blocks. Performing a whois lookup on each one is useless as this doesn’t tell us much about what the block is being used for, never mind how. See “Building a DUL on demand” regarding why not. Instead I went back to the “offender_blocks.txt” file, and sorted it by block, which will sort things by the block, and then the IP and helo string. Now my heuristic is rather simple, if we only see one entry for a block – it means we jumped across blocks – I’ve only ever seen this happen with DSL blocks, so I’m not phased, this is a highly probable hit (the helo string definitely appears in another block too). If multiple helo strings appear in the same block then the chances are even better. A rather thorough look-through doesn’t reveal any obvious problems.
There are, however, two things which I can see which can cause problems:
- The Google and Facebook phenomenon as described above.
- If a virus was to hit and use some fixed helo string from all over the world.
For case one I could find the following false positive (Cases where they ended up in my list even though they should not have) cases:
141.113.0.0-141.113.255.255 141.113.102.111 mail-out.emea.daimler.com
141.113.0.0-141.113.255.255 141.113.102.112 mail-out.emea.daimler.com
141.113.0.0-141.113.255.255 141.113.102.114 mail-out.emea.daimler.com
193.188.96.0-193.188.97.255 193.188.97.109 batelco.com.bh (1)
193.188.96.0-193.188.97.255 193.188.97.111 batelco.com.bh
193.252.22.0-193.252.22.127 193.252.22.29 smtp20.orange.fr
193.252.22.0-193.252.22.127 193.252.22.31 smtp20.orange.fr
193.252.22.128-193.252.22.159 193.252.22.152 smtp5.freeserve.com
193.252.22.128-193.252.22.159 193.252.22.159 smtp5.freeserve.com
194.88.230.0-194.88.231.255 194.88.230.47 outbound1.tripolis.com
194.88.230.0-194.88.231.255 194.88.230.48 outbound1.tripolis.com
194.88.230.0-194.88.231.255 194.88.230.49 outbound1.tripolis.com
196.11.146.0-196.11.149.255 196.11.146.226 vodamail.co.za (1)
196.11.146.0-196.11.149.255 196.11.146.227 vodamail.co.za
196.14.0.0-196.14.255.255 196.14.136.122 jupiter.mobax.co.za (2)
196.14.0.0-196.14.255.255 196.14.136.123 jupiter.mobax.co.za
196.14.0.0-196.14.255.255 196.14.176.125 im.is.co.za (1)
196.15.128.0-196.15.255.255 196.15.163.16 mailman.gijima.co.za
196.15.128.0-196.15.255.255 196.15.163.31 mailman.gijima.co.za (3)
196.15.128.0-196.15.255.255 196.15.186.185 saons1.saoutsourcing.com
196.15.168.0-196.15.168.63 196.15.168.43 mail.cybertrade.co.za (1)
196.15.168.0-196.15.168.63 196.15.168.44 mail.cybertrade.co.za
196.15.215.224-196.15.215.255 196.15.215.242 f2em.co.za (1)
196.15.215.224-196.15.215.255 196.15.215.242 faxc.foneworx.co.za (4)
196.15.215.224-196.15.215.255 196.15.215.242 faxg.foneworx.co.za
196.15.215.224-196.15.215.255 196.15.215.242 faxi.foneworx.co.za
196.212.0.0-196.215.255.255 196.212.103.130 mail.infogro.co.za (5)
196.212.0.0-196.215.255.255 196.212.121.90 mimedefang.ddconline.co.za
196.212.0.0-196.215.255.255 196.212.121.91 proxy.ddconline.co.za
196.212.0.0-196.215.255.255 196.212.147.42 xanaduecopark.co.za (5)
196.212.0.0-196.215.255.255 196.212.27.210 pop3.eccsystems.co.za
196.212.0.0-196.215.255.255 196.212.43.2 pondkoi.igain.co.za (5)
196.212.0.0-196.215.255.255 196.212.43.5 pondkoi.igain.co.za (7)
196.212.0.0-196.215.255.255 196.212.52.154 exchsvr04.stefanutti.co.za (5)
196.212.0.0-196.215.255.255 196.212.52.158 exchsvr04.stefanutti.co.za
196.212.0.0-196.215.255.255 196.212.64.154 groblersdal.ctec.co.za (5)
196.212.0.0-196.215.255.255 196.212.78.219 chiweni (6)
196.212.0.0-196.215.255.255 196.212.78.26 warmbad-gw1.webintact.net (5)
196.212.0.0-196.215.255.255 196.213.57.242 micexsrv01.mic.local (5)
196.220.33.0-196.220.39.255 196.220.36.29 epr01.epresense.co.za
196.220.33.0-196.220.39.255 196.220.36.31 epr01.epresense.co.za (5)
196.34.0.0-196.35.255.255 196.34.85.234 groblersdal.ctec.co.za (2)
196.34.0.0-196.35.255.255 196.34.85.82 groblersdal.ctec.co.za (2)
196.34.0.0-196.35.255.255 196.34.85.90 groblersdal.ctec.co.za (2)
196.34.0.0-196.35.255.255 196.35.70.114 excel.interexcel.co.za (5)
196.34.0.0-196.35.255.255 196.35.70.120 excel.interexcel.co.za
196.34.0.0-196.35.255.255 196.35.77.66 mfwj050.mfw.is.co.za
196.34.0.0-196.35.255.255 196.35.77.67 mfwj050.mfw.is.co.za (5)
196.36.0.0-196.39.255.255 196.36.142.42 Maxinelpt (6)
196.36.0.0-196.39.255.255 196.36.142.42 aerialfrancis (6)
196.36.0.0-196.39.255.255 196.36.224.102 ppwebserver1.onsite.hosting.co.za (5)
196.36.0.0-196.39.255.255 196.36.224.82 ppwebserver1.onsite.hosting.co.za (5)
196.36.0.0-196.39.255.255 196.37.171.162 warmbad-gw1.webintact.net (2)
196.36.0.0-196.39.255.255 196.37.171.194 warmbad-gw1.webintact.net (2)
196.36.0.0-196.39.255.255 196.38.246.154 mail.southafrica.net
196.36.0.0-196.39.255.255 196.38.246.158 mail.southafrica.net
196.36.0.0-196.39.255.255 196.38.64.208 judy (6)
196.36.0.0-196.39.255.255 196.38.83.170 navara.monitoringsa.co.za (2)
196.36.0.0-196.39.255.255 196.38.83.172 navara.monitoringsa.co.za (5)
196.41.164.16-196.41.164.31 196.41.164.20 rohligctx3.rohlig.co.za (2)
196.41.192.0-196.41.223.255 196.41.198.247 mail.yslzone.net
196.41.192.0-196.41.223.255 196.41.198.254 mail.yslzone.net (2)(5)
196.41.192.0-196.41.223.255 196.41.214.100 f2em.co.za (1)
196.41.192.0-196.41.223.255 196.41.214.100 faxc.foneworx.co.za (5)
196.41.192.0-196.41.223.255 196.41.214.100 faxi.foneworx.co.za (5)
196.41.3.0-196.41.3.255 196.41.3.46 skywalker.nelspruitonline.co.za
202.137.232.0-202.137.239.255 202.137.234.232 rediffmail.com (1)
202.137.232.0-202.137.239.255 202.137.234.247 rediffmail.com (1)
202.137.232.0-202.137.239.255 202.137.236.226 rediffmail.com (1)
202.137.232.0-202.137.239.255 202.137.236.235 rediffmail.com (1)
202.137.232.0-202.137.239.255 202.137.237.241 rediffmail.com (1)
203.10.110.0-203.10.110.255 203.10.110.71 mail.netspace.net.au (2)
203.10.110.0-203.10.110.255 203.10.110.72 mail.netspace.net.au (2)
203.10.110.0-203.10.110.255 203.10.110.92 mail.netspace.net.au (2)
204.15.20.0-204.15.23.255 204.15.20.129 fallbackmx-out.facebook.com (8)
204.15.20.0-204.15.23.255 204.15.20.130 fallbackmx-out.facebook.com
…
204.15.20.0-204.15.23.255 204.15.20.158 fallbackmx-out.facebook.com
204.15.20.0-204.15.23.255 204.15.20.159 fallbackmx-out.facebook.com
204.15.20.0-204.15.23.255 204.15.20.236 vipfallbackmx-out.facebook.com
204.15.20.0-204.15.23.255 204.15.20.236 vipmx-out.facebook.com
204.15.20.0-204.15.23.255 204.15.20.237 vipfallbackmx-out.facebook.com
204.15.20.0-204.15.23.255 204.15.20.237 vipmx-out.facebook.com
207.46.0.0-207.46.255.255 207.46.248.40 delivery2.pens.microsoft.com
207.46.0.0-207.46.255.255 207.46.248.41 delivery2.pens.microsoft.com
207.46.0.0-207.46.255.255 207.46.248.66 delivery.pens.microsoft.com
207.46.0.0-207.46.255.255 207.46.248.69 delivery.pens.microsoft.com
209.85.128.0-209.85.255.255 209.85.132.184 an-out-0910.google.com
209.85.128.0-209.85.255.255 209.85.132.185 an-out-0910.google.com
209.85.128.0-209.85.255.255 209.85.132.186 an-out-0910.google.com
…
209.85.128.0-209.85.255.255 209.85.200.170 wf-out-1314.google.com
209.85.128.0-209.85.255.255 209.85.200.171 wf-out-1314.google.com
209.85.128.0-209.85.255.255 209.85.200.172 wf-out-1314.google.com
211.150.100.0-211.150.100.255 211.150.100.26 smtp.263xmail.com
211.150.100.0-211.150.100.255 211.150.100.28 smtp.263xmail.com
211.150.100.0-211.150.100.255 211.150.100.50 smtp.263.net (5)
212.227.126.128-212.227.126.255 212.227.126.171 moutng.kundenserver.de
212.227.126.128-212.227.126.255 212.227.126.177 moutng.kundenserver.de
212.227.126.128-212.227.126.255 212.227.126.179 moutng.kundenserver.de
212.227.126.128-212.227.126.255 212.227.126.183 moutng.kundenserver.de
212.227.126.128-212.227.126.255 212.227.126.186 moutng.kundenserver.de
212.227.126.128-212.227.126.255 212.227.126.187 moutng.kundenserver.de
212.227.126.128-212.227.126.255 212.227.126.188 moutng.kundenserver.de
212.55.128.0-212.55.191.255 212.55.154.21 sapo.pt (1)
212.55.128.0-212.55.191.255 212.55.154.22 sapo.pt (1)
212.55.128.0-212.55.191.255 212.55.154.24 sapo.pt (1)
212.55.128.0-212.55.191.255 212.55.154.26 sapo.pt (1)
213.199.128.0-213.199.153.255 213.199.138.181 smtp-dub.microsoft.com
213.199.128.0-213.199.153.255 213.199.138.191 smtp-dub.microsoft.com
216.176.48.0-216.176.63.255 216.176.57.166 bayt.com (1)
216.176.48.0-216.176.63.255 216.176.57.171 bayt.com (1)
216.49.80.0-216.49.95.255 216.49.92.103 mcafee.com (1)
216.49.80.0-216.49.95.255 216.49.92.104 mcafee.com (1)
63.226.35.128-63.226.35.255 63.226.35.135 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.136 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.138 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.139 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.140 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.142 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.143 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.145 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.146 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.147 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.150 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.151 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.152 value-smtp.infusionsoft.com
63.226.35.128-63.226.35.255 63.226.35.153 basic-smtp.infusionsoft.com
64.233.160.0-64.233.191.255 64.233.166.176 py-out-1112.google.com
64.233.160.0-64.233.191.255 64.233.166.177 py-out-1112.google.com
64.233.160.0-64.233.191.255 64.233.166.178 py-out-1112.google.com
64.233.160.0-64.233.191.255 64.233.166.179 py-out-1112.google.com
64.233.160.0-64.233.191.255 64.233.166.180 py-out-1112.google.com
64.233.160.0-64.233.191.255 64.233.166.181 py-out-1112.google.com
64.233.160.0-64.233.191.255 64.233.166.182 py-out-1112.google.com
64.233.160.0-64.233.191.255 64.233.166.183 py-out-1112.google.com
69.63.176.0-69.63.191.255 69.63.184.101 fallbackmx-out.facebook.com (8)
69.63.176.0-69.63.191.255 69.63.184.102 fallbackmx-out.facebook.com
69.63.176.0-69.63.191.255 69.63.184.103 fallbackmx-out.facebook.com
69.63.176.0-69.63.191.255 69.63.184.104 fallbackmx-out.facebook.com
69.63.176.0-69.63.191.255 69.63.184.105 fallbackmx-out.facebook.com
69.63.176.0-69.63.191.255 69.63.184.106 fallbackmx-out.facebook.com
69.63.176.0-69.63.191.255 69.63.184.107 fallbackmx-out.facebook.com
69.63.176.0-69.63.191.255 69.63.184.108 fallbackmx-out.facebook.com
69.63.176.0-69.63.191.255 69.63.184.109 fallbackmx-out.facebook.com
69.63.176.0-69.63.191.255 69.63.184.110 fallbackmx-out.facebook.com
72.14.192.0-72.14.255.255 72.14.204.224 qb-out-0506.google.com
72.14.192.0-72.14.255.255 72.14.204.225 qb-out-0506.google.com
72.14.192.0-72.14.255.255 72.14.204.226 qb-out-0506.google.com
…
72.14.192.0-72.14.255.255 72.14.252.157 po-out-1718.google.com
72.14.192.0-72.14.255.255 72.14.252.158 po-out-1718.google.com
72.14.192.0-72.14.255.255 72.14.252.159 po-out-1718.google.com
80.12.242.0-80.12.242.65 80.12.242.26 smtp20.orange.fr
80.12.242.0-80.12.242.65 80.12.242.27 smtp20.orange.fr
80.12.242.0-80.12.242.65 80.12.242.46 smtp21.orange.fr
80.12.242.0-80.12.242.65 80.12.242.47 smtp21.orange.fr
81.169.144.0-81.169.156.255 81.169.146.161 mo-p00-ob.rzone.de
81.169.144.0-81.169.156.255 81.169.146.162 mo-p00-ob.rzone.de
With the exception entries marked with (?) these IPs all resolve back to the same supplied helo name, which indicates that these are in fact legit. There is probably a couple I missed but these jumped out at me, and with Facebook being the exception they can be identified using some reverse DNS mechanisms.
Notes:
- Resolves to a subdomain of the supplied HELO. Eg, vodamail.co.za helos resolves to relay1.vodamail.co.za and relay2.vodamail.co.za.
- Resolves to jupiter.mobaxgroup.com. This means the block is probably static but that mail coming from this mail server will (should) likely still be rejected due to the fact that it will fail any attempt at validating the helo string. Other entries marked with (2) has similar attributes.
- .16 resolves (currently) to mail.yabbie.co.za, however, .31 correctly resolves to mailman.gijima.co.za which in effect clears this whole block. saons1.saoutsourcing.com sits on what seems to be an IP that should helo with astralgw.astralfoods.com. Either way, it seems this block is, as a matter of fact, not dynamic.
- Same IP as mail2.f2em.co.za – NAT perhaps?
- Invalid, but in the same block as other hosts that seems legit. Therefor this would classify under misconfiguration as well.
- Would fail a HELO syntax check.
- Forward resolution works, but not reverse.
- Cleared based on information from whois.
This brings up a few requirements for implementing such a mechanism:
- The admin should have the ability to subdivide blocks even further than what whois does, and keep this information associated with the parent block. Thus each block except 0.0.0.0/0 will have a parent block. These parents are probably implicit in nature as 192.168.0.0/24 is obviously a sub-block of 192.168.0.0/16 of 192.128.0.0/9 of 192.0.0.0/8 of 0.0.0.0/0.
- The admin should have the ability to “fix” blocks as “static” or “dynamic” and the system should not automatically change these blocks, if these allocations should be changed the admin should merely be notified of such change request.
- Even if a HELO string appears for more than one host, if the reverse lookup of the IP resolves to the same name then it’s probably static and should be marked as such. This should probably mark the entire block as static, however, a bot could make a request to find it’s “visible” IP, perform a reverse resolution on that and then use that as it’s HELO string, thereby generating a false negative.
- (3) could potentially be relaxed even further to include cases marked with (1) above.
- The scheme should quite probably not be used without intervention, in other words: It should be used to identify probable DUL blocks, which should then be “ok”ed by an admin.
- IPs that reverse resolves to “localhost” should be blacklisted in some other mechanism. In fact, these should actually get nailed at HELO verification check time.
- whois information should be cached, and not re-looked up for a caching period time (say 30 days or something). In the case where an admin sub-divided a block and the whois info on the parent block changed the admin should probably be notified of such change.
- We should probably use a threshold mechanism where the same HELO triggers if it appears from multiple blocks, or if multiple HELOs hops around in the same block.
The concepts in this approach seems much more feasible than a previous pure whois concept, and in fact I believe this is workable with some refinement. I’ll probably start implementing this soon to see what effect it would have, but if I’m not mistaken I believe I should see a significant reduction in incoming SPAM – potentially at the cost of a few false positives, but these should be relatively easy to clear up.