Skip to content

Instantly share code, notes, and snippets.

@t0mtaylor
Created November 3, 2021 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save t0mtaylor/1c2d3d6a783f417832e4770e8ad50095 to your computer and use it in GitHub Desktop.
Save t0mtaylor/1c2d3d6a783f417832e4770e8ad50095 to your computer and use it in GitHub Desktop.
Cpanel Dyn DNS Custom updater script PHP for OpenWRT
<?php
// Based on the hard work of Mitchel Haan
// https://haanenterprises.com/2013/04/host-your-own-dynamic-dns-using-php-and-cpanel-apis/
//
// usage:
// http://username:password@website.com/dyndns.php?hostname=remote&myip=192.168.1.1
//
// per the settings below, the above will update the IP remote.example.com to 192.168.1.1
// myip is not required, will default to the remote IP calling the script
//
// most dyndns clients will work with a custom url setting. you will likely need to only
// provide the subdomain and not the full address.
// (ie: with this script, hostname=remote instead of hostname=remote.example.com
// How to use
// base64 encode username and password - this script will work with OpenWRT DynDNS Updater
#https://[USERNAME]:[PASSWORD]@host.com/dyndns/dnsupdater.php?R7n3QmWy=1&hostname=[DOMAIN]&myip=[IP]
#list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
/***** Variables *****/
#The username and password used by the updater to send the request.
#HTTP Basic authentication
$php_auth_user='USERNAME';
$php_auth_pw='PASSWORD';
#The url of the cpanel server
$dyndnsCpanel = 'https://cpanel.domain.com:2083';
#username and password used to login to cpanel
$dyndnsCpanelUser = 'username';
$dyndnsCpanelPass = 'password';
#the main domain name of the account on cpanel
$dyndnsDomain = 'sub.domain.com';
define('DYNDNS_ALLHOSTS', $dyndnsDomain);
#the base domain of which the subdomain has a dynamic ip
$dyndnsRemoteHostDomain = '.domain.com.';
// Plain text output
header('Content-type: text/plain');
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="CPanel DynDyns"');
header('HTTP/1.0 401 Unauthorized');
die('Authentication Required.');
}
if(!($_SERVER['PHP_AUTH_USER']==$php_auth_user && $_SERVER['PHP_AUTH_PW']==$php_auth_pw)) {
sleep(10);
die('Invalid Credentials');
}
// Make sure a host was specified
if (empty($_GET['hostname']))
die('Must specify host');
// Use server value for IP if none was specified
$ip = $_GET['myip'];
if (empty($ip))
$ip = $_SERVER['REMOTE_ADDR'];
// Validate IP address
if (!filter_var($ip, FILTER_VALIDATE_IP))
die('Invalid IP address');
// Get and validate ttl
$ttl = $_GET['ttl'];
if (!is_numeric($ttl) || $ttl < 60)
$ttl = 300;
// Create class object
$dyn = new DynDnsUpdater();
// Connection information
$dyn->setCpanelHost($dyndnsCpanel);
$dyn->setDomain($dyndnsDomain);
$dyn->setHostDomain($dyndnsRemoteHostDomain);
// Set username
$dyn->setCpanelUsername($dyndnsCpanelUser);
// Set password
$dyn->setCpanelPassword($dyndnsCpanelPass);
$dyn->updateHost(str_replace(".".$dyndnsDomain,"",$_GET['hostname']), $ip);
if ($dyn->apiCallTime > 0.0)
{
echo "\nTotal cPanel API call time: {$dyn->apiCallTime} seconds\n";
}
// End of processing
exit;
/**********************************/
/*** Function definitions below ***/
/**********************************/
class DynDnsUpdater
{
public $apiCallTime;
private $curl;
private $cpanelHost;
private $cpanelUsername;
private $cpanelPassword;
private $domain;
private $hostDomain;
/***** Constructor / Destructor *****/
function __construct()
{
// Create curl object
$this->curl = curl_init();
$curlDefaults = array(
CURLOPT_SSL_VERIFYPEER => false, // Allow self-signed certs
CURLOPT_SSL_VERIFYHOST => false, // Allow certs that do not match the hostname
CURLOPT_RETURNTRANSFER => true, // Return contents
);
curl_setopt_array($this->curl, $curlDefaults);
$this->apiCallTime = 0.0;
}
function __destruct()
{
// Release curl object
curl_close($this->curl);
}
/***** Setters *****/
function setCpanelHost($host)
{
$this->cpanelHost = $host;
}
function setCpanelUsername($username)
{
$this->cpanelUsername = $username;
}
function setCpanelPassword($password)
{
$this->cpanelPassword = $password;
}
function setDomain($domain)
{
$this->domain = $domain;
}
function setHostDomain($domain)
{
$this->hostDomain = $domain;
}
/***** Public Functions *****/
public function updateHost($host, $ip)
{
$hosts = $this->getHost($host);
if ($hosts === false)
return false;
foreach ($hosts as $hostInfo)
{
if ($hostInfo['address'] == $ip)
{
echo "No update required: {$hostInfo['name']} ($ip)\n";
return true;
}
$updateParams = array(
'cpanel_jsonapi_module' => 'ZoneEdit',
'cpanel_jsonapi_func' => 'edit_zone_record',
'domain' => $this->domain,
'Line' => $hostInfo['Line'],
'type' => $hostInfo['type'],
'address' => $ip
);
$result = $this->cpanelRequest($updateParams);
if ($result)
echo "Update successful: {$hostInfo['name']} ($ip)\n";
else
echo "Update failed: {$hostInfo['name']}\n";
}
}
/***** Private Functions *****/
private function getHost($host)
{
$fetchzoneParams = array(
'cpanel_jsonapi_module' => 'ZoneEdit',
'cpanel_jsonapi_func' => 'fetchzone_records',
'domain' => $this->domain,
'customonly' => 1
);
$result = $this->cpanelRequest($fetchzoneParams);
if (empty($result['data']))
return false;
// Get the payload
$zoneFile = $result['data'];
$hosts = array();
foreach ($zoneFile as $line)
{
if ( ($line['type'] == 'A') &&
($host == DYNDNS_ALLHOSTS || (strcasecmp($line['name'], $host.$this->hostDomain) === 0)) )
{
$hosts[] = $line;
}
}
if (!empty($hosts))
return $hosts;
else
echo "No hosts found\n";
return false;
}
private function cpanelRequest($params)
{
if (empty($this->curl) || empty($params))
return false;
curl_setopt($this->curl, CURLOPT_URL, $this->cpanelHost.'/json-api/cpanel?'.http_build_query($params));
curl_setopt($this->curl, CURLOPT_HTTPHEADER, array( 'Authorization: Basic ' . base64_encode($this->cpanelUsername.':'.$this->cpanelPassword)) );
$result = curl_exec($this->curl);
$this->apiCallTime += curl_getinfo($this->curl, CURLINFO_TOTAL_TIME);
$error = false;
// Check for valid result
if ($result === false)
{
echo curl_error($this->curl)."\n";
// If curl didn't return anything, there's nothing else to check
return false;
}
// Check for error code
if (curl_getinfo($this->curl, CURLINFO_HTTP_CODE) != '200')
{
$err = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
echo "Error $err\n";
$error = true;
}
// Attempt to process result
$jsonResult = json_decode($result, true);
if (empty($jsonResult))
{
echo "Invalid JSON: \n".$result."\n";
return false;
}
// Check for cpanelresult object
if (isset($jsonResult['cpanelresult']))
{
$jsonResult = $jsonResult['cpanelresult'];
}
else
{
$error = true;
}
// Check for cpanel error
if (isset($jsonResult['error']))
{
echo $jsonResult['error']."\n";
$error = true;
}
if ($error)
{
// No sense going past here... no more information to get
return false;
}
return $jsonResult;
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment