~ read.
Redémarrer une Box SFR Fibre THD (de merde) via curl

Redémarrer une Box SFR Fibre THD (de merde) via curl

tl;dr

curl -X POST 'https://192.168.0.1/goform/login' --data 'loginUsername=USERNAME&loginPassword=PASSWORD' \
'https://192.168.0.1/goform/WebUiOnlyReboot' --verbose --insecure

La version longue

Chez moi j'ai l'immense plaisir d'avoir la fibre by SFR... Bon en somme, c'est pas vraiment de la fibre (FTTH) car c'est une terminaison via coax (cable antenne TV = FTTB dans mon cas).

FTTx

Des problèmes avec cette merde j'en ai... :

  • réseau uniquement en 192.168.0.1/24
  • Wi-Fi en 2,4GHz capricieux de temps à autre
  • popup's TV indiquant des problèmes de signaux, alors que tout est OK
  • DMZ inacessible beaucoup trop souvent
  • interface d'admin inacessible après plusieurs jours

J'ai donc décidé de m'attaquer à la résolution des deux derniers problèmes à ma façon.

Problèmatique :

De temps à autre, lorsque j'essaye d'accéder à ma DMZ depuis l'extérieur je me fait bolay. Je constate les choses suivantes :

  1. mon IP publique est toujours la même
  2. l'interface d'administration de la box est elle aussi injoignable, depuis l'intérieur ainsi que de l'extérieur
  3. si je redémarrare ma box en lui coupant le jus tout refonctionne...

Hypothèse de résolution :

Vu que quand je redémarre ma box tout semble fonctionner pendant quelques jours, je n'ai qu'à essayer de la redémarrer tous les jours et peut-être ça permettra au logiciel interne de planter moins souvent...

Pour la redémarrer j'ai deux solutions :

  1. la sexy : redémarage via l'interface web d'administration
  2. la brutale : coller une prise électrique avec minuteur au cul de la box

Moi, j'aime les trucs sexy, mais je suis aussi un flémard. J'ai donc pas que ça à foutre tous les jour, donc on va essayer d'automatiser tout ça.

Résolution (le plus interessant) :

Comment faire tout ça ? La réponse est toute simple. Dans un premier temps on va essayer de déterminer ce qu'il se passe lorsque l'on fait la chose manuellement. Après avoir analysé tout ça, si tout vas bien, on devrait pouvoir créer une requête curl permettant d'effectuer la même action. Il ne restera alors qu'à automatiser exécution quotidienne de cette requête.

Comment ça se passe en manuel

  1. on va à l'adresse IP de la box, puis on clique sur "Configurer mon modem" :
    sfr_reboot_manuel_1

  2. on est redirigé vers /config.html, on s'authentifie :
    sfr_reboot_manuel_2

  3. on est redirigé une nouvelle fois vers /config.html, mais cette fois-ci on peut cliquer sur le bouton "Redémarrer votre modem" (puis sur la pop-up de confirmation)
    sfr_reboot_manuel_3

  4. tadaaaa ! la box reboot

Bon maintenant on va refaire tout ça mais cette fois en capturant le traffic pour vraiment voir la nature des échanges. Les puristes utiliseront Wireshark, mais dans mon cas il est tard et j'ai pas envie d'avoir un truc ultra verbeux donc je vais utiliser l'extension Postman pour Chrome. Et voilà ce qu'on obtient :

sfr_reboot_manuel_postman_1

On constate 2 choses choses intéressantes ici :

  • Les URL on l'air propres, donc pas de données mystiques envoyées via des GET. L'exécution des commandes semble donc possible par l'utilisation unique de requêtes POST.
  • On a deux requêtes POST : une semblant se gérer l'authentification, l'autre s'occupe du reboot

On passe direct à l'action et on regarde la première requête POST correspondant au login :

sfr_reboot_manuel_postman_2

Bon là dans les header y'a rien de particulier, donc on peut passer à la suite !

sfr_reboot_manuel_postman_3

Là par contre on peut voir les données d'authentification qui sont passées au routeur par le biais des variables "loginUsername" et "loginPassword". On passe à la suite en jetant un oeil à la requête permettant le reboot :

sfr_reboot_manuel_postman_4

Une nouvelle fois, rien de particulier. C'est plutôt une bonne nouvelle car ça va être assez simple pour la suite :)

Création de la requête

On va dérouler la création de la requête petit à petit, comme ça on ne perds personne en chemin

  1. Pour l'execution en commandline on va utiliser curl :
curl
  1. Les deux requêtes dont on a besoin sont en POST :
curl -X POST
  1. La première URL où l'on doit envoyer des données est 'https://192.168.0.1/goform/login' :
curl -X POST 'https://192.168.0.1/goform/login'
  1. On ajoute les identifiants :
curl -X POST 'https://192.168.0.1/goform/login' \
--data 'loginUsername=USERNAME&loginPassword=PASSWORD'
  1. On passe à la seconde URL à atteindre, permettant le reboot :
curl -X POST 'https://192.168.0.1/goform/login' \
--data 'loginUsername=USERNAME&loginPassword=PASSWORD' \
'https://192.168.0.1/goform/WebUiOnlyReboot'
  1. Et vu qu'on veut voir ce qu'il se passe un ajoute de la verbosité :
curl -X POST 'https://192.168.0.1/goform/login' \
--data 'loginUsername=USERNAME&loginPassword=PASSWORD' \
'https://192.168.0.1/goform/WebUiOnlyReboot' --verbose

Allez on execute tout ça et on est bon :

➜  kama ~ kama ~ curl -X POST 'https://192.168.0.1/goform/login' \
--data 'loginUsername=USERNAME&loginPassword=PASSWORD' \
'https://192.168.0.1/goform/WebUiOnlyReboot' --verbose
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 192.168.0.1...
* TCP_NODELAY set
* Connected to 192.168.0.1 (192.168.0.1) port 443 (#0)
* WARNING: using IP address, SNI is being disabled by the OS.
* SSL certificate problem: Invalid certificate chain
* Closing connection 0
curl: (60) SSL certificate problem: Invalid certificate chain
More details here: https://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
Note: Unnecessary use of -X or --request, POST is already inferred.
* Hostname 192.168.0.1 was found in DNS cache
*   Trying 192.168.0.1...
* TCP_NODELAY set
* Connected to 192.168.0.1 (192.168.0.1) port 443 (#1)
* WARNING: using IP address, SNI is being disabled by the OS.
* SSL re-using session ID
* SSL certificate problem: Invalid certificate chain
* Closing connection 1
curl: (60) SSL certificate problem: Invalid certificate chain
More details here: https://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

Oh le p'tit batard, il me fait chier avec le SSL ! Oui, regardez plus haut lorsqu'on a fait le reboot manuellement. Vous le voyez le petit triangle jaune sur le cadenas à juste avant l'URL ? Ce p'tit triangle qui veut dire "Le certificat SSL de cette page bah on le trust pas, bitch !". Ok, whatever, on va faire avec.

  1. On est un thug et on rajoute un "--insecure" indiquant qu'on est irresponsable :
curl -X POST 'https://192.168.0.1/goform/login' \
--data 'loginUsername=USERNAME&loginPassword=PASSWORD' \
'https://192.168.0.1/goform/WebUiOnlyReboot' --verbose --insecure

Et on teste une nouvelle fois :

➜  kama ~ curl -X POST 'https://192.168.0.1/goform/login' \
--data 'loginUsername=USERNAME&loginPassword=PASSWORD' \
'https://192.168.0.1/goform/WebUiOnlyReboot' --verbose --insecure
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 192.168.0.1...
* TCP_NODELAY set
* Connected to 192.168.0.1 (192.168.0.1) port 443 (#0)
* WARNING: disabling hostname validation also disables SNI.
* TLS 1.0 connection using TLS_RSA_WITH_AES_256_CBC_SHA
* Server certificate: xx:xx:xx:xx:xx:xx
> POST /goform/login HTTP/1.1
> Host: 192.168.0.1
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 48
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 48 out of 48 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 302 Redirect
< Server: PS HTTP Server
< Location: https://192.168.0.1:443/login.html
< Content-type: text/html
< Connection: close
< 
* SSLRead() return error -9806
* Closing connection 0
curl: (56) SSLRead() return error -9806
Note: Unnecessary use of -X or --request, POST is already inferred.
* Hostname 192.168.0.1 was found in DNS cache
*   Trying 192.168.0.1...
* TCP_NODELAY set
* Connected to 192.168.0.1 (192.168.0.1) port 443 (#1)
* WARNING: disabling hostname validation also disables SNI.
* SSL re-using session ID
* TLS 1.0 connection using TLS_RSA_WITH_AES_256_CBC_SHA
* Server certificate: xx:xx:xx:xx:xx:xx
> POST /goform/WebUiOnlyReboot HTTP/1.1
> Host: 192.168.0.1
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 48
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 48 out of 48 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: PS HTTP Server
< Content-type: text/html
< Connection: close
< 
* SSLRead() return error -9806
* Closing connection 1
curl: (56) SSLRead() return error -9806
<html><body BGCOLOR="#CCCCCC" TEXT=black><HR><h1>The device has been reset...<a href="https://192.168.0.1/login.html">RELOAD</a></h1></body></html

Et cette fois-ci on obtient le message suivant "The device has been reset...RELOAD". Mission accomplie !

Automatisation

Bon maintenant on veut s'assurer de ne plus avoir à executer cette commande manuellement tout les jours. Donc on va rajouter un magnifique CRON sur un serveur chez soi, en l'occurence je vais le mettre sur une de mes RaspberryPi.

On fait un "crontab -e", puis on ajoute cette ligne

0 5 * * * curl -X POST 'https://192.168.0.1/goform/login' --data 'loginUsername=USERNAME&loginPassword=PASSWORD' 'https://192.168.0.1/goform/WebUiOnlyReboot' --verbose --insecure

Bon, ça c'est fait, maintenant la box va redémarer tous les jours à 5h du mat !

Bilan

Je vais attendre quelques jours pour voir ce que ça donne maintenant...