Skip to Content

Chapitre 4.5 — Transferts & tunnels

⏱️ TL;DR — SSH ne sert pas qu’à ouvrir un shell : il transporte des fichiers et des connexions. Pour copier : scp (simple, scp fichier user@host:/chemin, -r pour un dossier) et surtout rsync -avz (incrémental — il ne renvoie que ce qui a changé —, avec --progress et l’option --delete), l’outil de déploiement par excellence. sftp offre une session interactive de transfert. Côté connexions, les tunnels SSH font passer un port dans le tunnel chiffré : -L (port local → service distant, ex. atteindre une base Postgres distante sans l’exposer), -R (l’inverse : exposer un service local sur le serveur), -D (proxy SOCKS pour router du trafic). Cas d’école : ssh -L 5433:localhost:5432 host, puis tu te connectes à Postgres en local comme s’il était sur ta machine.

🎯 Objectifs

  • Copier des fichiers vers/depuis un serveur avec scp (et scp -r pour un dossier).
  • Synchroniser efficacement avec rsync -avz (incrémental, --progress, --delete) et comprendre pourquoi c’est l’outil de déploiement.
  • Ouvrir une session sftp interactive.
  • Comprendre et utiliser les tunnels : -L (local), -R (remote), -D (SOCKS).
  • Atteindre un service distant non exposé (ex. Postgres) via un tunnel -L, en sécurité.

Copier des fichiers : scp

scp (secure copy) copie des fichiers dans le tunnel chiffré de SSH. La syntaxe ressemble à cp, mais un côté peut être distant, noté user@host:/chemin.

# envoyer un fichier local VERS le serveur : scp build.tar.gz deploy@203.0.113.10:/var/www/formacampus/ # scp -> secure copy # build.tar.gz -> le fichier LOCAL a envoyer # deploy@203.0.113.10 -> destination : utilisateur@hote # :/var/www/... -> le chemin DISTANT ou deposer le fichier # recuperer un fichier DEPUIS le serveur (source distante, destination locale) : scp deploy@203.0.113.10:/var/log/nginx/error.log ./ # le "." final = le dossier local courant

Pour un dossier entier, ajoute -r (recursive) :

scp -r ./dist deploy@203.0.113.10:/var/www/formacampus/ # -r -> copie recursive : le dossier dist et tout son contenu

scp profite de ton ~/.ssh/config : si tu as un alias prod (chapitre 4.3), tu écris directement scp build.tar.gz prod:/var/www/. Pas besoin de répéter user, port et clé.

💡 Réflexescp est parfait pour un fichier ponctuel. Mais dès que tu copies un dossier que tu réenverras plus tard (un déploiement, un dump, un dossier d’assets), passe à rsync : scp recopie tout à chaque fois, rsync ne renvoie que ce qui a changé. Sur un gros dossier, c’est le jour et la nuit.

Synchroniser malin : rsync

rsync est l’outil de synchronisation incrémentale. Il compare source et destination, et ne transfère que les différences. Sur SSH, il chiffre tout comme scp, mais en bien plus efficace pour les mises à jour répétées.

rsync -avz --progress ./dist/ deploy@203.0.113.10:/var/www/formacampus/dist/ # -a -> mode archive : preserve permissions, dates, liens (copie fidele, recursive) # -v -> verbeux : liste ce qui est transfere # -z -> compresse pendant le transfert (gain sur le reseau) # --progress -> barre de progression par fichier

⚠️ Piège — Le slash final sur la source change tout. rsync ./dist/ dest/ copie le contenu de dist dans dest. rsync ./dist dest/ (sans slash) copie le dossier dist lui-même dans dest (tu obtiens dest/dist/…). En cas de doute, teste avec -n (ou --dry-run) : il simule sans rien écrire et te montre ce qui serait transféré.

L’option --delete : miroir exact

Par défaut, rsync ajoute et met à jour, mais ne supprime rien côté destination. Pour obtenir un miroir exact (ce qui n’existe plus à la source disparaît de la destination), ajoute --delete :

rsync -avz --delete ./dist/ deploy@203.0.113.10:/var/www/formacampus/dist/ # --delete -> supprime cote destination les fichiers absents de la source # resultat : la destination devient une COPIE EXACTE de la source

⚠️ Piège--delete est puissant et dangereux : si tu te trompes de dossier source (un dossier vide, un mauvais chemin), tu effaces la destination. Toujours un --dry-run d’abord pour vérifier la liste des suppressions. Un rsync --delete mal ciblé a déjà vidé des dossiers de prod entiers.

💡 Réflexersync est le cœur du déploiement par SSH. En CI/CD (Partie 13), on build l’app puis on rsync le résultat sur le serveur : seuls les fichiers modifiés partent, le déploiement est rapide et atomique. On réutilisera exactement cette commande, pilotée par GitHub Actions. Ce que tu apprends ici sert directement plus tard.

Une session interactive : sftp

sftp ouvre une session de transfert interactive, façon FTP mais chiffrée par SSH. Utile pour explorer l’arborescence distante et déposer/récupérer des fichiers à la main.

sftp deploy@203.0.113.10 # ouvre une invite sftp> ; commandes typiques : # ls / cd -> naviguer cote DISTANT # lls / lcd -> naviguer cote LOCAL (prefixe "l" = local) # put fichier -> envoyer un fichier local vers le serveur # get fichier -> recuperer un fichier distant # bye -> quitter

C’est pratique pour du ponctuel manuel ou quand un client graphique (type gestionnaire de fichiers SFTP) se connecte. Pour de l’automatisation, on préfère scp/rsync en une ligne.

Les tunnels SSH : faire passer un port dans le tunnel

Un tunnel SSH transporte une connexion réseau (un port) à l’intérieur de ta connexion SSH chiffrée. Ça permet d’atteindre un service comme s’il était local, sans l’exposer sur Internet. Trois formes.

-L : redirection de port locale (la plus utile)

-L ouvre un port sur TA machine qui, quand tu t’y connectes, ressort côté serveur vers une destination que lui peut joindre. La syntaxe : -L portLocal:destination:portDest.

ssh -L 5433:localhost:5432 deploy@203.0.113.10 # -L 5433:localhost:5432 : # 5433 -> un port ouvert sur TA machine (choisi libre, ici 5433) # localhost -> "localhost" vu DEPUIS LE SERVEUR (donc le serveur lui-meme) # 5432 -> le port Postgres sur le serveur # tant que ce ssh est ouvert, ta machine expose un port 5433 # qui debouche sur le Postgres distant, a travers le tunnel chiffre

Concrètement : avec ce tunnel ouvert, tu lances ton client Postgres en local sur localhost:5433, et tu parles à la base distante — sans que Postgres soit jamais ouvert sur Internet. La base écoute uniquement en local côté serveur (comme il se doit) ; le tunnel est le seul chemin, et il est chiffré et authentifié par SSH.

🔒 Sécurité — C’est le bon pattern pour administrer une base distante. Le mauvais réflexe serait d’ouvrir le port 5432 de Postgres sur Internet pour s’y connecter directement : ce serait exposer ta base aux scans et aux attaques du monde entier. Avec -L, la base reste fermée à l’extérieur (écoute locale seulement) et tu y accèdes via SSH — rien de nouveau n’est exposé, tout passe par ta clé et ton tunnel. On applique ce principe en Partie 11.

-R : redirection remote (l’inverse)

-R fait le trajet opposé : il ouvre un port sur le serveur qui ressort vers une destination joignable depuis ta machine. Ça sert à exposer temporairement un service local (ex. ton app en dev) à travers le serveur.

ssh -R 8080:localhost:3000 deploy@203.0.113.10 # ouvre un port 8080 SUR LE SERVEUR, qui ressort vers localhost:3000 de TA machine # quelqu'un qui atteint le serveur sur 8080 tape en fait ton app locale sur 3000

À manier avec prudence : tu exposes ta machine via le serveur. Utile pour un démo/webhook ponctuel, pas pour du permanent.

-D : proxy SOCKS dynamique

-D transforme ta connexion SSH en proxy SOCKS local : tout le trafic que tu routes vers ce proxy sort par le serveur.

ssh -D 1080 deploy@203.0.113.10 # ouvre un proxy SOCKS local sur le port 1080 # configure ton navigateur pour utiliser SOCKS localhost:1080 # -> ta navigation sort par l'IP du serveur, dans le tunnel chiffre

Pratique pour tester ce que voit ton serveur (une API géo-restreinte, un service filtré par IP) ou router du trafic de façon sûre depuis un réseau non fiable.

🐚 Au terminal — Astuce lisibilité : ajoute -N pour un tunnel « pur » (pas de shell distant, juste le port) et -f pour le passer en arrière-plan.

ssh -fN -L 5433:localhost:5432 prod # -N -> n'execute AUCUNE commande distante (tunnel seul, pas de shell) # -f -> passe en arriere-plan une fois le tunnel etabli # (utilise l'alias "prod" de ~/.ssh/config : user, port et cle sont deja connus)

📚 La doc — Les options de redirection (-L, -R, -D), leurs formes complètes (avec adresse de bind) et les réglages associés (GatewayPorts, AllowTcpForwarding) sont détaillés dans man ssh et man sshd_config. Le principe est simple, la syntaxe a des variantes : vérifie-la au manuel plutôt que de deviner.

🧭 Sur FormaCampus — Deux usages concrets chez FormaCampus. (1) Déploiement : le pipeline build le front Next.js, puis rsync -avz --delete pousse le résultat sur /var/www/formacampus/ du VPS — seuls les fichiers modifiés transitent, déploiement rapide et reproductible (la brique qu’on automatisera en CI/CD). (2) Admin base : pour inspecter la prod, un dev ouvre ssh -fN -L 5433:localhost:5432 prod et branche son client SQL sur localhost:5433. Il voit la vraie base Postgres — qui n’est jamais exposée sur Internet (écoute locale + pare-feu). Le tunnel, chiffré et authentifié par sa clé, est le seul chemin. Confort et sécurité, sans compromis.

En résumé

  • Copier : scp fichier user@host:/chemin (-r pour un dossier).
  • Synchroniser : rsync -avz --progress (incrémental), --delete pour un miroir (avec --dry-run d’abord). L’outil du déploiement.
  • Explorer/déposer à la main : sftp.
  • Tunnels : -L (atteindre un service distant non exposé), -R (exposer un service local), -D (proxy SOCKS). -fN pour un tunnel pur en arrière-plan.

✏️ Exercices

Exercice 1 — Choisis l’outil. Pour chaque cas, scp ou rsync ? (a) Envoyer une archive .tar.gz sur le serveur. (b) Redéployer dix fois par jour un dossier dist/ de 500 fichiers dont 3 changent à chaque fois.

✅ Solution

(a) scp : un fichier unique, ponctuel, scp build.tar.gz prod:/var/www/ suffit. (b) rsync : redéploiements répétés d’un dossier — rsync -avz ./dist/ prod:/var/www/formacampus/dist/ ne renvoie que les 3 fichiers modifiés à chaque fois, là où scp -r recopierait les 500 à chaque déploiement. rsync est l’outil du déploiement incrémental.

Exercice 2 — Atteindre la base sans l’exposer. La base Postgres de la prod écoute sur 5432 en local uniquement (non exposée). Tu veux la brancher sur ton client SQL local. Quelle commande ouvres-tu, et sur quel port local branches-tu ton client ?

✅ Solution

ssh -L 5433:localhost:5432 prod (ou ssh -fN -L 5433:localhost:5432 prod pour un tunnel en arrière-plan). Le localhost:5432 est vu depuis le serveur (donc son Postgres). Je branche ensuite mon client SQL sur localhost:5433 de ma machine : le trafic ressort côté serveur vers Postgres, à travers le tunnel chiffré. La base reste fermée à l’extérieur — je n’ai rien exposé.

Exercice 3 — Le --delete qui fait peur. Tu tapes rsync -avz --delete ./dist/ prod:/var/www/formacampus/dist/ mais tu n’es pas sûr du contenu de ./dist/. Comment vérifies-tu avant d’exécuter, et pourquoi est-ce important ici ?

✅ Solution

J’ajoute --dry-run (ou -n) : rsync -avz --delete --dry-run ./dist/ prod:/var/www/formacampus/dist/. Ça simule et liste ce qui serait transféré et supprimé, sans rien écrire. C’est crucial avec --delete : si ./dist/ était vide ou mauvais, rsync effacerait le dossier de prod côté destination. Le --dry-run me montre les suppressions avant qu’elles n’arrivent.

🧠 Quiz de révision

1. Quelle est la différence de fond entre scp et rsync ?

scp recopie tout à chaque fois ; rsync est incrémental : il compare source et destination et ne transfère que les différences. Pour un fichier ponctuel, scp suffit ; pour des dossiers redéployés régulièrement, rsync est bien plus rapide (et c’est l’outil du déploiement).

2. Que fait l’option --delete de rsync, et quelle précaution prendre ?

Elle supprime côté destination les fichiers absents de la source, pour obtenir un miroir exact. Précaution : toujours lancer un --dry-run (-n) d’abord, car une erreur de dossier source peut effacer la destination.

3. À quoi sert un tunnel -L, et donne l’exemple Postgres.

-L portLocal:destination:portDest ouvre un port local qui ressort côté serveur vers une destination qu’il peut joindre. Exemple : ssh -L 5433:localhost:5432 host — se connecter à localhost:5433 sur ta machine atteint le Postgres distant (port 5432, vu du serveur), sans exposer la base sur Internet.

4. Pourquoi un tunnel -L est-il plus sûr qu’ouvrir le port de la base sur Internet ?

Parce que la base reste fermée à l’extérieur (écoute locale + pare-feu) : rien de nouveau n’est exposé aux scans et attaques. L’accès passe uniquement par le tunnel SSH, chiffré et authentifié par ta clé. Ouvrir le port 5432 au monde exposerait la base à Internet entier.

5. Que font -R et -D, brièvement ?

-R (remote) fait l’inverse de -L : il ouvre un port sur le serveur qui ressort vers un service local à toi (exposer temporairement ton app locale via le serveur). -D crée un proxy SOCKS local : le trafic que tu y routes sort par le serveur, dans le tunnel chiffré.


Fin de la Partie 4. Ta porte d’entrée est maîtrisée et durcie. On enchaîne : Partie 5 — Provisionner & durcir le VPS — pare-feu (UFW), fail2ban et mises à jour automatiques, pour boucler la sécurisation d’un serveur qu’on met en ligne.

Last updated on