A simple DynDNS server in PHP
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.
conf use keyfile instead of key Jun 23, 2013
examples Use composer Oct 4, 2013
src/Dyndns Update DNS server only if IP has changed. Oct 18, 2014
.gitignore Fix public/private Jun 18, 2013
README.md Update README.md for IPv6 support (Thanks @afrimberger) Oct 29, 2014


Dyndns: a simple DynDNS server in PHP

This script takes the same parameters as the original dyndns.org server does. It can update a BIND DNS server via nsupdate.

As it uses the same syntax as the original DynDNS.org servers do, a dynamic DNS server equipped with this script can be used with DynDNS compatible clients without having to modify anything on the client side.


This script handles DNS updates on the url


For security HTTP basic auth is used. You can create multiple users and assign host names for each user.


To be able to dynamically update the BIND DNS server, a DNS key must be generated with the command:


This command outputs instructions for your BIND installation. The generated key has to be added to the named.conf.local:

key "ddns-key" {
    algorithm hmac-sha256;
    secret "bvZ....K5A==";

and saved to a file which is referenced in index.php as "bind.keyfile". In the "zone" entry, you have to add an "update-policy":

zone "dyndns.example.com" {
    type master;
    file "db.dyndns.example.com";
    update-policy {
        grant ddns-key zonesub ANY;

In this case, the zone is also called "dyndns.example.com". The (initial) db.dyndns.example.com file (located in BIND's cache directory) looks like this:

$TTL 1h
@ IN SOA dyndns.example.com. root.example.com. (
        2007111501      ; serial
        1h              ; refresh
        15m             ; retry
        7d              ; expiration
        1h              ; minimum
        NS <your dns server>

Remember to change access rights so BIND is able to write to this file. On Ubuntu the zone need to be in /var/lib/bind due to AppArmor.

PHP script configuration

The PHP script is called by the DynDNS client, it validates the input and calls "nsupdate" to finally update the DNS with the new data. Its configuration is rather simple, the user database is implemented as text file "dyndns.user" with each line containing


Where the password is crypt'ed like in Apache's htpasswd files. Use -d parameter to select the CRYPT encryption.

htpasswd -c -d conf/dyndns.user user1

Hosts are assigned to users in using the file "dyndns.hosts":


(So users can update multiple hosts, and a host can be updated by multiple users).

Installation via Composer

# Install Composer
curl -sS https://getcomposer.org/installer | php

# Add Dyndns as a dependency
php composer.phar require nicokaiser/dyndns:*

Then you can create a simple index.php with the configuration:


require 'vendor/autoload.php';

$dyndns = new Dyndns\Server();

// Configuration
  ->setConfig('hostsFile', __DIR__ . '/../conf/dyndns.hosts') // hosts database
  ->setConfig('userFile', __DIR__ . '/../conf/dyndns.user')   // user database
  ->setConfig('debug', true)  // enable debugging
  ->setConfig('debugFile', '/tmp/dyndns.log') // debug file
  ->setConfig('bind.keyfile', __DIR__ . '/../conf/dyn.example.com.key') // secret key for BIND nsupdate ("<keyname>:<secret>")
  ->setConfig('bind.server', 'localhost') // address of the BIND server
  ->setConfig('bind.zone', 'dyndns.example.com') // BIND zone for the updates
  ->setConfig('bind.ttl', '300') // TTL for DNS entries



Authentication in URL:


Raw HTTP GET Request:

GET /?hostname=yourhostname&myip=ipaddress HTTP/1.0 
Host: yourdomain.tld 
Authorization: Basic base-64-authorization 
User-Agent: Company - Device - Version Number

Fragment base-64-authorization should be represented by Base 64 encoded username:password string.

Implemented fields

  • hostname Comma separated list of hostnames that you wish to update (up to 20 hostnames per request). This is a required field. Example: hostname=dynhost1.yourdomain.tld,dynhost2.yourdomain.tld
  • myip IP address to set for the update. Defaults to the best IP address the server can determine.

Return Codes

  • good The update was successful, and the hostname is now updated.
  • badauth The username and password pair do not match a real user.
  • notfqdn The hostname specified is not a fully-qualified domain name (not in the form hostname.dyndns.org or domain.com).
  • nohost The hostname specified does not exist in this user account (or is not in the service specified in the system parameter)
  • badagent The user agent was not sent or HTTP method is not permitted (we recommend use of GET request method).
  • dnserr DNS error encountered
  • 911 There is a problem or scheduled maintenance on our side.


  • @afrimberger (IPv6 support)