Return false

Un blog IT de plus le blog de Hubebert.

Articles taggés avec ‘shell’

Tu as un serveur hébergé chez toi? Une box qui change d’IP quand ça lui chante? Voici une solution pour y pallier.

Cet article fait suite à celui d’ecaheti du 16 Août concernant la configuration de son Raspberry Pi le changement d’IP de sa box.  Il a lui même réalisé une solution expliquée dans son article, mais celle-ci nécessite qu’un moteur PHP tourne sur le Rasp. Bien qu’il éxiste des outils pour gérer ça de façon automatique, il peut être préférable de le faire soi même, c’est pourquoi je propose ici une autre approche, moins gourmande pour le serveur local et plus simple à mettre en place à mon goût.

Voici la configuration d'origine

La configuration d'origine

Ingrédients:

  • Un serveur chez soi (Raspberry ou autre, peu importe)
  • Un serveur web avec PHP (free.fr en fournit gracieusement, ça fait parfaitement l’affaire)
  • Une box permettant le NAT (la redirection des ports)

L'objectif final: mise à jour de l'IP et redirection automatique

L'objectif final: mise à jour de l'IP et redirection automatique

Sur la box:

Rediriger les ports auquels ont veut accéder depuis l’extérieur vers l’adresse IP locale du serveur. Je ne rentrerais pas dans les détails, on trouve de très bons tutos un peu partout pour ça.

Espace Web 1/2 :

Comment connaître l’ip de ma box/mon serveur local?

La meilleure façon de connaître l’IP de mon serveur local est encore de regarder l’adresse d’origine d’une requête allant de mon serveur local à mon espace web.

Pour différencier une requête qui provient d’un visiteur “normal” de celles servant a mettre à jour l’adresse de ma box on va utiliser des variables POST. On va même “sécuriser” ça sous la forme d’un ensemble clé-valeur pour éviter que n’importe qui puisse changer l’IP de référence.
On va ensuite stocker l’IP d’ou provient la requête valide dans un fichier texte. Pour récupérer l’ip d’origine d’une requête en PHP, on utilise la variable $_SERVER["REMOTE_ADDR"]. C’est pratique d’autant plus qu’en ouvrant le fichier avec l’attribut "w+" on ne se préoccupe même pas de l’effacer, le nouveau contenu remplacera toujours l’ancien contenu du dit fichier.

$KEY      =    "le_serveur";
$VALEUR =    "c'est moi!";
$FICHIER =    "ip.txt";

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}

Voilà pour la partie mise à jour de l’IP côté PHP. Rien de bien méchant. Chaque fois qu’une requête contenant “le serveur=c’est moi” sera envoyée sur ce fichier, le fichier “ip.txt” sera mis à jour avec l’adresse d’origine. Il ne reste plus qu’a le faire régulièrement…

Serveur personnel:

La partie la plus facile. On va demander l’envoi de l’ensemble clé-valeur vers le serveur web. Pour gérer les tâches répétitives on utilise le cron, auquel on ajoute la ligne suivante:

user$: crontab -e #edition du fichier crontab avec votre editeur par défaut

#Ajout d'une ligne pour envoyer la requête toutes les 5 minutes
*/5 * * * * curl --silent -F le_serveur="c'est moi!" http://addresse/de/mon/fichier.php

Espace Web 2/2 :

Revenons à l’espace Web. Pour l’instant, le fichier PHP permet de mettre à jour l’IP de notre auto-hébergement automatiquement, mais si un visiteur arrive sur la page, il ne se passe rien (page blanche). À mon goût, il y a deux trucs sympas a faire pour un visiteur:

  • Une redirection transparente et instantanée vers le serveur local
  • Une liste des services proposés par le serveur local

Option 1: Redirection transparente

Sur le fichier côté serveur on va tout simplement… rediriger le navigateur, d’où le titre ! Pour cela il existe une fonction PHP: header(). Sans rentrer dans les détails, celle-ci ne fonctionnera si elle est utilisée en tête de fichier. Si on veut rediriger, il est important de l’appeler le plus tôt possible. (Typiquement: avant le code HTML s’il y en a). La fonction header prends comme paramètre une chaîne de caractères. Si elle content “location: http://uneurl“, elle va nous rediriger vers une adresse du type: http://uneurl. On déclare donc deux variables en tête de fichier: $PORT et $PROTOCOL.

Port étant le port sur lequel rediriger (par défaut :80 pour le web), et le protocole a utiliser (http://, https:// …). À nouveau je ne vais pas rentrer dans les détails, le port 80 et le http couvrant la majorité des cas.

<?php
$KEY        =    "le_serveur";
$VALEUR     =    "c'est moi!";
$FICHIER    =    "ip.txt";
$PORT       =    ":80";
$PROTOCOL   =    "http://";

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {//Mise à jour de l'ip
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}else{//Redirection du client
$addresse   =   file_get_contents($FICHIER);
$addresse   =   $PROTOCOL . $addresse . $PORT;
header("location: $addresse");
}
?>

Protip: En PHP, lorsqu’on utilise des guillements doubles, on peut mettre nos variables directement entre les guillements. (Comme dans la ligne 15)

Option 2: Liste des services

Exemple de rendu de la liste de services

Exemple de rendu de la liste de services

On peut tout à fait s’arrêter ici et faire une page d’accueil sur le serveur local, permettant de lister les services dispos. Cependant, dans certains cas, il peut être utile de faire cela directement sur le serveur distant : pour économiser les (maigres) ressources d’un Raspberry Pi par exemple, et éviter d’y faire tourner un PHP juste pour afficher une page.

Pour lister les différents services, on va faire ça “en dur” ou de façon statique, pour éviter de scanner systématiquement tous les ports de votre serveur local à chaque visite. On va donc faire une liste des différents services que procure notre serveur. Cette liste va prendre la  forme d’un tableau associatif contenant le nom du service, et le port sur lequel il est publié.

Voici un exemple pour mon serveur.

$SERVICES    =    Array(
"Pages Web"=>":80",
"Streaming Video"=>":1234",
"Interface web qBittorrent"=>":8112",
"Interface web Transmission"=>":9091"
);

On va ensuite réaliser une boucle qui parcours ce tableau pour nous réaliser une liste au format HTML qu’il nous suffira ensuite d’afficher dans le corps d’une page HTML.

$IP = file_get_contents($FICHIER);
$listeHTML = "<ul>";
foreach($SERVICES as $nom => $port){
$URL = $PROTOCOL . $IP . $port;
$listeHTML .= "<li><a href='$URL'>$nom</a></li>";
}
$listeHTML .= "</ul>";

Pour les fénants, le code de la page HTML entière:


<?php
$KEY        =    "le_serveur";
$VALEUR     =    "c'est moi!";
$FICHIER    =    "ip.txt";
$PORT       =    ":80";
$PROTOCOL   =    "http://";
$SERVICES    =    Array(
"Web"=>":80",
"Streaming"=>":1234",
"qBittorrent"=>":8112",
"Transmission"=>":9091"
);

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}else{
$IP = file_get_contents($FICHIER);
$listeHTML = "<ul>";
foreach($SERVICES as $nom => $port){
$URL = $PROTOCOL . $IP . $port;
$listeHTML .= "<li><a href='$URL'>$nom</a></li>";
}
$listeHTML .= "</ul>";
}
?>
<!DOCTYPE HTML>
<html lang="en">
<head>
<link href='http://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css'>
<title>Mon chouette serveur Perso!</title>
<style type="text/css" media="screen">
*{
text-align:center;
}
h1{
font-family:'Ubuntu';
}
ul{
list-style-type:none;
}
</style>
</head>

<body>
<h1>Mon chouette serveur Perso...</h1>
<p>...est à votre disposition, et fournit les services suivants:</p>
<?php echo $listeHTML;?>
</body>
</html>
Voilà, en espérant avoir été clair et que cela resserve à d’autres.
Avec la démocratisation du Raspbery Pi, ce genre de petit script peut éviter des déboires à certains d’entre vous et vous permettre de vous concentrer sur des problèmes plus intérressants.