Installation
------------
-To mimic the original DynDNS.org behavior, the Script's URL must be
+This script acts like the original DynDNS.org server and handles DNS updates on the url
+
+ http://yourdomain.tld/?hostname=<domain>&myip=<ipaddr>
- http://members.dyndns.org/nic/update
You may have to adjust your own DNS configuration to make "members.dyndns.org" point to your own
Server and you Web Servers configuration to make "/nic/update" call the PHP script provided in this
Authentication in URL:
-http://username:password@members.dyndns.org/nic/update?hostname=yourhostname&myip=ipaddress&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG
+http://username:password@yourdomain.tld/?hostname=yourhostname&myip=ipaddress
Raw HTTP GET Request:
-GET /nic/update?hostname=yourhostname&myip=ipaddress&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG HTTP/1.0
-Host: members.dyndns.org
+GET /?hostname=yourhostname&myip=ipaddress HTTP/1.0
+Host: yourdomain.tld
Authorization: Basic base-64-authorization
User-Agent: Company - Device - Version Number
hostname
Comma separated list of hostnames that you wish to update (up to 20 hostnames per request).
This is a required field.
- Example: hostname=test.dyndns.org,customtest.dyndns.org
+ Example: hostname=dynhost1.yourdomain.tld,dynhost2.yourdomain.tld
myip
IP address to set for the update.
(If this parameter is not specified, the best IP address the server can determine will be used)
-(See http://www.dyndns.com/developers/specs/syntax.html for more details)
-
Return Codes
------------
There is a problem or scheduled maintenance on our side.
(See http://www.dyndns.com/developers/specs/return.html for more details)
-
-
-Todo
-----
-
-* Implement Wildcards
-* Implement NOCHG
-* Implement more features from DynDNS.org
-* Provide Apache templates (for mod_rewrite, etc.)
+++ /dev/null
-#
-# This is the Apache configuration for the Dyndns package.
-#
-# An alias is set from /nic to /usr/local/Dyndns/htdocs and a Rewrite rule
-# is added for the /nic/update URL.
-#
-Alias /nic /usr/local/Dyndns/htdocs
-
-<Directory /usr/local/Dyndns/htdocs>
- Options FollowSymLinks
- AllowOverride None
- Order allow,deny
- Allow from all
- RewriteEngine On
- RewriteBase /nic
- RewriteRule ^update$ /nic/index.php
-</Directory>
+++ /dev/null
-dyndns.example.com. IN KEY 513 3 157 bvZfFHkl16wNGL/LuEUAqvlBeue9lw7C8GkHnQucN6jpKDMjOu29zFR6LlO5YlpNzYquDBmDSPVddX9SuFIK5A==
+++ /dev/null
-Private-key-format: v1.2
-Algorithm: 157 (HMAC)
-Key: bvZfFHkl16wNGL/LuEUAqvlBeue9lw7C8GkHnQucN6jpKDMjOu29zFR6LlO5YlpNzYquDBmDSPVddX9SuFIK5A==
-client1.dyndns.example.com:user1,user2
-client2.dyndns.example.com:user1,user2
-user1.dyndns.example.com:user1
-user2.dyndns.example.com:user2
-*.u1.dyndns.example.com:user1
+client1.dyn.example.com:user1,user2
+client2.dyn.example.com:user1,user2
+user1.dyn.example.com:user1
+user2.dyn.example.com:user2
+*.u1.dyn.example.com:user1
/**
* Helper functions.
- *
+ *
* @package Dyndns
* @author Nico Kaiser <nico@kaiser.me>
*/
class Helper
-{
+{
/**
* Check valid IP address
*
* @param string IP address
* @return boolean True if IP is valid
- */
+ */
public static function checkValidIp($ip)
{
- if (! eregi("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", $ip))
+ if (! eregi("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", $ip))
return false;
$tmp = explode(".", $ip);
return true;
}
-
+
/**
* Check valid hostname (FQDN)
*
* @param string Hostname
* @return boolean
- */
+ */
public static function checkValidHost($hostname)
{
return eregi('^[a-z0-9.-]+$', $hostname);
/**
* Tries to get the IPv4 of the client
*
- * @return string ip
+ * @return string ip
*/
public static function getMyIp()
{
public static function compareHosts($host1, $host2, $wildcard = false)
{
$a = explode('.', $host1);
- $b = explode('.', $host2);
+ $b = explode('.', $host2);
if (count($a) != count($b))
return false;
/**
* Host database.
- *
+ *
* @package Dyndns
* @author Nico Kaiser <nico@kaiser.me>
*/
class Hosts
-{
+{
/**
* Filename of the hosts file (dyndns.hosts)
* @var string
* @var array
*/
private $hosts;
-
+
/**
* List of updates in the format 'hostname' => 'ip'
* @var array
*/
private $updates;
-
+
/**
* This is true if the status / user files were read
* @var boolean
if (! $this->initialized) {
$this->init();
}
-
+
$this->debug('Update: ' . $hostname . ':' . $ip);
$this->updates[$hostname] = $ip;
return true;
}
/**
- * Checks if the host belongs to the user
+ * Checks if the host belongs to the user
*
* @param string $user
* @param string $hostname
*/
function checkUserHost($user, $hostname)
{
- if ($hostname === 'members.dyndns.org') {
- $this->debug('Cannot change members.dyndns.org');
- return false;
- }
-
if (! Helper::checkValidHost($hostname)) {
$this->debug('Invalid host: ' . $hostname);
return false;
}
if (! $this->initialized) {
- $this->init();
+ $this->init();
}
if (is_array($this->hosts)) {
foreach ($this->hosts as $line) {
if (preg_match("/^(.*?):(.*)/", $line, $matches)) {
- if (Helper::compareHosts($matches[1], $hostname, '*') &&
+ if (Helper::compareHosts($matches[1], $hostname, '*') &&
in_array($user, explode(',', strtolower($matches[2])))) {
return true;
}
$this->debug('Host '.$hostname.' does not belong to user '.$user);
return false;
}
-
+
/**
- * Write cached changes to the status file
+ * Write cached changes to the status file
*/
public function flush()
{
return $this->updateBind();
}
-
+
/**
- * Initializes the user and status list from the file
- *
+ * Initializes the user and status list from the file
+ *
* @access private
*/
private function init()
$this->initialized = true;
}
-
+
function readHostsFile()
{
$lines = @file($this->hostsFile);
$this->debug('Empty hosts file: "' . $this->hostsFile . '"');
}
}
-
+
/**
* Sends DNS Updates to BIND server
- *
+ *
* @access private
*/
private function updateBind()
$this->debug('ERROR: Invalid bind.key config value');
return false;
}
-
+
// create temp file with nsupdate commands
$tempfile = tempnam('/tmp', 'Dyndns');
$fh = @fopen($tempfile, 'w');
}
fwrite($fh, "send\n");
fclose($fh);
-
+
// Execute nsupdate
$result = exec('/usr/bin/nsupdate -y ' . $key . ' ' . $tempfile . ' 2>&1');
unlink($tempfile);
$this->debug('ERROR: nsupdate returns: ' . $result);
return false;
}
-
+
return true;
}
private function getConfig($key)
{
- return $GLOBALS['dyndns']->getConfig($key);
+ return $GLOBALS['dyndns']->getConfig($key);
}
private function debug($message)
{
- return $GLOBALS['dyndns']->debug($message);
+ return $GLOBALS['dyndns']->debug($message);
}
}
/**
* Simple Dynamic DNS server.
- *
+ *
* @package Dyndns
* @author Nico Kaiser <nico@kaiser.me>
*/
class Server
-{
+{
/**
* Storage for all configuration variables, set in config.php
* @var array
/**
* Debug buffer
* @var string
- */
+ */
private $debugBuffer;
public function __construct()
{
$this->config = array (
- 'hostsFile' => 'dyndns.hosts', // Location of the hosts database
+ 'hostsFile' => 'dyndns.hosts', // Location of the hosts database
'userFile' => 'dyndns.user', // Location of the user database
- 'debugFile' => 'dyndns.log', // Debug file
+ 'debugFile' => 'dyndns.log', // Debug file
'debug' => false, // Enable debugging
-
+
'bind.server' => false,
'bind.zone' => '',
'bind.ttl' => 300,
{
$this->users = new Users($this->config['userFile']);
$this->hosts = new Hosts($this->config['hostsFile']);
-
+
$this->checkHttpMethod();
$this->checkAuthentication();
-
+
// Get IP address, fallback to REMOTE_ADDR
$this->myIp = Helper::getMyIp();
if (array_key_exists('myip', $_REQUEST)) {
$this->debug('Invalid parameter myip. Using default REMOTE_ADDR');
}
}
-
+
// Get hostnames to be updated
$this->hostnames = array ();
if (array_key_exists('hostname', $_REQUEST) && ($_REQUEST['hostname'] != '')) {
} else {
$this->returnCode('notfqdn');
}
-
+
$this->updateHosts();
-
+
// Return "good" code as everything seems to be ok now
$this->returnCode('good');
}
-
+
public function setConfig($key, $value)
{
$this->config[$key] = $value;
}
-
+
public function getConfig($key)
{
return $this->config[$key];
private function checkHostnames()
{
foreach ($this->hostnames as $hostname) {
- // check if the hostname is valid FQDN
+ // check if the hostname is valid FQDN
if (! Helper::checkValidHost($hostname)) {
$this->returnCode('notfqdn');
}
$this->returnCode('dnserr');
}
}
-
+
// Flush host database (write to hosts file)
if (! $this->hosts->flush()) {
$this->returnCode('dnserr');
foreach ($lines as $line) {
if (preg_match("/^(.*?):(.*)/", $line, $matches)) {
if (strtolower($matches[1]) == strtolower($user)) {
- $salt = substr($matches[2], 0, 2);
- if (crypt($password, $salt) == $matches[2]) {
+ $salt = substr($matches[2], 0, 2);
+ if (crypt($password, $salt) === $matches[2]) {
$this->debug('Login successful for user ' . $user);
return true;
} else {
private function debug($message)
{
- $GLOBALS['dyndns']->debug($message);
+ $GLOBALS['dyndns']->debug($message);
}
}