[Tuto] Résoudre le problème de hairpinning Orange avec le DHCP/DNS de YunoHost

fr

#1

Avertissement

Dans un premier je voudrais préciser que cette méthode fonctionne avant tout pour moi ! Je n’ai aucune idée du respect des “bonnes pratiques” avec ces propositions là.

Cependant, je serais ravi d’échanger avec vous tous (utilisateurs de YunoHost ou bien dev YunoHost) par rapport à cette méthode là ; est-ce une bonne pratique ? ; est-ce que je me prends la tete ? ; est ce qu’il y a moyen de faire ça plus facilement ? Enfin bref j’attend avec impatience vos retours :wink:

Introduction

Étant client Orange fibre j’ai comme beaucoup le problème de hairpinning avec ma Livebox.

En épluchant un peu le forum ici et d’autres sur internet voici la solution que je propose pour contourner ce problème.

Pour résumer je n’utilise la Livebox que comme bridge internet, c’est mon serveur YunoHost qui fait office de serveur DHCP et résolveur DNS. Tout ça grace à DNSmasq qui est normalement installé est activé par défaut sur votre serveur YunoHost.

Pour résumé voici les avantages de cette méthode :

  • Vous pouvez accéder à l’interface YunoHost et à vos services depuis vos machines locales directement via l’URL de votre domaine et non plus en utilisant l’ip locale de votre serveur YunoHost
  • Vous pouvez renouveler vos certificats Let’s Encrypt sans avoir besoin d’utiliser l’option --no-checks (plus de Warning de hairpinning)
  • YunoHost sera capable de renouveler automatiquement vos certificats Let’s Encrypt

La TV par internet

Personnellement je n’utilise pas le décodeur TV d’orange (en plus j’ai le décodeur blanc qui est complètement buggé …). Cependant, je le précise plus tard, mais il est important que le décodeur reçoive son IP du serveur DHCP de la box et non pas par YunoHost. Je crois que c’est dû au fait que la TV d’Orange a besoin d’utiliser les DNS hardcodés dans la LiveBox.

Finalement : Si vous voulez garder la TV d’Orange il faut laisser activer le DHCP de la LiveBox, pour les autres aucun problème à le désactiver.

Je précise les deux cas dans le tuto.

Vérification de la config actuelle

Avant de commencer je propose de faire un petit tour d’horizon afin d’être sûr que la base soit bonne. De mon coté, voici le contenu des différents fichiers de configuration qui nous intéresse dans leurs états juste après une installation fraiche de YunoHost.

  • /etc/network/interfaces
source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp
  • /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1
  • /etc/resolv.dnsmasq.conf
nameserver 84.200.69.80
nameserver 141.255.128.100
nameserver 80.67.169.12
nameserver 80.67.188.188
nameserver 80.67.169.40
nameserver 89.234.186.18
nameserver 213.73.91.35
nameserver 89.234.141.66
nameserver 89.233.43.71
nameserver 91.239.100.100
nameserver 85.214.20.141
nameserver 141.255.128.101
nameserver 84.200.70.40
  • /etc/dnsmasq.conf
domain-needed
expand-hosts

listen-address=127.0.0.1
resolv-file=/etc/resolv.dnsmasq.conf
cache-size=256

1. Attribution d’une IP fixe au serveur YunoHost

Si ce n’est pas déjà fait, je pense que c’est une bonne chose de fixer l’adresse IP du serveur YunoHost étant donné que nous allons désactiver le serveur DHCP de la LiveBox.

Pour ça, il suffit d’éditer le fichier /etc/network/interfaces et de modifier la ligne correspondant à l’interface réseau utilisée. Mais avant, on fait une petite sauvegarde du fichier avec sudo cp /etc/network/interfaces /etc/network/interfaces.bak et enfin on édite le fichier avec sudo nano /etc/network/interfaces et on le modifie comme ceci :

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet static # On passe en static
    address 192.168.1.2 # Adresse IP locale que l'on souhaite pour YunoHost
    netmask 255.255.255.0 # Le masque du sous-réseau
    gateway 192.168.1.1 # L'adresse de notre passerelle, ici c'est notre box qui a normalement cette IP

Un petit redémarrage et normalement vous pouvez vous connecter à votre serveur avec sa nouvelle IP.

2. Activer le serveur DHCP de DNSmasq

Maintenant on va activer le serveur DHCP de YunoHost. Le rôle du serveur DHCP est de fournir une adresse IP valide aux machines qui se connectent à votre réseau local ainsi que les différentes informations utiles comme la passerelle ou encore le resolveur DNS.

Jusqu’à présent c’était votre LiveBox qui était chargée de faire ça. Maintenant c’est votre serveur YunoHost qui va s’en charger. L’avantage en utilisant celui-ci, c’est qu’il va communiquer comme résolveur DNS sa propre IP et faire travailler DNSmasq, contrairement à LiveBox qui fourni les DNS d’Orange.

Pour activer le serveur DHCP de YunoHost il faut éditer le fichier /etc/dnsmasq.conf mais avant on fait une sauvegarde avec sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.bak et enfin sudo nano /etc/dnsmasq.conf afin de modifier le fichier comme ceci :

domain-needed
expand-hosts

# listen-address=127.0.0.1 # On veut écouter aussi les machines de notre LAN
resolv-file=/etc/resolv.dnsmasq.conf

cache-size=2048 # Nombre d'entrées DNS max à garder en cache
bogus-priv
dhcp-range=192.168.1.10,192.168.1.50,255.255.255.0,24h # Active le serveur DHCP, 
# celui-ci fournira des adresses IP entre 192.168.1.10 et 192.168.1.50 aux machines du réseau
dhcp-option=option:router,192.168.1.1 # Indique la passerelle de notre réseau

# Seulement si vous gardez la TV d'Orange, il faut récupérer l'adresse MAC du décodeur et la renseigner ici
# Cette ligne dit à DNSmasq de ne pas s'occuper du décodeur TV et de ne pas lui donner d'IP
# C'est la LiveBox qui le fera (voir plus bas)
dhcp-host=8c:10:d4:d7:a7:ad,ignore

Il ne faut pas oublier d’ouvrir le port 67 UDP sur votre serveur pour que le serveur DHCP soit visible sur votre réseau. Nous faisons ça avec la commande sudo yunohost firewall allow UDP 67.

Enfin, on relance DNSmasq pour prendre en compte la configuration avec sudo service dnsmasq restart et on regarde que tout se passe bien avec sudo service dnsmasq status.

À partir de maintenant votre serveur DHCP doit être fonctionnel, vous pouvez peut être essayer sur une autre machine dans vos paramètres réseau en demandant de renouveler le bail DHCP et en spécifiant l’adresse IP de votre serveur afin de ne pas utiliser le DHCP de la LiveBox.

Si vous récupérez bien une adresse IP dans la tranche que vous avez spécifié et que votre connexion internet fonctionne alors on peut passer à la suite et désactiver le serveur DHCP de la LiveBox

3. Désactiver le serveur DHCP de la LiveBox

Rien de bien compliquer, connectez vous sur l’interface admin de votre Box depuis un navigateur en entrant l’URL 192.168.1.1. Connectez vous en tant qu’admin et rendez vous dans l’onglet “Configuration avancée” et l’onglet “DHCP”.

  • Si vous n’utilisez pas la TV d’orange alors vous pouvez simplement cocher “désactiver” et enregistrer
  • Si vous utilisez la TV d’orange il faut laisser activer le serveur DHCP mais restreindre la plage à seulement une adresse et si possible hors de la plage d’IP que vous avez donné pour le serveur DHCP de YunoHost. L’idée en laissant seulement une IP disponible c’est de permettre au décodeur TV de prendre cette IP là.

4. Vérification du fonctionnement de DNSmasq

Maintenant votre serveur DHCP et resolveur DNS perso de YunoHost devrait fonctionner correctement. Pour tester tout ça il vous suffit sur une de vos machines de la déconnecter du réseau et de la reconnecter pour qu’elle interroge le serveur DHCP de YunoHost. Si tout va bien elle devrait récupérer une adresse IP de l’intervalle que vous avez défini dans /etc/dnsmasq.conf et votre connexion internet devrait fonctionner.

Pour vous assurer que le résolveur DNS utilisé est bien celui de YunoHost faites un petit dig www.google.fr dans votre shell ; le serveur indiqué devrait être l’adresse IP de votre serveur YunoHost.

Mais pour l’instant, si dans votre navigateur vous essayez d’accéder à votre interface YunoHost via votre domaine principal cela ne fonctionne pas. Tout simplement parce que DNSmasq retourne à votre machine votre adresse IP publique. Il va falloir modifier la config de DNSmasq pour qu’il vous retourne l’adresse IP locale de votre serveur et non pas l’adresse IP publique.

5. Ajouter vos domaines à la config de DNSmasq

Pour chacun de vos domaines il va falloir modifier le fichier qui correspond dans le dossier /etc/dnsmasq.d comme par exemple le fichier /etc/dnsmasq.d/toto.fr indiqué ici :

# address=/toto.fr/80.80.80.80 # On remplace la ligne avec notre IP publique
address=/toto.fr/192.168.1.2 # par l'IP locale de notre serveur YunoHost
txt-record=toto.fr,"v=spf1 mx a -all"
mx-host=toto.fr,toto.fr,5
srv-host=_xmpp-client._tcp.toto.fr,toto.fr,5222,0,5
srv-host=_xmpp-server._tcp.toto.fr,toto.fr,5269,0,5

Après un sudo service dnsmasq restart vous devriez pouvoir accéder sur chacune de vos machines à votre interface Yunohost en utilisant votre nom de domaine comme URL.

6. Mise en place et renouvellement des certificats Let’s Encrypt

Cependant il reste encore un problème. Lorsque vous mettez en place un certificat pour vos noms de domaine vous obtenez le message suivant :

Attention : Expiration du délai lors de la tentative du serveur de se contacter 
via HTTP en utilisant son adresse IP publique (domaine toto.fr avec l’IP
xx.xxx.xxx.xxx). Vous rencontrez peut-être un problème d’hairpinning ou
alors le pare-feu/routeur en amont de votre serveur est mal configuré.

En effet, le NAT loopback de la Livebox ne fonctionne pas, donc quand YunoHost interroge votre IP publique sur le port 80 celle-ci n’est pas capable de renvoyer l’IP locale de votre serveur.

Le seul moyen que j’ai trouvé pour le moment est d’utiliser iptables afin de transférer tout le trafic de votre IP publique vers l’IP locale de votre serveur YunoHost.

Dans un premier temps il faut activer l’ip forwarding en éditant le fichier /etc/sysctl.conf avec un sudo nano /etc/sysctl.conf et dé-commenter la ligne net.ipv4.ip_forward afin d’avoir net.ipv4.ip_forward=1.

Maintenant il faut ajouter une règle Iptables afin de maintenir la redirection d’IP même si l’IP publique change.
Pour cela j’utilise Cron afin de vérifier toutes les 15 minutes si mon IP a changé et modifier la redirection si besoin.

Dans un premier temps je créé un dossier dans mon home afin d’accueillir mon script : mkdir ~/ynh_hairpinning_fix.
Enfin je créé mon script avec nano ~/ynh_hairpinning_fix/ynh_hairpinning_fix.sh et voici son contenu :

#!/usr/bin/env bash

local_ip="192.168.1.2"
last_ip_file="/home/admin/ynh_hairpinning_fix/last_ip.txt"


function delete_previous_iptables_rule {
	rule_number=$(/sbin/iptables -L --line-numbers -t nat | grep 'ynh_hairpinning_fix' | awk '{print $1}')
	cmd="/sbin/iptables -t nat -D OUTPUT $rule_number"
	echo "$cmd"
	eval $cmd
}


function add_iptables_rule {
   	cmd="/sbin/iptables -t nat -A OUTPUT -d $public_ip -j DNAT --to-destination $local_ip -m comment --comment \"ynh_hairpinning_fix\""
	echo "$cmd"
	eval $cmd
}


# Get current public IP
public_ip=`dig +short myip.opendns.com @resolver1.opendns.com`
echo "Current public IP: $public_ip"


# Check if the iptables rule exists, if not, 
# just add the rule and save the current public IP
iptables_save=$(/sbin/iptables-save)
if [[ $iptables_save != *"ynh_hairpinning_fix"* ]];
then
	echo "Iptables rule does not exist, let's add it"

	# Add iptables rule
	add_iptables_rule
	
	# Save current public ip
	echo "$public_ip" > $last_ip_file

	exit 0
fi


# If the iptables rule exists,
# check if the public IP has changed
if [ -f "$last_ip_file" ]
then
	previous_ip=$(head -n 1 $last_ip_file)
	
	if [ "$previous_ip" = "$public_ip" ];
	then 
	    echo "Public IP unchanged, nothing to do"
	
	else
		echo "Public IP changed, let's modify iptables rule"
		echo "Previous public IP: $previous_ip"
		delete_previous_iptables_rule
		add_iptables_rule
		echo "$public_ip" > $last_ip_file
	fi;


else
	echo "Previous public IP unkown, let's modify iptables rule"
	delete_previous_iptables_rule
	add_iptables_rule
	echo "$public_ip" > $last_ip_file	
fi

exit 0

N’oubliez pas d’adapter la variable local_ip en mettant l’IP locale de votre YunoHost. Et enfin, rendez votre script exécutable avec chmod +x ~/ynh_hairpinning_fix/ynh_hairpinning_fix.sh.
Vous pouvez maintenant le lancer une première fois avec la commande sudo ~/ynh_hairpinning_fix/ynh_hairpinning_fix.sh (important de se placer root car on utilise ici Iptables).
Maintenant vous pouvez vérifier que la règle a bien été ajouté dans Iptables avec sudo iptables -L --line-numbers -t nat.

Il ne reste plus qu’à ajouter ce script à Cron pour vérifier régulièrement que si votre IP publique change.
Faite un sudo crontab -e afin d’éditer vos entrée Cron root et ajoutez la ligne suivante :
*/15 * * * * /home/admin/ynh_hairpinning_fix/ynh_hairpinning_fix.sh.

Redémarrez votre YunoHost et essayez de renouveler votre certificat ; normalement le warning a disparu !

Conclusion

Voilà tout !

J’espère que les explications sont assez claires et aussi que ce tuto peut servir à d’autre personnes (je ne sais pas pour les autres box comme Bbox ou encore SFR, peut être que ça peut servir, ou même chez nos amis Belges avec Proximus?).

Si d’autres clients Orange sont dans le même cas que je moi je veux bien vos trucs et astuces pour résoudre ce problème là, peut être qu’il y a plus simple et plus efficace ?

Et surtout merci à la communauté YunoHost :heart_eyes:


Cannot access YunoHost by domain name in LAN or over VPN
Yunohost-firewall local connection bloked
[RÉSOLU] Erreur certificat LE sous-domaine
Orange et hairpinning et modem-routeur
#2

Tuto qui m’a vraiment aidé, merci beaucoup :wink: marche aussi très bien pour Proximus en Belgique (Bbox3).

Simplement, pour un ip statique, la manœuvre semble avoir changée sur Debian Strech et Yunohost 3. J’ai du éditer le fichier /etc/dhcpcd.conf et dé-commenter “static ip_address” et “static routers” en adaptant à mes adresses ip comme suit:

interface eth0
static ip_address=192.168.1.2 #l'adresse ip locale de votre serveur
static routers=192.168.1.1 #l'adresse ip de la box (gateway)

Petites questions, pour la solution exposée ici pour permettre let’s encrypt:
1)Quel est l’avantage par rapport à

sudo yunohost domain yourdomain.tld cert-install --no-checks

?
2) Comment faire avec une ip publique dynamique? (dans l’exemple donné il faut changer 80.80.80.80 par son ip publique, c’est bien ça?)


How to change domaine of yunohost installation
#3

Salut Narvod,

Cool alors si tu as pu t’inspirer de ces indications pour ton problème avec la box de Proximus :grinning:

Concernant les changements pour Debian Strech j’en prends bonne note, je n’ai personnellement pas encore upgrade, je ferais ça après un bon backup et avec un peu de temps libre :stuck_out_tongue:

Alors pour ta question 1) : (ça a peut être changé depuis mes derniers tests qui sont assez vieux)
Normalement YunoHost est capable de renouveler automatiquement les certificats avant qu’ils expirent, le problème c’est que si je ne faisais pas le petit hack avec l’iptable alors YunoHost n’arrive pas à renouveler les certificat automatiquement. Du coup il faut le faire à la main avec la ligne de commande que tu donnes (–no-checks).
Donc le hack de l’iptable sert simplement à permettre à YunoHost de faire le renouvellement automatiquement et moi ça m’évite d’avoir à penser à renouveler à la main mes certificats :wink:

Pour la 2), c’est bien ça, il faut changer 80.80.80.80 par son ip publique, est effectivement avec une ip dynamique c’est assez chiant car il faut modifier la ligne du crontab.
Je ne l’ai pas encore fait mais je pense qu’on peut très bien imaginer le remplacement de cette ligne crontab par l’exécution d’un script Bach qui, dans un premier temps, récupère l’ip publique (par exemple avec ça : curl -s http://whatismyip.akamai.com/), tu stockes le retour de cette commande dans une variable que tu utilises dans la commande iptable :wink:

Si tu mets ça en place n’hésites pas à partager ton script/méthode si tu le veux bien :wink:

Bonne journée !


#4

voilà, j’ai fais comme suggéré un script qui récupère l’ip publique, et la stock dans une varible. J’ai donc:

  • un fichier /bin/iptable-berrypi (je n’étais pas très inspiré pour le nom :blush:)

    #!/bin/bash
    MYIPPUB=$(curl -s checkip.dyndns.org | sed -e ‘s/.Current IP Address: //’ -e 's/<.$//’);
    /sbin/iptables -t nat -A OUTPUT -d $MYIPPUB -j DNAT --to-destination 192.168.1.2
    exit 0

(fait à l’aide de ce post : https://askubuntu.com/questions/95910/command-for-determining-my-public-ip
et ce post https://www.commentcamarche.net/forum/affich-4755454-shell-stocker-le-resultat-d-une-commande )

  • et ensuite je fais sudo crontab -e et j’ajoute le ligne @reboot /bin/iptable-berrypi

Merci beaucoup pour cette solution en tout cas, j’aurais été bien embêté sans ce tuto :wink:


#5

Ah super ! Merci pour le partage du script ; je le mets en place chez moi dès que j’ai le temps :wink:

Content que ce petit tuto puisse aider.
Toujours avec du temps, j’essayerai de le mettre à jour pour la dernière version de YunoHost ainsi que l’intégration de ton script pour l’IP publique.


#6

En fait, je pensais que ça marchait, mais (maintenant que j’ai enfin tenté de configuré postfix) je reçois un mail de notfication qui me dit :

Bad argument DNAT' Tryiptables -h’ or ‘iptables --help’ for more information.

Je ne sais pas vraiment ce qui cloche :confused:


#7

Ah mince, ça serait donc ta commande iptables qui n’est pas bonne ?
J’avoue ne pas être un pro d’iptables et je n’ai pas encore pris le temps de tester ça …

En tapant directement ta commande iptables en SSH tu as une erreur aussi ?


#8

Mhhhhh :thinking: je viens justement de vérifier et non, pas d’erreurs lorsque je tap directement la commande. Peut être y a-t-il eu souci avec mon code pour récupérer l’ip (problème de connexion avec ma requête curl sur checkip.dyndns.org)?

Par souci d’écologie, il m’arrive d’éteindre mon raspberry pi et ma box la nuit, il suffit que quand je redémarre mon raspberry pi, la box n’ait pas encore fini de charger pour que le code ne marche plus, j’ai rajouter “sleep 5m;” avant pour être sur que la connexion internet soit active lorsque la commande est lancée. Je n’ai plus reçu l’email, mais si j’ai de nouveau le souci, je préviendrai ici :wink:


#9

Dac ça marche.

De mon coté je viens (enfin) d’intégrer ta méthode à mon YunoHost, voici mon script fake_loopback.sh au cas ou :

#!/usr/bin/env bash

public_ip=`dig +short myip.opendns.com @resolver1.opendns.com`
/sbin/iptables -t nat -A OUTPUT -d "$public_ip" -j DNAT --to-destination 192.168.1.2

et mon entrée crontab (bien faire sudo crontab -e et pas crontab -e pour être sûr d’étirer le crontab de root et pas de l’user)

@reboot /home/admin/fake_loopback.sh

#10

Bonsoir à tous,

Petit up pour signaler que j’ai amélioré le tutoriel en ajoutant un script permettant de vérifier si l’IP publique change et ainsi modifier la redirection d’IP de ma règle Iptables. Tout ça pour faire fonctionner le renouvellement automatique des certificats Let’s Encrypt par YunoHost avec le problème de loopback de la Livebox d’Orange.

Si un dev YunoHost passe par là ; je me demande à quel point on pourrait améliorer/populariser cette technique car je pense que beaucoup de personnes sont victime de ce problème non ? Et personnellement je trouve assez chiant le fait que sans ça le certificat ne se renouvelle pas automatiquement.

Merci d’avance :wink:


#11

Hmoui en effet, en regardant en diagonale ça a l’air séduisant … d’un autre côté, ça reste un peu “touchy” dans le sens où désactiver le DHCP de sa livebox, ça veut dire que l’on devient dépendant du serveur pour gérer le DHCP, et que si jamais il arrive un problème dessus ou que la personne laisse tomber l’autohebergement, il faut qu’elle pense a réactiver ce paramètre …

Mais on pourrait tout de même imaginer avoir un tuto “officiel” dans la doc, ou inclure un mécanisme pour configurer dnsmasq automatiquement dans ce mode.


#12

Bonsoir Aleks,

Merci pour ton retour.

Oui c’est certain que tout le monde ne va pas désactiver le DHCP de sa box, et effectivement si YunoHost tombe alors plus d’internet pour aucun appareil du réseau local … (obligé de passer en IP fixe sur son appareil sans oublier d’ajouter un DNS pour s’en sortir …).

Par contre il y a un point que je ne comprends pas : pourquoi lors d’une demande d’un certificat Let’s Encrypt il y a ce test d’accès par l’IP publique qui est fait par YunoHost ? Je veux dire ; le problème de hairpinning n’empêche en rien de demander un certificat non ?
Ou bien c’est simplement un test pour s’assurer que le serveur YNH est opérationnel avant de demander un certificat “pour rien” ?


#13

Oui :wink:


#14

Hello,

Joli partage et belle initiative, GG !

martoni