Internal DNSBL - use at your own risk
Posted: Thu Aug 27, 2009 3:36 pm
Here is an ugly little script I whipped together to create my own DNSBL visible from the normal DNS tools withing Plesk. Basically it looks for all IPs that are responsible for more than two rejected mails for the last day, subtracts IPs that sent at least one good message in the same time frame, then adds DNS entries (A and TXT record) into Plesk. The TXT record has some information about that IP at the time it was listed, as well as the date. My goal wasn't to end spam, but as an exercise in creating an internal block list that was visible to Plesk. A return of 127.0.0.2 is added via the script, and 127.0.0.3 by manual entry.
Caveats:
1. Perl would almost certainly be a better choice, but my perl-fu is weak
2. IPs are pretty stale - up to 24 hours old
3. Roach motel design - IPs go in, but they don't come out
4. Probably won't work on any system but mine.
5. Did I mention it is pretty ugly? And slow.
6. Designed for my email traffic. Yours is different.
7. One good email negates blacklisting
8. Limited time horizon for pseudo-reputation evaluation
9. Requires qmail-scanner to REJECT messages. If you aren't having qmail-scanner reject, then all you will do is waste cpu.
10. It will cause you to lose email (duh), break your system, date your sister, shoot your dog, and set fire to your house. You've been warned!
OK, now to it!
Step 1:
Create the directory /var/spool/qscan/rep - this will act as the working directory for the script, as well as keep a record of ham IPs and spam IPs/hit count per day.
Step 2:
I had to adjust the maillog.processed file to rotate daily. Mine was originally set to rotate every 3 days. Just make sure you run the script before maillog.processed is rotated off, or all you'll end up parsing is an empty file.
Step 3:
Create a suitable domain in plesk with only DNS turned on. Optional: I removed all default DNS entries except for the NS and A records.
Step 4:
Add the following script to /etc/cron.daily (I prefixed the name with "00" to make sure it is run before maillog.processed is rotated off.) You will need to modify it to work in your environment.
Like I said - UGLY! I thought about hacking up qmail-scanner to spit out an easier to parse line of text in the log file, but that would mean any updates to qmail-scanner would break the script - hence the awk/sed insanity.
You can query my setup at dnsbl.pessimists.net, but please be gentle! You can test with the following commands, where 127.0.0.2 are test records that will always return something:
I HIGHLY recommend testing before you use it to outright block connections. The way I like best is to add it to spamassassin with a score of 0.001 and then parse the qmail-scanner log. Here is my asbl.cf file I used for testing. If you add this to spamassassin unmodified it will query my server, not yours.
Feedback is most welcome!
Caveats:
1. Perl would almost certainly be a better choice, but my perl-fu is weak
2. IPs are pretty stale - up to 24 hours old
3. Roach motel design - IPs go in, but they don't come out
4. Probably won't work on any system but mine.

5. Did I mention it is pretty ugly? And slow.
6. Designed for my email traffic. Yours is different.
7. One good email negates blacklisting
8. Limited time horizon for pseudo-reputation evaluation
9. Requires qmail-scanner to REJECT messages. If you aren't having qmail-scanner reject, then all you will do is waste cpu.
10. It will cause you to lose email (duh), break your system, date your sister, shoot your dog, and set fire to your house. You've been warned!
OK, now to it!
Step 1:
Create the directory /var/spool/qscan/rep - this will act as the working directory for the script, as well as keep a record of ham IPs and spam IPs/hit count per day.
Step 2:
I had to adjust the maillog.processed file to rotate daily. Mine was originally set to rotate every 3 days. Just make sure you run the script before maillog.processed is rotated off, or all you'll end up parsing is an empty file.
Step 3:
Create a suitable domain in plesk with only DNS turned on. Optional: I removed all default DNS entries except for the NS and A records.
Step 4:
Add the following script to /etc/cron.daily (I prefixed the name with "00" to make sure it is run before maillog.processed is rotated off.) You will need to modify it to work in your environment.
Code: Select all
#/bin/bash
# DNSBL list generator for Plesk
# Andy Sutton - sutton@nefw.net
today=`date +%Y%m%d`
workdir='/var/spool/qscan/rep'
logloc='/usr/local/psa/var/log'
logfile='maillog.processed'
#Generate list of more than one rejected and any clear IP addresses
cat $logloc/$logfile | grep Clear | awk '{print $6}' | sed -e 's/Clear\:RC\:\([0-1]\)(//' | \
sed -e 's/)\:SA\:\([0-1]\)(/ /' | awk '{print $1}'| sort | uniq > $workdir/hamip_$today
cat $logloc/$logfile | grep SPAM-REJECTED | awk '{print $6}' | sed -e 's/SA\:SPAM-REJECTED\:RC\:0(//' | \
sed -e 's/)\:SA\:1(/ /' | awk '{print $1}' | sort | uniq -c | sort -n | grep -v " 1 " > $workdir/spamip_$today
# Give 'em a pass for even one ham message
awk >$workdir/dns_file 'NR==FNR{arr[$1];next}!($2 in arr)' $workdir/hamip_$today $workdir/spamip_$today
# Feed 'em into Plesk DNS
while read i; do
j=`echo $i | awk '{print $2 }'`
k=`echo $j | sed -e 's/\./ /g' | awk '{print $4"."$3"."$2"."$1}'`
l=`echo $i | awk '{print $1 }'`
m=`dig $k.in-addr.arpa ptr +short | tr '\n' ' '`
/usr/local/psa/bin/dns -a dnsbl.pessimists.net -a $k -ip 127.0.0.2 >/dev/null 2>&1
/usr/local/psa/bin/dns -a dnsbl.pessimists.net -txt "Added: $today IP: $j Hits: $l Names: $m" -domain $k >/dev/null 2>&1
done < $workdir/dns_file
# Cleanup
rm $workdir/dns_file
You can query my setup at dnsbl.pessimists.net, but please be gentle! You can test with the following commands, where 127.0.0.2 are test records that will always return something:
Code: Select all
host 2.0.0.127.dnsbl.pessimists.net
host -t TXT 2.0.0.127.dnsbl.pessimists.net
Code: Select all
header RCVD_IN_ASBL eval:check_rbl('asbl-lastexternal', 'dnsbl.pessimists.net.', '127.0.0.2')
describe RCVD_IN_ASBL Received via relay listed in Pessimists.net RBL - script genned
score RCVD_IN_ASBL 0.0001
tflags RCVD_IN_ASBL net
header RCVD_IN_ASMBL eval:check_rbl('asmbl-lastexternal', 'dnsbl.pessimists.net.', '127.0.0.3')
describe RCVD_IN_ASMBL Received via relay listed in Pessimists.net RBL - manual add
score RCVD_IN_ASMBL 0.0001
tflags RCVD_IN_ASMBL net