Para entender este texto você precisa estar familiarizado pelo menos com o que expliquei neste outro.
A proposta de Scott Helme é uma solução mista de código aberto, que funciona no Windows e no Linux, mas requer que você tenha um servidor na internet com suporte a php.
São dois scripts. Um php rodando no servidor na internet e outro “batch” rodando na rede cujo ddns você quer manter atualizado. Todo o trabalho é feito pelo script php e o batch apenas serve para que o script php possa determinar qual seu atual endereço IP.
Se você usa Windows, ignore o script .sh fornecido e use os seguintes criados por mim (só funciona nas versões do Windows com suporte a Powershell – Windows 7 SP1 em diante):
cloudflare.bat
1 2 3 4 |
:loop powershell -executionpolicy bypass -File cloudflare_updater.ps1 timeout /t 120 goto loop |
Esse arquivo .bat vai executar o script a seguir a cada 120s.
cloudflare_updater.ps1
1 2 3 |
$postParams = @{auth='IjIraF4325678d1X8OI8j'} [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Invoke-WebRequest -Uri https://ryan.com.br/atualizar_ddns_cloudflare.php -Method POST -Body $postParams |
Notas:
- O que vem depois de “auth=” é uma senha/token que você pode definir como você quiser mas que precia ser igual ao que você definiu no script php. Por esse token é que o script vai saber ao mesmo tempo que você tem autorização e qual host você quer atualizar.
- Você tem que mudar o URL indicado (https://ryan.com.br/atualizar_ddns_cloudflare.php) para o endereço onde está hospedado o seu script php.
- Se o script .ps1 acusar um erro relacionado com o Internet Explorer, certifique-se de ter executado o IE na máquina ao menos uma vez para se livrar daquela pergunta que ele faz.
- A senha é necessária para evitar que alguém que descubra o endereço do seu script até mesmo por acidente (o mais provável é que seja maliciosamente) redirecione o ddns para si.
- Você pode precisar mudar o SecurityProtocolType do script para o usado pelo seu servidor de hospedagem. Eu usei tls12 porque foi o que funcionou com o meu.
Para que alguma mudança feita por Scott não quebre a compatibilidade da minha contribuição, aqui está uma cópia do script php dele da forma como funciona hoje, com algumas coisas traduzidas e/ou explicadas por mim. Note que com o token dado no meu arquivo .ps1 o subdomínio que terá o DDNS atualizado é subdominio1.automalabs.com.br:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
<?php /* Author: Scott Helme Site: https://scotthelme.co.uk */ // Você pode (mas não é obrigatório) gerar senhas aqui: https://scotthel.me/v1n0 // Exemplo: Kqt9TH4qBEOfNSGWfPM0 // Insert the appropriate "key" => "subdomain" values below $hosts = array( "IjIraF4325678d1X8OI8j" => "subdominio1", "ewrfwbffgyw8yrt43br4uf" => "subdominio2", "dhsahdaugdaswteq2we23q" => "subdominio3", "kariryeryhyhgrgfweaygq" => "subdominioX" ); // Verifica se o cliente chamador tem uma senha válida. if (empty($_POST['auth'])) { die("Requer autenticação\n"); } elseif (!array_key_exists($_POST['auth'], $hosts)) { die("Chave de autorização inválida\n"); } // Atualize os valores abaixo com as informações da sua conta Cloudflare. $apiKey = "CloudFlareApiKey"; // Sua CloudFlare API Key. $myDomain = "automalabs.com.br"; // O nome do seu domínio cadastrado na cloudflare. $emailAddress = "xxxxx@ryan.com.br"; // O endereço de email do seu cadastro na Cloudflare // Estes valores não precisam ser alterados. if (empty($hosts[$_POST['auth']])) $ddnsAddress = $myDomain; // If no subdomain is given, update the domain itself. else $ddnsAddress = $hosts[$_POST['auth']].".".$myDomain; // The subdomain that will be updated. $ip = $_SERVER['REMOTE_ADDR']; // The IP of the client calling the script. //$ip = $_SERVER['HTTP_CF_CONNECTING_IP']; // Replace the above line with this one if the DDNS server is behind Cloudflare $baseUrl = 'https://api.cloudflare.com/client/v4/'; // The URL for the CloudFlare API. // Array with the headers needed for every request $headers = array( "X-Auth-Email: ".$emailAddress, "X-Auth-Key: ".$apiKey, "Content-Type: application/json" ); // Sends request to CloudFlare and returns the response. function send_request($requestType) { global $url, $fields, $headers; $fields_string=""; if ($requestType == "POST" || $requestType == "PUT") { $fields_string = json_encode($fields); } // Send the request to the CloudFlare API. $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERAGENT, "curl"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $requestType); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if ($requestType == "POST" || $requestType == "PUT") { curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); curl_close($ch); return json_decode($result); } // Prints errors and messages and kills the script function print_err_msg() { global $data; if (!empty($data->errors)) { echo "Errors:\n"; print_r($data->errors); echo "\n"; } if (!empty($data->messages)) { echo "Messages:\n"; print_r($data->messages); echo "\n"; } die(); } // Determine protocol version and set record type. if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $type = 'AAAA'; } else { $type = 'A'; } //Update $baseUrl $baseUrl .= 'zones'; // Build the request to fetch the zone ID. // https://api.cloudflare.com/#zone-list-zones $url = $baseUrl.'?name='.$myDomain; $data = send_request("GET"); // Continue if the request succeeded. if ($data->success) { // Extract the zone ID (if it exists) and update $baseUrl if (!empty($data->result)) { $zoneID = $data->result[0]->id; $baseUrl .= '/'.$zoneID.'/dns_records'; } else { die("Zone ".$myDomain." doesn't exist\n"); } // Print error message if the request failed. } else { print_err_msg(); } // Build the request to fetch the record ID. // https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records $url = $baseUrl.'?type='.$type; $url .= '&name='.$ddnsAddress; $data = send_request("GET"); // Continue if the request succeeded. if ($data->success) { // Extract the record ID (if it exists) for the subdomain we want to update. $rec_exists = false; // Assume that the record doesn't exist. if (!empty($data->result)) { $rec_exists = true; // If this runs, it means that the record exists. $id = $data->result[0]->id; $cfIP = $data->result[0]->content; // The IP Cloudflare has for the subdomain. } // Print error message if the request failed. } else { print_err_msg(); } // Create a new record if it doesn't exist. if (!$rec_exists) { // Build the request to create a new DNS record. // https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record $fields = array( 'type' => $type, 'name' => $ddnsAddress, 'content' => $ip, ); $url = $baseUrl; $data = send_request("POST"); // Print success/error message. if ($data->success) { echo $ddnsAddress."/".$type." record successfully created\n"; } else { print_err_msg(); } // Only update the entry if the IP addresses do not match. } elseif ($ip != $cfIP) { // Build the request to update the DNS record with our new IP. // https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record $fields = array( 'name' => $ddnsAddress, 'type' => $type, 'content' => $ip ); $url = $baseUrl.'/'.$id; $data = send_request("PUT"); // Print success/error message. if ($data->success) { echo $ddnsAddress."/".$type." successfully updated to ".$ip."\n"; } else { print_err_msg(); } } else { echo $ddnsAddress."/".$type." is already up to date\n"; } ?> |
Eu já conhecia o dnsomatic.com mas ainda assim preferia usar minha solução, mas eu tenho tantos DDNS e vivia tendo que atualizar meu script de autenticação por conta de atualizações nas APIs que desisti e agora meu script atualiza somente no DNSOmatic que se encarrega de atualizar em todo o restante, a gama de servidores suportados é imensa.
Ontem, enquanto escrevia este texto, eu dei uma olhada no dns-o-matic mas achei complicado demais para quem quer apenas atualizar uma meia dúzia de endereços no mesmo serviço (Cloudflare). O fato de eu ter que criar uma conta com eles, mesmo sendo gratuita, já me incomodou. Não quero depender de mais serviços. Meu setup já é confuso o bastante com hospedagem na Hostgator e DNS na Cloudflare.