J'ai essayé de nombreuses solutions comme les gestionnaires de tunnel SSH, mais tous étaient inconvinient pour moi: trop de fenêtres de configuration, parfois buggés (une fois le gestionnaire de tunnel SSH a purgé tous les réglages que j'avais! Donc j'ai dû restaurer les réglages pour les 30 tunnels). Donc ils ont tous perdu ma confiance. C'est pourquoi j'ai créé un script personnalisé Powershell, facile à configurer, modifiable, petit, mais fonctionne. Publié ici et ci-dessous :
Pour commencer à l'utiliser, vous avez besoin d'une configuration comme ceci :
# LocalPort TargetHost TargetPort SshHost SshUsername SshKeyPath
18080 google.com 80 bastion.example.com User D:\secure\path\to\private_key.ppk
Enregistrez-le en tant que config.csv. Et utilisez un script Powershell pour le maintenir en marche :
<#
.SYNOPSIS
Script Powershell pour maintenir un tunnel ssh actif et fonctionnel
.DESCRIPTION
Ce script utilise la configuration des tunnels située dans config.csv. Pour plus d'informations, visitez http://tsherlock.tech/2019/03/13/simple-ssh-tunnel-auto-reconnect-using-putty-and-powershell/
.NOTES
Version : 1.0
Auteur : Anton Shkuratov
Date de création : 2019-03-13
Objectif/Changement : Développement du script initial
#>
$currentDir = $PSScriptRoot
if (-not $env:PATH.Contains($currentDir)) {
$env:PATH="$env:PATH;$currentDir"
}
# Vérifier que plink est accessible
try {
Start-Process plink.exe -WindowStyle Hidden
} catch {
Write-Host Erreur en exécutant plink.exe. Assurez-vous que son chemin est bien dans la variable d'environnement PATH
EXIT 1
}
# Analyse de la configuration
$config = [System.IO.File]::ReadAllLines("$currentDir\config.csv");
$bindings = New-Object System.Collections.ArrayList
$regex = New-Object System.Text.RegularExpressions.Regex("(\d)+\s([^ ]+)\s(\d+)\s([^ ]+)\s([^ ]+)\s([^ ]+)", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase);
$keyPasswords = @{}
$procs = @{}
foreach($line in $config) {
$match = $regex.Match($line)
if ($match.Success) {
$sshKey = $match.Groups[6];
$bindings.Add(@{
LocalPort = $match.Groups[1];
TargetHost = $match.Groups[2];
TargetPort = $match.Groups.Groups[3];
SshHost = $match.Groups[4];
SshUser = $match.Groups[5];
SshKey = $match.Groups[6];
});
if (-not $keyPasswords.ContainsKey($sshKey)) {
$pass = Read-Host "Veuillez entrer le mot de passe pour la clé (si définie) : $sshKey" -AsSecureString
$keyPasswords.Add($sshKey, $pass);
}
}
}
# Démarrer les processus
function EnsureRunning($procs, $keyPasswords, $binding) {
if ($procs.ContainsKey($binding) -and $procs[$binding].HasExited) {
$proc = $procs[$binding]
$sshKey = $binding.sshKey
$out = $proc.StandardError.ReadToEnd()
if ($out.Contains("Wrong passphrase")) {
Write-Host "Mauvaise phrase passe pour $sshKey, veuillez réessayer"
$pass = Read-Host "Veuillez entrer le mot de passe pour : $sshKey" -AsSecureString
$keyPasswords[$sshKey] = $pass;
} else {
$exitCode = $proc.ExitCode
$tHost = $binding.sshHost
Write-Host "Connexion à $tHost est perdue, code de sortie : $exitCode"
}
}
if (-not $procs.ContainsKey($binding) -or $procs[$binding].HasExited) {
$sshUser = $binding.SshUser
$sshHost = $binding.SshHost
$sshKey = $binding.SshKey
$lPort = $binding.LocalPort
$tPort = $binding.TargetPort
$tHost = $binding.TargetHost
$sshKeyPass = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($keyPasswords[$sshKey]))
$psi = New-Object System.Diagnostics.ProcessStartInfo;
$psi.FileName = "plink.exe";
$psi.UseShellExecute = $false;
$psi.CreateNoWindow = $true;
$psi.RedirectStandardInput = $true;
$psi.RedirectStandardError = $true;
$psi.Arguments = "-ssh $sshUser@$sshHost -i `"$sshKey`" -batch -pw $sshKeyPass -L $lPort`:$tHost`:$tPort"
$proc = [System.Diagnostics.Process]::Start($psi);
Start-Sleep 1
if (-not $proc.HasExited) {
Write-Host Connecté à $sshUser@$sshHost
}
$procs[$binding] = $proc;
}
}
function EnsureAllRunning($procs, $keyPasswords, $bindings) {
while($true) {
foreach($binding in $bindings) {
EnsureRunning $procs $keyPasswords $binding
}
Start-Sleep 1
}
}
try {
# En attente de la commande de sortie
Write-Host En cours d'exécution... Appuyez sur Ctrl+C pour arrêter l'exécution...
EnsureAllRunning $procs $keyPasswords $bindings
} finally {
# Nettoyage
Write-Host Nettoyage
foreach($proc in $procs.Values) {
if ($proc -ne $null -and -not $proc.HasExited) {
$proc.Kill();
}
}
}
Une fois configuré, exécutez-le simplement comme suit :
powershell -File autossh.ps1