SSH: Fornisce ulteriori "pipe" fds oltre a stdin, stdout, stderr


12

Quando si collega ad un host con SSH, di solito tre "tubi" sono previsti tra host e guest, per stdin, stdoute stderr.

Esiste un'opzione da riga di comando per creare forward per descrittori di file aggiuntivi ( 3e successivi)?

Ad esempio, mi piacerebbe fare

ssh --forwardfd=10:3 remotehost 'echo test >&3'

che stamperebbe 'test' sul descrittore di file aperto localmente 10.


2
Probabilmente non senza complicate modifiche alla fonte, date le varie closefrom(STDERR_FILENO + 1)chiamate sotto il codice sorgente OpenSSH. Cosa stai cercando di fare questo richiede questo?
thrig

Il protocollo supporta il tunneling di flussi aggiuntivi oltre a stdin/ out/ err, ma AFAIK, nessun server / client fornisce supporto in alcun modo tale funzionalità.
salva il

@thrig Non OP, ed è passato molto tempo, ma nel caso in cui sei ancora curioso di sapere cosa potrebbe essere utile, quello che speravo di trovare qui era un indizio su come reindirizzare ssh, una sceneggiatura per bash e il stdin per quella sceneggiatura. Qualcosa di simile a:infinite-output-cmd | ssh user@host bash /proc/self/fd/3 3< local-script-to-execute-remotely.sh
JoL

@thrig Mi viene in mente che qualcosa di simile --forwardfdnon dovrebbe nemmeno essere necessario. sshpotrebbe verificare quali sono i descrittori di file aperti prima di aprire qualsiasi altra cosa e inoltrarli automaticamente agli stessi descrittori di file sul lato remoto. Potrebbe essere totalmente trasparente come il mio esempio. Mi chiedo quanto sarebbe difficile rimediare ssh. Come hai detto, potrebbe essere complicato a seconda delle ragioni che stanno dietro closefrom(STDERR_FILENO + 1).
JoL

Risposte:


6

Puoi farlo usando l'inoltro socket, che è disponibile da openssh-6.7. Questa è una specie di pipa. Questa tecnica è descritta ad esempio qui: http://www.25thandclement.com/~william/projects/streamlocal.html

Otterrai un percorso bidirezionale per i tuoi dati. C'è un esempio con mysql:

Connessioni client proxy MySQL su un server remoto all'istanza locale:

ssh -R/var/run/mysql.sock:/var/run/mysql.sock \
    -R127.0.0.1:3306:/var/run/mysql.sock somehost 

1

Sono sicuro che dovrebbe essere possibile. Posso solo suggerire un hack in cui usi connessioni extra ssh per ognuna porta un'altra coppia di descrittori di file. Ad esempio, il seguente script di proof of concept fa un primo ssh per eseguire un comando fittizio (sleep) per connettere fds locali 5 e 6 a stdin e stdout remoti, presumendo che questi fds siano quelli che vuoi aggiungere al solito 0,1, 2.

Quindi il vero ssh è fatto, e sul telecomando collega i telecomandi 5 e 6 remoti allo stdin e allo stdout dell'altro ssh.

Proprio come un esempio, questo script passa una pagina man con zip al telecomando, che decomprime e la esegue attraverso man. Lo stdin e lo stdout del vero ssh sono ancora disponibili per altre cose.

#!/bin/bash
exec 5</usr/share/man/man1/ssh.1.gz 6>/tmp/out6 # pretend need 5 and 6

ssh remote 'echo $$ >/tmp/pid; exec sleep 99999' <&5 >&6 &
sleep 1 # hack. need /tmp/pid to be set

ssh remote '
  pid=$(</tmp/pid) 
  exec 5</proc/$pid/fd/0 6>/proc/$pid/fd/1
  echo start
  gzip -d <&5 | man /dev/stdin >&6
  echo stop
  kill -hup $pid
'
wait
less /tmp/out6

1

Il problema con la risposta di @jakuje è: funziona solo con i socket , ma non è possibile utilizzare strumenti UNIX standard che prevedono file con loro:

ssh -R/tmp/sock.remote:/tmp/sock.local "$HOST" 'LANG=C cat >/tmp/sock.remote'

bash: /tmp/sock.remote: nessun dispositivo o indirizzo

Inoltre c'è il problema che il file socket locale non viene cancellato sull'host remoto; alla successiva esecuzione dello stesso comando, viene visualizzato un avviso e il socket non viene ricreato correttamente. Puoi dare la possibilità -o StreamLocalBindUnlink=yesdi sshscollegare quel vecchio socket, ma nei miei test non era abbastanza; devi anche modificarti sshd_configper contenere StreamLocalBindUnlink=yesaffinché quell'opzione funzioni.

Ma puoi usare socato netcatqualsiasi altro strumento simile che supporti i socket locali UNIX ( NONnetcat-traditional è abbastanza!) Per utilizzare l'inoltro socket locale per il trasferimento di file:

# start local process listening on local socket, which receives the data when ssh opens the connections and saves it to a local file
nc -l -N -U /tmp/sock.local >/tmp/file.local &
# connect to remote $HOST and pipe the remote file into the remote socket end
ssh \
 -o ExitOnForwardFailure=yes \
 -o StreamLocalBindUnlink=yes \
 -R /tmp/sock.remote:/tmp/sock.local \
 "$HOST" \
 'nc -N -U /tmp/sock.remote </tmp/file.remote'

È inoltre possibile eseguire comandi interattivi, nel qual caso è necessario utilizzare ssh -tper allocare TTY.

Il problema con questa soluzione è che è necessario codificare i percorsi dei socket locali UNIX: a livello locale questo non è un problema tanto è possibile includerlo $$nel percorso per renderlo univoco per processo o utente una directory temporanea, ma sul è meglio che tu non usi la directory scrivibile dal mondo /tmp/come nel mio esempio. La directory deve anche esistere già all'avvio della sshsessione. E l'inode del socket rimarrà anche dopo la chiusura della sessione, quindi usare qualcosa come "$ HOME / .ssh. $$" ingombrerà la tua directory con inode morti nel tempo.

Potresti anche usare i socket TCP associati localhost, che ti eviteranno di ingombrare i tuoi file system con inode morti, ma anche con loro devi ancora avere problemi a scegliere un numero di porta (univoco) inutilizzato. Quindi non è ancora l'ideale. ( sshha un codice per allocare dinamicamente le porte, ma non ho trovato alcun modo per recuperare quelle informazioni sull'host remoto.)

Probabilmente la soluzione più semplice per copiare i file è utilizzare la funzionalità di condivisione della connessione integrata di ssh ed eseguire un comando scpo sfrpmentre la sessione interattiva è ancora in esecuzione in parallelo. Vedere Copia di un file sul sistema locale con ssh .

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.