Deux changements liés, qui achèvent le déplacement de la sécurité vers
le serveur.
1. Le tunnel n'est plus recréé à chaque connexion. Créer ou supprimer un
service Windows n'est jamais délégable à un utilisateur standard, le
démarrer peut l'être : c'est cette réinstallation systématique qui
imposait une authentification administrateur à chaque connexion ET à
chaque déconnexion. Désormais connect() démarre le service s'il
existe déjà, disconnect() se contente de l'arrêter, et le tunnel
reste installé entre les deux.
Trois voies en cascade pour ce démarrage/arrêt : sc.exe sans
élévation, puis le service wgsecure-helper, puis l'élévation en
dernier recours. Le helper gagne donc deux commandes
(start/stop_tunnel_service). Cette cascade tient quelle que soit la
configuration du poste — le test en session standard a montré que
l'ACL posée sur le service WireGuard ne donne aucun droit sur le
service du tunnel, qui est un objet distinct.
2. Après le montage, l'application demande le code à 6 chiffres et le
fait valider PAR LE SERVEUR (app/core/vpn_session.py). Jusqu'ici le
code était vérifié localement, contre un secret que l'application
détenait : elle validait donc un code qu'elle pouvait produire, et ne
verrouillait que sa propre interface. L'ordre est imposé par le
réseau — l'API n'est joignable que depuis le tunnel, qui sert de
réseau de quarantaine tant que le code n'est pas passé.
L'URL de l'API est déduite de l'adresse du client (10.6.0.6 →
10.6.0.1) faute de valeur explicite : c'est l'adresse du serveur
lui-même, la seule jamais filtrée depuis la quarantaine.
Sans identifiant VPN configuré, l'étape est ignorée : le serveur peut
tourner en mode permissif, où un compte non enrôlé garde son accès, et
imposer la saisie bloquerait des installations qui fonctionnent.
Chemins Linux inchangés (branches is_windows()).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>