Steps will be added soon!
Last active
May 5, 2022 21:20
-
-
Save emotality/bc5f699b553e51acbcebf25a14bcf2fd to your computer and use it in GitHub Desktop.
CloudFlare Dynamic DNS (DDNS) for home server
This file contains hidden or 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 | |
/** | |
* Class CloudFlareAPI | |
* | |
* @author Jean-Pierre Fourie (emotality) | |
* @link https://github.com/emotality | |
* @link https://gist.github.com/emotality/bc5f699b553e51acbcebf25a14bcf2fd | |
*/ | |
class CloudFlareAPI | |
{ | |
/** | |
* The cURL handler. | |
* | |
* @var \CurlHandle $curl | |
*/ | |
private $curl; | |
/** | |
* If this script output needs to be logged to .log file. | |
* | |
* @var bool $save_to_log | |
*/ | |
private $save_to_log = true; | |
/** | |
* CloudFlare API base URL. | |
* | |
* @var string $cf_base_url | |
*/ | |
private $cf_base_url = 'https://api.cloudflare.com/client/v4'; | |
/** | |
* CloudFlare API auth token (40 characters). | |
* | |
* @var string $cf_auth_token | |
*/ | |
private $cf_auth_token = 'XXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXX'; | |
/** | |
* The CF DNS domain (32 characters). | |
* | |
* @var string $cf_dns_zone | |
*/ | |
private $cf_dns_zone = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; | |
/** | |
* The CF DNS record that should be updated (32 characters). | |
* | |
* @var string $cf_dns_record | |
*/ | |
private $cf_dns_record = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; | |
/** | |
* The domain/DNS record parameters. | |
* | |
* @var string $record_params | |
* @link https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record | |
*/ | |
private $record_params = [ | |
'type' => 'A', | |
'name' => 'home.example.com', // The domain you are updating. | |
'content' => null, // This will be filled with new IP address. | |
'ttl' => 1800, // Will be set to "Auto" if `proxied` is set to "true". | |
'proxied' => true, // Do NOT set to "true" if you want to SSH or get the real IP. | |
]; | |
/** | |
* CloudFlareAPI constructor. | |
*/ | |
public function __construct() | |
{ | |
$url = sprintf('%s/zones/%s/dns_records/%s', $this->cf_base_url, $this->cf_dns_zone, $this->cf_dns_record); | |
$this->curl = curl_init($url); | |
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); | |
} | |
/** | |
* Compare IP addresses then update to CloudFlare. | |
* | |
* @return bool | |
*/ | |
public function updateCloudFlareIP() | |
{ | |
$my_ip = $this->getMyCurrentIP(); | |
$cf_ip = $this->getCloudFlareIP(); | |
if (! $my_ip || ! $cf_ip) { | |
$this->echo('Could not get your current and/or CloudFlare IP address!', true, false); | |
return false; | |
} | |
if ($my_ip == $cf_ip) { | |
$this->echo('Your CloudFlare IP is already up to date!'); | |
return true; | |
} | |
return $this->setCloudFlareIP($my_ip); | |
} | |
/** | |
* Get my current public IP address. | |
* | |
* @return string|null | |
*/ | |
private function getMyCurrentIP() : ?string | |
{ | |
return trim(file_get_contents('http://ipecho.net/plain')) ?? null; | |
} | |
/** | |
* Get the current IP on CloudFlare. | |
* | |
* @return string|null | |
* @link https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details | |
*/ | |
private function getCloudFlareIP() : ?string | |
{ | |
$header = [ | |
'Accept: application/json', | |
sprintf('Authorization: Bearer %s', $this->cf_auth_token), | |
]; | |
curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, 'GET'); | |
curl_setopt($this->curl, CURLOPT_HTTPHEADER, $header); | |
$response = curl_exec($this->curl); | |
$error = curl_error($this->curl); | |
if (! empty($error)) { | |
$this->echo($error, true); | |
} elseif ($json = json_decode($response)) { | |
return $json->result->content ?? null; | |
} | |
return null; | |
} | |
/** | |
* Set the new IP on CloudFlare. | |
* | |
* @param string $new_ip | |
* @return bool | |
* @link https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record | |
*/ | |
private function setCloudFlareIP(string $new_ip) : bool | |
{ | |
$header = [ | |
'Content-Type: application/json', | |
'Accept: application/json', | |
sprintf('Authorization: Bearer %s', $this->cf_auth_token), | |
]; | |
// Set the new IP in the record parameters. | |
$this->record_params['content'] = $new_ip; | |
curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, 'PUT'); | |
curl_setopt($this->curl, CURLOPT_HTTPHEADER, $header); | |
curl_setopt($this->curl, CURLOPT_POSTFIELDS, json_encode($this->record_params)); | |
$response = curl_exec($this->curl); | |
$error = curl_error($this->curl); | |
if (! empty($error)) { | |
$this->echo($error, true); | |
} elseif ($json = json_decode($response)) { | |
$success = $json->success ?? false; | |
$message = $success ? 'DNS updated successfully!' : 'DNS update failed!'; | |
$this->echo($message, ! $success); | |
return $success; | |
} | |
return false; | |
} | |
/** | |
* Echo out and append to log file. | |
* | |
* @param string $message | |
* @param bool $error | |
* @param false $exit | |
* @return void | |
*/ | |
private function echo(string $message, bool $error = false, $exit = true) | |
{ | |
echo $message = sprintf("[%s] %s\n", date('Y-m-d H:i:s'), $message); | |
if ($this->save_to_log) { | |
$log = sprintf('%s/%s.log', __DIR__, basename(__FILE__, '.php')); | |
file_put_contents($log, $message, FILE_APPEND); | |
} | |
if ($exit) { | |
exit($error ? 1 : 0); | |
} | |
} | |
/** | |
* CloudFlareAPI destructor. | |
*/ | |
public function __destruct() | |
{ | |
curl_close($this->curl); | |
} | |
} | |
(new CloudFlareAPI())->updateCloudFlareIP(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment