infra / linux-bash
SSH avancé (clés, agent, tunneling, config)
Explication
Un mot de passe peut être deviné, volé par phishing, ou intercepté sur le réseau. Une paire de clés SSH fonctionne complètement différemment : une clé privée, gardée secrète sur ta machine, et une clé publique, déposée sur les serveurs auxquels tu te connectes, grâce à un principe de cryptographie asymétrique qui vérifie ton identité sans jamais exposer ta clé privée.
Ce que vous allez apprendre
- Générer une paire de clés SSH moderne (ed25519) et la déployer sur un serveur distant
- Utiliser l'agent SSH pour éviter de retaper une passphrase à chaque connexion
- Centraliser la configuration de plusieurs serveurs dans
~/.ssh/configavec des alias - Rebondir automatiquement via un bastion grâce à
ProxyJump - Créer un tunnel SSH pour accéder à un service interne sans ouvrir de port public
Dans quel contexte ?
Un ingénieur DevOps gère une infrastructure avec un bastion public et plusieurs serveurs internes non exposés à Internet, dont une base de données PostgreSQL. Pour se connecter à db-interne depuis son poste, il doit d'abord passer par bastion.exemple.com, puis rebondir vers l'intérieur — un enchaînement manuel fastidieux que ~/.ssh/config avec ProxyJump transforme en une simple commande ssh interne.
Une fois la clé en place, un petit désagrément apparaît
Une clé privée protégée par une phrase de passe demande de la retaper à chaque connexion, ce qui devient vite fatigant. C'est exactement le problème que résout l'agent SSH : il déverrouille la clé une seule fois en mémoire pour toute la session, puis la réutilise automatiquement ensuite.
Bonne pratique
Génère toujours une clé en ed25519 plutôt qu'en RSA pour un nouveau serveur (ssh-keygen -t ed25519) : elle est plus courte, plus rapide à vérifier, et considérée au moins aussi sûre que RSA 4096 bits par les standards actuels. Ne réserve RSA qu'aux cibles anciennes qui ne supportent pas encore ed25519.
Maintenant, un autre confort : arrêter de retaper des lignes à rallonge
Retaper l'adresse, le port, la clé et l'utilisateur à chaque connexion devient vite pénible dès qu'on gère plusieurs serveurs. Le fichier ~/.ssh/config règle ce problème en permettant de définir des alias mémorisables comme "prod" ou "bastion", avec toute leur configuration associée.
Sans ~/.ssh/config | Avec ~/.ssh/config |
|---|---|
ssh -p 2222 -i ~/.ssh/cle_prod deploy@203.0.113.10 | ssh prod |
| Rebond manuel en deux commandes SSH | ssh interne (ProxyJump automatique) |
C'est aussi ce fichier qui permet le rebond automatique via un bastion, grâce à ProxyJump. C'est une pratique très courante en entreprise, pour ne jamais exposer directement des serveurs internes à Internet.
Pour aller plus loin : le tunneling
Un tunnel SSH réutilise une connexion déjà établie et sécurisée pour faire transiter d'autres flux réseau, par exemple accéder à une base de données interne ou exposer un service local. Le vrai avantage, c'est qu'aucun nouveau port public n'a besoin d'être ouvert, donc aucune nouvelle surface d'attaque n'est créée.
Piège fréquent
Désactiver PasswordAuthentication dans /etc/ssh/sshd_config avant d'avoir vérifié que ta clé publique est bien installée et fonctionnelle peut te bloquer complètement hors du serveur. Teste toujours une nouvelle connexion par clé dans un second terminal AVANT de fermer la session actuelle et de redémarrer sshd.
Maintenant que tu maîtrises les connexions distantes, la suite logique est d'automatiser des tâches sur ces mêmes serveurs grâce à cron.
Commandes & code
SSH avancé
# Génération d'une paire de clés (ed25519 recommandé, plus court et plus sûr que RSA)
ssh-keygen -t ed25519 -C "ned@technologik.dev"
ssh-keygen -t rsa -b 4096 -C "ned@technologik.dev" # si ed25519 non supporté par la cible
# Déployer sa clé publique sur un serveur distant
ssh-copy-id ned@serveur.exemple.com
# Équivalent manuel :
cat ~/.ssh/id_ed25519.pub | ssh ned@serveur.exemple.com "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
# Connexion
ssh ned@serveur.exemple.com
ssh -p 2222 ned@serveur.exemple.com # port custom
ssh -i ~/.ssh/cle_projet ned@serveur.exemple.com # clé spécifique
# ssh-agent : évite de retaper la passphrase à chaque connexion
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add -l # liste les clés chargées dans l'agent
# ~/.ssh/config : centralise tous tes hosts (LE fichier à connaître en pro)
cat <<'EOF' >> ~/.ssh/config
Host prod
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/cle_prod
ForwardAgent yes
Host bastion
HostName bastion.exemple.com
User ned
Host interne
HostName 10.0.5.20
User ned
ProxyJump bastion
EOF
ssh prod # se connecte en utilisant tous les paramètres définis ci-dessus
ssh interne # rebondit automatiquement via le bastion (ProxyJump)
# Exécuter une commande distante sans ouvrir de session interactive
ssh prod "systemctl status nginx"
ssh prod "df -h" > rapport_disque.txt
# Copie de fichiers
scp fichier.txt prod:/home/deploy/
scp -r dossier/ prod:/home/deploy/backup/
rsync -avz --progress dossier/ prod:/home/deploy/app/ # rsync : plus rapide, reprend les transferts
# Tunneling SSH
ssh -L 8080:localhost:80 prod # tunnel local : localhost:8080 -> port 80 sur "prod"
ssh -R 9000:localhost:3000 prod # tunnel distant : expose un service local vers "prod"
ssh -D 1080 prod # proxy SOCKS5 dynamique via "prod"
ssh -N -f -L 5432:db-interne:5432 bastion # tunnel vers une base derrière un bastion, en fond (-f -N)
# Durcissement côté serveur : /etc/ssh/sshd_config
# PermitRootLogin no
# PasswordAuthentication no <- force l'authentification par clé uniquement
# AllowUsers deploy ned
# Port 2222
sudo systemctl restart sshdRésumé
~/.ssh/configremplace des lignes de commande à rallonge (Host,ProxyJump,IdentityFile).- Les tunnels (
-L/-R/-D) exposent des services sans ouvrir de port public. - En production : clés uniquement (
PasswordAuthentication no),PermitRootLogin no.
Exercices pratiques
Mission : atteindre une base interne via un bastion sans exposer de port
Objectif : Configurer un accès SSH via ProxyJump et un tunnel, puis identifier le risque d'un durcissement sshd mal séquencé.
Contexte
Ton infrastructure a un bastion public bastion.exemple.com et un serveur interne db-interne (IP 10.0.5.20) non exposé à Internet. Tu dois pouvoir t'y connecter simplement, puis accéder à sa base PostgreSQL depuis ton poste local sans jamais ouvrir de port public.