Lors de mon installation Jeedom j'ai été confronté à un problème :
- Comment accéder à mon serveur web Jeedom alors que celui-ci est hébergé derrière un routeur 4G
La problématique : Afin de limiter la consommation d'adresses publiques pour tous les équipements mobiles (téléphones portables, routeurs 4g, girouette connectée...), les opérateurs mobiles utilise le routage CGNAT afin de partager une adresse publique entre plusieurs apareils.
Ce qui veut dire que notre boxe 4g n'a donc pas d'IP publique (sauf si l'on a pris une option couteuse chez l'opérateur).
Donc à chaque fois que nous effectuons une requête vers internet, elle passe par notre routeur 4G qui attribue un port de réponse à notre machine puis par le routeur CGNAT qui en fait de même en réservant un port de réponse savoir vers quel routeur 4g ( = quel client) envoyer la réponse.
Comme ces ports de retours sont encapsulés dans la requête que nous envoyons, le serveur d'en face peut alors répondre en reprécisant grâce à ces port le chemin inverse. Une fois la requête reçue par le routeur CGNAT il décapsulera il va la décapsuler, lire le port de réponse qui lui indiquera alors à quel routeur 4g l'envoyé, qui reproduira ce processus pour la router vers la bonne machine du réseau local.
Là où ça se complique, c'est lorsque l'on veut joindre notre serveur web, hébergé sur notre réseau domestique car tout ce qui nous est transmis c'est l'adresse publique du routeur CGNAT de l'opérateur. En effet notre routeur 4G étant situé sur un réseau privé de l'opérateur, n'avons pas le moyen de le joindre.
On pourrait faire l'analogie avec un service postale. Vous voulez envoyer une lettre à une personne habitant dans une résidence où il y a plusieurs logements. Le routeur CGNAT qui a l'adresse publique dans ce cas correspond à l'adresse de votre correspondant ("4 rue de la biscotte - 51300 le Fion"). Or pour le que la facteur mette le courrier dans la boite au lettre il faut qu'il rentre dans l'espace privé de la résidence et se dirige vers la bonne boite aux lettres grâce au nom de la personne ("Jean claude Duss"). Or ce nom et ce prénom gravés sur la boite aux lettres correspond à l'adresse IP privé de notre routeur 4G sur le réseau de l'opérateur que nous n'avons pas.
Donc envoyé une trame vers cette adresse publique revient à envoyer une lettre dans une grande résidence sans connaitre le nom et le prénom du destinataire. Le courrier / la trame est perdue et ne peut donc arriver.
La solution proposée : La solution que je propose est de passer par une autre machine qui elle à une IP publique.
Dans mon cas cette machine est un serveur VPS loué chez un hébergeur web ( ≃ 4€/mois). Cette machine peut aussi bien être un petit raspberry pi qu'un proche vous laisse brancher gentiment chez lui dans le cas ou il a une connexion avec une IP fixe. Dans ce cas il ne faut pas oublié de refaire la redirection NAT sur sa box/routeur des ports que nous allons ouvrir au publique vers votre raspberry (ou tout autre machine linux).
Ici j'ai schématisé 3 étapes. La première (1) correspond à la mise en place de la solution et la deuxième (2+3) à son utilisation.
Etape 1, la mise en place :
Comme nous ne pouvons pas atteindre depuis l'extérieur notre serveur web, nous allons donc en joindre un autre accessible par une IP publique, nous l'appellerons le relai. Le relai n'a pas plus accès que notre serveur au client. Si l'on reprend notre analogie, le relai correspondrait à une adresse ou l'on peut poster notre courrier sans ambiguïté (" Popeye - 5 rue de la biscotte - 51300 le Fion). C'est pas parce que l'on poste notre courrier à cette adresse qu'il va se retrouver dans la boite au lettre de notre bon vieux JC. C'est à ce moment que l'analogie se complique un peu, car nous allons créer un tunnel qui va faire glisser toutes les enveloppes mises dans boite aux lettres de Popeye vers celle de JC.
Techniquement on traduit ça par du "reverse ssh tunneling". En pratique comme notre relai ne peut pas joindre directement notre serveur web, c'est notre serveur web qui va se manifester à lui en lui envoyant une requête. Or comme dit tout a l'heure, dans l'architecture où nous trouvons nous savons très bien faire revenir le trafic vers notre machine à l'intérieur de notre réseau local, si c'est lui qui a émis la première requête.
Comme l'aller retour est possible le relai est donc capable maintenant de joindre le serveur web. Cette requête est un peu plus que ça car en fait c'est une demande au relai d'ouverture d'un tunnel SSH ( = un canal de communication bidirectionnel chiffré qui reste ouvert entre les deux équipements pour un temps donné).
Grâce à des arguments de la requête SSH (que je détaillerai plus tard), nous allons pouvoir demander au relai de nous transmettre via le tunnel tout le trafic reçu sur un certain port (80/443 pour du web). Ça y est le tuyau est posé entre nos 2 boites aux lettres et le courrier va pouvoir glisser.
en une phrase : Le serveur web initie un tunnel ssh avec le relay en lui demandant de faire transiter tout le trafic qu'il reçoit sur un port donné.
Etape 2, Utilisation :
Maintenant que le tuyau est posé il n'y a plus qu'a mettre l'enveloppe chez Popeye pour qu'elle glisse chez JC.
Indiqué en 2 le client va joindre notre serveur relai grace à son IP publique sur le port 80 par exemple. Suite à la configuration que nous avons faite dans l'étape précédente, sa requête va donc automatiquement être transmise au serveur web. La réponse du serveur web se fera ensuite en empruntant le chemin inverse.
Mise en place :
prérequis :
- avoir un jeedom / serveur web installé sur une machine linux(je pars du principe que celui-ci écoute les ports 80 et 443
- avoir une machine relai avec un serveur openvpn installé et pour la quelle les ports 22/80/443 sont joignables via une ip publique (ou nom de domaine)
étape 1: installer auto SSH
Code : Tout sélectionner
sudo apt install autossh -y
étape 2: installer auto SSH
Pour éviter de devoir retaper le mot de passe à chaque connexion ssh vers le relai, nous allons créer une paire de clé publique/privée.
Code : Tout sélectionner
ssh-keygen -t rsa -b 16384
cette commande est un peu longue, même sur une machine performante.
Une clé privée id_rsa et une clé publique id_rsa.pub sont créées dans le répertoire /home/votreuser/.ssh
étape 3: transférer la clé au relai
Code : Tout sélectionner
cd
ssh-copy-id -i .ssh/id_rsa.pub root@relai
on peut alors faire un
Code : Tout sélectionner
ssh root@relai
étape 4: autoriser le port forwarding
comme nous sommes connectés au relai, nous allons en profiter pour autoriser la redirection de flux dans la conf du serveur openssh.
Code : Tout sélectionner
sudo nano /etc/ssh/sshd_config
il faut alors modifier la ligne :
#GatewayPorts yes
en
GatewayPorts yes
ctrl +x pour sauvegarder puis quitter.
Redémarrer le serveur sshd pour qu'il prenne en compte la modification
Code : Tout sélectionner
sudo service sshd restart
étape 5: créer un script ouvrant les tunnels
De retour sur notre serveur web nous allons créer un script de création des tunnel ssh de port forwading.
Code : Tout sélectionner
cd
nano sshtunnel
Code : Tout sélectionner
#/bin/sh
export AUTOSSH_FIRST_POLL=30
export AUTOSSH_GATETIME=0
export AUTOSSH_POLL=60
autossh -i /home/user/.ssh/id_rsa -NR 80:127.0.0.1:80 root@relai &
autossh -i /home/user/.ssh/id_rsa -NR 443:127.0.0.1:443 root@relai &
Ce sont les deux dernière lignes quoi ouvrent les tunnels et que vous devez adapter.
la première pour le http (80) et la deuxième pour le https(443)
voici comment elles sont composées :
autossh = nom de l’exécutable a lancer
-i = arguement pour indique que l'authentification se fera par clé et non par mot de passe
/home/user/.ssh/id_rsa = le chemin de la clé de déchiffrement. il faudra changer user par votre nom d'utilisateur
-NR = arguments signifiants que le tunnel n'est pas fait pour lancer des commandes a distances mais pour faire du reverse ssh tunneling
80:127.0.0.1:80 =le premier 80 correspond au port d'écoute du relai, la suite à l'endroit ou il faut le rediriger. ici tout ce qui arrive sur le port 80 de notre relai sera donc rediriger vers 127.0.0.1:80 (=le port 80 du serveur sur le quel nous somme)
root@relai = pour dire que pour se faire nous allons nous connecter en tant que root sur notre relai. Vous devez changer relai par l'IP publique ou le nom de domaine de votre relai
& = ce caractère en fin de commande libère le prompt pour pouvoir passer à la commande suivante
Une fois adapté, fermer enregistrer et fermer l'éditeur de texte.
étape 6: rendre le script éxécutable
Code : Tout sélectionner
sudo chmod +x sshtunnel
Code : Tout sélectionner
./sshtunnel
https://relai (où relai est l'ip publique de votre serveur web)
ou http://relai si vous n'avez pas encore activé le https.
étape 7: démarrer automatiquement le script à chaque redémarrage du serveur web
Nous allons éditer la crontab
Code : Tout sélectionner
crontab -e
Code : Tout sélectionner
@reboot /home/user/sshtunnel
Et voila vous avez les tunnels se montent automatiquement à chaque redémarrage de votre machine et vous avez contourné vous même la barrière du CGNAT
vous exposez votre serveur au monde entier alors au minimum pensez a mettre en place le https sur votre jeedom (procédure ici).