On 2014-12-09 11:33, John Merriam wrote:
On Tue, 9 Dec 2014, Ted Unangst wrote:
Curious if anyone knows a simple way to prevent resolution of one word
hostnames. Either via resolv.conf or unbound.conf.
*snip*
I'm by no means a DNS expert but I've been dealing with it for a long
time. The only thing I can think of to force one word hostnames to be
resolved in the search domain exclusively would be to patch the
resolver
library.
*snip*
This TLD explosion bothers me too. After thinking about it for a while
I came up with a solution that works for me. It does not involve
patching the resolver library as I mentioned before. It would be nice
to patch the resolver library because it would guarantee that your
systems wouldn't look up any of the crummy TLDs that you don't want them
to regardless of what DNS servers they're using. But I decided against
doing that because I figured it would be a controversial issue and it
probably wouldn't be accepted for inclusion in OpenBSD and carrying
around local patches isn't fun.
So, I quickly hacked together a dirty little script I call tldblocker.
It downloads the list of TLDs from IANA then removes the TLDs you want
to allow then uses the trimmed TLD list that contains the TLDs you want
to block to create a file that can be included in your DNS server config
that points the blocked TLDs at an empty zone file. This isn't exactly
what you were looking for but I am sending it along in case you find it
useful.
Here is the script:
#!/usr/bin/perl
# tldblocker v0.0.1
# Use this at your own risk...
# You should check what this thing is really doing at least
occasionally.
$tldurl = "http://data.iana.org/TLD/tlds-alpha-by-domain.txt";
$adminaddress = "admin\@example.com";
$allowedfile = "/usr/local/var/tldblocker/tldblocker.allowedtlds";
$tldfile = "/usr/local/var/tldblocker/tldblocker.alltlds";
$tempfile = "/tmp/tldblocker.alltlds.temp";
$md5cmd = "/bin/md5 -q";
$downloadcmd = "/usr/local/bin/wget -q -O " . $tempfile . " " . $tldurl;
$outfile = "/var/named/namedb/named.zones.tldblocker";
$emptyzonefile = "namedb/empty.zone";
$namedrestartcmd = "/etc/rc.d/isc_named restart";
$smprog = "/usr/sbin/sendmail";
if (!-s $allowedfile) {
# I think we should allow at least some TLDs!
die "I could not find the allowed TLDs file!\n";
}
system $downloadcmd;
# Did download command exit with status 0?
if ($? != 0) {
# Download command failed, send message to admin...
system "echo -e \"Subject: tldblocker failed to download TLD
file!\\n\\ntldblocker failed to download the TLD file from the following
URL:\\n\\n$tldurl\\n\\nGo take a look.\" | $smprog $adminaddress";
exit 1;
}
# Do a basic sanity check on the downloaded file
open TLDFH, "<$tempfile";
@tldsin = <TLDFH>;
close TLDFH;
$quickcheck = join "", @tldsin;
if (($tldsin[0] !~ /^# Version /) ||
($quickcheck !~ /\nCOM\n/i) ||
($quickcheck !~ /\nNET\n/i) ||
($quickcheck !~ /\nORG\n/i) ||
($quickcheck !~ /\nEDU\n/i) ||
($quickcheck !~ /\nGOV\n/i) ||
($quickcheck !~ /\nMIL\n/i) ||
($quickcheck !~ /\nINT\n/i) ||
($quickcheck !~ /\nARPA\n/i)) {
# This doesn't look right, send message to admin
system "echo -e \"Subject: tldblocker dowloaded TLD file failed sanity
check!\\n\\nThe TLD file downloaded by tldblocker from the following
URL:\\n\\n$tldurl\\n\\nfailed the basic sanity check. Go take a look.\"
| $smprog $adminaddress";
exit 1;
}
undef $quickcheck;
# See if we need to do anything
$oldtldmd5 = `$md5cmd $tldfile`;
$newtldmd5 = `$md5cmd $tempfile`;
$oldallowedmd5 = `cat $allowedfile.MD5`;
$newallowedmd5 = `$md5cmd $allowedfile`;
$updateneeded = 0;
$dontunlink = 0;
if ($oldtldmd5 ne $newtldmd5) {
$updateneeded = 1;
system "mv $tempfile $tldfile";
$dontunlink = 1;
}
if ($oldallowedmd5 ne $newallowedmd5) {
$updateneeded = 1;
system "$md5cmd $allowedfile > $allowedfile.MD5";
}
# Update if necessary
if ($updateneeded == 1) {
open ALLOWEDFH, "<$allowedfile";
@allowed = <ALLOWEDFH>;
close ALLOWEDFH;
$i = 0;
foreach $i (0..$#allowed) {
chomp $allowed[$i];
}
@blocktlds = @tldsin;
undef @tldsin;
splice @blocktlds, 0, 1;
$c = 0;
$blocktldsend = $#blocktlds;
while ($c <= $blocktldsend) {
chomp $blocktlds[$c];
if ($blocktlds[$c] =~ /^([A-Za-z0-9\-])+$/) {
$i = 0;
foreach $i (0..$#allowed) {
if ($blocktlds[$c] =~ /^$allowed[$i]$/i) {
splice @blocktlds, $c, 1;
$c--;
$blocktldsend--;
last;
}
}
} else {
# Probably a comment?
splice @blocktlds, $c, 1;
$c--;
$blocktldsend--;
}
$c++;
}
if (($#blocktlds >= 0) && ($blocktlds[0] ne "")) {
$i = 0;
foreach $i (0..$#blocktlds) {
$zonesout .= "zone \"";
$zonesout .= $blocktlds[$i];
$zonesout .= "\" in { type master; file \"";
$zonesout .= $emptyzonefile;
$zonesout .= "\"; };\n";
}
$zonesoutlen = length $zonesout;
open OUTFH, ">$outfile";
syswrite OUTFH, $zonesout, $zonesoutlen;
close OUTFH;
system "$namedrestartcmd >/dev/null 2>&1";
}
}
if ($dontunlink != 1) {
unlink $tempfile;
}
-------------------
And here is an empty.zone file:
$TTL 28800
@ IN SOA dns1.example.com. hostmaster.example.com. (1
1800 900 604800 28800)
IN NS dns1.example.com.
IN NS dns2.example.com.
-------------------
The tldblocker.allowedtlds file should contain the TLDs that you want to
allow, one per line without the dot (don't forget arpa...).
To actually use it, you include the named.zones.tldblocker that is
produced by the tldblocker script in your DNS server config.
Setting a cron job to run it once a week or so would probably be a good
idea to keep the list updated.
I designed this for ISC BIND which is what I use but it should be easy
enough to modify it for other DNS servers assuming their configuration
syntax allows the inclusion of additional files like BIND does.
If anyone wants a copy of my allowedtlds file that basically puts things
back the way they were before the TLD explosion, send me a message.
Doing it this way in the DNS server has the advantage that it works for
all machines that use your DNS servers including Windows and mobile
devices. I would imagine that blocking the crud TLDs will have a spam
reducing and increased malware avoidance effect as well.
Oh, and if you do use this, don't forget that it is there and doing its
thing when something isn't working in DNS...
--
John Merriam