Mise en place d'un NAT46 sur un linux. Il est nécessaire dans certains cas de mettre en place une redirection de port UDP depuis IPv4 vers IPv6. Cette solution peu être utilisé lors qu'on à besoin de joindre des services accessible uniquement via IPv6, depuis une IPv4.
Dans le cas de cette documentation, j'ai besoin de joindre un service wireguard accessible uniquement en IPv6 également en IPv4. La spécificité de l'UDP est qu'il est pas possible d'utiliser haproxy qui pourrais lors de connexion TCP, convertir un front-end IPv4 ou IPv6 vers un back-end IPv4 ou IPv6. L'avantage de haproxy, la syntaxe est assez simple et dans le cadre de serveurs web en plus de pouvoir tester le service de la couche 4 à 7.
Dans mon cas, j'ai une contrainte technique est qu'aucun firewall dans mon architecture n'a une IPv4, mais uniquement de l'IPv6. J'utilise une IPv4 d'un VPS pris chez un hébergeur qui porte un IPv4, mais également une IPv6. Il me permet de faire une conversion assez simple, mais tous en ayant tous de même un point de défaillance ayant un seul VPS permettant d'effectuer cette conversion. Au vu de la cirticité de mes services, l'IPv4 n'est pas un impératif pour ma part. Mais il serait possible d'avoir plusieurs VPS avec une configuration IPv4/IPv6 pour pouvoir avoir un semblant de redondance. Il faut cependant aussi prendre en compte le service exposé lui aussi doit avoir une tolérance/redondance aussi.
Le nat64 est une méthode de traduction d'adresse IPv4 en IPv6 permettant de pouvoir communiquer entre les deux deux version du protocole IP. Cette méthode peu être fait de façon dynamique et automatique par exemple chez Cisco. Elle permet en autres à une infrastructure 100% configuré par IPv6 à communiquer vers une infrastructure IPv4 avec quelques spécificités ce n'est pas transparent une réécriture doit être fait à la volé pour passer d'IPv6 vers des IPv4 mais pour le client il n'est pas conscience de communiquer réellement vers un système d'IPv4.
Le nat46 est une méthode de traduction d'adresse IPv4 vers IPv6, cette méthode n'est pas trop utilisée car aujourd'hui peu de services sont compatible en IPv6, la plus part fonctionne en IPv4.
cette méthode n'est pas la plus utilisé, mais elle peu avoir un intéret pour certaines particularité comme rendre accessible des services qui fonctionne uniquement en IPv6, pouvoir les joindre depuis des IPv4. Ces cas de figures reste assez rare.
Dans mon cas, j'ai utilisé socat qui est une des nombres possibilités. C'était pour moi un systeme assez simple permettant de faire une traduction d'IPv4 vers IPv6 via un port spécifique en IN/OUT.
Pour mettre en place cette solution, vous avez besoin de plusieurs pré-requis:
L'objectif est de rendre accéssible dans mon cas le service wireguard écoutant uniquement en IPv6, car l'infrastructure n'est pas déservie par une IP publique IPv4. Wireguard fonctionne exculusivement en UDP, ce qui ne permet pas d'utiliser par exemple haproxy qui permet de faire un équivalent avec en plus des possibilité d'equilibrage charge qui supporte uniquement les services TCP.
Il faut commencer par l'installation du package sur la machine qui vas s'occuper de la traduction d'IPv4 vers IPv6.
Pour l'installation du package, il est juste necessaire d'installer socat via la commande apt.
apt install socat
Je préfére gérer chaque redirection de façon indépendante sans faire tourner le service en deamon pour avoir accés plus facilement au logs et également couper facilement chaque redirection si besoin. Dans mon cas, je lance un script créer au préalable qui se lancer dans une instance systemctl. Cette méthode permet de voir facilement l'état de chaque redirection, démarrer/arréter chaque redirection mais égelement envoyer si possible les logs de systemctl vers un syslog.
Ma méthode de script pourrais facilement être optimisable via l'ajout de variable paser en argument. De mon côté je préfére avoir un script par redirection.
Création du script dans l'emplacement de votre choix.
nano /etc/autoscript/auto_script_nat64_udp_XXXXX.sh
#!/bin/bash
IP_v4="<IPv4>"
IP_v6="<IPv6>"
Port_in="<Port_IN>"
Port_out="<Port_OUT>"
Service="<Log_nom_du_service>"
Restarting_Count=0
echo "[$(date '+%d-%m-%Y %H:%M:%S')] Starting listen forward $IP_v4:$Port_out to $IP_v6:$Port_in for Service $Service...."
while true
do
if [[ $Restarting_Count -eq 0 ]]; then
echo "[$(date '+%d-%m-%Y %H:%M:%S')] try listen $IP_v4:$Port_out to $IP_v6:$Port_in for $Service"
else
echo "[$(date '+%d-%m-%Y %H:%M:%S')] try again [$Restarting_Count] listen $IP_v4:$Port_out to $IP_v6:$Port_in for $Service"
fi
socat -d -d UDP4-LISTEN:$Port_out,bind=$IP_v4,fork,su=nobody UDP6:[$IP_v6]:$Port_in
((Restarting_Count++))
echo "[$(date '+%d-%m-%Y %H:%M:%S')] end of listen $IP_v4:$Port_out to $IP_v6:$Port_in for $Service"
sleep 1
done
Il suffit de remplacer les informations suivantes par les bonnes informations :
Création du fichier systemctl pour la redirection nat46.
nano /lib/systemd/system/nat46_XXXXX.service
[Unit]
Description=Socat NAT46 to UDP XXXXX
After=network.target
[Service]
Type=simple
ExecStart=/etc/autoscript/auto_script_nat64_udp_XXXXX.sh
[Install]
WantedBy=multi-user.target
Remplacement des informations:
Activation du service pour qu'il démarre automatiquement au démarrage du serveur via la commande suivante :
systemctl enable wireguard_nat46.service
Lors de la création du service, il est necessaire de démarrer manuellement le service. Pour des maintenances, il est parfois necessaire de couper le service. Il est possible de le démarrer le service via la commande suivante :
systemctl start wireguard_nat46.service
Eteindre le service, par exemple pour couper la translation :
systemctl stop wireguard_nat46.service
Il est possible d'afficher les logs derniers logs et l'état du services via la commande suivante :
systemctl status wireguard_nat46.service
En cas de debug ou afficher les logs plus détaillé du services, il est possible de les afficher via les commandes suivantes :
journalctl -u wireguard_nat46.service
En cas de modification du services, il est necessaire de recharger le service daemon-reload pour prendre en compte la modification effectué sur le service.
systemctl daemon-reload