DNS dinamico fai-da-te senza servizi di terze parti

Rimpiazzare il proprio servizio di DNS dinamico con una coppia di script PHP e bash.

Esistono moltissimi servizi online anche gratuiti per il DNS dinamico quali DynDNS o NoIP. Questi servizi permettono l’associazione del propro indirizzo IP dinamico ad un nome DNS statico. Grazie ad essi è possibile raggiungere i servizi web installati dietro le proprie ADSL casalinghe (opportunamente nattate) senza dover ricordare e prendere nota dell’indirizzo IP pubblico che il provider di volta in volta ci fornisce.

Avevo un account su DynDNS per gestire da remoto il mio disco di backup ReadyNAS ma purtroppo dopo molto tempo il servizio è stato revocato e messo a pagamento. A tal punto, avendo già un dominio web PHP+MySQL (questo blog per l’appunto) ho deciso di implementarvi sopra un semplice servizio di traduzione IP in modo da raggiungere di nuovo il disco di backup.

Si è trattato semplicemente di realizzare una pagina web PHP che fornisce un redirect automatico (redirect HTML) al proprio indirizzo IP pubblico. L’indirizzo IP pubblico è memorizzato online in un file di testo ip.txt. E’ chiaro che tale indirizzo cambia con regolarità (al termine del lease-time impostato dal provider o ad ogni riavvio del modem ADSL) e quindi deve esistere un meccanismo per aggiornare tale file con il nuovo indirizzo. Un piccolo script bash che gira localmente sul ReadyNAS provvede ad aggiornare periodicamente il file remoto tramite una semplice richiesta HTTP GET.

In sostanza si tratta di realizzare due software distinti:

  1. ipremote.php: pagina PHP remota sul proprio dominio web che effettua il redirect all’indirizzo IP di casa
  2. ipupdater.sh: script bash locale (dietro ADSL) che ad intervalli regolari notifica la pagina web inviando il nuovo indirizzo IP

1) Pagina PHP (ipremote.php)

Molto semplicemente assolve alla duplice funzione di 1) redirect automatico e 2) aggiornamento del file ip.txt da parte dello script bash locale. Per accedere come redirect basta fornire la password corretta (in questo caso 123456) tramite una semplice richiesta GET: la pagina legge l’indirizzo IP pubblico corrente dal file e crea l’HTML per il redirect a quell’indirizzo. Per accedere in modalità aggiornamento (script bash presumibilmente) basta fornire, sempre in GET,  la password e il nuovo indirizzo IP: la pagina salverà l’indizzo IP specificato nel file di testo.

Ecco il codice:


<?php

$file = "ip.txt";

if(isset($_GET['newip']) == true && isset($_GET['pass']) == true)
{
   $ip = $_GET['newip'];
   $pass = $_GET['pass'];

   if($pass == "123456")
   {
      // update IP address
      file_put_contents($file, $ip);
   }
   else
   {
      echo "wrong password";
   }
}
else if(isset($_GET['pass']) == true)
{
   $pass = $_GET['pass'];

   if($pass == "123456")
   {
      // get IP address
      $ip = file_get_contents($file);
      echo '<html>';
      echo '<head>';
      echo '<meta http-equiv="refresh" content="0; url=http://'.$ip.'" />';
      echo '</head>';
      echo '<body>';
      echo '</html>';
   }
   else
   {
      echo "wrong password";
   }
}

?>

2) Script bash locale (ipupdater.sh)

Lo script bash viene eseguito periodicamente grazie a cron (ebbene si, il ReadyNAS è un embedded Linux a tutti gli effetti) e provvede a rilevare l’indirizzo pubblico corrente e a notificarlo alla pagina web PHP remota. La regola cron può essere impostata su una volta al minuto, una volta all’ora o quello che si vuole: più il rate di notifica è alto più bassa sarà la probabilità di trovare la pagina web momentaneamente disallineata col vero indirizzo IP.

Ecco lo script:

#!/bin/bash
ip=$(curl -s icanhazip.com)
password="123456"
url="http://www.mysite.it/ipremote.php?newip=$ip&pass=$password"
wget -qO- $url &> /dev/null

Lo script valorizza la variabile $ip con l’IP pubblico corrente. A tal file viene utilizzato il servizio web icanhazip.com che molto semplicemente restituisce l’indirizzo corrente.
Viene quindi composta la stringa URL con la richiesta GET di aggiornamento IP verso la pagina ipremote.php. www.mysite.it è il proprio dominio web, dove risiede ipremote.php.
Infine viene mandata la richiesta HTTP GET tramite wget ovviamente disabilitando opportunamente l’output su file e su console (a noi non interessa).

Come si usa

Accedere al ReadyNAS locale diventa ora banale: basta collegarsi all’indirizzo http://www.mysite.it/ipremote.php?pass=123456 per ottenere il redirect.
Ovvimente il sistema funziona non solo per accedere a dischi di rete, ma tutto quello che avete deciso di esporre nella vostra rete LAN (pannello di gestione remota del modem ADSL, VNC server, programmi vari etc..).

Perchè la password?

E’ chiaro che solo lo script bash locale deve essere in grado di aggiornare l’indirizzo altrimenti potreste ritrovarvi con un redirect ad un IP impostato da terzi. Anche il semplice redirect deve essere protetto da password, più che altro per questioni di privacy: conviene che solo voi possiate raggiungere i servizi della vostra rete LAN (protetti anch’essi da password, ovviamente).

Conclusioni

Vantaggi del sistema? Innanzitutto non occorre registrarsi e fare affidamento a servizi di terze parti (DynDNS, NoIP etc..). Il sistema non soffre dei ritardi di propagazione tipici del DNS per cui il nuovo IP pubblico è prontamente rilevato e aggiornato (basta settare un rate di aggiornamento ragionevolmente breve, tipo 5 minuti). Con un pò di fortuna è possibile embeddare lo script bash direttamente nel modem ADSL; è sufficiente che il modem si appoggi su una qualche distro Linux e abbia il demone cron installato.

Esistono alcuni contro però: la password fissa è soggetta ad attacchi di tipo replay-attack. Converrebbe implementare o un rolling code (ma introduce la possibilità di disallineamento) o meglio ancora uno schema più raffinato di tipo challenge-response.
Altro problema è che occore avere un dominio web PHP funzionante dove appoggiare la pagina ipremote.php.

Posted in Software, Tips.
Gianluca

Gianluca

Leave a Reply

avatar
Thunder

Ciao Gianluca, ottima soluzione. Temporaneamente stavo usando uno script php che mi aggiorna l’host su no-ip con una chiamata http, a seguito del down del dyndns proprietario di un NAS che uso. Non mi preoccuperei del IP in chiaro, dato che una volta che si decide di aprire alcune porte i rischi ci sono a prescindere, sta a noi difenderci. Segnalo un ottimo ARM Debian che uso https://excitostore.com/ ha tutte le soluzioni che un server debian/linux può darti.
Marco

Maurizio

Ciao, ho provato il tuo script, ma inserito ipremote.php sul sito, quando richiamo la pagina, ottengo questo errore:
Parse error: syntax error, unexpected T_VARIABLE in /membri/clinegenerators/i.php on line 8
riesci ad aiutarmi?
Grazie
Maurizio

Maurizio

Risolto
Grazie

Maurizio

Ciao Gianluca,
penso fosse il ; che manca in $ip.
Grazie per il tuo interessamento e complimenti per l’idea.

roby

Ciao,
Sto provando come hai detto. Non conosco php, ma sto usando asp. Non riesco ad ottenere il mio IP visto dall’esterno. Mi spiego, ho una piccola rete locale con un router esposto in internet. In asp se cerco di leggere il mio IP, ricevo l’IP della macchina nella rete interna (per intenderci del tipo 192.168.1.123) e non l’IP che viene visto dall’esterno (quello che viene restituito da un servizio del tipo “www.ilmioip.it”). E’ un limite di asp? Probabilmente, comunque anche se usassi php potrei leggere l’IP attraverso cui vado in internet ??
Grazie

Giorgio

con mysql forse si può avviare al problema di vedere in chiaro nel file ip.txt
facendo una query sia per agiornarlo con il file iplocale, sia per estrapolarlo con il file ipremote

Giorgio

e come si potrebbe risolvere??
potresti fare un’altra versione magari usando una query e per la pssword boh 🙁

Marco

Ciao, volevo segnalare un punto e virgola scappato, succede.
Riga 7, $ip = $_GET[‘newip’] manca il punto e virgola alla fine della riga.

Per il resto lo script funziona alla grande e ti ringrazio per averlo condiviso
Marco

Marco

Mi sono dimenticato di dire che riguarda il file ipremote.php

wpDiscuz