tuxgyverandClaude Opus 5 556f22e7c9 fix(auth): fiabilise la sortie de quarantaine
Audit du parcours complet — montage du tunnel, sondage de l'état, saisie
du code, ouverture de l'accès. Neuf défauts, dont plusieurs laissaient le
poste en quarantaine sans moyen visible d'en sortir : exactement ce que le
bouton « Saisir le code d'accès » existe pour éviter depuis la v0.8.2.

Adresse de l'API. api_base_url retranchait le dernier octet de l'adresse
du client, ce qui suppose un /24 et ignore les IPs autorisées. Or une
adresse client en /32 est la forme la plus courante et ne décrit aucun
réseau : un client en 10.6.1.7/32 sur un 10.6.0.0/16 était expédié vers
10.6.1.1, qui n'existe pas. La déduction passe désormais par
wireguard.tunnel_gateway, qui servait déjà au diagnostic et gère /32,
IPv6 et le repli sur les IPs autorisées. Une adresse IPv6 est encadrée de
crochets, sans quoi son « : » se confondait avec celui du port.

Révocation invisible. Le client ne sondait qu'au retour du tunnel : une
révocation avant terme — redémarrage du serveur, purge de sa table de
sessions, décision d'un administrateur — n'était annoncée par rien et
l'application affichait « Ouvert ✓ » devant un réseau muet, bouton
masqué, jusqu'à la chute du tunnel. Sans échéance annoncée, indéfiniment.
L'accès est reconfirmé chaque minute tant qu'il est cru ouvert.

Authentification perdue. « Plus tard » restait actif pendant la
vérification, Échap et la croix aussi. Fermer là rendait la main sur un
refus alors que le serveur pouvait encore accepter : sa réponse arrivait
après la sortie d'exec() et n'était lue par personne. L'accès était
ouvert côté serveur, l'application affichait la quarantaine, et le code
saisi était consommé pour rien. La fenêtre ne se ferme plus tant qu'une
requête est en vol.

Fenêtre survivante. Ni accept() ni reject() ne passent par closeEvent :
le minuteur de 500 ms continuait à battre après la fermeture, et la
fenêtre — parentée à la principale — survivait à sa disparition.
dispose() l'arrête et programme la destruction ; _access_dialog est remis
à None, son thread n'étant plus attendu à l'arrêt de l'application.

Repli 404 trompeur. La sonde d'accessibilité tenait pour preuve toute
réponse du serveur DNS du split-DNS, sans vérifier qu'il était joint par
le tunnel. Une adresse RFC1918 routée par le réseau local du poste
répondait donc hors tunnel, et le repli censé éviter le blocage le
provoquait : accès déclaré ouvert sans échéance, bouton masqué. La route
est vérifiée d'abord, sans émettre de paquet — connect() sur une socket
UDP suffit à connaître l'adresse source retenue par le noyau.

Proxy. urlopen emploie l'ouvreur par défaut, dont le ProxyHandler lit
http_proxy dans l'environnement : sur un poste d'entreprise la requête
vers l'adresse privée du tunnel partait au proxy, dont la réponse — 404
souvent — était prise pour celle du serveur, déclenchant le repli
ci-dessus. Panne intermittente parfaite : selon l'environnement de
lancement, ça passait ou non.

Silence pris pour un refus. Un ok faux couvrait « le serveur refuse » et
« le serveur n'a rien dit », traités pareil : un hoquet au montage du
tunnel faisait surgir la fenêtre et brûler un code alors que l'accès
était peut-être déjà ouvert. AuthResult porte désormais authoritative.
Un refus du serveur referme du premier coup, il en est seul juge ; un
silence déclenche un second sondage avant de déranger l'utilisateur, et
n'entame l'accès qu'après trois minutes sans réponse.

Annulation destructrice. _open_access_dialog écrivait l'état d'accès
quoi qu'il arrive. Un sondage abouti pendant que la fenêtre était ouverte
— les minuteries tournent dans la boucle imbriquée d'exec() — pouvait
établir que l'accès l'était, que « Plus tard » remettait aussitôt à
fermé. Renoncer à saisir un code ne referme rien côté serveur ; plus rien
ici non plus.

api_url. Le schéma est vérifié plutôt que repris tel quel : identifiant
et code partent dans cette URL. Reste ouvert, et hors de ce dépôt : l'API
par défaut est en clair et le serveur n'est pas authentifié.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 09:27:36 +02:00
2026-06-01 22:31:22 +02:00

🛡️ WGSecure (WGS)

🚀 v0.8.7 · 🐍 · 🪟🐧 · 🔐 Accès validé par le serveur · 🛡️ WireGuard

WGSecure est une interface graphique multiplateforme (Windows & Linux) pour gérer une connexion WireGuard dont l'accès aux ressources distantes est ouvert par un code à 6 chiffres validé par le serveur.


Fonctionnalités

# Fonctionnalité Détail
🖥️ Interface systray Icône bouclier dans la barre de notification, connexion en un clic
👤 Mode User (défaut) Connexion / déconnexion WireGuard, statut RX/TX en temps réel
📊 Graphique bande passante Courbes RX/TX en direct sur les 30 dernières secondes
📋 Journal d'événements Horodatage de chaque connexion, déconnexion, erreur
🕘 Historique des sessions Durée, données transférées, serveur par session
⚙️ Mode Admin Configuration complète, protégé par mot de passe
🔑 Génération de clés Paire Curve25519 native (sans dépendance au binaire wg)
👤 Multi-profils Sauvegarde / bascule entre profils, import/export .conf
🛡️ Configuration WireGuard Serveur, port UDP, DNS, IP client, keepalive
🔐 Code d'accès serveur Le tunnel monte en quarantaine ; le serveur ouvre l'accès après validation du code
🔍 Test DNS leak Vérifie que le DNS passe bien par le tunnel
🏓 Ping en temps réel Badge de latence dans l'interface principale
🔄 Auto-reconnexion Surveillance et reconnexion automatique si le tunnel tombe — activée par défaut (15 s)
📡 Test de connexion Handshake WireGuard réel, sans monter le tunnel, avec détection du filtrage sur port source
🚀 Démarrage automatique Lancement au démarrage du système — activé par défaut
1️⃣ Instance unique Un second lancement réveille l'instance déjà active plutôt que d'en ouvrir une seconde
🪟🐧 Cross-platform Windows 10+ et Linux (wg-quick)

📋 Prérequis

🐧 Linux

sudo apt install wireguard-tools   # Debian/Ubuntu
sudo dnf install wireguard-tools   # Fedora

🪟 Windows

🐍 Python

Python >= 3.11

📦 Installation

git clone <repo>
cd WGSecure
pip install -r requirements.txt

🚀 Utilisation

Mode User (par défaut)

python main.py
# ou via Makefile :
make run

⚙️ Mode Administrateur (configuration)

python main.py --admin
# ou via Makefile :
make run-admin

Sans systray

python main.py --no-tray

🔧 Makefile

Commande Description
make install Installe les dépendances Python
make linux Compile un binaire Linux autonome (PyInstaller)
make windows Compile un binaire Windows via Wine
make release Binaire Linux renommé avec la version
make install-gnome Installe dans le menu GNOME (~/.local/)
make uninstall-gnome Désinstalle du menu GNOME
make reset-password Supprime le mot de passe administrateur
make run Lance l'application
make run-admin Lance en mode administrateur
make clean Supprime les artefacts de build

🗺️ Workflow recommandé

  1. 🚀 Lancer python main.py --admin
  2. 🛡️ Onglet WireGuard : renseigner l'adresse, le port et la clé publique du serveur
  3. 🔑 Onglet Clés : générer une paire de clés → copier la clé publique sur le serveur
  4. 🔐 Onglet WireGuard : renseigner l'identifiant VPN connu du serveur (le QR code TOTP est délivré par le serveur, pas par ce client)
  5. 🔒 Onglet Sécurité : définir un mot de passe pour l'accès admin
  6. Enregistrer → quitter → lancer python main.py en mode user

🐧 Élévation de privilèges Linux

wg-quick, la lecture de l'état du tunnel (wg show) et le nettoyage réseau (interface orpheline, DNS) nécessitent les droits root. WGSecure tente dans l'ordre :

  1. sudo -n — silencieux, fonctionne si une règle NOPASSWD est en place (voir ci-dessous)
  2. sudo -A avec programme askpass graphique (ssh-askpass, etc.)
  3. pkexec (polkit) — dialogue graphique GNOME/KDE ; nécessite un agent d'authentification actif, absent d'un simple terminal (SSH, tmux)

Le sondage périodique de l'état du tunnel (toutes les 3 s) ne tente que l'étape 1 : sans règle NOPASSWD, aucun dialogue n'apparaît, le handshake et les compteurs RX/TX restent simplement vides.

Supprimer la demande de mot de passe (recommandé)

make setup-sudoers

Invite le mot de passe une fois dans le terminal (via sudo, plus fiable que pkexec hors session graphique), puis installe une règle NOPASSWD limitée à wg-quick, wg, et au nettoyage d'une interface/DNS orpheline — jamais un accès root généralisé. Idempotent : une relance ne redemande le mot de passe que si le contenu a changé. make check-privileges affiche l'état courant.

Pour le faire à la main :

sudo visudo -f /etc/sudoers.d/wgsecure
<utilisateur> ALL=(ALL) NOPASSWD: /usr/bin/wg-quick
<utilisateur> ALL=(ALL) NOPASSWD: /usr/bin/wg
<utilisateur> ALL=(ALL) NOPASSWD: /usr/sbin/ip link delete dev *
<utilisateur> ALL=(ALL) NOPASSWD: /usr/sbin/resolvconf -d *
<utilisateur> ALL=(ALL) NOPASSWD: /usr/bin/resolvectl revert *
<utilisateur> ALL=(ALL) NOPASSWD: /usr/bin/resolvectl dns *
<utilisateur> ALL=(ALL) NOPASSWD: /usr/bin/resolvectl domain *
<utilisateur> ALL=(ALL) NOPASSWD: /usr/bin/install -D -m 600 -o root -g root * /etc/wireguard/*

Réinitialiser le mot de passe admin oublié

make reset-password

🏗️ Architecture

WGSecure/
├── main.py                      # 🚀 Point d'entrée
├── requirements.txt
├── Makefile
├── app/
│   ├── __init__.py              # Version
│   ├── app_info.py              # ️  Contenu de la page « À propos »
│   ├── core/
│   │   ├── config.py            # 💾 Configuration JSON persistante + bcrypt
│   │   ├── wireguard.py         # 🛡️ Clés, tunnel, statut, DNS leak
│   │   ├── wg_handshake.py      # 🤝 Sonde de handshake réel, sans monter le tunnel
│   │   ├── single_instance.py   # 1️⃣  Garde une seule instance active
│   │   ├── history.py           # 🕘 Historique des sessions (sessions.json)
│   │   ├── log.py               # 📋 Journal d'événements (events.json)
│   │   └── vpn_session.py       # 🔐 Validation du code auprès du serveur
│   ├── ui/
│   │   ├── icons.py             # 🎨 Icônes bouclier générées par QPainter
│   │   ├── main_window.py       # 👤 Fenêtre principale (mode user)
│   │   ├── admin_window.py      # ⚙️  Panneau admin (onglets, thème sombre)
│   │   ├── bw_graph.py          # 📊 Widget graphique bande passante
│   │   ├── history_dialog.py    # 🕘 Dialogue historique des sessions
│   │   ├── access_code_dialog.py # 🔐 Saisie du code d'accès
│   │   └── systray.py           # 🖥️ Icône systray + menu contextuel
│   └── utils/
│       └── platform_utils.py    # 🔧 Détection OS, élévation de privilèges

🔒 Sécurité

Élément Protection
🔑 Mot de passe admin bcrypt (rounds=12) + sel intégré — migration transparente depuis SHA-256
🗝️ Clé privée WireGuard ~/.wgsecure/config.json (Linux) / %APPDATA%\WGSecure\ (Windows)
🔐 Secret TOTP Jamais sur le poste client — détenu par le serveur, qui seul valide le code et ouvre l'accès réseau
📄 Fichier .conf WireGuard Permissions 0600 (lecture propriétaire uniquement)

⚠️ Recommandation : chiffrez votre disque pour protéger le fichier de configuration.


👤 Auteur

Développé par JohnnyJT-Tools Version : v0.8.0 — Septembre 2026

S
Description
No description provided
Readme
148 MiB
2026-09-08 18:03:06 +00:00
Languages
Python 92.5%
Makefile 5.1%
Inno Setup 2.4%