rsync hack per far rimbalzare i file tra due server non connessi


8

Ecco la connessione:

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

Server1 e server2 non sono autorizzati a parlare direttamente tra loro (non chiedere). Il mio desktop, tuttavia, è in grado di accedere a entrambi i server tramite ssh.

Devo copiare i file da server1 a server2.

Traidamentalmente ho usato un hack ssh + tar, come tale:

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

E funziona benissimo, ma vorrei fare un ulteriore passo avanti e far funzionare rsync tra i due server VIA il mio desktop.

Ora so che potrei avviare un tunnel port-forward ssh in un terminale e poi risincronizzare su quel tunnel in un'altra finestra, ma non voglio agitarmi con un secondo terminale o creare e rompere un tunnel di port forward separato. quello che voglio è:

  • Un comando di linea per sincronizzare i file da Server1 a Server2 VIA il mio desktop
  • tutto su UNA riga di comando, una finestra terminale
  • Voglio che il tunnel port forward esista solo per la durata del comando rsync.
  • Non voglio scp, voglio risincronizzare.

Qualcuno ha un trucco per farlo?

EDIT: ecco il comando funzionante! Ottimo lavoro a tutti: 1. Per il percorso chiave di rsa, non posso usare le tildae, ho dovuto usare "/ root /". 2. Ecco la riga di comando finale:

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 diventa la dinamite.


Questo è davvero eccellente L'unica cosa che deve essere modificata è disabilitare la verifica della chiave host. Hai la chiave SSH per l'autenticazione TTYless, ma poiché i server non hanno mai parlato tra loro non possono verificare le chiavi dell'host. Quindi è meglio disabilitarlo: -o StrictHostKeyChecking = no dopo i flag -p o -i.
Amala,

Risposte:


5

Se sei felice di conservare una copia dei dati sul computer intermedio, puoi semplicemente scrivere uno script che aggiorni la copia locale usando server1 come riferimento, quindi aggiorni il backup su server2 usando la copia locale come riferimento:

#!/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'uso di un semplice script significa che hai desiderato un singolo comando per fare tutto. Questo ovviamente potrebbe essere un no-no di sicurezza se i dati sono sensibili (tu, o altri nella tua azienda, potresti non volerne una copia fluttuante sul tuo laptop). Se server1 è locale per te, puoi semplicemente eliminare la copia locale in seguito (poiché la prossima volta sarà veloce ricostruire sulla LAN locale).

Costruire un tunnel in modo che i server possano dialogare efficacemente tra loro in modo più diretto dovrebbe essere possibile in questo modo:

  1. Sul server 2 fare una copia di / bin / sh come / usr / local / bin / shforkeepalive. Utilizzare un collegamento simbolico anziché una copia, quindi non è necessario aggiornarlo dopo gli aggiornamenti di sicurezza che patch / bin / sh.
  2. Sul server 2 crea uno script che non fa altro che dormire in loop per alcuni secondi, poi riecheggia una piccola quantità di testo e usa questo comando "copia" di sh:

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

    ( echoprobabilmente non è necessario, poiché la sessione non sarà inattiva per il tempo necessario per il timeout anche se SSHd è configurato per ignorare i pacchetti keep-alive dal client ssh)

  3. Ora puoi scrivere uno script sul tuo laptop che avvia il tunnel inverso in background, dice a server1 di usare rsync per eseguire l'operazione di copia, quindi uccide il tunnel inverso uccidendo lo script di loop (che chiuderà la sessione 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 user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'
    ssh user@server2 killall shforkeepalive
    

Il modo in cui funziona:

  • Riga 1: marcatore "comando da utilizzare per interpretare questo script" standard
  • Linea 2: avvia una connessione SSH con tunnel inverso ed esegui lo script keepalive tramite esso per tenerlo aperto. Il trailing & dice a bash di eseguire questo in background in modo che le righe successive possano essere eseguite senza aspettare che finisca
  • Linea 3: avvia un tunnel che si collegherà al tunnel sopra in modo che server1 possa vedere server2 ed esegui rsync per eseguire la copia / aggiornamento su questa disposizione
  • Riga 4: uccidi lo script keep-alive una volta completata l'operazione rsync (e così ritorna la seconda chiamata SSH), che sarà e la prima sessione ssh.

Questo non sembra particolarmente pulito, ma dovrebbe funzionare. Non ho testato quanto sopra, quindi potrebbe essere necessario modificarlo. Rendere il comando rsync uno script a riga singola su server1 può aiutare riducendo l'eventuale necessità di sfuggire a caratteri come il 'sul comando ssh chiamante.

A proposito: dici "non chiedere" perché i due server non possono vedersi direttamente, ma spesso c'è una buona ragione per questo. Il mio server di casa e il server su cui sono conservati i backup online non possono accedere l'uno all'altro (e hanno password + chiavi diverse per tutti gli utenti) - ciò significa che se uno dei due viene violato non può essere utilizzato come percorso facile per hackerare l'altro in modo che i miei backup online siano più sicuri (qualcuno che elimina dal vivo i miei dati non può usare la sua capacità di aggiornare i backup per eliminare tali backup, poiché non ha la possibilità diretta di toccare il sito di backup principale). Entrambi i server possono entrambi connettersi a un server intermedio altrove: il server live è impostato per inviare i suoi backup (tramite rsync) alla macchina intermedia al mattino presto e il server di backup è impostato (un po 'più tardi per consentire il completamento del passaggio 1) per connettersi e raccogliere gli aggiornamenti (di nuovo tramite rsyc seguito da un passaggio di snapshot per mantenere più età del backup). Questa tecnica può essere utilizzabile anche nelle tue circostanze, e in tal caso la consiglierei come un modo molto più pulito di fare le cose.

Modifica: Unendo il mio hack con Aaron per evitare tutto il caos con copie di / bin / sh e uno script keep-alive separato su server2, questo script sul tuo laptop dovrebbe fare tutto il lavoro:

#!/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 user@127.0.0.1:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

Come sopra, rsync si sta connettendo a localhost: 2222 che inoltra giù nel tunnel all'host locale del tuo laptop: 2222 che inoltra attraverso l'altro tunnel all'host locale di server2: 22.

Modifica 2: se non ti dispiace che server1 abbia una chiave che gli consente di autenticarsi direttamente con server2 (anche se non riesce a vedere server2 senza un tunnel) puoi semplificare ulteriormente con:

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

dove 123.123.123.123 è un indirizzo pubblico per server2, che può essere utilizzato come copia + incolla un solo liner anziché uno script.


È una grande quantità di dati (20 + gb) e preferisco trasmetterli in entrata e in uscita contemporaneamente anziché archiviarli localmente. Desidero trasmettere i dati attraverso il mio PC senza che nulla venga archiviato. hai ragione sul "non chiedere", è per una buona ragione, anche se una pita.
regolamento,

Plesae vede nuove modifiche sulla domanda originale
regolamento

Penso che la mia ultima modifica (pubblicata pochi secondi prima del tuo commento in base ai timestamp, quindi probabilmente stavamo digitando allo stesso tempo) potrebbe darti la linea che stai cercando.
David Spillett,

EVVIVA !!! Funziona! 1. per la chiave rsa, non posso usare tildae, ho dovuto usare "/ root /". 2. ecco la riga di comando finale: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

Ciao @ David, grazie per questo fantastico hack. Tuttavia, per farlo funzionare, ho bisogno della chiave del server 2 sul server 1 utilizzando entrambe le soluzioni (nella prima e nella seconda modifica). Penso che sia normale (port forwarding o meno, server1 sta ancora cercando di autenticarsi su server2), ma tu scrivi If you don't mind server1 having a key .... Potete dirmi se è davvero possibile evitare di avere la chiave di server2 su server1 per favore?
ssssteffff,

2

Ecco alcuni metodi che rendono la sincronizzazione un semplice one-liner, ma richiedono un po 'di lavoro di installazione.

  • Installa un tunnel SSH inverso dal server1 al desktop (mi dispiace, non posso dirti l' .ssh/configincantesimo dalla cima della mia testa). Incatenalo con una connessione dal desktop al server2. Esegui rsync dal server1.

  • Configurare un proxy socks (o un proxy http che accetta CONNECT) sul desktop. Usalo per stabilire una connessione ssh da server1 a server2. Esegui rsync da server2.

  • Usa unisono invece di rsync. Ma il flusso di lavoro è diverso.

  • Montare le directory da uno o entrambi i server sul desktop usando sshfs .


1

Perché una riga? Usa uno script di shell piccolo:

#!/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, è possibile impostare un tempo di sonno inferiore; il primo sshnon terminerà finché qualcuno utilizzerà il canale.


Sono abbastanza sicuro che rsync non possa funzionare tra due server remoti su SSH in quel modo (solo local-> remote o remote-> local) - sebbene il tuo uso di sleepe trapsia più pulito del metodo "keep alive and kill" nella mia risposta .
David Spillett,

si prega di consultare le modifiche alla domanda originale.
regolamento,

Accidenti, hai ragione. Non è consentito specificare due host come argomenti sul comando ling. ... hmmm ..
Aaron Digulla,

Ok, ho migliorato la mia soluzione. È necessario creare due port forwarding per rendere visibile il servizio ssh di server2 su server1.
Aaron Digulla,

Aggiungi un paio di ";" per trasformarlo in una fodera. L'idea è più facile da capire con una sceneggiatura.
Aaron Digulla,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.