Contenuti

Python, Fritz e l'elfo - parte 1

Il problema

Ecco il mio problema (uno dei tanti): a volte il mio provider invece di assegnare alla mia connessione un indirizzo IP direttamente esposto su internet mi propina un IP “nattato”. Spiego cosa significa. In buona sostanza, normalmente quando ci si connette ad internet, viene assegnato alla connessione un indirizzo IP raggiungibile da internet, quindi se mi trovo al BrigX e conosco l’indirizzo IP assegnato al mio router di casa, posso pingarlo e/o accedere ai servizi che esso pubblica. Viceversa, quando viene assegnato un IP “nattato” significa che il router non è esposto su internet, ma su una rete “interna” al provider. Questo porta vantaggi e svantaggi:

  • vantaggio: il mio router/firewall casalingo è separato da internet da un qualche router/firewall superfigo e superblindato del provider. Difficilmente l’hackeronzolo di turno passerà di lì.
  • vantaggio (per il provider): usa meno indirizzi IPv4 per i suoi clienti. Questo è positivo (per il provider) perché gli indirizzi IPv4 sono praticamente finiti a livello mondiale, mentre la richiesta di indirizzi aumenta.
  • svantaggio: il router non è raggiungibile dall’esterno da nessuno, rendendo impossibile accedere ai servizi che si vogliono eventualmente pubblicare verso internet (VPN, telecamere, …)

Nel mio caso, l’irraggiungibilità della mia rete casalinga è un peso insostenibile. Soprattutto quando sei lontano da casa ed hai bisogno di accedere via VPN alla macchina di virtualizzazione. O peggio alle telecamere. L’assistenza del provider è stata piuttosto veloce a rispondere, ma la risposta non è stata soddisfacente: “abbiamo pochi IPv4 disponibili, quindi a volte ti capita un IP interno alla nostra rete, nonostante tu abbia chiesto di avere sempre un IP esterno”. La soluzione proposta dal provider è semplice: basta acquistare il servizio IP statico per circa 100€ annui. Il problema non erano i 100€ annui; il fatto è che a volte sulla mia spalla sinistra compare un elfo tossicodipendente e antipatico che mi obbliga a trovare una soluzione diversa.

Una soluzione non convenzionale

Fortunatamente ho un router “sopra la media” che ha anche la possibilità di essere comandato tramite api web. Ecco la soluzione: ho trovato una bellissima libreria in python per dialogare con il mio router!

Quindi l’idea è semplice: produco uno script da far girare tramite cron ogni 5 minuti, questo si collega al router, legge l’indirizzo IP assegnato alla connessione e se somiglia a “100...*” significa che è un IP nattato, quindi eseguo una riconnessione. E si comincia installando la libreria:

pip install FritzConnection

Clicca qui e qui se non sai cosa sia il comando qui sopra. Dando un’occhiata all’homepage della libreria FritzConnection si trovano due righe di codice che producono l’elenco dei comandi e parametri supportati dal mio modello di router. Quindi creo uno script contenente:

import fritzconnection as fc
fc.print_api(password='your_password')

lo eseguo e salvo il contenuto in un file:

fritz_dump_api.py > fritz_api.txt

Dal file si evince che dando il comando “GetInfo” alla sezione “WANPPPConnection” si ottiene un elenco di valori, tra i quali c’è anche ‘NewExternalIPAddress’. Ecco quindi la prima versione dello script:

from fritzconnection import FritzConnection
import re
fritzpass = 'lamiapassworddelrouter'
connection = FritzConnection(password=fritzpass)
ip = connection.call_action('WANPPPConnection', 'GetInfo')['NewExternalIPAddress']
match = re.search('^100\.', ip)
if match:
  connection.reconnect()

E’ sufficiente eseguire questo script tramite cron e vivere felici.

Script in produzione

A casa mia c’è una macchina che sicuramente è sempre accesa e può essere usata per monitorare la connessione: un nas che fortunatamente ha l’accesso SSH aperto e python installato. A dire il vero ogni macchina linux potrebbe funzionare, ma lasciare accesa un’altra apparecchiatura solo per questo mi sembrava uno spreco.

Ergo: Mi collego al nas via ssh

ssh root@nas

Installo PyPI e la libreria

wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py
pip install FritzConnection

Copio lo script da qualche parte e lo eseguo, giusto per vedere che funzioni

python /root/bin/reconnect_if_natted.py

Il mio nas mi permette di gestire gli script cron da interfaccia grafica, ma supponendo di avere una macchina linux il comando da dare è:

crontab -e

per aggiungere una riga come questa:

*/5 * * * * python /root/bin/reconnect_if_natted.py

una volta salvato il file, il nostro script verrà eseguito ogni 5 minuti, puntuale come i santi.

Conclusione

Sebbene tutto questo sia sufficiente per risolvere il problema, l’elfo non se n’è andato. Stay tuned per la seconda puntata.