progressif

A clever person solves a problem. A wise person avoids it.

Build your own DNSBL and roll it with ruby

written 11 months ago

Intro

We are assuming that CentOS 5.5 is our Linux distribution. A free derivative of RHEL. Basically a DNSBL is a DNS zone.

If we want to reject 192.168.0.1 we need an entry like this one:

1.0.168.192.dnsbl.tehif.eu 360 IN A 127.0.0.2

A reverse resolve of the IP with the domain name ending pointing to 127.0.0.x when x > 1 will trigger reject. In such cases the zone has to be updated dynamic with nsupdate.

Getting wet

Let's generate a random TSIG key which we will be used to update our dnsbl domain.

# dnssec-keygen -a hmac-md5 -b 512 -n HOST dnsbl.tehif.eu

The secret key can be extracted from Kdnsbl*.private like that:

# cat Kdnsbl*.private |grep Key| awk '{print $2'}
n0eLOLK9V4DqdOn225oIJMKF0sUZnthwZFHGYjhlyEg6fwBfQSDtqn==

We need to append our secret key to named.conf like that:

key "dnsbl" {
    algorithm hmac-md5;
    secret "n0eLOLK9V4DqdOn225oIJMKF0sUZnthwZFHGYjhlyEg6fwBfQSDtqn==";
};

Then we need to configure our dnsbl domain in named.conf like that:

zone "dnsbl.tehif.eu" {
    type master;
    file "dnsbl.tehif.eu";
    allow-update { key dnsbl; };
    allow-transfer { none; };
};

An example dnsbl.tehif.eu zone file to start with:

$ORIGIN .
$TTL 86400  ; 1 day
dnsbl.tehif.eu      IN SOA  ns.tehif.eu. if.tehif.eu. (
            2007100344 ; serial
            3600       ; refresh (1 hour)
            900        ; retry (15 minutes)
            2419200    ; expire (4 weeks)
            14400      ; minimum (4 hours)
            )
        NS  ns.tehif.eu.
        A   46.40.126.144
        TXT "v=spf1 a mx ~all"
        AAAA    2001:67c:20d0:29::1

Refresh named:

# rndc reconfig

Administrating with ruby

# mkdir /root/bin/; vim /root/bin/dnsbl

Press 'i' and paste there:

#!/usr/bin/env ruby
require 'ipaddr'
key = "dnsbl:n0eLOLK9V4DqdOn225oIJMKF0sUZnthwZFHGYjhlyEg6fwBfQSDtqn=="
if ARGV[0].nil? or ARGV[1].nil?
puts "No arguments supplied"
puts "Arguments: [add/delete] [IPv4/IPv6 Address]"
puts "Example: ./nsupdate.rb add 192.168.0.1" 
else
if ARGV[0] != 'add' and ARGV[0] != 'delete'
puts "The first argument can be: [add/delete]"
else
begin
  ip = IPAddr.new ARGV[1]
  if ip.ipv6?
    reverse = ip.reverse[0,ip.reverse.length-9]
  elsif ip.ipv4?
    reverse = ip.reverse[0,ip.to_s.length]
  end 
  reverse += '.dnsbl.tehif.eu'
  query = "server ns.tehif.eu\nupdate #{ARGV[0]} #{reverse} 360 A 127.0.0.2\nsend"
  `echo "#{query}" | nsupdate -y #{key}`
  puts `host #{reverse}`
rescue
  puts "Wrong IP supplied."
end 
end 
end

Edit the secret key by hand. Press Escape. You can change the domain name with search and replace like this:

:%s/tehif\.eu/domain\.com/g

Write and quit from vim with:

:wq

Make your script executable:

# chmod 700 /root/bin/dnsbl

Then you can finally add/delete IPs to/from your dnsbl like that:

# dnsbl add 192.168.0.1
# dnsbl delete 192.168.0.1

It works for IPv6 too:

# dnsbl add ::1
# dnsbl delete ::1

Add dnsbl.tehif.eu to sendmail

In /etc/sendmail/sendmail.mc before "MAILER(smtp)dnl" append:

FEATURE(`dnsbl', `dnsbl.tehif.eu')dnl

Then just restart sendmail:

# service sendmail restart

Happy Spam rejecting!

Leave a Reply