Thursday, February 28, 2008

Rbldns How to

What is this document?

I wrote this HOWTO so that others can have one place to stop and see how to setup their own private RBL list. The information is out there, but scattered all over the place.

The color convention I use is to have the headlines in gray and the code / shell scripts in yellow

What is rbldns?

Rbldns is a suite of programs in conjunction with dnscache to provide RBL service. In a nutshell IPs put into the rbldns data file show up as 127.0.0.1 responses to a specially crafted DNS query.

The IP address go into the file in the normal readable way, ie 192.168.0.1, and you query for them by reversing the address, like 1.0.168.192.example.com

How do I use rbldns?

Normally you don't use it directly, you have a program query an RBL server and based on the result of the query it either runs or doesn't run the program following it.

For example with Qmail you'll change your qmail-smtpd/run file from
tcpserver 0 smtp /var/qmail/bin/qmail-smtpd
to
tcpserver 0 smtp /usr/local/bin/rblsmtpd -a whitelist.example.com -r blacklist.example.com -r relays.ordb.org /var/qmail/bin/qmail-smtpd

According to the rblsmtpd man page, the -r and -a switches mean:

Switch If successful, do this
-r Quit
-a Don't do other lookups, and continue on


In this case the steps are:
1. Do a lookup against whitelist.example.com, if sucessful then skip the other lookups and go on to accepting the smtp request
2. Do a lookup against blacklist.example.com, if that's successful then quit out printing a "RBL denied" message to the client.
3. Same as #2 but against relays.ordb.org

How do I make my own RBL?

You should know how to setup Dnscache before trying to do this. The steps are pretty easy, but its helpful if you know your way around

Setting up the rbldns is pretty easy, just follow the directions on the RBLdns-conf page:

 rbldns-conf rbldns dnslog /etc/rbldns/black 127.0.0.2 rbl.example.com
rbldns-conf rbldns dnslog /etc/rbldns/white 127.0.0.3 whitelist.example.com

This says to setup a RBL on 127.0.0.2 that answers queries for *.rbl.example.com, and and RBL on 127.0.0.3 that answers for *.whitelist.example.com

Note: the 'rbl' and 'whitelist' names are arbitrary. RBLdns doesn't know if this is a 'good' or a 'bad' list of addresses -- it just knows that if someone asks for 1.0.168.192.bad.example.com on IP 127.0.0.2 it should answer with a 127.0.0.1 if it has it, or nothing if it doesn't.

Start these services up like all of DJB's other daemons:

 ln -s /etc/rbldns/black /service
ln -s /etc/rbldns/white /service


To see if they are running, do a
 lsof -n -i:53


And you should see listeners on 127.0.0.2 and 127.0.0.3

Why would I want to use a local RBL?

Why shouldn't you just relay on publically available RBLs? For a couple of reasons:
1. You know a couple of IPs are good and you don't want to waste bandwith by checking them against an RBL on the internet
2. Same thing for bad ones
3. You know your friend has a DSL line at home and an RBL blocks all home DSL users, you want to continue using the service but want to accept his mail.
4. You want to keep a 2nd source of information about who is sending mail to your server

So part of this is being a good netizen. If you know you're getting a lot of email from a handful of IPs, you should put those in your own whitelist so that you're not continously asking the public RBLs if they are okay

How to resolve *.(whitelist|rbl).example.com -- DNScache way

Now that we have the RBL service ready to go we have to be able to query it. Like we told dnscache to send all queries for *.example.com to the local tinydns IP address, we're going to do that for the RBL service.

This is the part that took me a while to think about: how do I serve both *.example.com and *.rbl.example.com? Well the same way you've already done it: through a dnscache setting.

Add two entries to your dnscache "forwarding" information:

 cd /service/dnscache/root/servers
echo 127.0.0.2 > rbl.example.com
echo 127.0.0.3 > whitelist.example.com
svc -h /service/dnscache


This tells dnscache that when it gets a query for *.whitelist.example.com to send it off to the server on 127.0.0.3, *.rbl.example.com queries should go to 127.0.0.2. If you're setup TinyDns this should be familiar

How to resolve *.(whitelist|rbl).example.com -- TinyDns way

This might be a little cleaner if you're already serving up *.example.com results. You put in your tinydns file pointers to the (rbl|whitelist) lists:

 cd /service/tinydns/root/
echo "&rbl.example.com:127.0.0.2:a" >> data
echo "&whitelist.example.com:127.0.0.3:a" >> data
make
svc -h /service/tinydns

So now when your tinydns server is queried for 1.0.168.192.rbl.example.com it will look at its file and say "That's handled by 127.0.0.2 and I'll ask it"

How do I add entries to my RBL?

Scenerio: a spammer is continously sending us email from 192.168.5.100 while our friend is sending from 192.168.6.56. We would like to avoid using public RBL servers for these two addresses.

Step 1: add the spammer to your spam list:

 cd /service/rbl/black/root
echo 192.168.5.100 >> data
make

Step 2: Add your friend to your good list:

 cd /service/rbl/white/root
echo 192.168.6.56 >> data
make

Now query to see if they are in there:

 dnsip 100.5.168.192.rbl.example.com
dnsip 100.5.168.192.whitelist.example.com
dnsip 56.6.168.192.rbl.example.com
dnsip 56.6.168.192.whitelist.example.com

Notice I queried both sets of databases to make sure we didn't screw up who is a spamer versus who is our friend.

If you don't get a 127.0.0.1 result from a query when you think you should, HUP the appropriate daemon:

 svc -h /service/rbl/black
svc -h /service/rbl/white

How do I now use an RBL service?

Now that you have the local RBLdns server(s) working through simple queries, modify your other scripts to use them. With qmail you do that like this:

exec /usr/local/bin/tcpserver -R -v -p \
-x /var/qmail/control/tcp.smtp.cdb \
-u $QMAILUID -g $QMAILGID \
mail.example.com smtp \
/usr/local/bin/rblsmtpd \
-a whitelist.example.com \
-r rbl.example.com \
-r relays.ordb.org \
-r bl.spamcop.net \
/var/qmail/bin/qmail-smtpd 2>&1

This is what your implementation will probably look like: an initial test against your goodlist, if that passes the continue on to the qmail-smtpd part. If that fails, then test against your local bad list. If that is sucessful then quit out. If not, continue on to your 2nd and 3rd RBLs.

How do I test my RBL?

You test an RBL by sending it a query. If it is in the database then it should return with a 127.0.0.x (1 or 2) answer. If it isn't in there, then nothing comes back.

The trick is to remember to reverse your IP address, so that 192.168.0.1 becomes 1.0.168.192.myrbldomain.com

Here's a simple program to check names fed on stdin:

 #!/usr/bin/perl

use Net::DNS;
use strict;
my ($res, @rbls);

@rbls = qw (rbl.example.com whitelist.example.com);

$res = Net::DNS::Resolver->new;
while (<>) {
my ($rev, $ip);
chomp;
$ip = $_;
$rev = (join ".", reverse (split /\./, $ip) ); # ie 4.3.2.1.
foreach my $rbl (@rbls) {
my $query = $res->search("$rev.$rbl");
next unless ($query);
my $hit;
foreach my $rr ($query->answer) {
next unless $rr->type eq "A";
$hit = $rr->address;
last;
}
next unless $hit;
printf "%-20s %-20s $hit\n", $ip, $rbl;
}
}

How do I contact you?

If you have any questions or comments, or just want to say thanks, drop me a line at anand.shah@coolaquarius.com

No comments: