diff --git a/dns/dyndns/src/etc/inc/plugins.inc.d/dyndns.inc b/dns/dyndns/src/etc/inc/plugins.inc.d/dyndns.inc index bfe345048..5e664daa2 100644 --- a/dns/dyndns/src/etc/inc/plugins.inc.d/dyndns.inc +++ b/dns/dyndns/src/etc/inc/plugins.inc.d/dyndns.inc @@ -99,6 +99,7 @@ function dyndns_list() '3322' => '3322', 'citynetwork' => 'City Network', 'cloudflare' => 'CloudFlare', + 'cloudflare-v6' => 'CloudFlare (v6)', 'custom' => 'Custom', 'custom-v6' => 'Custom (v6)', 'dhs' => 'DHS', diff --git a/dns/dyndns/src/etc/inc/plugins.inc.d/dyndns/phpDynDNS.inc b/dns/dyndns/src/etc/inc/plugins.inc.d/dyndns/phpDynDNS.inc index 75dfff515..6120661c5 100644 --- a/dns/dyndns/src/etc/inc/plugins.inc.d/dyndns/phpDynDNS.inc +++ b/dns/dyndns/src/etc/inc/plugins.inc.d/dyndns/phpDynDNS.inc @@ -28,6 +28,7 @@ * - Custom dynamic DNS (any URL) * - Custom dynamic DNS IPv6 (any URL) * - CloudFlare (www.cloudflare.com) + * - CloudFlare IPv6 (www.cloudflare.com) * - Eurodns (eurodns.com) * - GratisDNS (gratisdns.dk) * - City Network (citynetwork.se) @@ -75,7 +76,8 @@ * SelfHost - Last Tested: 26 December 2011 * Amazon Route53 - Last Tested: 01 April 2012 * DNS-O-Matic - Last Tested: 9 September 2010 - * CloudFlare - Last Tested: 30 May 2013 + * CloudFlare - Last Tested: 19 September 2018 + * CloudFlare IPv6 - Last Tested: 19 September 2018 * Eurodns - Last Tested: 25 July 2018 * GratisDNS - Last Tested: 15 August 2012 * OVH DynHOST - Last Tested: NEVER @@ -236,6 +238,7 @@ class updatedns } switch ($dnsService) { + case 'cloudflare-v6': case 'custom-v6': case 'he-net-v6': case 'regfish-v6': @@ -284,6 +287,7 @@ class updatedns case '3322': case 'citynetwork': case 'cloudflare': + case 'cloudflare-v6': case 'custom': case 'custom-v6': case 'dhs': @@ -705,41 +709,52 @@ class updatedns curl_setopt($ch, CURLOPT_URL, $server); break; case 'cloudflare': - $dnsServer ='api.cloudflare.com'; - $dnsHost = str_replace(' ', '', $this->_dnsHost); - $host_names = explode('.', $dnsHost); - $bottom_host_name = $host_names[count($host_names) - 2] . '.' . $host_names[count($host_names) - 1]; + case 'cloudflare-v6': + $baseUrl = 'https://api.cloudflare.com/client/v4'; + $fqdn = str_replace(' ', '', $this->_dnsHost); + $fqdnParts = explode('.', $fqdn); + $hostName = array_shift($fqdnParts); + $domainName = implode('.', $fqdnParts); + $recordType = ($this->_useIPv6) ? 'AAAA' : 'A'; + $hostData = array( + "content" => "{$this->_dnsIP}", + "type" => $recordType, + "name" => $fqdn + ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array( - 'X-Auth-Email: '.$this->_dnsUser.'', - 'X-Auth-Key: '.$this->_dnsPass.'', + "X-Auth-Email: {$this->_dnsUser}", + "X-Auth-Key: {$this->_dnsPass}", 'Content-Type: application/json' )); // Get zone ID - $getZoneId = "https://{$dnsServer}/client/v4/zones/?name={$bottom_host_name}"; + $zonesUrl = "$baseUrl/zones"; + $getZoneId = "$zonesUrl/?name=$domainName"; curl_setopt($ch, CURLOPT_URL, $getZoneId); $output = json_decode(curl_exec($ch)); - $zone = $output->result[0]->id; - if ($zone) { // If zone ID was found get host ID - $getHostId = "https://{$dnsServer}/client/v4/zones/{$zone}/dns_records?name={$this->_dnsHost}"; + $zoneId = $output->result[0]->id; + if ($zoneId) { // If zone ID was found get host ID + $dnsRecordsUrl = "$zonesUrl/$zoneId/dns_records"; + $getHostId = "$dnsRecordsUrl?name=$fqdn&type=$recordType"; curl_setopt($ch, CURLOPT_URL, $getHostId); $output = json_decode(curl_exec($ch)); - $host = $output->result[0]->id; - if ($host) { // If host ID was found update host - $hostData = array( - "content" => "{$this->_dnsIP}", - "type" => "A", - "name" => "{$this->_dnsHost}", - "proxiable" => $output->result[0]->proxiable, - "proxied" => $output->result[0]->proxied - ); - $data_json = json_encode($hostData); - $updateHostId = "https://{$dnsServer}/client/v4/zones/{$zone}/dns_records/{$host}"; - curl_setopt($ch, CURLOPT_URL, $updateHostId); + $recordCount = count($output->result); + if ($recordCount === 0) { + // create record + curl_setopt($ch, CURLOPT_URL, $dnsRecordsUrl); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + } elseif ($recordCount >= 1) { + // update record + $recordId = $output->result[0]->id; + $hostData["proxied"] = $output->result[0]->proxied; + curl_setopt($ch, CURLOPT_URL, "$dnsRecordsUrl/$recordId"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json); + } + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($hostData)); + if ($recordCount > 1) { + log_error("Dynamic DNS ($fqdn): Warning: multiple records for $hostName found"); } } break; @@ -1118,6 +1133,7 @@ class updatedns } break; case 'cloudflare': + case 'cloudflare-v6': $output = json_decode($data); if ($output->result->content === $this->_dnsIP) { $status = "Dynamic DNS: (Success) {$this->_dnsHost} updated to {$this->_dnsIP}"; @@ -1125,7 +1141,7 @@ class updatedns } elseif ($output->errors[0]->code === 9103) { $status = "Dynamic DNS ({$this->_dnsHost}): ERROR - Invalid Credentials! Don't forget to use API Key for password field with CloudFlare."; } elseif (($output->success) && (!$output->result[0]->id)) { - $status = "Dynamic DNS ({$this->_dnsHost}): ERROR - Zone or Host ID was not found, check that your hostname is correct and an A record already exists."; + $status = "Dynamic DNS ({$this->_dnsHost}): ERROR - Zone ID was not found."; } else { $status = "Dynamic DNS ({$this->_dnsHost}): UNKNOWN ERROR - {$output->errors[0]->message}"; log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");