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>
Ajoute un fichier log texte rotatif (wgsecure.log) dans le dossier
applicatif, en complément du journal JSON interne, pour diagnostiquer
un échec (ex. split-DNS) sans dépendre de l'UI. Corrige le panneau
Journal qui coupait les messages longs sans moyen de les lire en
entier (défilement horizontal réactivé + infobulle).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- CHANGELOG.md n'était pas empaqueté par PyInstaller (datas=[]) et son
chemin, calculé depuis __file__, ne survivait pas à l'extraction
onefile : la page « À propos » restait vide une fois compilée. Le
fichier est désormais embarqué (--add-data) et son chemin bascule sur
sys._MEIPASS en mode frozen.
- Le badge de latence se basait uniquement sur un ping ICMP vers
l'endpoint : de nombreux serveurs/pare-feux le bloquent alors que le
tunnel WireGuard fonctionne, d'où « hors ligne » permanent. Repli sur
l'âge du dernier handshake réel quand l'ICMP échoue.
- wgsecure.iss installe désormais WireGuard for Windows en silencieux
(prérequis manquant jusqu'ici), au même titre que le VC++
Redistributable ; make installer-deps télécharge les deux binaires.
- Instance unique : un second lancement réveille l'instance active.
- Autostart et reconnexion auto activés par défaut (nouvelle installation).
- Page « À propos » refaite en 5 onglets (contenu séparé dans app_info.py).
- Corrige le handshake/RX-TX qui ne s'affichaient plus (wg show sans élévation).
- Corrige le diagnostic sudo trompeur (sondes qui ne matchaient jamais les règles).
- Corrige make setup-sudoers bloqué hors session graphique (pkexec -> sudo), idempotent.
- Corrige le README : Kill Switch inexistant retiré, ordre d'élévation réel documenté.
- wg-quick down échoue silencieusement si l'interface a déjà disparu
(crash, kill, veille) et ne retire donc jamais l'entrée DNS posée par
wg-quick up : la résolution reste pointée sur un résolveur mort.
Ajout d'un nettoyage DNS inconditionnel (app/core/dns.py) déclenché à
la connexion, la déconnexion, la fermeture et au démarrage suivant.
- is_connected() se basait sur `wg show`, qui rend un code 0 même en cas
d'échec de permission pour un utilisateur non-root : l'app se croyait
déconnectée en permanence et ne démontait donc jamais le tunnel à la
fermeture. Détection réécrite via sysfs (sans privilèges).
- Connexion/déconnexion et ping tournaient sur le thread Qt : gel de
l'UI pendant les élévations de privilèges. Déportés dans des
QThread (app/ui/worker.py).
- Restauration réseau garantie sur toutes les sorties (croix, tray,
SIGINT/SIGTERM, atexit, exception) via app/core/shutdown.py.
- run_privileged() : la détection "sudo veut un mot de passe" ratait en
session non-anglophone et sur les comptes ALL=(ALL) ALL ; réécrite
pour se fier au message d'erreur réel plutôt qu'à `sudo -l`.
- Écriture de la config WireGuard dans /etc/wireguard (root:root 0700)
passe maintenant par install -D via la chaîne de privilèges complète
au lieu d'un tee non autorisé par les sudoers.
- Ajout d'un diagnostic des droits (make check-privileges, bouton
Admin) et mise à jour de setup-sudoers pour couvrir toutes les
commandes désormais utilisées.