From ea2e6d772bda9f78d4df5ae7454a6b867e2a6662 Mon Sep 17 00:00:00 2001 From: tuxgyver Date: Mon, 29 Jun 2026 10:19:16 +0200 Subject: [PATCH] update --- Makefile | 71 ++++++++++++++++++++++++++++++++++--------- app/core/config.py | 2 +- app/core/wireguard.py | 22 +++----------- app/ui/main_window.py | 10 ++++++ app/ui/systray.py | 10 ++++++ 5 files changed, 82 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 8536142..15767a1 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,9 @@ APP := wgsecure VERSION := 0.4.0 -PYTHON := python3 +VENV := .venv +PYTHON := $(VENV)/bin/python3 +PIP := $(VENV)/bin/pip SRC := main.py DIST := dist BUILD := build @@ -25,11 +27,18 @@ PI_OPTS := \ --hidden-import cryptography.hazmat.primitives.asymmetric.x25519 \ --collect-submodules PyQt6 -.PHONY: all linux windows release install install-gnome uninstall-gnome run run-admin icon reset-password clean help +.PHONY: all linux windows release install install-gnome uninstall-gnome run run-admin icon reset-password setup-sudoers clean clean-all help venv # ── Cible par défaut ──────────────────────────────────────────────────────── all: linux +# ── Environnement virtuel ──────────────────────────────────────────────────── +venv: $(VENV)/bin/python3 + +$(VENV)/bin/python3: + python3 -m venv $(VENV) + $(PIP) install --upgrade pip --quiet + # ── Génération de l'icône PNG (utilisée par PyInstaller) ──────────────────── icon: @$(PYTHON) -c "\ @@ -41,7 +50,7 @@ print(' Icône générée →', '$(ICON)')" 2>/dev/null @test -f $(ICON) || (echo " ❌ Génération icône échouée"; exit 1) # ── Binaire Linux ──────────────────────────────────────────────────────────── -linux: icon +linux: install icon @echo "" @echo " 🐧 Compilation Linux (PyInstaller onefile)…" @echo "" @@ -60,7 +69,7 @@ windows: icon @echo "" @which wine > /dev/null 2>&1 \ || (echo " ❌ Wine non installé → sudo apt install wine"; exit 1) - @wine python -m PyInstaller $(PI_OPTS) \ + @wine $(WINE_PYTHON) -m PyInstaller $(PI_OPTS) \ --onefile \ --windowed \ --icon=$(ICON) \ @@ -74,11 +83,25 @@ windows: icon @echo "" # ── Installation de Python dans Wine ───────────────────────────────────────── +WINE_PY_VER := 3.11.9 +WINE_PY_URL := https://www.python.org/ftp/python/$(WINE_PY_VER)/python-$(WINE_PY_VER)-amd64.exe +WINE_PY_EXE := /tmp/python-$(WINE_PY_VER)-amd64.exe +WINE_PYTHON := $(HOME)/.wine/drive_c/users/$(USER)/AppData/Local/Programs/Python/Python311/python.exe + setup-wine: - @echo " 📦 Installation Python + pip dans Wine…" - winetricks python3 - wine pip install -r requirements.txt - wine pip install pyinstaller + @echo " 📦 Installation Python $(WINE_PY_VER) Windows dans Wine…" + @which wine > /dev/null 2>&1 \ + || (echo " ❌ wine non installé → sudo apt install wine"; exit 1) + @test -f $(WINE_PY_EXE) \ + || (echo " ⬇️ Téléchargement Python Windows…" \ + && curl -L -o $(WINE_PY_EXE) $(WINE_PY_URL)) + @echo " 🔧 Installation silencieuse…" + wine $(WINE_PY_EXE) /quiet InstallAllUsers=0 PrependPath=1 + @echo " 📦 Installation des dépendances…" + wine $(WINE_PYTHON) -m pip install --upgrade pip + wine $(WINE_PYTHON) -m pip install -r requirements.txt + wine $(WINE_PYTHON) -m pip install pyinstaller + @echo " ✅ Python Windows prêt dans Wine" # ── Release (Linux renommé avec version) ───────────────────────────────────── release: clean linux @@ -119,10 +142,25 @@ uninstall-gnome: @echo " ✅ WGSecure désinstallé" # ── Dépendances Python ──────────────────────────────────────────────────────── -install: - $(PYTHON) -m pip install -r requirements.txt - $(PYTHON) -m pip install pyinstaller - @echo " ✅ Dépendances installées" +install: venv + $(PIP) install -r requirements.txt + $(PIP) install pyinstaller + @echo " ✅ Dépendances installées dans $(VENV)" + +# ── Droits sudo wg-quick sans dialogue de mot de passe ─────────────────────── +setup-sudoers: + @echo "" + @echo " 🔧 Configuration sudoers pour wg-quick (sans mot de passe)…" + @$(PYTHON) -c "\ +import os, subprocess; \ +user = os.environ.get('USER', os.path.basename(os.path.expanduser('~'))); \ +rule = user + ' ALL=(ALL) NOPASSWD: /usr/bin/wg-quick\n'; \ +tmp = '/tmp/wgsecure_sudoers_tmp'; \ +open(tmp, 'w').write(rule); \ +r = subprocess.run(['pkexec', 'bash', '-c', 'cp ' + tmp + ' /etc/sudoers.d/wgsecure && chmod 440 /etc/sudoers.d/wgsecure']); \ +os.unlink(tmp); \ +print(' ✅ /etc/sudoers.d/wgsecure configuré — WGSecure n\\'a plus besoin de dialogue admin.' if r.returncode == 0 else ' ❌ Échec. Exécutez manuellement : sudo bash -c \"echo ' + user + ' ALL=(ALL) NOPASSWD: /usr/bin/wg-quick > /etc/sudoers.d/wgsecure && chmod 440 /etc/sudoers.d/wgsecure\"')" + @echo "" # ── Réinitialisation du mot de passe administrateur ────────────────────────── reset-password: @@ -137,10 +175,10 @@ print(' ✅ Mot de passe supprimé — accès admin sans restriction au procha @echo "" # ── Lancer l'application ───────────────────────────────────────────────────── -run: +run: venv DISPLAY=:0 $(PYTHON) $(SRC) -run-admin: +run-admin: venv DISPLAY=:0 $(PYTHON) $(SRC) --admin # ── Nettoyage ──────────────────────────────────────────────────────────────── @@ -151,6 +189,10 @@ clean: @find . -name "*.pyc" -delete 2>/dev/null; true @echo " ✅ Artefacts supprimés" +clean-all: clean + @rm -rf $(VENV) + @echo " ✅ Venv supprimé" + # ── Aide ───────────────────────────────────────────────────────────────────── help: @echo "" @@ -164,6 +206,7 @@ help: @echo " ║ make setup-wine Python Windows dans Wine ║" @echo " ║ make install-gnome Installe dans GNOME ║" @echo " ║ make uninstall-gnome Désinstalle de GNOME ║" + @echo " ║ make setup-sudoers wg-quick sans sudo ║" @echo " ║ make reset-password Supprime le MDP admin ║" @echo " ║ make run Lance l'application ║" @echo " ║ make run-admin Lance en mode admin ║" diff --git a/app/core/config.py b/app/core/config.py index 978741d..e93e58a 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -19,7 +19,7 @@ _WG_DEFAULT: dict[str, Any] = { "client_public_key": "", "client_address": "10.8.0.2/24", "dns": "1.1.1.1", - "allowed_ips": "0.0.0.0/0", + "allowed_ips": "10.8.0.0/24", "keepalive": 25, } diff --git a/app/core/wireguard.py b/app/core/wireguard.py index 156c6cc..b996b76 100644 --- a/app/core/wireguard.py +++ b/app/core/wireguard.py @@ -48,11 +48,7 @@ def build_client_config(cfg: Config) -> str: def get_client_config_path(cfg: Config) -> str: name = cfg.wg.get("interface_name", "wgs0") - if is_windows(): - config_dir = get_config_dir() - else: - config_dir = get_wg_config_dir() - return os.path.join(config_dir, f"{name}.conf") + return os.path.join(get_config_dir(), f"{name}.conf") def write_client_config(cfg: Config) -> tuple[bool, str]: @@ -65,18 +61,8 @@ def write_client_config(cfg: Config) -> tuple[bool, str]: if not is_windows(): os.chmod(path, 0o600) return True, path - except PermissionError: - # Écriture via sudo sur Linux - config_dir_path = get_config_dir() - tmp = os.path.join(config_dir_path, "wgs_tmp.conf") - with open(tmp, "w") as f: - f.write(content) - code, _, err = run_privileged(["cp", tmp, path]) - os.unlink(tmp) - if code == 0: - run_privileged(["chmod", "600", path]) - return True, path - return False, err + except Exception as e: + return False, str(e) def is_connected(cfg: Config) -> bool: @@ -341,7 +327,7 @@ def generate_server_config( "[Peer]", f"PublicKey = {srv_pub}", f"PresharedKey = {psk}", - "AllowedIPs = 0.0.0.0/0", + "AllowedIPs = 10.8.0.0/24", "Endpoint = :" + str(server_port), "PersistentKeepalive = 25", ]) diff --git a/app/ui/main_window.py b/app/ui/main_window.py index 154e41c..ed6e1ac 100644 --- a/app/ui/main_window.py +++ b/app/ui/main_window.py @@ -605,4 +605,14 @@ class MainWindow(QMainWindow): event.ignore() self.hide() else: + self._status_timer.stop() + self._clock_timer.stop() + self._bw_timer.stop() + self._ping_timer.stop() + self._reconnect_timer.stop() + try: + if wg_core.is_connected(self._cfg): + wg_core.disconnect(self._cfg) + except Exception: + pass event.accept() diff --git a/app/ui/systray.py b/app/ui/systray.py index 016030a..bd35a05 100644 --- a/app/ui/systray.py +++ b/app/ui/systray.py @@ -108,4 +108,14 @@ class SystemTray(QSystemTrayIcon): def _quit(self): self._poll.stop() + try: + if wg_core.is_connected(self._cfg): + wg_core.disconnect(self._cfg) + except Exception: + pass + self._win._status_timer.stop() + self._win._clock_timer.stop() + self._win._bw_timer.stop() + self._win._ping_timer.stop() + self._win._reconnect_timer.stop() QApplication.quit()