This site is now 100% read-only, and retired.

Creating Bind DNS-Entries with regular dyndns-clients in routers

Posted by stefanbauer on Thu 31 Dec 2009 at 10:46

Recently there was a message posted upon the debian-user-german mailing list asking if there is a way to create BIND-compliant DNS-Updates with regulars dyndns-clients from routers. The Idea behind this is to get rid of dyndns.org services and provide an independent way to maintain dynamic dns entries for boxes without a static ip-address without the need of dyndns providers. The goal was to create a text file which could be used as input for nsupdate with cron to run it frequently.

As this was a quick and dirty hack, ideas to improve the current setup are greatly appreciated.

Server side requirements:

  • Working Bind setup
  • Apache with CGI capabilites
  • perl
  • nsupdate

Router-requirments:

  • The router must be able to let the user specify a special update-url for dyndns-updates. In my case i used a FRITZ!Box Fon WLAN 7113

Specify the following URL as an UPDATE-Url in your routers dyndns-setup:

Most routers provide fields to specify username and password as well as the domain. On my fritzbox the variables (marked in <variable>) get replaced at runtime.

In this example I have the following details:

username is stefan in this example
pass = supersecret
hostname = dyndnstest.plzk.de

(ipaddr get replaced by the current ip-address of the routers wan-interface)

On the server-side, save the following perl snippet in your cgi-bin directory and call it dns.cgi:


#!/usr/bin/perl -w

# Print a CGI-header.
print "Content-type: text/plain\n\n";


#
# if the router sends a correct update string
#
if ($ENV{QUERY_STRING} =~ /username=(.*?)&pass=(.*?)hostname=(.*?)&myip=(.*)/)
{
    #
    # and the supplied username & password is correct as well
    #
    if ($1 eq 'stefan' and $2 eq 'supersecret')
    {
        #
        # then confirm the update with an OK (good)
        #
        print "$3 IN A $4 good";

        # add a nsupdate-compliant line to a temporary file
        # can be used afterward with 'nsupdate /tmp/zonetest'
        # this can be done automatically by a cronjob
        #
        # NOTE: This file needs to be writeable by your webserver
        #
        `/bin/echo "update add $3 600 IN A $4" > /tmp/zonetest`;
    }
}
else
{
    # if something went wrong, reply with a temporary error (911)
    print "a problem occured - 911";
}


If we setup everything correctly, the client sends the following string to the webserver:

91.8.21.139 - - [29/Dec/2009:19:45:08 +0100] 
   "GET /cgi-bin/dns.cgi?user=stefan&pass=supersecret&hostname=dyndnstest.plzk.de&myip=91.8.21.139 HTTP/1.1" 200 23 "-" "Fritz!Box DDNS"

Right after that, we have a new entry in /tmp/zonetest

# cat /tmp/zonetest
update add dyndnstest.plzk.de 600 IN A 91.8.21.139

This file could now be used with nsupdate to update the zone-informations for the domain *.plzk.de

 

 


Re: Creating Bind DNS-Entries with regular dyndns-clients in routers
Posted by Anonymous (80.101.xx.xx) on Thu 31 Dec 2009 at 14:18
Nice hack,

Personally I'd use PowerDNS with a MySQL backend to store both user credentials and DNS record information, and PHP on Apache to handle the user's update request.

[ Parent ]

Re: Creating Bind DNS-Entries with regular dyndns-clients in routers
Posted by Anonymous (83.119.xx.xx) on Sat 2 Jan 2010 at 19:03
Well anonymous, I really like to know your setup as I'm also a mysql-powerdns user.

[ Parent ]

Re: Creating Bind DNS-Entries with regular dyndns-clients in routers
Posted by Anonymous (71.41.xx.xx) on Mon 25 Jan 2010 at 20:06
How about defaulting the IP address to $ENV{REMOTE_ADDR} if it's not specified? Most times it's the router itself that's hitting the CGI, right? So it's the remote host of the CGI.

[ Parent ]

Re: Creating Bind DNS-Entries with regular dyndns-clients in routers
Posted by Anonymous (2001:0xx:0xx:0xxx:0xxx:0xxx:xx) on Sat 1 Jan 2011 at 23:56
How can I start a update with nsupdate, what is the right syntax to use?

[ Parent ]

Re: Creating Bind DNS-Entries with regular dyndns-clients in routers
Posted by Anonymous (79.214.xx.xx) on Mon 30 Jul 2012 at 16:21
Can't work because of a typo in
"if ($ENV{QUERY_STRING} =~ /username=(.*?)&pass=(.*?)hostname=(.*?)&myip=(.*)/)" ;
right before hostname an ampersand is missing, so always the ampersand given in the link will be added to the password. After finding this typo, everything works fine for me. Big thanks.

[ Parent ]

Re: Creating Bind DNS-Entries with regular dyndns-clients in routers
Posted by Anonymous (84.158.xx.xx) on Thu 11 Oct 2012 at 22:05
if you edit a textfile, you can edit the zone file because it is a text file too.

[ Parent ]