inadyn

I’ve started using inadyn to be able to access my home server using a DNS name, as I only have a dynamic IP address

This is not a problem, but I made life more complicated, as I wanted to use my own domain. Luckily my DNS provider offered a solution which worked fine, BUT I’m about to set up a plesk installation at the moment, and planning to move all my domains to this server, so needed a solution, which allows me to update the IP address in plesk

So after some research and messing around, I came up with the following code, which I’m not perfectly happy with, but it does the job, and I’ve had to move on to the next project.

First of all the request came in as <host>/nic/update, so I had to forward this to my php script

Small .htaccess file done the job:

RewriteEngine On
RewriteBase /nic
RewriteRule ^update update.php?&%{QUERY_STRING}
Options -Indexes

The php script was based on one of their examples, but I’ve changed most of it, to make it a bit simpler (at least for me)
One thing I could not work out was what IP address I should enter to generate a secret key, to be able to use that for authentication instead of the username / password combination, maybe another day
What the script does:

  1. checks the username, and compares this against the domain name (yes, the username must be <domain>-<subdomain>)
  2. checks the submitted IP address, to ensure it’s the same from where the call comes
  3. gets the domain list from plesk (I prefer arrays, other people objects, it’s a personal preference)
  4. ensures that the given subdomain is registered on the server
  5. checks the IP address it’s associated with
  6. if the IP changed, removes the previous record, and adds a new one with the new IP address
<?php
/**
 * Reports error during API RPC request
 */
class ApiRequestException extends Exception {}

/**
 * Performs a Panel API request, returns raw API response text
 *
 * @return string
 * @throws ApiRequestException
 */
function sendRequest($host, $login, $password, $key = '', $packet)
{
      $curl = curl_init();
      curl_setopt($curl, CURLOPT_URL, "https://{$host}:8443/enterprise/control/agent.php");
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($curl, CURLOPT_POST,           true);
      curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
      if (!empty($key))
      {
              curl_setopt($curl, CURLOPT_HTTPHEADER,
                     array("KEY: {$key}",
                            "HTTP_PRETTY_PRINT: TRUE",
                            "Content-Type: text/xml")
              );
      }
      else
      {
              curl_setopt($curl, CURLOPT_HTTPHEADER,
                     array("HTTP_AUTH_LOGIN: {$login}",
                            "HTTP_AUTH_PASSWD: {$password}",
                            "HTTP_PRETTY_PRINT: TRUE",
                            "Content-Type: text/xml")
              );
      }
      curl_setopt($curl, CURLOPT_POSTFIELDS, $packet);
      $result = curl_exec($curl);
      if (curl_errno($curl)) {
             $errmsg  = curl_error($curl);
             $errcode = curl_errno($curl);
             curl_close($curl);
             throw new ApiRequestException($errmsg, $errcode);
      }
      curl_close($curl);
      return $result;
}

/**
 * Looks if API responded with correct data
 *
 * @return SimpleXMLElement
 * @throws ApiRequestException
 */
function parseResponse($response_string)
{
      $xml = new SimpleXMLElement($response_string);
      if (!is_a($xml, 'SimpleXMLElement'))
             throw new ApiRequestException("Cannot parse server response: {$response_string}");
      return $xml;
}

function getDomainList()
{
        global $hostname, $login, $password, $key;
        $request = "<packet version=\"1.6.3.0\">\n\t<dns>\n\t\t<get_rec>\n\t\t\t<filter/>\n\t\t</get_rec>\n\t</dns>\n</packet>";
        $response = sendRequest($hostname, $login, $password, $key, $request);
        $dnsResponse = parseResponse($response);
        $hosts = array();
        $hostByID = array();
        foreach ($dnsResponse->dns->get_rec->result AS $item)
        {
                $hostInfo = (array) $item;
                $hostInfo += (array) $item->data;
                if (isset($hostInfo['data'])) unset($hostInfo['data']);
                if (isset($hostInfo['opt'])) unset($hostInfo['opt']);
                $hosts[$hostInfo['host']] = $hostInfo;
        }
        return $hosts;
}

function getMyHost($hosts, $hostname)
{
        $host = false;
        if (isset($hosts["{$hostname}."]))
        {
                $host = $hosts["{$hostname}."];
        }
        return $host;
}

function updateHostInfo($host, $ip)
{
        global $hostname, $login, $password, $key;
        $parts = explode(".", $host['host']);
$xml = "<packet version=\"1.6.3.0\">
<dns>
 <del_rec>
  <filter>
   <id>{$host['id']}</id>
  </filter>
 </del_rec>
  <add_rec>
   <site-id>{$host['site-id']}</site-id>
   <type>A</type>
   <host>{$parts[0]}</host>
   <value>{$ip}</value>
  </add_rec>
 </dns>
</packet>";
        $response = sendRequest($hostname, $login, $password, $key, $xml);
        $updateResponse = parseResponse($response);
        if (isset($updateResponse->dns->del_rec->result->status) && $updateResponse->dns->del_rec->result->status == 'ok' && isset($updateResponse->dns->add_rec->result->status) && $updateResponse->dns->add_rec->result->status == 'ok')
        {
                return true;
        }
        return false;
}


$hostname = 'localhost';
$login = 'admin';
$password = '***';
$key = '';

$userparts = explode("-", $_SERVER['PHP_AUTH_USER']);
if (count($userparts) != 2 || !isset($_GET['hostname']) || ($_GET['hostname'] != "{$userparts[1]}.{$userparts[0]}"))
{
        echo "invalid domain";
        return ;
}


if (isset($_GET['hostname']) && isset($_GET['myip']))
{
        if ($_GET['myip'] != $_SERVER['REMOTE_ADDR'])
        {
                echo "invalid ip";
                return ;
        }
        else
        {
                $hosts = getDomainList();
                $host = getMyHost($hosts, $_GET['hostname']);
                if (!is_array($host))
                {
                        echo "invalid host";
                        return ;
                }
                else
                {
                        if ($host['value'] == $_SERVER['REMOTE_ADDR'])
                        {
                                echo "nochg {$_SERVER['REMOTE_ADDR']}";
                        }
                        else
                        {
                                if (updateHostInfo($host, $_SERVER['REMOTE_ADDR']))
                                {
                                        echo "good {$_SERVER['REMOTE_ADDR']}";
                                        return ;
                                }
                                else
                                {
                                        echo "failed";
                                        return ;
                                }
                        }
                }
        }
}
else
{
        echo "notfqdn";
}

Leave a Reply