rsync pirater pour renvoyer des fichiers entre deux serveurs non connectés

8

Voici la connexion:

[Server1] <---> [my desktop] <---> [Server2]

Server1 et server2 ne sont pas autorisés à parler directement entre eux (ne demandez pas). Mon bureau est cependant capable d'accéder aux deux serveurs via ssh.

J'ai besoin de copier des fichiers de server1 vers server2.

Traditionnellement, j'utilise un hack ssh + tar, en tant que tel:

ssh -q root@Server1 'tar -vzc /path/to/files ' | ssh -q root@Server2 'tar -vzx -C /'

Et cela fonctionne très bien, mais je voudrais aller plus loin et faire fonctionner rsync entre les deux serveurs via mon bureau.

Maintenant, je sais que je pourrais démarrer un tunnel de transfert de port ssh dans un terminal, puis rsync sur ce tunnel dans une autre fenêtre, mais je ne veux pas discuter avec un deuxième terminal ou créer et casser un tunnel de transfert de port séparé. ce que je veux c'est:

  • Une commande liner pour rsync des fichiers de Server1 à server2 VIA mon bureau
  • le tout sur UNE seule ligne de commande, une seule fenêtre de terminal
  • Je souhaite que le tunnel de transfert de port n'existe que pour la durée de vie de la commande rsync.
  • Je ne veux pas scp, je veux rsync.

Quelqu'un at-il une astuce pour le faire?

EDIT: Voici la commande de travail! Excellent travail tout le monde: 1. Pour le chemin de clé rsa, ne peut pas utiliser de tildae, a dû utiliser "/ root /". 2. Voici la dernière ligne de commande:

ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"

Boom va la dynamite.

regulatre
la source
C'est vraiment excellent. La seule chose qui doit être modifiée est de désactiver la vérification de la clé d'hôte. Vous disposez de la clé SSH pour l'authentification TTYless, mais comme les serveurs ne se sont jamais parlé, ils ne peuvent pas vérifier les clés d'hôte. Il vaut donc mieux le désactiver: -o StrictHostKeyChecking = no après les drapeaux -p ou -i.
Amala

Réponses:

5

Si vous êtes heureux de conserver une copie des données sur la machine intermédiaire, vous pouvez simplement écrire un script qui a mis à jour la copie locale en utilisant le serveur1 comme référence, puis a mis à jour la sauvegarde sur le serveur2 en utilisant la copie locale comme référence:

#!/bin/sh
rsync user@server1:/path/to/stuff /path/to/loca/copy -a --delete --compress
rsync /path/to/loca/copy user@server2:/path/to/where/stuff/should/go -a --delete --compress

L'utilisation d'un script simple signifie que vous avez souhaité une seule commande pour tout faire. Bien sûr, cela pourrait être un non-non de sécurité si les données sont sensibles (vous ou d'autres personnes de votre entreprise, ne voudrez peut-être pas qu'une copie flotte sur votre ordinateur portable). Si server1 est local pour vous, vous pouvez simplement supprimer la copie locale par la suite (car il sera rapide de reconstruire sur le LAN local la prochaine fois).

Construire un tunnel pour que les serveurs puissent communiquer efficacement entre eux plus directement devrait être possible comme ceci:

  1. Sur le serveur 2, faites une copie de / bin / sh sous / usr / local / bin / shforkeepalive. Utilisez un lien symbolique plutôt qu'une copie, alors vous n'avez pas à le mettre à jour après les mises à jour de sécurité qui corrigent / bin / sh.
  2. Sur le serveur 2, créez un script qui ne fait rien d'autre que de dormir en boucle pendant quelques secondes puis de faire écho à une petite quantité de texte, et utilisez-le maintenant la "copie" de sh:

    #!/usr/local/bin/shforkeepalive
    while [ "1" != "0" ]; do
            echo Beep!
            sleep 5
    done
    

    (le echon'est probablement pas nécessaire, car la session ne restera pas inactive assez longtemps pour expirer même si SSHd est configuré pour ignorer les paquets persistants du client ssh)

  3. Vous pouvez maintenant écrire un script sur votre ordinateur portable qui démarre votre tunnel inverse en arrière-plan, indique à server1 d'utiliser rsync pour effectuer l'opération de copie, puis tue le tunnel inverse en tuant le script de bouclage (qui fermera la session SSH):

    #!/bin/sh
    ssh user@server2 -L2222:127.0.0.1:22 /usr/local/bin/keepalivesctipt &
    ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff [email protected]:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'
    ssh user@server2 killall shforkeepalive
    

La façon dont cela fonctionne:

  • Ligne 1: marqueur "commande à utiliser pour interpréter ce script" standard
  • Ligne 2: démarrez une connexion SSH avec tunnel inverse et exécutez le script keepalive via celui-ci pour le garder ouvert. Le signe de fin et indique à bash de l'exécuter en arrière-plan afin que les lignes suivantes puissent s'exécuter sans attendre la fin
  • Ligne 3: démarrez un tunnel qui se connectera au tunnel ci-dessus afin que server1 puisse voir server2 et exécutez rsync pour effectuer la copie / mise à jour sur cet arrangement
  • Ligne 4: tuez le script keep-alive une fois l'opération rsync terminée (et donc le deuxième appel SSH revient), qui le fera et la première session ssh.

Cela ne semble pas particulièrement propre, mais cela devrait fonctionner. Je n'ai pas testé ce qui précède, vous devrez peut-être le modifier. Faire de la commande rsync un script sur une seule ligne sur server1 peut aider en réduisant le besoin d'échapper des caractères comme le 'sur la commande ssh appelante.

BTW: vous dites "ne demandez pas" pourquoi les deux serveurs ne peuvent pas se voir directement, mais il y a souvent une bonne raison à cela. Mon serveur domestique et le serveur sur lequel ses sauvegardes en ligne sont conservées ne peuvent pas se connecter les uns aux autres (et ont des mots de passe + clés différents pour tous les utilisateurs) - cela signifie que si l'un des deux est piraté, il ne peut pas être utilisé comme un chemin facile pour pirater l'autre pour que mes sauvegardes en ligne soient plus sûres (quelqu'un malveillant supprimant mes données en direct ne peut pas utiliser sa capacité à mettre à jour les sauvegardes pour supprimer lesdites sauvegardes, car il n'a pas la capacité directe de toucher le site de sauvegarde principal). Les deux serveurs peuvent tous deux se connecter à un serveur intermédiaire ailleurs - le serveur en direct est configuré pour envoyer ses sauvegardes (via rsync) à la machine intermédiaire tôt le matin et le serveur de sauvegarde est défini (un peu plus tard pour permettre à la première étape de se terminer) de se connecter et collecter les mises à jour (à nouveau via rsyc suivi d'une étape d'instantané afin de maintenir plusieurs âges de sauvegarde). Cette technique peut également être utilisable dans votre cas, et si c'est le cas, je la recommanderais comme une façon beaucoup plus propre de faire les choses.

Edit: Fusionner mon hack avec Aaron pour éviter tout le bourdonnement avec des copies de / bin / sh et un script persistant séparé sur server2, ce script sur votre ordinateur portable devrait faire tout le travail:

#!/bin/sh
ssh user@server2 -L2222:127.0.0.1:22 sleep 60 &
pid=$!
trap "kill $pid" EXIT 
ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff [email protected]:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

Comme avec ce qui précède, rsync se connecte à localhost: 2222 qui transmet le tunnel vers l'hôte local de votre ordinateur portable: 2222 qui transmet à travers l'autre tunnel à l'hôte local de server2: 22.

Edit 2: Si cela ne vous dérange pas que server1 ait une clé qui lui permet de s'authentifier directement avec server2 (même s'il ne peut pas voir server2 sans tunnel), vous pouvez simplifier davantage avec:

#!/bin/sh
ssh user@server1 -R2222:123.123.123:22 rsync /path/to/stuff [email protected]:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

où 123.123.123.123 est une adresse publique pour server2, qui pourrait être utilisée comme un + liner one-liner au lieu d'un script.

David Spillett
la source
C'est une grande quantité de données (20 + Go) et je préfère les diffuser en entrée et en sortie en même temps plutôt que de les stocker localement. Je souhaite diffuser les données via mon PC sans rien stocker. vous avez raison sur le "ne demandez pas", c'est pour une bonne raison, bien qu'un pita.
regulatre
Plesae voir de nouvelles modifications sur la question d'origine
regulatre
Je pense que mon dernier montage (publié quelques secondes avant votre commentaire en fonction des horodatages, donc nous étions probablement en train de taper en même temps) peut vous donner le one-liner que vous recherchez.
David Spillett
HOORAY !!! Ça marche! 1. pour la clé rsa, ne peut pas utiliser de tildae, a dû utiliser "/ root /". 2. voici la dernière ligne de commande:ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"
regulatre
Salut @David, merci pour ce super hack. Cependant, pour le faire fonctionner, j'ai besoin de la clé du serveur 2 sur le serveur 1 en utilisant les deux solutions (lors des première et deuxième modifications). Je pense que c'est normal (redirection de port ou non, server1 essaie toujours de s'authentifier sur server2), mais vous écrivez If you don't mind server1 having a key .... Pouvez-vous me dire s'il est vraiment possible d'éviter d'avoir la clé de server2 sur server1 s'il vous plaît?
ssssteffff
2

Voici quelques méthodes qui rendent la synchronisation simple, mais nécessitent un certain travail de configuration.

  • Mettre en place un tunnel ssh inverse de server1 à votre bureau (désolé, je ne peux pas vous dire l' .ssh/configincantation du haut de ma tête). Enchaînez-le avec une connexion de votre bureau au serveur2. Exécutez rsync à partir de server1.

  • Configurez un proxy de chaussettes (ou un proxy http qui accepte CONNECT) sur votre bureau. Utilisez-le pour établir une connexion ssh de serveur1 à serveur2. Exécutez rsync à partir de server2.

  • Utilisez unisson au lieu de rsync. Mais le flux de travail est différent.

  • Montez les répertoires à partir d'un ou des deux serveurs de votre bureau à l'aide de sshfs .

Gilles 'SO- arrête d'être méchant'
la source
1

Pourquoi une ligne? Utilisez un petit script shell:

#!/bin/bash
# Run me on server1

# Create the port forward server1 -> desktop -> server2 (i.e.
# the first forward creates a second tunnel running on the desktop)
ssh -L/-R ... desktop "ssh -L/-R ... server2 sleep 1h" &    
pid=$!

# Kill port forward process on exit and any error
trap "kill $pid" EXIT 

rsync -e ssh /path/to/files/ root@localhost:/path/to/files/on/server2

IIRC, vous pouvez régler le temps de sommeil plus bas; le premier sshne prendra pas fin tant que quelqu'un utilisera le canal.

Aaron Digulla
la source
Je suis à peu près sûr que rsync ne peut pas fonctionner entre deux serveurs distants sur SSH de cette façon (uniquement local-> distant ou distant-> local) - bien que votre utilisation de sleepet trapsoit plus nette que la méthode "garder en vie et tuer" dans ma réponse .
David Spillett
veuillez consulter les modifications apportées à la question d'origine.
regulatre
Merde, tu as raison. Il n'est pas autorisé de spécifier deux hôtes comme arguments dans la commande ling. ... hmmm ..
Aaron Digulla
D'accord, j'ai amélioré ma solution. Vous devez créer deux ports vers l'avant pour rendre le service ssh de server2 visible sur server1.
Aaron Digulla
Ajoutez quelques ";" pour en faire une doublure. L'idée est plus facile à comprendre avec un script.
Aaron Digulla