fix: DNS coupée après arrêt du tunnel, gel UI, dialogues sudo à répétition

- 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.
This commit is contained in:
tuxgyver
2026-08-31 11:16:04 +02:00
parent 2fa50a5873
commit 1b74719204
11 changed files with 1295 additions and 233 deletions
+6 -8
View File
@@ -196,11 +196,10 @@ class Config:
self.save()
def _apply_autostart(self, enabled: bool) -> None:
import sys
from app.utils.platform_utils import is_linux, is_windows
script = os.path.abspath(os.path.join(
os.path.dirname(__file__), "..", "..", "main.py"
))
from app.utils.platform_utils import is_linux, is_windows, launch_command
# launch_command() gère le cas du binaire PyInstaller, où main.py
# n'existe pas : l'ancien « python3 <…>/main.py » ne démarrait jamais.
command = launch_command()
if is_linux():
autostart_dir = os.path.expanduser("~/.config/autostart")
desktop = os.path.join(autostart_dir, "wgsecure.desktop")
@@ -208,7 +207,7 @@ class Config:
os.makedirs(autostart_dir, exist_ok=True)
content = (
"[Desktop Entry]\nType=Application\nName=WGSecure\n"
f"Exec=python3 {script}\nIcon=wgsecure\n"
f"Exec={command}\nIcon=wgsecure\n"
"Hidden=false\nX-GNOME-Autostart-enabled=true\n"
)
with open(desktop, "w") as f:
@@ -225,8 +224,7 @@ class Config:
reg = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key, 0,
winreg.KEY_SET_VALUE)
if enabled:
winreg.SetValueEx(reg, "WGSecure", 0, winreg.REG_SZ,
f'pythonw "{script}"')
winreg.SetValueEx(reg, "WGSecure", 0, winreg.REG_SZ, command)
else:
winreg.DeleteValue(reg, "WGSecure")
winreg.CloseKey(reg)