Accès distant à un Raspberry Pi via Modem LTE (IoT) Accès distant à un Raspberry Pi via Modem LTE (IoT) 1. Module LTE utilisé : SIM8230G-M2 RedCap Le modem utilisé dans ce projet est le module SIM8230G-M2 , un module 5G RedCap basé sur la norme 3GPP Release 17. Compatibilité avec d'autres modems Le script reste compatible avec la majorité des modems LTE/5G utilisant des commandes AT standards. Installation du module Documentation officielle : https://www.waveshare.com/wiki/SIM8230G-M2 2. Objectif Ce projet vise à établir un accès distant fiable à un Raspberry Pi connecté via modem LTE, en contournant les contraintes NAT habituelles des réseaux mobiles. Les points couverts sont : connexion LTE via APN dédié tunnel SSH inverse vers un serveur intermédiaire accès distant malgré le NAT opérateur reconnexion automatique en cas de perte réseau 3. Contexte réseau Dans un réseau LTE, le Raspberry Pi est placé derrière un NAT opérateur : le modem obtient une adresse IP côté réseau, mais le Raspberry est en réalité derrière une adresse privée non accessible depuis l'extérieur. Conséquences directes : impossible de se connecter directement en SSH depuis l'extérieur impossible de joindre le Raspberry depuis Internet Solution retenue : reverse SSH (tunnel SSH inverse). 4. Accès via serveur de logs L'accès au Raspberry ne se fait pas directement , mais via un serveur intermédiaire appelé serveur de logs. Ce serveur est accessible à la fois depuis le Raspberry (via le réseau LTE) et depuis les postes d'administration. Le principe est le suivant : le Raspberry initie lui-même une connexion SSH vers le serveur de logs il expose un port local redirigé sur le serveur l'administrateur se connecte ensuite à ce port depuis le serveur ssh localhost -p 2222 Cette approche présente plusieurs avantages : tous les membres de l'équipe ont accès au serveur de logs les connexions directes vers les équipements sont évitées l'accès aux équipements IoT est centralisé la gestion des accès SSH est simplifiée autossh est utilisé pour maintenir le tunnel actif : il relance automatiquement la connexion SSH en cas de déconnexion, sans intervention manuelle. 5. Préparation du Raspberry Pi Ces étapes sont à réaliser en amont, directement sur le Raspberry Pi, avant de déployer le script. Création d'un utilisateur dédié # Création d'un utilisateur dédié sudo adduser iot # Ajout aux droits sudo sudo usermod -aG sudo iot Génération de la clé SSH ssh-keygen -t ed25519 -f ~/.ssh/modem_tunnel -N "" 6. Script complet #!/bin/bash # Arrêt du script en cas d'erreur set -euo pipefail # Port série du modem PORT="/dev/ttyUSB2" # Nombre max d'essais modem max_tries=100 try=0 # IP de test Internet ping_ip="8.8.8.8" # Interface réseau modem iface="usb0" # Nombre max d'essais réseau max_ping_tries=100 # Paramètres SSH SSH_HOST="192.108.119.79" SSH_USER="procom" SSH_KEY="/home/iot/.ssh/modem_tunnel" # Demande une IP via DHCP sudo dhclient -4 -v usb0 || true # Ajout des IDs USB modem bind_ids() { sudo sh -c 'echo "1e0e 9073" > /sys/bus/usb-serial/drivers/option1/new_id' sudo sh -c 'echo "1e0e 9071" > /sys/bus/usb-serial/drivers/option1/new_id' sudo sh -c 'echo "1e0e 9072" > /sys/bus/usb-serial/drivers/option1/new_id' sudo sh -c 'echo "1e0e 9078" > /sys/bus/usb-serial/drivers/option1/new_id' sudo sh -c 'echo "1e0e 907b" > /sys/bus/usb-serial/drivers/option1/new_id' } # Attente du modem wait_for_port() { while [ ! -e "$PORT" ]; do try=$((try+1)) # Reboot si modem absent trop longtemps if [ "$try" -ge "$max_tries" ]; then sudo reboot fi bind_ids sleep 5 done } # Envoi d'une commande AT au modem send_at() { local cmd="$1" echo -e "${cmd}\r" | sudo tee "$PORT" >/dev/null } wait_for_port # Initialisation modem send_at "AT" send_at "AT+CFUN=0" sleep 5 send_at "AT+CFUN=1" sleep 5 # Configuration APN send_at 'AT+CGDCONT=1,"IP","iot"' sleep 2 # Sélection opérateur send_at 'AT+COPS=1,2,"99970"' sleep 5 # Test réseau ping_ok() { ping -I "$iface" -c 1 -W 2 "$ping_ip" >/dev/null 2>&1 } # Reset modem restart_module() { send_at "AT+CFUN=0" sleep 10 send_at "AT+CFUN=1" sleep 5 send_at 'AT+CGDCONT=1,"IP","iot"' sleep 2 send_at 'AT+COPS=1,2,"99970"' sleep 10 } # Attente de l'attachement réseau sleep 20 # Boucle de connexion for i in $(seq 1 "$max_ping_tries"); do if ping_ok; then break fi restart_module done # Reboot si pas de réseau après toutes les tentatives if ! ping_ok; then sudo reboot fi # Tunnel SSH permanent while true; do autossh -M 0 \ -i "$SSH_KEY" \ -o StrictHostKeyChecking=no \ -o ServerAliveInterval=30 \ -o ServerAliveCountMax=3 \ -N \ -R 2222:localhost:22 \ ${SSH_USER}@${SSH_HOST} # Si le tunnel tombe et que le réseau est absent → reboot if ! ping_ok; then sudo reboot fi sleep 10 done 7. Démarrage automatique Le script est déclaré comme un service systemd pour être lancé automatiquement au démarrage du Raspberry Pi. Créer le fichier /etc/systemd/system/modem.service : [Unit] Description=Modem LTE launcher After=network-online.target [Service] ExecStart=/usr/local/bin/modem-launch.sh Restart=always RestartSec=10 [Install] WantedBy=multi-user.target Puis activer le service : sudo systemctl daemon-reload sudo systemctl enable modem.service 8. Paramètres à adapter Paramètre Valeur par défaut Description PORT /dev/ttyUSB2 Port série du modem APN iot APN déclaré dans la configuration réseau Opérateur 99970 Code PLMN de l'opérateur iface usb0 Interface réseau du modem SSH_USER procom Utilisateur SSH sur le serveur de logs SSH_HOST 192.108.119.79 IP du serveur de logs Port tunnel 2222 Port exposé sur le serveur pour rebondir SSH_KEY /home/iot/.ssh/modem_tunnel Chemin vers la clé SSH privée