Contrat API — camouflage MAC (application mobile)
Révision : 2026-09-17 Statut : générée et injectée par l’application mobile ; validée et réservée par le backend uniquement en mode Cloud.
Mode Standalone — aucune dépendance RADIUS/NAS
Le camouflage manuel est une opération locale. Si le routeur n’a pas de nas_id, ou si le
gérant n’a pas activé la gestion Cloud, l’application doit pouvoir le réaliser depuis le LAN :
- elle génère une MAC localement administrée, lit l’adresse d’origine, injecte le script local et vérifie le retour de connectivité ;
- elle conserve localement l’adresse d’origine et le script de retour arrière ;
- elle n’appelle aucune route
/api/v1/radius/starlink/mac/*ni/api/v1/radius/bandwidth/*; - elle n’essaie jamais de créer, rechercher ou enregistrer un NAS pour débloquer le bouton.
Le backend reste silencieux et ne crée aucun état dans ce mode. L’écran doit indiquer « Mode local — non synchronisé au Cloud ». Les protections centralisées (réservation globale de MAC, audit Cloud, statut distant et relance serveur) ne sont alors pas disponibles.
Les routes décrites ci-dessous concernent exclusivement le mode Cloud optionnel, activé par le gérant sur un NAS déjà existant. Elles ne sont pas un prérequis au camouflage.
Contrat
POST /api/v1/radius/starlink/mac/{nasId} accepte ce corps de déclaration :
{
"router_serial": "HH40AF7YVNP",
"resultat": "POSEE",
"interface": "ether1",
"mac_origine": "48:A9:8A:11:22:33",
"camouflage_mac": "02:AB:CD:EF:01:02",
"internet_confirme": true
}
camouflage_mac est requis, y compris avec resultat: "ECHEC", afin que la tentative reste
traçable et que la colonne d’identité réseau ne soit jamais vide. Le backend accepte uniquement une MAC normalisable à six
octets, unicast (bit 0 du premier octet à 0), localement administrée (bit 1 à 1) et
différente de mac_origine. Il l’enregistre en forme majuscule avec : comme séparateur.
Si une autre ligne la possède déjà, le serveur répond :
{
"success": false,
"error": "MAC_COLLISION",
"message": "L'adresse MAC générée est déjà utilisée par un autre équipement."
}
avec HTTP 409. L’application doit générer une nouvelle valeur et rejouer la même demande ; elle
ne doit pas réessayer une valeur refusée.
Algorithme historique transmis au mobile
Le générateur backend historique est conservé dans
src/modules/vpn-management/utils/macVirtuelle.js. Son mode sûr par défaut était déterministe :
SHA-256 de ${sel}|${identifiant}, premier octet forcé à 0x02, puis les cinq octets suivants du
hash. 0x02 garantit unicast et localement administrée. Pour la nouvelle stratégie,
l’application doit plutôt tirer cinq octets cryptographiquement aléatoires et préfixer 02 :
function generateCamouflageMac(randomBytes: Uint8Array): string {
if (randomBytes.length < 5) throw new Error('five random bytes required');
return [0x02, ...randomBytes.slice(0, 5)]
.map((byte) => byte.toString(16).toUpperCase().padStart(2, '0'))
.join(':');
}
Ne pas utiliser les OUIs constructeur optionnels de l’ancien générateur : ils ne sont ni
localement administrés ni nécessaires à ce contrat. Utiliser une source cryptographique du
système mobile pour randomBytes.
Déviations par rapport à l’ancien contrat
mac_poseeest remplacé parcamouflage_mac.- Le serveur ne calcule plus de MAC, ne retourne plus de commande de pose, et ne renvoie plus
MAC_MISMATCH. - La base impose l’unicité, en plus de la vérification préalable : deux requêtes simultanées ne peuvent donc pas enregistrer la même adresse.
Lecture déléguée par un compte assistant
GET /api/v1/radius/starlink/mac/{nasId}/statut et
GET /api/v1/radius/starlink/mac/{nasId}/consigne sont accessibles à tout compte mobile
authentifié et lié, y compris s’il n’est pas propriétaire du routeur. Cette exception sert les
interventions physiques et l’assistance multi-compte. Les routes de déclaration et relance
conservent le contrôle d’appartenance.
Chaque lecture tierce est journalisée ; le propriétaire reçoit un push et un e-mail, dédoublonnés par quart d’heure et par type de lecture pour ne pas alerter à chaque cycle de polling.
Obtenir les commandes de discrétion (Consigne)
Lors de l’appel à GET /api/v1/radius/starlink/mac/{nasId}/consigne, l’application mobile doit obligatoirement fournir l’inventaire des interfaces du routeur dans les paramètres d’URL (query parameters) afin que le backend puisse générer les commandes de discrétion (masquage MNDP/Winbox).
Paramètres requis :
interface: L’interface WAN principale (ex:ether1)interfaces_locales: Liste séparée par des virgules des interfaces LAN du routeur (ex:bridge,ether2,ether3,wlan1)interfaces_wan(optionnel) : Liste séparée par des virgules des autres interfaces WAN éventuelles.nom_hote(optionnel) : Le nom d’hôte actuel du routeur.
Exemple d’appel complet :
GET /api/v1/radius/starlink/mac/{nasId}/consigne?router_serial=HH40AF7YVNP&interface=ether1&interfaces_locales=bridge,ether2,ether3
Comportement de sécurité :
Si interfaces_locales est vide ou manquant, le backend refusera de générer les commandes pour éviter de bloquer l’accès local. Dans ce cas, la réponse contiendra "discretion": null et "discretion_motif": "INVENTAIRE_INTERFACES_MANQUANT". L’application mobile ne doit pas considérer cela comme un crash, mais corriger sa requête d’inventaire.