remote.DocumentationAccueil

Initialisation, QR codes d’appareil et connexion par code à six chiffres

L’Exchange par défaut de l’Agent est wss://exchange.ivjn.us ; l’API d’administration CLI/Console se trouve à https://exchange.ivjn.us. Les configurations existantes ont priorité : les adresses d’Exchange auto-hébergés ne sont pas remplacées.

Inscription SaaS et première connexion

remote-cli register --username alice --email alice@example.com
# 按隐藏输入提示设置密码,注册后向邮箱发送验证码。
remote-cli verify-email --username alice
# 隐藏输入邮件中的 8 位数字验证码,然后登录。
remote-cli login --email alice@example.com
# init 是 login 的别名,不带 --email 时交互输入邮箱和密码。
remote-cli init
# 原有令牌仍可使用:
remote-cli login --server https://exchange.ivjn.us --token-stdin

L’inscription et la connexion utilisent par défaut https://exchange.ivjn.us ; ajoutez --server pour un serveur auto-hébergé. L’adresse e-mail identifie le compte : les espaces sont supprimés et l’adresse convertie en minuscules ; un format invalide est immédiatement refusé. Le nom d’utilisateur est le nom d’espace de travail choisi à l’inscription (3 à 64 lettres, chiffres ou ._-). Les mots de passe des comptes ne sont soumis à aucune restriction de longueur ou de caractères ; le serveur ne conserve que leurs empreintes. L’automatisation peut utiliser --password-stdin ; ne placez pas le mot de passe dans les arguments de commande. Les nouveaux comptes ne peuvent pas se connecter avant la vérification de leur adresse. La CLI ne conserve que le jeton de session renvoyé, jamais le mot de passe ; une connexion existante est conservée pendant l’attente de vérification d’une inscription.

Chaque inscription crée un espace de travail indépendant, dont le compte est administrateur. Appareils, membres, sessions distantes, métriques et audit sont isolés ; plusieurs espaces peuvent utiliser les mêmes identifiants d’appareil. L’approbation d’un code à six chiffres ajoute l’appareil ou le nouveau membre à l’espace de travail de la personne qui approuve. Pour rejoindre un espace existant, utilisez le jeton ou l’autorisation par code à six chiffres fourni par son administrateur.

Android Console prend également en charge l’inscription, la connexion par mot de passe, par jeton existant et par code à six chiffres. Le mot de passe ne sert qu’à la requête en cours ; les identifiants restent stockés dans SecureStore.

Les sessions par mot de passe sont valides 30 jours, avec au maximum 32 sessions actives par compte ; une nouvelle connexion ne déconnecte pas les autres clients. POST /api/auth/logout révoque la session Bearer actuelle ; les WebSockets déjà établis sont fermés dans un délai maximal de 5 secondes. Reconnectez-vous après expiration. Les jetons d’appareil et les anciens jetons d’exploitation conservent leur cycle de vie.

Les identités utilisant seulement un jeton n’ont pas de compte avec mot de passe et ne peuvent pas être récupérées par e-mail. La facturation et le routage WebSocket entre instances ne sont pas inclus actuellement.

Vérification de l’adresse et récupération du mot de passe

remote-cli resend-verification --email alice@example.com
remote-cli verify-email --username alice
remote-cli forgot-password --email alice@example.com
remote-cli reset-password --email alice@example.com
# 按提示输入邮件验证码、新密码,再重新登录。

# 已登录的旧密码账号绑定或更换邮箱,需要再次验证当前密码。
remote-cli set-email --email alice@example.com
remote-cli verify-email --username alice

La vérification et la récupération utilisent des codes numériques à 8 chiffres distincts selon leur usage, valides 15 minutes. Cinq erreurs consécutives invalident le code ; un nouvel envoi invalide le précédent. Chaque compte ne peut recevoir qu’un envoi par minute et par usage. Les commandes de vérification et de réinitialisation acceptent --code pour l’automatisation ; par défaut, la saisie du code est masquée. Une réinitialisation réussie révoque toutes les sessions de connexion du compte et ferme les WebSockets établis sous 5 secondes au maximum ; les autres membres et appareils de l’espace ne sont pas affectés.

Dans Console, saisissez l’adresse sur la page d’inscription, puis passez à la page de vérification ; la page de connexion propose Vérifier l’adresse e-mail et Mot de passe oublié. Un changement d’adresse conserve l’ancienne jusqu’à la fin de la vérification. Les demandes de renvoi et de récupération affichent un message uniforme, sans révéler si l’adresse est inscrite.

La messagerie exige la migration 0004_email.sql et la configuration SMTP : SMTP_HOST, SMTP_PORT, SMTP_FROM, SMTP_USERNAME, SMTP_PASSWORD, SMTP_SECURITY. STARTTLS est utilisé par défaut ; TLS implicite est pris en charge. Le SMTP non chiffré est réservé aux adresses de bouclage des tests locaux. Placez les identifiants SMTP dans le fichier d’environnement du service, sans les committer dans Git. Sans service de messagerie, les nouvelles interfaces d’inscription et d’envoi renvoient 503, sans affecter la connexion des comptes existants ; configurez donc l’envoi avant l’activation en production. Une panne SMTP temporaire peut laisser un compte en attente de vérification : après rétablissement, renvoyez le message de vérification sans vous réinscrire.

API des comptes Exchange

Méthode et chemin Authentification Usage
POST /api/auth/register Aucune, débit limité {username,password,email}, crée un compte en attente de vérification, renvoie 202 et verification_required, sans session
POST /api/auth/login Aucune, débit limité {email,password} délivre une session indépendante
GET /api/auth/me Jeton d’exploitation ou session de connexion Renvoie name, tenant_id, role
POST /api/auth/logout Session actuelle Révoque la session actuelle, sans révoquer les autres clients
POST /api/auth/verify-email Aucune, débit limité {username,code}, consomme le code de vérification d’adresse
POST /api/auth/resend-verification Aucune, débit limité {email}, renvoie un message à l’adresse en attente de vérification
POST /api/auth/forgot-password Aucune, débit limité {email}, envoie un code de récupération à l’adresse vérifiée
POST /api/auth/reset-password Aucune, débit limité {email,code,password}, modifie le mot de passe et révoque les anciennes sessions
POST /api/auth/email Session actuelle et mot de passe du compte {email,password}, demande l’ajout ou le changement d’adresse, effectif après vérification

Une connexion réussie renvoie username, email (si une adresse est associée), tenant_id, token, expires_in et définit Cache-Control: no-store. Les mots de passe sont stockés salés avec les paramètres par défaut d’Argon2id. Les limites sont de 20 requêtes de compte par minute par IP source TCP, 10 par minute par nom d’utilisateur et 4 calculs de hachage simultanés. Les IP transférées fournies par le client ne sont pas fiables ; les clients derrière un proxy inverse partagent le quota IP. Les déploiements publics doivent appliquer une limitation supplémentaire à un point d’entrée fiable.

Rust Exchange désactive les inscriptions publiques par défaut. Activez-les explicitement avec EXCHANGE_ALLOW_REGISTRATION=true et configurez SMTP ; false bloque les nouvelles inscriptions, les comptes existants peuvent toujours se connecter.

Afficher un code à six chiffres dans l’Agent

Dans Android Remote Agent, l’adresse par défaut est déjà renseignée : cliquez sur Connect with a six-digit code. L’application affiche un code à six chiffres valable 5 minutes. Dans une CLI déjà connectée comme administrateur, exécutez :

remote-cli pair 012345
# 可选:覆盖默认 ID 和显示名称
remote-cli pair 012345 --device-id my-android --name "我的手机"

Lors de la consultation du code de connexion, la CLI affiche le nom de l’appareil, le type d’identité et l’identifiant d’appareil suggéré ; autorisez après avoir vérifié qu’il s’agit de votre appareil. L’identifiant par défaut est construit avec les lettres ASCII minuscules, chiffres et ._- du nom d’appareil, en retirant espaces et autres caractères ; sans caractère utilisable, il devient device, avec une limite de 64 caractères. En cas de doublon dans un même espace, des chiffres sont ajoutés successivement, par exemple realmev5, realmev51, realmev52, en tronquant la base si nécessaire. Exchange gère les conflits concurrents à la création ; la CLI affiche l’identifiant finalement attribué. Un identifiant explicite en doublon reçoit aussi un suffixe numérique. Android utilise le nom système de l’appareil (ou son modèle à défaut), l’Agent natif utilise le nom d’hôte. L’Agent obtient automatiquement un jeton d’appareil indépendant, le conserve chiffré et démarre la connexion. Cela n’active pas automatiquement l’accessibilité ou le contrôle d’écran. Une annulation, une expiration ou un échec d’authentification ne remplace pas la configuration existante ; arrêtez d’abord l’Agent s’il est en cours de connexion.

Ajouter un appareil avec l’Agent sur ordinateur, routeur et Linux

Les Agents Windows, macOS, OpenWrt et Linux permettent d’éviter la saisie manuelle du jeton d’appareil. Choisissez une méthode :

Plateforme Méthode 1 : code d’appairage / QR code d’appareil Méthode 2 : coller une invitation
Windows / macOS (bureau --ui, lancement par double-clic) Page locale Add this device → Get pairing code, affiche code à six chiffres et QR code Collez dans le champ Invite de la page locale puis cliquez sur Join with invite
OpenWrt (luci-app-remote) LuCI Services → Administration distante → Ajouter un appareil → Obtenir un code d’appairage, affiche code à six chiffres et QR code Sur la même page, collez dans Méthode 2 : contenu de l’invitation puis cliquez sur Rejoindre
Linux / ligne de commande sur toutes les plateformes remote-agent pair (code à six chiffres et QR code en caractères dans le terminal) remote-agent join '<邀请内容>', ou remote-agent join - pour lire l’entrée standard

Méthode 1 : l’Agent demande un code à six chiffres valable 5 minutes et affiche aussi un QR code contenant remote://pair?code=012345&server=wss%3A%2F%2Fexchange.ivjn.us (sans identifiants). L’administrateur peut choisir : Android Console Ajouter un appareil → Saisir un code d’appairage → Scanner le QR code d’appareil (scanner avec la caméra, vérifier le serveur, consulter puis confirmer l’approbation) ; saisir le code à six chiffres ; dans Web Console, Approuver un code d’appairage, saisir les six chiffres ou coller remote://pair?... ; ou utiliser remote-cli pair 012345 (qui accepte aussi cette URI). Après approbation, l’Agent enregistre le jeton et se connecte automatiquement.

Méthode 2 : l’administrateur génère une invitation à usage unique dans Android Console, Ajouter un appareil → Ajouter par scan, puis clique sur Copier l’invitation (à coller sur ordinateur / routeur) ; ou exécute remote-cli qr --device-id pc-01 --text. L’invitation est le JSON du QR code ({"type":"remote-enrollment",...}), valable 5 minutes et utilisable une seule fois. Le contenu d’un QR code de jeton d’appareil (remote-cli device qr) est également accepté.

Emplacement d’enregistrement et connexion :

  • Interface de bureau : écrit dans le fichier de configuration actuel (par défaut %LOCALAPPDATA%\remote-agent\config.json / ~/.config/remote-agent/config.json) puis se connecte immédiatement.
  • OpenWrt : écrit dans UCI remote-agent.main (server / device_id / token, enabled=1) puis redémarre le service procd.
  • Ligne de commande : écrit par défaut dans le chemin de configuration du bureau (dans UCI par défaut sur OpenWrt). --config PATH précise un fichier JSON, --uci impose UCI ; après enregistrement, la connexion s’effectue au premier plan (--no-connect enregistre seulement). Si un service utilise déjà cette configuration, redémarrez-le.

Le remplacement d’identifiants déjà configurés est refusé par défaut : la ligne de commande exige --force, et les interfaces de bureau et LuCI demandent d’abord confirmation. Les méthodes existantes par jeton (--device-id/--token, fichier de configuration, page de réglages LuCI) restent disponibles.

remote-agent pair                       # 显示六位码 + 二维码,批准后保存并连接
remote-agent pair --server wss://your-exchange.example.com --config ./agent.json
remote-agent join '{"type":"remote-enrollment","version":1,...}'
remote-agent join - < invite.txt --no-connect

L’appairage natif exige wss:// ; ws:// n’est autorisé qu’en bouclage local pour les tests. L’appairage Android et Console exige HTTPS/WSS.

Connexion Console par code à six chiffres

Sur la page de connexion Android Remote Console, cliquez sur Se connecter avec un code à six chiffres ; dans Web Console (/console), sélectionnez l’onglet Code à six chiffres de la carte de connexion et demandez un code. L’administrateur peut approuver avec l’une des méthodes :

remote-cli pair 012345 --operator-name mobile-alice
# 只读客户端:追加 --role readonly

Ou, dans l’espace de travail de Web Console déjà connecté, cliquez sur Approuver un code d’appairage (visible seulement pour les administrateurs ; absent pour les opérateurs en lecture seule), saisissez les six chiffres affichés sur l’autre écran, vérifiez le type et le libellé puis approuvez.

Un compte operator indépendant est créé par défaut, sans copier le jeton personnel de l’administrateur. Celui-ci peut préciser --role admin ou --role readonly. Après autorisation, Android Console vérifie à nouveau les identifiants, les enregistre dans SecureStore et ouvre la liste des appareils ; Web Console conserve les identifiants opérateur dans la mémoire de la page actuelle (comme pour la connexion par compte ou jeton) puis ouvre la liste. En cas d’annulation ou d’échec, la connexion avec le compte ou le jeton existant reste possible ; les valeurs saisies ensuite avec les autres méthodes ne sont pas effacées.

Connexion de Remote Agent par scan du QR code de la CLI

remote-cli qr --device-id my-phone
# 输出 SVG 供手机扫描:
remote-cli qr --device-id my-phone --output ./phone-login.svg

Générez le QR code dans une CLI déjà connectée comme administrateur. Dans Remote Agent sur le téléphone, cliquez sur Scan connection QR code, vérifiez le serveur et l’identifiant d’appareil, puis cliquez sur Connect. Le QR code ne contient qu’un ticket temporaire aléatoire de 256 bits, valable 5 minutes, associable à un seul appareil, sans jeton d’appareil permanent. Après scan, Exchange délivre le jeton d’appareil ; le téléphone l’enregistre avec Keystore puis se connecte. L’identifiant d’appareil du QR code doit être nouveau : aucun appareil existant n’est remplacé et aucun jeton existant n’est renouvelé.

Les demandes de récupération du même téléphone portent un claim_id aléatoire fixe : une nouvelle tentative après interruption réseau peut récupérer le même résultat ; un autre claim_id ne peut pas le récupérer à nouveau. Après enregistrement, le téléphone confirme l’effacement du ticket. Les tickets temporaires sont conservés en mémoire du processus et expirent au redémarrage d’Exchange ; les résultats dont la récupération a commencé sont conservés jusqu’à 5 minutes supplémentaires pour les nouvelles tentatives du client d’origine.

Méthode et chemin Authentification Usage
POST /api/pairing/invite Administrateur {device_id,name?}, génère un ticket ; limite de 10 par minute par administrateur, 256 au total
POST /api/pairing/claim Bearer <ticket> {claim_id}, renvoie des identifiants d’appareil indépendants ; toute nouvelle tentative doit conserver le même claim_id hexadécimal de 32 caractères
POST /api/pairing/claim/complete Identique Confirme l’effacement après enregistrement réussi

Générer un QR code d’appareil

# 创建设备,同时在终端显示二维码
remote-cli device add my-android --qr
# 新建 SVG 文件,可在电脑打开后供手机扫描
remote-cli device add another-phone --qr-output ./another-phone.svg
# 使用手里已有的设备令牌,不创建或轮换设备
remote-cli device qr my-android --output ./my-android.svg
# 明确轮换令牌并生成二维码;原令牌立即失效
remote-cli device rotate-token my-android --qr

device qr lit le jeton d’appareil avec une saisie masquée et accepte aussi --token-stdin. Les QR codes d’appareil ne contiennent que des jetons d’appareil ; les jetons d’exploitation ne conviennent pas. Le fichier de sortie refuse tout écrasement ; il contient des identifiants et doit être protégé puis supprimé après utilisation. Les QR codes exigent HTTPS/WSS.

Android Console affiche directement le QR code après la création d’un appareil. Dans les détails d’appareil, Renouveler le jeton et générer un QR code explique d’abord l’effet sur la connexion et demande confirmation. Le serveur ne conserve que le hachage du jeton et ne peut pas récupérer l’ancien QR code depuis un appareil existant ; il ne renouvelle donc pas silencieusement le jeton pour simplement afficher un QR code.

API d’appairage Exchange

Méthode et chemin Authentification Usage
POST /api/pairing/start Aucune, débit limité Envoie kind: device/operator, label, obtient code, poll_token, expires_in: 300, interval: 3
GET /api/pairing/{code} Jeton d’exploitation administrateur Consulte le type de demande, le libellé et le temps restant, sans renvoyer d’identifiants
POST /api/pairing/approve Jeton d’exploitation administrateur Envoie code, kind, identity, éventuellement name, role, et crée un appareil ou compte indépendant
POST /api/pairing/poll Authorization: Bearer <poll_token> Renvoie pending ou approved ; le résultat approuvé contient credentials.kind/identity/token
POST /api/pairing/complete Identique Efface l’autorisation temporaire après enregistrement réussi par le client ; appels répétés sans danger
GET /ws/pairing Aucune, débit limité WebSocket d’appairage de l’Agent natif ; reçoit successivement les événements code, approved ou expired, puis envoie le texte complete après enregistrement

Le code à six chiffres sert uniquement à un administrateur authentifié pour trouver et confirmer la demande ; il ne permet ni interrogation répétée ni échange contre des identifiants. Le jeton d’interrogation est un secret aléatoire de 256 bits, jamais placé dans l’URL. Les approbations répétées sont refusées ; l’échec de création d’identité libère la réservation d’autorisation pour permettre une nouvelle tentative. Le résultat approuvé peut être relu avec le même jeton d’interrogation privé, pour éviter qu’une perte réseau ne rende les identifiants définitivement introuvables ; le client confirme leur effacement après enregistrement.

L’attente d’autorisation et l’approbation en attente de récupération sont chacune conservées au maximum 5 minutes. Sans REDIS_URL, les sessions temporaires ne résident que dans la mémoire du processus Exchange actuel ; après redémarrage, il faut demander un nouveau code, et plusieurs instances doivent diriger les requêtes d’appairage vers la même instance. Avec Redis, les entrées d’appairage et compteurs de limitation sont écrits dans Redis (avec un TTL de 5 minutes) ; la distribution entre instances est libre et n’exige pas d’affinité. Chaque IP source TCP réelle peut demander au maximum 10 codes par minute ; chaque administrateur peut effectuer au maximum 20 consultations ou approbations par minute. Le mode mémoire impose aussi un plafond global de 256 sessions en attente. Les IP client transférées par un proxy ne sont pas une base fiable de limitation ; les utilisateurs derrière le même proxy inverse partagent le quota source. Les données expirées sont supprimées par TTL ou nettoyage périodique. Les réponses définissent Cache-Control: no-store et aucun secret d’appairage ni jeton délivré en clair n’est journalisé.

Les demandes d’appairage ne peuvent pas écraser un identifiant d’appareil ou compte existant sur le serveur. L’administrateur doit vérifier le code et le client demandeur ; n’approuvez pas un code de connexion fourni à l’incitation d’un tiers.

API de code de connexion : POST /api/pairing/start accepte un device_name facultatif et renvoie ce nom dans la réponse. Pour l’administrateur, GET /api/pairing/{code} renvoie device_name et le suggested_device_id de l’espace actuel ; la consultation ne réserve pas l’identifiant. L’identity d’appareil peut être omis dans POST /api/pairing/approve ; le succès renvoie 200 et {identity} (identifiant final, sans jeton). Le WebSocket natif /ws/pairing?device_name=... accepte les noms d’appareil encodés pour une URL.