Files
snek/README.md
T
tarcourt 66db42b362 docs: security section + fix MAX_DEVICES doc
- Add "Sécurité, vie privée & aspects légaux" section covering:
  - What the SDR dongle actually captures (RF broadcast)
  - What SNEK exposes by default (nothing for unregistered devices)
  - Theoretical interception attack scenario
  - Legal aspects (Article 226-15, RGPD)
  - Best practices to mitigate

- Fix MAX_DEVICES doc: 5 is the hard limit (JS frontend hardcoded)
  Removed misleading claim that config change to 10 works

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-03 17:30:59 +02:00

15 KiB
Raw Blame History

SNEK — Sigfox Network Emulator (K8s Edition)

Une stack complète pour émuler un réseau Sigfox depuis n'importe quel cluster Kubernetes, avec un dongle SDR physique.

Cas d'usage : recevoir en direct les messages Sigfox de tes devices (Sens'it, capteurs custom, etc.) sans passer par le backend public Sigfox, décoder les payloads, et transférer les données vers n'importe quel service (API, base, webhook, etc.).


Sommaire

  1. Vue d'ensemble
  2. Hardware — le dongle Sigfox SDR
  3. Software — SNEK
  4. Déploiement
  5. Configuration des devices
  6. Réception de messages (uplink)
  7. Décodage des payloads
  8. Callbacks HTTP (intégration avec autres services)
  9. Sécurité, vie privée & aspects légaux ⚠️
  10. Downlink (messages serveur → device)
  11. Persistance & backups
  12. Dépannage

Vue d'ensemble

    ┌─────────────┐
    │  Device     │  (Sens'it, capteur custom, etc.)
    │  Sigfox     │
    └──────┬──────┘
           │ RF 868 MHz (EU)
           ▼
    ┌─────────────┐
    │  Dongle     │  (NXP LPC 2cc1:8001 → 2cc1:0001 après flash)
    │  SDR USB    │
    └──────┬──────┘
           │ USB via /dev/bus/usb (hostPath mount)
           ▼
    ┌──────────────────────────┐
    │  Pod SNEK (K8s)          │
    │  - Container privileged  │
    │  - Ubuntu 20.04          │
    │  - SNEK 2.3.4            │
    │  - Web UI :8085          │
    └──────┬───────────────────┘
           │ HTTP callback (JSON)
           ▼
    ┌─────────────┐
    │  Ton API,   │  (Elasticsearch, Postgres,
    │  ton bot,   │   Telegram, Kafka, …)
    │  ton front  │
    └─────────────┘

Hardware — le dongle Sigfox SDR

Modèle utilisé : Sigfox SDR Dongle officiel (chipset NXP LPC).

Identifiants USB :

  • Au boot : 2cc1:8001 (mode DFU / bootloader)
  • Après flash firmware par foxctl : 2cc1:0001 (mode opérationnel)

Prérequis :

  • Port USB 2.0 High Speed (les ports 3.0 rétrocompatibles marchent aussi)
  • Antenne 868 MHz (fournie ou fil quart d'onde 8.6 cm)
  • Zone RC1 pour l'Europe (868 MHz), autres zones (RC2 US, RC3 Asie, etc.) configurables dans SNEK

Le firmware n'est pas persistent : à chaque unplug ou reboot du dongle, il repart en mode DFU. Le script entrypoint.sh du container reflashe automatiquement au démarrage via foxctl.


Software — SNEK

SNEK 2.3.4 (Sigfox Network Emulator) est le logiciel officiel Sigfox qui :

  • Pilote le dongle SDR
  • Émule le réseau Sigfox localement
  • Enregistre les devices (up to 5 par défaut, extensible à 10 via config)
  • Reçoit et décode les messages uplink
  • Envoie des messages downlink
  • Expose une interface web (port 8085)
  • Envoie des callbacks HTTP en JSON à des URL externes

Dépendances système (pré-installées dans l'image Docker) :

  • Ubuntu 20.04 (obligatoire — libgtk2-perl n'existe pas en 22.04+)
  • libgtk2-perl, zenity, python, libdbus-glib-1-2, usbutils
  • libffi6 (ABI 18.04, downloadée depuis les archives Ubuntu)

Configuration : fichier /root/Snek/snek.conf (JSON), monté sur PVC pour persistance.


Déploiement

Prérequis cluster

  1. Kubernetes ≥ 1.24
  2. Namespace privileged (le container a besoin de securityContext.privileged: true)
  3. StorageClass pour PVC (ex: local-path)
  4. MetalLB ou équivalent pour exposer le service en LoadBalancer (optionnel — ClusterIP suffit si tu accèdes depuis un autre pod)
  5. Node avec le dongle physiquement branché en USB

Build & Push

cd snek/build
docker build --platform linux/amd64 -t 192.168.1.100:30500/snek:latest .
docker push 192.168.1.100:30500/snek:latest

Remplace 192.168.1.100:30500 par ton registry.

Deploy

kubectl apply -f snek/deploy/snek.yaml

Le manifest crée :

  • Namespace snek avec label pod-security.kubernetes.io/enforce=privileged
  • PVC snek-data (2 Gi, persistance de la config /root/Snek)
  • Deployment snek avec securityContext.privileged=true + hostPath /dev/bus/usb
  • Service LoadBalancer sur port 8085

Vérification

kubectl get pods -n snek
kubectl logs -n snek -l app=snek --tail=30

Tu dois voir dans les logs :

==> Dongle detected
==> Flashing firmware (foxctl)...
==> Starting SNEK main_sigfox on port 8085...
INFO - SNEK Software Version : "2.3.4"
INFO - Server started at http://0.0.0.0:8085
INFO - Frequence RX : 868130000
INFO - Frequence TX : 869525000

Accès UI

  • Depuis ton LAN : http://<LoadBalancer-IP>:8085/staticv234/index.html
  • Depuis un autre pod K8s : http://snek.snek.svc.cluster.local:8085

Configuration des devices

Chaque device Sigfox a un identifier hex 6 caractères (ex: B440C7). Tu le trouves :

  • Sur l'autocollant du device
  • Ou dans le backend Sigfox → Device details
  • Ou sur les Sens'it via l'app mobile

Dans SNEK → onglet Configuration → Devices → ajoute jusqu'à 5 devices (limite hardcodée dans le frontend JS de SNEK 2.3.4). Pour plus, lancer plusieurs instances de SNEK.

Important : SNEK ne décode que les messages des devices enregistrés dont l'auth passe. Un message d'un ID non enregistré est simplement logué comme Receiving message with bad authentication (not public key) sans détail sur l'ID ni le payload.


Une fois un device configuré, dès qu'il émet un message Sigfox (bouton double-clic, réveil périodique, alerte capteur…) :

  1. Réception RF par le dongle SDR
  2. Décodage bas-niveau par le firmware
  3. Traitement par SNEK (auth, dedup, décodage payload)
  4. Affichage dans l'onglet Messages de la web UI
  5. Envoi callback vers ton service si configuré (voir section suivante)

Format d'un message dans la UI SNEK :

Date            Device      Payload         RSSI    SNR
2026-07-03 15:23 B440C7     b60dc86e       -85 dBm  12 dB

Debug : si un device n'apparaît pas, vérifie dans les logs :

kubectl logs -n snek -l app=snek -f | grep -i "receiving\|register"

Décodage des payloads

Les payloads Sigfox sont binaires, format propre à chaque device. Voici le décodage pour un Sens'it Discovery en mode Temperature (4 bytes).

Structure

Byte Bits Contenu
0 7-3 Battery Level (5 bits, formule V = val × 0.05 + 2.7)
0 2-0 Reserved 0b110
1 7-3 Mode (00001 = Temperature)
1 2 Temperature MSB (1 bit)
1 1 Spare
1 0 Button Alert Flag (1 si double-clic)
2 7-0 Temperature LSB (formule T = (val 200) / 8 °C)
3 7-0 Humidity (formule H = val / 2 %)

Exemple

Payload hex : b60dc86e

  • Byte 0 = 0xB6 = 1011 0110 → Battery = 22 × 0.05 + 2.7 = 3.8V
  • Byte 1 = 0x0D = 0000 1101 → Mode = 1 (Temperature), Temp MSB = 1, Button = 1
  • Byte 2 = 0xC8 = 200 → Temp raw = 1×256 + 200 = 456 → 32°C
  • Byte 3 = 0x6E = 110 → Humidity = 110 / 2 = 55%

Doc officielle Sens'it

Sens'it Discovery Payload Structure (PDF)

Le document décrit les 6 modes (Standby, Temperature, Light, Door, Vibration, Magnet) et le format Config payload pour les downlinks.


Callbacks HTTP (intégration avec autres services)

C'est là que ça devient puissant : à chaque message reçu, SNEK peut faire un POST HTTP vers une URL de ton choix avec le payload en JSON.

Configuration

Dans la UI SNEK → onglet CallbacksAdd callback :

  • URL : http://mon-service.mon-ns.svc.cluster.local:3000/api/sigfox
  • Method : POST
  • Content-Type : application/json
  • Body : template avec variables SNEK (voir doc SNEK)

Exemple de body template

{
  "device": "{device}",
  "time": "{time}",
  "data": "{data}",
  "rssi": {rssi},
  "snr": {snr},
  "seqNumber": {seqNumber}
}

Variables disponibles :

  • {device} : ID hex du device
  • {time} : timestamp Unix
  • {data} : payload en hex
  • {rssi} : force du signal reçu
  • {snr} : rapport signal/bruit
  • {seqNumber} : compteur de séquence

Cas d'usage

  • Ingester dans une base : POST vers une API Node/Go/Python qui insert dans Postgres/InfluxDB
  • Alertes : POST vers Telegram bot API pour notification instantanée
  • Bus de messages : POST vers Kafka REST proxy, RabbitMQ HTTP plugin, etc.
  • Dashboard live : POST vers un WebSocket relay (Socket.io, Server-Sent Events)

Sécurité, vie privée & aspects légaux

⚠️ À lire attentivement avant tout déploiement en production ou test avancé.

Ce que capte physiquement le dongle

Le dongle SDR est un récepteur RF broadcast sur 868 MHz (RC1). Il capte tous les messages Sigfox dans sa portée physique :

  • ~1-5 km en zone urbaine dense
  • ~10-40 km en zone dégagée avec bonne antenne

Cela inclut les émissions de tes voisins, entreprises locales, capteurs de ville, alarmes, trackers… — pas seulement les tiens.

Ce que SNEK expose

Par défaut (auth activée, device non enregistré) :

  • Message logué comme bad authentication
  • Aucun ID, aucun payload, aucun RSSI accessible
  • Bonne protection par défaut

Attaque théoriquement possible :

  1. Enregistrer l'ID d'un device tiers dans SNEK (ID trouvé sur l'étiquette, dans une doc leakée, en OSINT)
  2. Désactiver globalement l'authentification (option UI)
  3. Recevoir les payloads bruts en clair du device cible tant qu'il est à portée radio

Limites de l'attaque :

  • Nécessite la proximité physique (pas d'attaque via internet)
  • Le format des 12 bytes de payload est propriétaire à chaque vendor — inutile sans reverse engineering
  • Certains devices utilisent le chiffrement AES-128 optionnel de Sigfox → payload chiffré

Aspect légal (France)

  • Réception passive du spectre RF public : légal
  • Analyse de tes propres devices : légal
  • Recherche sécurité en labo perso : légal
  • Interception intentionnelle de communications tierces : délit pénal
    • Article 226-15 du Code Pénal → 1 an prison + 45 000 € d'amende
  • Collecte / redistribution / monétisation des données captées : illégal (RGPD si données identifiantes, concurrence déloyale si usage commercial)

Bonnes pratiques

  • Ne configure QUE tes propres devices dans SNEK
  • Laisse l'auth activée (paramètre par défaut)
  • Baisse le log level à WARNING pour ne pas garder de trace des messages non-authentifiés :
    "root": {"level": "WARNING", ...}
    
  • Purge régulièrement /root/Snek/snek.log
  • Pour tes propres devices sensibles → utilise l'AES-128 optionnel de Sigfox

Sigfox est conçu pour l'authenticité (HMAC empêche l'usurpation), pas la confidentialité par défaut. C'est une limitation connue du protocole, à prendre en compte pour tout use case impliquant des données sensibles.


Sigfox permet 4 downlinks max par device par jour. Envoi depuis SNEK :

  1. Web UI → onglet Devices → sélectionner un device
  2. Zone Downlink → 8 bytes hex à envoyer
  3. Le message sera envoyé lors du prochain uplink (le device demande un downlink en cours d'émission)

Note : le downlink est utilisé pour reconfigurer un Sens'it (changer de mode, ajuster seuils, etc.) via le format Config payload documenté dans le PDF Sens'it.


Persistance & backups

Le PVC snek-data (2 Gi, local-path) monté sur /root/Snek contient :

  • snek.conf : configuration serveur (devices, callbacks, MAX_DEVICES, radio)
  • snek.log : logs applicatifs (rotation 5 × 10 MB)
  • Historique des messages reçus

Backup : Velero avec defaultVolumesToFsBackup: true dans les schedules capture le PVC.

Pour un backup manuel :

kubectl exec -n snek -l app=snek -- cat /root/Snek/snek.conf > snek-backup-$(date +%F).json

Dépannage

Le dongle n'est pas détecté

kubectl exec -n snek -l app=snek -- lsusb | grep 2cc1

Rien ? Vérifier :

  • Le dongle est branché physiquement sur le node
  • hostPath /dev/bus/usb est bien monté (dans la spec du deployment)
  • Le pod est en privileged: true
  • Sur Talos : talosctl ls /sys/bus/usb/devices sur le node depuis le Mac

Erreur "libxfox.so.0: cannot open shared object file"

Manque de LD_LIBRARY_PATH=/opt/snek. L'image Docker le définit dans le ENV, si tu débug en shell interactif, il faut le re-exporter.

Erreur "cannot import name Fox, introspection typelib not found"

Manque de GI_TYPELIB_PATH=/opt/snek. Idem que ci-dessus.

"No xfox device detected" en boucle

Le dongle est branché mais le firmware ne s'est pas flashé. Causes possibles :

  • Autre process tient le lock USB (ex: si tu as tenté KubeVirt USB passthrough avant)
  • Débranche/rebranche physiquement le dongle
  • Restart le pod : kubectl delete pod -n snek -l app=snek

Interface UI affiche 5 devices même après passer MAX_DEVICES à 10

Cache navigateur. Hard refresh (Cmd+Shift+R / Ctrl+Shift+R) ou fenêtre privée.

Le pod crash au démarrage

kubectl logs -n snek -l app=snek --previous

Le plus souvent : dongle absent → foxctl fait sys.exit(1). Solution : brancher le dongle, redémarrer le pod.


Structure du repo

snek/
├── README.md                ← ce document
├── build/
│   ├── Dockerfile           ← image Ubuntu 20.04 + SNEK + deps
│   └── entrypoint.sh        ← flash firmware + start server
└── deploy/
    └── snek.yaml            ← namespace + PVC + deployment + service

Ressources


Made with Kubernetes, some patience, and a Sigfox dongle. 📡