feat: support split-DNS, infobulles UI et corrections Windows

- Ajout du support complet du split-DNS pour Linux (systemd-resolved) et Windows (NRPT)
- Bouton de configuration des permissions ACL pour WireGuard sous Windows
- Suppression de tous les appels à sc.exe (remplacés par PowerShell + wireguard.exe)
- UAC gérée par wireguard.exe lui-même (pas par WGSecure)
- Infobulles ajoutées sur tous les champs de configuration principaux
- Correction du blocage du handshake lié au redémarrage de systemd-resolved
- Incrémentation de la version à 0.7.3

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
2026-09-03 07:20:13 +02:00
parent e747f2a1ea
commit 38b48fc428
9 changed files with 326 additions and 11 deletions
+56
View File
@@ -231,6 +231,10 @@ class AdminWindow(QDialog):
self._srv_endpoint = QLineEdit()
self._srv_endpoint.setPlaceholderText("vpn.exemple.com ou 1.2.3.4")
self._srv_endpoint.setToolTip(
"Adresse IP ou nom d'hôte du serveur WireGuard. "
"Si vous utilisez un nom, assurez-vous qu'il est résolvable."
)
self._row(form, "Adresse serveur :", self._srv_endpoint)
self._srv_port = QSpinBox()
@@ -246,6 +250,10 @@ class AdminWindow(QDialog):
self._srv_pubkey = QLineEdit()
self._srv_pubkey.setPlaceholderText("Clé publique du serveur (base64)")
self._srv_pubkey.setToolTip(
"Clé publique du serveur (format base64). "
"Doit correspondre exactement à la clé publique du serveur."
)
self._row(form, "Clé publique serveur :", self._srv_pubkey)
# Un champ vide ne disait pas si la PSK était oubliée ou volontairement
@@ -303,15 +311,44 @@ class AdminWindow(QDialog):
self._iface_name = QLineEdit()
self._iface_name.setPlaceholderText("wgs0")
self._iface_name.setToolTip(
"Nom de l'interface réseau WireGuard. "
"Doit être unique et correspondre au nom du service sous Windows."
)
self._row(form2, "Nom interface :", self._iface_name)
self._client_addr = QLineEdit()
self._client_addr.setPlaceholderText("10.8.0.2/24")
self._client_addr.setToolTip(
"Adresse IP du client dans le réseau VPN. "
"Format: IP/Masque (ex: 10.8.0.2/24)."
)
self._row(form2, "Adresse IP client :", self._client_addr)
self._dns = QLineEdit()
self._dns.setPlaceholderText("1.1.1.1")
self._dns.setToolTip(
"Serveur DNS principal utilisé par le tunnel. "
"Laisser vide si vous utilisez le split-DNS ou le DNS système."
)
self._row(form2, "DNS :", self._dns)
# Split-DNS : serveur dédié pour les noms du réseau distant
self._split_dns_server = QLineEdit()
self._split_dns_server.setPlaceholderText("192.168.1.210")
self._split_dns_server.setToolTip(
"Serveur DNS dédié pour résoudre les noms du réseau distant. "
"Laisser vide pour utiliser le DNS par défaut."
)
self._row(form2, "DNS pour réseau distant :", self._split_dns_server)
self._split_dns_domains = QLineEdit()
self._split_dns_domains.setPlaceholderText("local, internal")
self._split_dns_domains.setToolTip(
"Domaines à résoudre via le DNS distant (séparés par des virgules). "
"Ex: local, internal. Laisser vide pour désactiver le split-DNS."
)
self._row(form2, "Domaines distants :", self._split_dns_domains)
self._allowed_ips = QLineEdit()
self._allowed_ips.setPlaceholderText("10.8.0.0/24")
@@ -325,6 +362,10 @@ class AdminWindow(QDialog):
self._keepalive = QSpinBox()
self._keepalive.setRange(0, 300)
self._keepalive.setValue(25)
self._keepalive.setToolTip(
"Intervalle (en secondes) pour envoyer un paquet keepalive. "
"0 = désactivé. Utile pour maintenir la connexion active à travers un NAT."
)
self._keepalive.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self._row(form2, "Keepalive (s) :", self._keepalive)
@@ -358,6 +399,10 @@ class AdminWindow(QDialog):
self._priv_key = QLineEdit()
self._priv_key.setEchoMode(QLineEdit.EchoMode.Password)
self._priv_key.setPlaceholderText("(générer ou coller)")
self._priv_key.setToolTip(
"Clé privée de ce client (format base64). "
"À garder SECRETE ! La clé publique est dérivée automatiquement."
)
self._priv_key.setFixedHeight(28)
show_priv = QPushButton("Afficher")
show_priv.setFixedSize(70, 28)
@@ -1147,6 +1192,11 @@ class AdminWindow(QDialog):
self._allowed_ips.setText(wg.get("allowed_ips", "0.0.0.0/0"))
self._keepalive.setValue(int(wg.get("keepalive", 25)))
self._mtu.setValue(int(wg.get("mtu") or 0))
# Split-DNS
self._split_dns_server.setText(wg.get("split_dns_server", ""))
domains = wg.get("split_dns_domains") or []
self._split_dns_domains.setText(", ".join(domains) if isinstance(domains, list) else domains)
self._priv_key.setText(wg.get("client_private_key", ""))
self._pub_key.setText(wg.get("client_public_key", ""))
self._mfa_enabled_cb.setChecked(self._cfg.mfa_enabled)
@@ -1166,6 +1216,12 @@ class AdminWindow(QDialog):
self._cfg.set("wg", "mtu", self._mtu.value())
self._cfg.set("wg", "client_private_key", self._priv_key.text().strip())
self._cfg.set("wg", "client_public_key", self._pub_key.text().strip())
# Split-DNS
self._cfg.set("wg", "split_dns_server", self._split_dns_server.text().strip())
domains_text = self._split_dns_domains.text().strip()
domains_list = [d.strip() for d in domains_text.split(",") if d.strip()] if domains_text else []
self._cfg.set("wg", "split_dns_domains", domains_list)
self._cfg.mfa_enabled = self._mfa_enabled_cb.isChecked()
self._cfg.mfa_secret = self._mfa_secret.text().strip()
self._cfg.save()