leica
12-23-2010, 09:15 AM
Warning: The majority of this post is unexplained code and config. The uninitiated shall enter at their own risk and I shall not be liable for any head explosions or other damages.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Last week, my Qwest gateway/router went out and I replaced it with an ancient D-Link that doesn't resolve local domain names. Many applications on my network depend on local DNS, so I decided to set up BIND on my HTPC. Initially, this was done using static IP addresses and a static zone file.
This morning, after having no sleep last night (I stayed up working on a Tumblr layout), I figured out this cool thing you can do with Avahi:
$ avahi-browse -prt _workstation._tcp
+;eth0;IPv4;travis\032\09148\0585b\05839\05863\058 83\05891\093;Workstation;local
+;eth0;IPv4;htpc\032\09100\05813\05872\05831\058e6 \058a0\093;Workstation;local
=;eth0;IPv4;travis\032\09148\0585b\05839\05863\058 83\05891\093;Workstation;local;travis.local;192.16 8.0.101;9;
=;eth0;IPv4;htpc\032\09100\05813\05872\05831\058e6 \058a0\093;Workstation;local;htpc.local;192.168.0. 103;9;So yeah, a parsable list of workstations on the network, their domain names, and their IPs. But how do we get this information to the DNS server?
I ended up writing a cron script (in PHP, lol). The implementation is horrible due to my sleep deprivation but you can get the general idea from this:
#!/usr/bin/php
<?php
$avahidata = explode("\n",`avahi-browse -ptr _workstation._tcp`);
$hosts="server localhost\nzone local\n";
$pointers="server localhost\nzone 0.168.192.in-addr.arpa\n";
$oldhosts="server localhost\nzone local\n";
$oldpointers="server localhost\nzone 0.168.192.in-addr.arpa\n";
for($i=0;$i<count($avahidata)-1;$i++){
$hostInformation=explode(";",$avahidata[$i]);
if($hostInformation[0] != "=") continue;
$hostname=$hostInformation[6];
$hostaddr=$hostInformation[7];
$ptraddr=implode(".",array_reverse(explode(".",$hostaddr)));
$hosts.="update add $hostname 2400 A $hostaddr\n";
$pointers.="update add $ptraddr.in-addr.arpa 2400 PTR $hostname\n";
$oldhosts.="update delete $hostname A\n";
$oldpointers.="update delete $ptraddr.in-addr.arpa PTR\n";
}
$hosts.="send\n";
$pointers.="send\n";
$oldhosts.="send\n";
$oldpointers.="send\n";
echo `cat .dns_purge_hosts | nsupdate`;
echo `cat .dns_purge_pointers | nsupdate`;
echo `echo "$hosts" | nsupdate`;
echo `echo "$pointers" | nsupdate`;
file_put_contents(".dns_purge_hosts",$oldhosts);
file_put_contents(".dns_purge_pointers",$oldpointers);
?>
Now, of course BIND is configured to allow updates from localhost...
acl lan { 192.168.0/24; 127.0.0.1; };
options {
directory "/var/named";
pid-file "/var/run/named/named.pid";
auth-nxdomain yes;
datasize default;
listen-on { any; };
forward first;
forwarders {
8.8.8.8;
8.8.4.4;
};
};
zone "local" {
type master;
file "local.zone";
check-names ignore;
allow-transfer { lan; };
allow-update { lan; };
};
zone "0.168.192.in-addr.arpa" {
type master;
file "0.168.192.in-addr.arpa.zone";
check-names ignore;
allow-transfer { lan; };
allow-update { lan; };
};
Now, the cron script runs every minute, which isn't really a problem since it doesn't use many resources. Everything works fine and here's some output from BIND to prove it.
23-Dec-2010 07:47:02.266 client 127.0.0.1#50731: updating zone 'local/IN': deleting rrset at 'travis.local' A
23-Dec-2010 07:47:02.266 client 127.0.0.1#50731: updating zone 'local/IN': deleting rrset at 'htpc.local' A
23-Dec-2010 07:47:02.643 client 127.0.0.1#44082: updating zone '0.168.192.in-addr.arpa/IN': deleting rrset at '101.0.168.192.in-addr.arpa' PTR
23-Dec-2010 07:47:02.643 client 127.0.0.1#44082: updating zone '0.168.192.in-addr.arpa/IN': deleting rrset at '103.0.168.192.in-addr.arpa' PTR
23-Dec-2010 07:47:02.731 client 127.0.0.1#61526: updating zone 'local/IN': adding an RR at 'travis.local' A
23-Dec-2010 07:47:02.732 client 127.0.0.1#61526: updating zone 'local/IN': adding an RR at 'htpc.local' A
23-Dec-2010 07:47:02.832 client 127.0.0.1#19283: updating zone '0.168.192.in-addr.arpa/IN': adding an RR at '101.0.168.192.in-addr.arpa' PTR
23-Dec-2010 07:47:02.833 client 127.0.0.1#19283: updating zone '0.168.192.in-addr.arpa/IN': adding an RR at '103.0.168.192.in-addr.arpa' PTR
And now I can successfully look up other hosts on the network.
$ nslookup htpc
Server: 192.168.0.103
Address: 192.168.0.103#53
Name: htpc.local
Address: 192.168.0.103
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Last week, my Qwest gateway/router went out and I replaced it with an ancient D-Link that doesn't resolve local domain names. Many applications on my network depend on local DNS, so I decided to set up BIND on my HTPC. Initially, this was done using static IP addresses and a static zone file.
This morning, after having no sleep last night (I stayed up working on a Tumblr layout), I figured out this cool thing you can do with Avahi:
$ avahi-browse -prt _workstation._tcp
+;eth0;IPv4;travis\032\09148\0585b\05839\05863\058 83\05891\093;Workstation;local
+;eth0;IPv4;htpc\032\09100\05813\05872\05831\058e6 \058a0\093;Workstation;local
=;eth0;IPv4;travis\032\09148\0585b\05839\05863\058 83\05891\093;Workstation;local;travis.local;192.16 8.0.101;9;
=;eth0;IPv4;htpc\032\09100\05813\05872\05831\058e6 \058a0\093;Workstation;local;htpc.local;192.168.0. 103;9;So yeah, a parsable list of workstations on the network, their domain names, and their IPs. But how do we get this information to the DNS server?
I ended up writing a cron script (in PHP, lol). The implementation is horrible due to my sleep deprivation but you can get the general idea from this:
#!/usr/bin/php
<?php
$avahidata = explode("\n",`avahi-browse -ptr _workstation._tcp`);
$hosts="server localhost\nzone local\n";
$pointers="server localhost\nzone 0.168.192.in-addr.arpa\n";
$oldhosts="server localhost\nzone local\n";
$oldpointers="server localhost\nzone 0.168.192.in-addr.arpa\n";
for($i=0;$i<count($avahidata)-1;$i++){
$hostInformation=explode(";",$avahidata[$i]);
if($hostInformation[0] != "=") continue;
$hostname=$hostInformation[6];
$hostaddr=$hostInformation[7];
$ptraddr=implode(".",array_reverse(explode(".",$hostaddr)));
$hosts.="update add $hostname 2400 A $hostaddr\n";
$pointers.="update add $ptraddr.in-addr.arpa 2400 PTR $hostname\n";
$oldhosts.="update delete $hostname A\n";
$oldpointers.="update delete $ptraddr.in-addr.arpa PTR\n";
}
$hosts.="send\n";
$pointers.="send\n";
$oldhosts.="send\n";
$oldpointers.="send\n";
echo `cat .dns_purge_hosts | nsupdate`;
echo `cat .dns_purge_pointers | nsupdate`;
echo `echo "$hosts" | nsupdate`;
echo `echo "$pointers" | nsupdate`;
file_put_contents(".dns_purge_hosts",$oldhosts);
file_put_contents(".dns_purge_pointers",$oldpointers);
?>
Now, of course BIND is configured to allow updates from localhost...
acl lan { 192.168.0/24; 127.0.0.1; };
options {
directory "/var/named";
pid-file "/var/run/named/named.pid";
auth-nxdomain yes;
datasize default;
listen-on { any; };
forward first;
forwarders {
8.8.8.8;
8.8.4.4;
};
};
zone "local" {
type master;
file "local.zone";
check-names ignore;
allow-transfer { lan; };
allow-update { lan; };
};
zone "0.168.192.in-addr.arpa" {
type master;
file "0.168.192.in-addr.arpa.zone";
check-names ignore;
allow-transfer { lan; };
allow-update { lan; };
};
Now, the cron script runs every minute, which isn't really a problem since it doesn't use many resources. Everything works fine and here's some output from BIND to prove it.
23-Dec-2010 07:47:02.266 client 127.0.0.1#50731: updating zone 'local/IN': deleting rrset at 'travis.local' A
23-Dec-2010 07:47:02.266 client 127.0.0.1#50731: updating zone 'local/IN': deleting rrset at 'htpc.local' A
23-Dec-2010 07:47:02.643 client 127.0.0.1#44082: updating zone '0.168.192.in-addr.arpa/IN': deleting rrset at '101.0.168.192.in-addr.arpa' PTR
23-Dec-2010 07:47:02.643 client 127.0.0.1#44082: updating zone '0.168.192.in-addr.arpa/IN': deleting rrset at '103.0.168.192.in-addr.arpa' PTR
23-Dec-2010 07:47:02.731 client 127.0.0.1#61526: updating zone 'local/IN': adding an RR at 'travis.local' A
23-Dec-2010 07:47:02.732 client 127.0.0.1#61526: updating zone 'local/IN': adding an RR at 'htpc.local' A
23-Dec-2010 07:47:02.832 client 127.0.0.1#19283: updating zone '0.168.192.in-addr.arpa/IN': adding an RR at '101.0.168.192.in-addr.arpa' PTR
23-Dec-2010 07:47:02.833 client 127.0.0.1#19283: updating zone '0.168.192.in-addr.arpa/IN': adding an RR at '103.0.168.192.in-addr.arpa' PTR
And now I can successfully look up other hosts on the network.
$ nslookup htpc
Server: 192.168.0.103
Address: 192.168.0.103#53
Name: htpc.local
Address: 192.168.0.103