Order of Responses to Queries from Outside a Network
Kevin Darcy
kcd at daimlerchrysler.com
Tue Jan 27 04:03:40 UTC 2004
Martin McCormick wrote:
> Address sorting in bind works beautifully for queries inside
>our network, but I have been asked to add a slight modification.
>
> Is there a way to tell BIND 9.2.2rc1 to always put a given A
>record first in the list sent to queries from outside the network
>while still maintaining the address sorting for queries from inside the
>network?
>
> In other words, we want not to break the address sorting
>feature which works inside our network, but add a sort order for
>everyone outside.
>
> The idea is to guide outsiders to a specific server that can
>handle the load and list servers on campuses with less network
>capacity last.
>
>
Well, as you've no doubt noticed, negation doesn't seem to work too well
in sortlist clauses.
The only thing that comes to mind is to create an ACL of everything
*but* your network(s) and then add a subclause for that to your sortlist
clause, favoring a particular address or range of addresses, e.g.
(assuming you hypothetically had the entire lowest quarter -- nets 0
through 63 -- of the IPv4 address range assigned to you):
acl notmynet { 128/1; 64/2; };
options {
...
sortlist {
{ mysubnet1; mysubnet1; };
{ mysubnet2; mysubnet2; };
...
{ notmynet; { 1.2.3.4 }; };
};
};
It's a little laborious to work out by hand all of the prefixes which
define the "negative" of a given prefix, so here's a little
quick-and-dirty Perl script that can do it:
#!/usr/bin/perl
$input = $ARGV[0];
die "invalid syntax!" unless ($input =~ m%^\d+(\.\d+)*/\d{1,2}$%);
($netstring, $numbits) = split(m%/%, $input);
die "prefix too large!" if ($numbits > 32);
@octet = split(/\./, $netstring);
die "too many octets!" if (scalar(@octet) > 4);
for ($i = $#octet; $i >= 0; $i--) {
die "oversized octet!" if ($octet[$i] > 255);
$netnum += ($octet[$i] * (256**(3-$i)));
}
die "network not on power-of-two boundary" if ($netnum%(2**(32-$numbits)));
for ($i = 31; $i >= (32 - $numbits); $i--) {
if ($netnum & (1 << $i)) {
print_prefix($partial, (32 - $i));
$partial += (1 << $i);
} else {
print_prefix($partial + (1 << $i), (32 - $i));
}
}
sub print_prefix {
my ($raw, $bits) = @_;
my ($octet, $newbits) = (0, $bits - 8);
print int($raw/(1<<24));
$raw %= (1<<24);
while ($newbits > 0) {
$octet++;
print "." . int($raw/(1<<(24 - ($octet * 8))));
$raw %= (1<<(24 - ($octet * 8)));
$newbits -= 8;
}
print "/$bits\n";
}
E.g. running the script with a command-line parameter of "53/8" yields:
128/1
64/2
0/3
32/4
56/5
48/6
54/7
52/8
(Figuring out the "negative" of several different non-adjacent prefixes
combined is left as an algorithmic exercise for the reader :-)
- Kevin
P.S. You do realize that other nameservers/resolvers caching the query
results will muck up your careful ordering, right?
More information about the bind-users
mailing list