Les redirections -L et -R existaient deja ; il manquait -D, ou le port local
ouvert se comporte comme un proxy SOCKS dont la destination est negociee par
chaque client (navigateur, curl...) plutot que fixee a l'avance.
- app/tunnels.py : implementation minimale d'un serveur SOCKS4/4a/5 (CONNECT
uniquement, sans authentification - largement suffisant pour un usage
local/personnel). Reutilise le meme _ForwardServer et le meme _relay() que
-L/-R ; seul le handshake initial differe (negocie la destination au lieu
de la recevoir en config). DIRECTION_DYNAMIC s'integre dans describe() et
Tunnel.stop() sans code specifique supplementaire.
- TunnelDialog : nouvelle option "Dynamique - SOCKS (-D)" ; les champs
Machine/Port de destination se masquent automatiquement pour ce mode
(QFormLayout.setRowVisible), puisque la destination n'est pas fixee ici.
tests/test_socks_tunnel.py : verifie SOCKS5 (adresse IPv4) et SOCKS4a (nom de
domaine) avec un vrai client SOCKS et un transport SSH mocke - a d'ailleurs
revele un bug reel (decode("idna", errors="replace") leve une exception, le
codec idna ne supportant pas errors="replace") sur le chemin nom-de-domaine,
corrige ici (decode("ascii", errors="replace"), les noms d'hote SOCKS etant
de l'ASCII simple).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Une session peut desormais passer par un jump host avant d'atteindre sa
cible, avec 3 sources possibles (limite a un seul saut pour l'instant) :
une session PySSH existante, un Host de ~/.ssh/config, ou une configuration
manuelle (hote/port/utilisateur/authentification/cle).
- session_manager.py : BastionConfig (mode + parametres), champ
Session.bastion. Jamais de mot de passe stocke : un bastion en mode "mot
de passe" le redemande a la connexion, comme le fait deja Session.auth_type.
- app/bastion.py : resolve_bastion_target() convertit un BastionConfig en
parametres de connexion concrets quelle que soit sa source, et leve une
erreur claire si la reference est cassee (session supprimee, alias OpenSSH
introuvable, config manuelle incomplete) plutot que d'echouer plus tard
avec un message obscur.
- ssh_connection.py : la logique de connexion (auth, cle d'hote modifiee,
mot de passe de secours en mode auto) est factorisee dans _connect_host(),
reutilisee a l'identique pour le bastion et pour la cible.
_open_bastion_channel() connecte d'abord le bastion puis ouvre un canal
direct-tcpip vers la cible, passe en sock= a la connexion finale (mecanisme
ProxyJump standard de paramiko). Le bastion a son propre SSHClient, ferme
proprement a la fin de la connexion.
- SessionDialog : section "Bastion / Jump Host" (choix de la source + champs
associes, caches/affiches via un QStackedWidget).
- ConnectionController resout le bastion et demande son mot de passe (si
nécessaire) avant d'ouvrir l'onglet ; erreur affichee immediatement si la
reference est invalide plutot que de lancer une connexion vouee a l'echec.
- app/openssh/config.py : un Host avec ProxyJump produit maintenant une
Session dont le bastion reference cet alias (mode BASTION_OPENSSH) : le
scenario proxmox-prod / bastion de la Phase 2 fonctionne de bout en bout.
tests/test_bastion.py (resolution des 3 sources + erreurs, et ouverture du
canal via un bastion entierement mocke, sans reseau reel) et
tests/test_session_dialog_bastion.py (UI : construction, pre-remplissage a
l'edition, resultat par mode).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Les info-bulles suffisent : le texte fixe sous le formulaire allongeait la
fenetre sans rien apporter de plus.
L'explication reste accessible de deux façons : en survolant une entree de la
liste deroulante, et en survolant le champ lui-meme, dont l'info-bulle reprend
desormais celle du type selectionne. Sans cette seconde info-bulle, l'explication
n'aurait ete visible qu'en ouvrant la liste.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Choisir entre Ed25519, trois courbes NIST et RSA n'a de sens que si l'on sait
ce qu'elles impliquent. Chaque type dispose desormais d'un resume, affiche a la
fois en info-bulle dans la liste deroulante et sous le formulaire, mis a jour a
chaque changement de selection.
Chaque resume indique la courbe (ou l'absence de courbe pour RSA), l'equivalence
de robustesse avec RSA selon les recommandations du NIST (SP 800-57), la
compatibilite OpenSSH, et le cas d'usage : Ed25519 par defaut, ECDSA quand une
politique de conformite impose les courbes NIST, RSA pour du materiel ancien.
La reserve sur l'origine jamais expliquee des parametres des courbes NIST est
mentionnee, puisqu'elle motive le choix d'Ed25519 par defaut.
Le champ de taille en bits, qui ne concerne que RSA, est desormais active par la
meme fonction : un seul endroit gere la reaction au changement de type.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Le panneau des sessions etait declare Movable|Floatable mais pas Closable : il
n'avait donc aucun bouton de fermeture et ne pouvait pas etre masque. Sa largeur
plancher etait par ailleurs imposee par son contenu, ce qui empechait de le
retrecir vraiment.
- ajout de DockWidgetClosable, largeur minimale ramenee a 120 px
- bascule par F9, par le menu Affichage, ou par la croix du panneau, les trois
restant synchronises
- separateur elargi a 6 px et surligne au survol, pour etre attrape facilement
Generation de cles : ajout d'ECDSA sur les courbes NIST P-256, P-384 et P-521,
en plus d'Ed25519 et RSA. Ed25519 reste le choix par defaut : c'est aussi une
courbe elliptique (Curve25519), plus courte et plus rapide, et sans les
interrogations qui entourent le choix des parametres des courbes NIST. Chaque
type est verifie relisible par paramiko, donc utilisable pour se connecter.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tunnels (redirection de ports), la specialite de Bitvise : un bouton dans la
barre d'un onglet SSH ouvre un gestionnaire de redirections.
- locale (-L) : un port de votre poste est relaye, via la connexion SSH, vers
une machine joignable depuis le serveur (typiquement un service qui n'ecoute
que sur la boucle locale du serveur)
- distante (-R) : l'inverse
Chaque tunnel tourne dans son propre thread, un relais bloque ne genant ni
l'interface ni les autres tunnels. Ils sont fermes avec la session.
Envoi simultane, façon MobaXterm : le bouton "Multi" diffuse la frappe vers
tous les onglets terminal. La diffusion ecrit directement dans les connexions
et non via les widgets terminal, sinon chaque onglet rediffuserait a son tour.
Reparation : un de mes scripts de correction avait reecrit main_window.py en
retraduisant deux fois les fins de ligne, produisant des sequences \r\r\n ;
le fichier avait ete committe ainsi (2538 lignes au lieu de 856, une ligne vide
inseree partout). Le contenu etait intact, seule la mise en forme etait touchee.
Le fichier est reconstitue par normalisation des fins de ligne, et un controle
d'integrite a ete ajoute a la verification de non-regression.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reunit en un seul outil les fonctions utiles de MobaXterm, Termius et Bitvise,
sans compte ni service tiers, avec toutes les donnees en local.
- Terminaux multi-onglets : sessions SSH et terminaux Windows locaux
(PowerShell / cmd) via la pseudo-console native ConPTY
- Gestionnaire de fichiers SFTP facon WinSCP : double panneau, colonnes
triables, glisser-deposer, renommage, permissions, file de transferts.
Ouvrable sur une connexion en cours sans creer de favori
- Gestion des cles SSH : generation Ed25519/RSA, import, export
- Gestion du fichier known_hosts, avec remplacement guide d'une cle d'hote
modifiee (cas frequent des serveurs en DHCP)
- Trois themes (clair, bleu nuit, noir), commutables a chaud
- Authentification automatique reprenant le comportement de la commande ssh
(agent SSH et cles ~/.ssh), mot de passe demande seulement en secours
Aucun mot de passe n'est stocke sur le disque.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>