Created
November 3, 2021 16:16
-
-
Save t0mtaylor/1c2d3d6a783f417832e4770e8ad50095 to your computer and use it in GitHub Desktop.
Cpanel Dyn DNS Custom updater script PHP for OpenWRT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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