Retour aux mises à jour
New releaseAug 20, 2026

sshroute v0.2.11

Routeur SSH conscient du réseau - achemine les connexions vers différentes IP/ports/clés/hôtes de saut en fonction du VPN actif ou du réseau

Partager

sshroute

CICodeOpenSpecSecurity
CI
Release
OpenSpec Badge
Scorecard
Latest Release
codecov
Go Report Card
Go Reference
Specs
Requirements
Tasks
Open Changes
OpenSSF Scorecard
CII Best Practices
License: Apache 2.0

Routeur SSH conscient du réseau. Détecte votre réseau actif ou VPN et sélectionne automatiquement le bon hôte, port, fichier d'identité et hôte de rebond pour chaque connexion SSH — sans toucher à ~/.ssh/config.

Comment ça marche

Définissez chaque hôte logique une seule fois avec un profil default et des surcharges optionnelles par réseau. À chaque connexion, sshroute détecte sur quel réseau vous êtes (VPN, LAN de bureau, pair WireGuard, etc.) et résout les paramètres SSH corrects avant de passer la main au vrai /usr/bin/ssh.

ssh myserver
  → sshroute detecte : corp-vpn est actif
  → résout : 10.100.0.50:2222 via bastion.corp.internal
  → exec /usr/bin/ssh -p 2222 -i ~/.ssh/corp_key -J bastion.corp.internal 10.100.0.50

Pourquoi sshroute ?

Pour les homelabbers

Votre lab a probablement au moins deux réalités : vous êtes soit à la maison sur le LAN, soit absent et vous vous connectez via WireGuard ou un autre VPN. Le problème est que ~/.ssh/config ne sait pas dans lequel vous êtes — vous finissez donc avec des alias séparés (server-lan, server-vpn), ou un hôte de rebond qui ne fonctionne qu'à moitié, ou vous mémorisez les IP.

sshroute résout ce problème en détectant votre réseau actuel avant chaque connexion. Lorsque l'interface WireGuard est active et que la route du pair existe, il se connecte directement à l'IP du tunnel. Quand vous êtes sur le LAN, il utilise l'adresse locale. Quand aucun des deux n'est joignable, il utilise le nom d'hôte public en secours. Un alias, trois réalités, zéro changement manuel.

Il intercepte également SSH de manière transparente — git push, rsync, scp passent tous automatiquement par lui une fois que vous avez configuré le mode shadow. Pas de wrappers, pas de fonctions shell, pas de réflexion.

Pour les environnements professionnels

Les réseaux d'entreprise sont pires. Vous avez l'internet public, peut-être un VPN site-à-site, peut-être un VPN personnel split-tunnel, et à l'intérieur vous avez différents hôtes de rebond selon l'environnement que vous ciblez — dev, staging, prod, chacun avec son bastion et sa clé. Garder cela en ordre dans ~/.ssh/config signifie soit un énorme fichier qui plante dès que l'infrastructure change, soit un script que toute l'équipe maintient différemment.

sshroute vous permet de définir la logique de routage de manière déclarative, de la conserver dans un fichier YAML versionné et de la partager dans toute l'équipe. La même configuration fonctionne pour tout le monde — le bon réseau est détecté automatiquement en fonction des interfaces ou routes actives sur chaque machine. Les clés, ports, utilisateurs et hôtes de rebond se résolvent sans que l'utilisateur ait à y penser.

Comparaison

Fonctionnalité~/.ssh/configWireGuard seulementTeleport / Boundarysshroute
Détecte votre réseau actuel
Choisit automatiquement le meilleur chemin
Secours en cas d’échec de connexion
Reconnexion automatique + reroutage à la coupure⚠️ itinérance du tunnel⚠️ via proxy fixe
Une commande par hôte, n’importe où⚠️ VPN doit être actif
Taille de config pour 10 hôtes × 4 chemins📄 ~600 lignes📄 ~600 lignes + config VPN📄 config côté serveur📄 ~60 lignes
Appareils mobiles itinérants⚠️ alias manuels⚠️ VPN requis
Chaînage automatique d’hôte de rebond⚠️ -J manuel➖ n/a
Fonctionne avec scp / rsync / git / Ansible⚠️ partiel
Aucune installation côté serveur sur les cibles
Pas de serveur d’authentification ni de démon
Pas d’agent client
Open source, entièrement auto-hébergé⚠️ open-core

Teleport et Boundary sont une catégorie différente — ils ajoutent le contrôle d’accès, les journaux d’audit et l’authentification par certificat en plus du routage. Si c’est ce dont vous avez besoin, utilisez-les. sshroute est pour quand vous voulez l’intelligence de routage sans la surcharge opérationnelle de gérer un serveur d’authentification central.

Installation

Téléchargement binaire

Téléchargez la dernière version depuis GitHub Releases. Des binaires sont disponibles pour Linux, macOS et Android sur AMD64 et ARM64.

Go install

go install github.com/thereisnotime/sshroute@latest

Android (Termux)

Téléchargez l’archive android_arm64 depuis GitHub Releases, extrayez-la et placez le binaire dans ~/.local/bin :

mkdir -p ~/.local/bin
curl -Lo "$TMPDIR/sshroute.tar.gz" \
  https://github.com/thereisnotime/sshroute/releases/latest/download/sshroute_android_arm64.tar.gz
tar -xzf "$TMPDIR/sshroute.tar.gz" -C ~/.local/bin sshroute
chmod +x ~/.local/bin/sshroute

Ajoutez ~/.local/bin à votre PATH dans ~/.bashrc ou ~/.profile si ce n’est pas déjà fait :

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Sinon, compilez depuis les sources avec le Go de Termux. Comme la chaîne d’outils officielle de Go ne publie pas de binaires android/arm64, définissez GOTOOLCHAIN=local pour utiliser ce que Termux fournit :

GOTOOLCHAIN=local go install github.com/thereisnotime/sshroute@latest

Après l’installation, définissez le chemin du binaire SSH car Termux n’a pas /usr/bin/ssh :

# ~/.config/sshroute/config.yaml
ssh_binary: /data/data/com.termux/files/usr/bin/ssh

Ou via variable d’environnement : export SSHROUTE_SSH=$(which ssh)

Docker

docker run --rm -v ~/.config/sshroute:/root/.config/sshroute \
  ghcr.io/thereisnotime/sshroute network

Podman

podman run --rm -v ~/.config/sshroute:/root/.config/sshroute \
  ghcr.io/thereisnotime/sshroute network

Sur les systèmes avec SELinux activé (Fedora, RHEL, etc.), ajoutez :Z au drapeau de volume :

podman run --rm -v ~/.config/sshroute:/root/.config/sshroute:Z \
  ghcr.io/thereisnotime/sshroute network

Mode shadow (remplacement transparent de SSH)

Installez sshroute en tant que ssh plus tôt dans votre $PATH. Tous les appels SSH — depuis votre terminal, git, rsync, scp — sont interceptés automatiquement. Les hôtes qui ne sont pas dans votre configuration sont transmis tels quels à /usr/bin/ssh.

mkdir -p ~/.local/bin
ln -s $(which sshroute) ~/.local/bin/ssh

# Ajoutez à ~/.bashrc ou ~/.zshrc si ce n’est pas déjà présent :
export PATH="$HOME/.local/bin:$PATH"

Démarrage rapide

# Ajouter un hôte avec un profil par défaut
sshroute add myserver --host myserver.example.com --user alice --key ~/.ssh/id_ed25519

# Ajouter une surcharge spécifique à un VPN
sshroute add myserver --network vpn --host 10.8.0.50 --port 2222 --jump bastion.vpn

# Se connecter — le réseau est détecté automatiquement
sshroute connect myserver

# Afficher la commande résolue sans l’exécuter
sshroute connect myserver --dry-run

# Voir quel réseau est actif actuellement
sshroute network

Commandes

Drapeaux globaux

Ces drapeaux s’appliquent à chaque commande :

DrapeauVariable d’environnementDéfautDescription
--configSSHROUTE_CONFIG~/.config/sshroute/config.yamlChemin du fichier de configuration
-o, --outputtableFormat de sortie : table, json, yaml
-v, --verboseSSHROUTE_VERBOSE=1falseJournalisation de débogage sur stderr
--dry-runfalseAffiche la commande SSH résolue sans l'exécuter

init

Crée un fichier de configuration de démarrage avec des exemples commentés. Échoue si le fichier existe déjà.

DrapeauDéfautDescription
--forcefalseÉcrase un fichier de configuration existant

connect <alias>

Détecte le réseau actif, résout les paramètres SSH pour alias et exécute le vrai binaire SSH. Les arguments supplémentaires après l’alias sont transmis tels quels à SSH.

DrapeauDéfautDescription
--fallbackfalseEssaie chaque profil dans l’ordre de priorité, en réessayant le suivant seulement en cas d’échec de connexion (code de sortie 255)
--reconnectfalseSupervise la connexion et se reconnecte automatiquement lorsqu’elle est interrompue, en redétectant le réseau actif et en résolvant à nouveau la route à chaque fois
--reconnect-delay2sDélai entre les tentatives de reconnexion quand --reconnect est défini

Avec --reconnect, sshroute maintient ssh actif malgré les coupures de connexion (mise en veille du portable, basculement WiFi, itinérance entre réseaux). Comme il redétecte le réseau à chaque reconnexion, il vous suit sur une route différente : par exemple, se mettre en veille sur le LAN et se réveiller sur un hotspot se reconnecte via la route publique au lieu de réessayer l’adresse LAN maintenant inaccessible. Une déconnexion propre (exit 0) ou un échec d’authentification/commande distante arrête la boucle ; seules les véritables coupures de connexion déclenchent une reconnexion. Reconnect exécute ssh comme un sous-processus (comme --fallback), donc sshroute reste résident pendant la session ; SIGINT/SIGTERM le termine. L’état de session au-delà de la coupure est géré par votre multiplexeur (tmux/zellij) ; combinez --reconnect avec -- tmux attach ou -- zellij attach -c <nom> pour retomber directement dans votre session :

sshroute connect myserver --reconnect --fallback -- zellij attach -c work

list

Liste tous les hôtes configurés et les paramètres SSH qui seraient utilisés sur le réseau actuel. Supporte -o table|json|yaml.

add <alias>

Ajoute un hôte ou met à jour un existant. Les drapeaux omis conservent leur valeur actuelle. Exécutez plusieurs fois avec différentes valeurs de --network pour construire des surcharges par réseau.

DrapeauDéfautDescription
--hostNom d’hôte ou adresse IP
--port22Port SSH
--userNom d’utilisateur SSH
--keyChemin du fichier d’identité (supporte ~)
--jumpHôte de rebond — passé en -J à SSH
--networkdefaultProfil réseau dans lequel écrire les paramètres

remove <alias>

Supprime tous les profils de alias de la configuration.

network

Affiche le nom du réseau actuellement détecté (ou default si aucun ne correspond).

network list

Liste tous les réseaux configurés avec leur priorité, leurs règles de vérification et leur état actif actuel. Supporte -o table|json|yaml.

network test <name>

Exécute chaque vérification pour le réseau name et affiche succès/échec par règle. Utile pour déboguer la logique de détection.

config

Affiche le chemin résolu vers le fichier de configuration.

config edit

Ouvre le fichier de configuration dans $EDITOR (utilise nano par défaut). Crée le fichier et son répertoire parent s’ils n’existent pas.

resolve <alias>

Affiche les paramètres SSH qui seraient utilisés pour alias sur le réseau actuel. Utile pour le débogage et les scripts. Utilisez --network <name> pour remplacer le réseau détecté. Supporte -o table|json|yaml.

DrapeauDéfautDescription
--networkauto-détectionProfil réseau pour lequel résoudre

copy <alias> <src> <dst>

Copie des fichiers vers ou depuis un hôte configuré en utilisant scp avec les mêmes paramètres résolus (clé, port, rebond) que connect. Utilisez la syntaxe <alias>:<path> pour les chemins distants :

sshroute copy myserver ./local.txt myserver:/remote/path/
sshroute copy myserver myserver:/remote/file.txt ./local/

La variable d’environnement SSHROUTE_SCP remplace le binaire scp utilisé.

version

Affiche la version, le commit git, la date de build et les informations d’exécution Go.

update

Met à jour sshroute sur place vers la dernière version GitHub. Il télécharge l’archive pour votre plateforme, vérifie son sha256 par rapport à checksums.txt, et — si cosign est installé — vérifie la signature cosign de la version, avant de remplacer atomiquement le binaire en cours d’exécution.

sshroute update            # télécharger, vérifier et installer la dernière version
sshroute update --check    # seulement signaler si une version plus récente est disponible
sshroute update --force    # réinstaller la dernière version même si déjà à jour

Si la vérification sha256 (ou cosign, quand présente) échoue, la mise à jour est annulée et le binaire reste intact. Cette commande cible les installations du binaire de version ; si vous avez installé via go install ou un gestionnaire de paquets, mettez à jour avec ceux-ci.

Fichier de configuration

Emplacement par défaut : ~/.config/sshroute/config.yaml

networks:
  corp-vpn:
    priority: 10          # plus petit = vérifié en premier
    checks:
      - type: interface
        match: wg0
      - type: route
        match: 10.100.0.0

  office:
    priority: 20
    checks:
      - type: ping
        host: 192.168.1.1
        timeout: 500ms

hosts:
  myserver:
    default:              # obligatoire — utilisé quand aucun réseau ne correspond
      host: myserver.example.com
      port: 22
      user: alice
      key: ~/.ssh/id_ed25519
      options:            # optionnel — passé comme drapeaux SSH -o Key=Value
        ConnectTimeout: "10"
        ServerAliveInterval: "30"
    corp-vpn:
      host: 10.100.0.50
      port: 2222
      key: ~/.ssh/corp_key
      jump: bastion.corp.internal
      options:
        ConnectTimeout: "5"   # remplace le défaut pour ce réseau uniquement
    office:
      host: 192.168.1.50

Chaque hôte doit avoir un profil default. Les profils réseau n’ont besoin de spécifier que les champs qui diffèrent du défaut — les champs non définis héritent de default.

Champs d’un profil hôte

ChampTypeDescription
hoststringNom d'hôte ou adresse IP
portintPort SSH (défaut : 22)
userstringUtilisateur SSH
keystringChemin du fichier d'identité (~ est expansé)
jumpstringAlias d'hôte de rebond ou user@host
optionsmapDrapeaux SSH arbitraires -o Key=Value (ex. ConnectTimeout, StrictHostKeyChecking)
commentstringDescription affichée dans sshroute list
tagslistTags pour le filtrage avec sshroute list --tag

Les clés de options sont fusionnées de default dans les profils réseau — les valeurs réseau remplacent les clés correspondantes, les clés non chevauchantes sont héritées.

Détection du réseau

Les réseaux sont évalués dans l’ordre de priority (la valeur la plus petite en premier). L’ordre alphabétique départage les ex æquo. Le premier réseau dont toutes les vérifications réussissent est utilisé ; si aucun ne correspond, default s’applique.

Type de vérificationRéussite quandChamps requis
routeLe sous-réseau/IP apparaît dans la table de routage du noyaumatch
interfaceL’interface nommée existe et est opérationnellement activematch
pingL’hôte répond à l’écho ICMP dans le délai impartihost, timeout (optionnel, défaut 2s)
execLa commande shell se termine avec le code 0command

Plusieurs vérifications au sein d’une même définition de réseau utilisent la logique ET — toutes doivent réussir.

Exemples

Des fichiers de configuration prêts à l’emploi se trouvent dans examples/ :

FichierCas d’utilisation
basic.yamlHôte unique, VPN vs secours public
multi-network.yamlLAN du bureau, VPN entreprise, VPN distant, public
wireguard-backconnect.yamlPair WireGuard qui se connecte en retour vers vous
jump-hosts.yamlDifférents bastions par réseau
multi-zone-roaming.yamlHome lab multi-zone avec passerelle WireGuard et appareils mobiles itinérants

Documentation

Des guides détaillés se trouvent dans docs/ :

GuideDescription
Configuration home labHome lab multi-zone avec WireGuard, hôtes de rebond, NAS, nœuds k3s
Itinérance multi-zonePlusieurs LAN, passerelle WireGuard, appareils mobiles qui se déplacent entre réseaux
Environnement professionnel / multi-environnementDev/staging/prod avec bastions par environnement et détection VPN
Mode shadowRemplacement transparent de SSH — git, rsync, scp, Ansible
Complétion shellComplétion dynamique d’alias pour bash, zsh, fish
Scripts et automatisationUtilisation de resolve et copy dans des scripts et pipelines CI

Formats de sortie

Toutes les commandes de liste supportent plusieurs formats de sortie :

sshroute list                  # table (défaut)
sshroute list -o json          # JSON — pour les scripts
sshroute list -o yaml          # YAML
sshroute network list -o json

Communauté

Obtenir le logiciel — téléchargez un binaire pré-compilé depuis Releases, installez avec go install github.com/thereisnotime/sshroute@latest, ou compilez depuis les sources.

Retours et signalements de bugs — ouvrez un ticket sur GitHub Issues. Utilisez le modèle de rapport de bug pour les comportements inattendus et le modèle de demande de fonctionnalité pour les idées.

Contribuer — voir CONTRIBUTING.md pour savoir comment configurer le projet, exécuter les tests et ouvrir une pull request. Les vulnérabilités de sécurité doivent être signalées de manière privée via GitHub Security Advisories.

Construction à partir des sources

Nécessite Go 1.22+ et just.

git clone [email protected]:thereisnotime/sshroute.git
cd sshroute

just build        # sortie dans bin/sshroute
just build-all    # cross-compile linux/darwin × amd64/arm64
just test         # exécute les tests avec détecteur de race
just install      # go install avec les ldflags de version injectés

Catégories