Skip to content
This repository has been archived by the owner. It is now read-only.
🌍 A small cgi script providing a dynamic dns service written in perl, using a mysql database.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


A small cgi script providing a dynamic dns service written in perl, using a mysql database.
The script is desined to work for dyndns client integrated in the "FritzBox" routers, but can be customized for your needs.




  • bind9 dns server
  • apache web server
  • perl and some modules
    • cgi
    • dbi and dbd::mysql
    • mime::base64
  • mysql database


the examples are meant for debian systems.

create a new dns zone in bind

create zone file and key:

sudo /usr/sbin/ddns-confgen -z

this generates output like

# To activate this key, place the following in named.conf, and
# in a separate keyfile on the system or systems from which nsupdate
# will be run:
key "" {
	algorithm hmac-sha256;
	secret "u/1n3/bDu2pBr9KaBhYaYxltA7QfjHIrx3e9HjxA/mk=";

# Then, in the "zone" definition statement for "",
# place an "update-policy" statement like this one, adjusted as 
# needed for your preferred permissions:
update-policy {
	  grant zonesub ANY;

# After the keyfile has been placed, the following command will
# execute nsupdate using this key:
nsupdate -k <keyfile>

put the single parts of the output in your /etc/bind/named.conf.local file:

key "" {
        algorithm hmac-sha256;
        secret "u/1n3/bDu2pBr9KaBhYaYxltA7QfjHIrx3e9HjxA/mk=";

zone "" {
        type master;
        file "/var/cache/bind/";
        update-policy {
                grant subdomain A;

restart your bind9 daemon:

sudo /etc/init.d/bind9 restart

(optional) try if your bind9 works as expected

user@host:~> echo -e "update delete A\
update add 60\
send" | /usr/bin/nsupdate -y

Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:      0
;; flags:; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0

user@host:~> dig +short @

user@host:~> echo -e "update delete A\
send" | /usr/bin/nsupdate -y

set your server as primary nameserver for the zone

how you can do this depends on your provider.
i created a new ns entry pointing to my server for a subdomain in the admin-panel of my provider.

create database and insert custom records

create empty database

mysql> create database dyndns;

load structure

user@host:~> mysql -u root -p -B dyndns < mysql_setup.sql

insert custom records

mysql> insert into user (username, password_hash, password_salt, email) values
	('foo', MD5(CONCAT('mypassword','mysupersecrethash')),'mysupersecrethash', '');
mysql> insert into zones (zone, `key`) values ('', 'secretzoneupdatekey');
mysql> insert into domains (zone_id, user_id, domain, ip) values (1, 1, 'foo', NULL);

setup cgi script

set up apache to execute the cgi script and pass http auth to env variable

put the customized version of this example in your apache config:

<Directory /mydir/>
	AddHandler cgi-script .pl
	RewriteEngine on
	RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
<Directory /var/www/>
	Options ExecCGI

put in the directory and try to open in your browser.
you should see the message "nohost", what means the script was beend executed by the webserver.

set database config in script

edit and change the following code:

my $database = {
  "host"     => "localhost",
  "database" => "dyndns",
  "user"     => "root",
  "password" => "toor"

set the new update-script in your routers dyndns client


You can’t perform that action at this time.