Un tunnel SSH attraverso più luppoli

I dati di tunneling su SSH sono abbastanza diretti:

ssh -D9999 [email protected] 

imposta la port 9999 sul tuo localhost come tunnel a example.com , ma ho una necessità più specifica:

  • Sto lavorando localmente su localhost
  • host1 è accessibile a localhost
  • host2 accetta solo le connessioni da host1
  • Ho bisogno di creare un tunnel da localhost a host2

In effetti, voglio creare un tunnel SSH "multi-hop". Come posso fare questo? Idealmente, vorrei farlo senza bisogno di superusare su nessuna delle macchine.

In pratica hai tre possibilità:

  1. Tunnel da localhost a host1 :

     ssh -L 9999:host2:1234 -N host1 

    Come sopra osservato, la connessione da host1 a host2 non sarà protetta.

  2. Tunnel da localhost a host1 e da host1 a host2 :

     ssh -L 9999:localhost:9999 host1 ssh -L 9999:localhost:1234 -N host2 

    Questo aprirà un tunnel da localhost a host1 e un altro tunnel da host1 a host2 . Tuttavia la port 9999 a host2:1234 può essere utilizzata da chiunque sul host1 . Questo può o non può essere un problema.

  3. Tunnel da localhost a host1 e da localhost a host2 :

     ssh -L 9998:host2:22 -N host1 ssh -L 9999:localhost:1234 -N -p 9998 localhost 

    Questo aprirà un tunnel da localhost a host1 attraverso il quale è ansible utilizzare il servizio SSH su host2 . Poi un secondo tunnel viene aperto da localhost a host2 attraverso il primo tunnel.

Normalmente, vorrei andare con l'opzione 1. Se la connessione da host1 a host2 deve essere protetta, andare con l'opzione 2. L'opzione 3 è principalmente utile per accedere a un servizio in host2 che è raggiungibile solo da host2 .

Esiste una risposta eccellente che spiega l'uso della direttiva di configuration di ProxyCommand per SSH :

Aggiungi questo al tuo ~/.ssh/config (vedere l' man 5 ssh_config per i dettagli):

 Host host2 ProxyCommand ssh host1 -W %h:%p 

Poi ssh host2 tunnel automaticamente attraverso host1 (funziona anche con l'inoltro X11 ecc.).

Questo funziona anche per un'intera class di host, ad esempio identificata dal dominio:

 Host *.mycompany.com ProxyCommand ssh gateway.mycompany.com -W %h:%p 

Aggiornare

OpenSSH 7.3 introduce una direttiva ProxyJump , semplificando il primo esempio a

 Host host2 ProxyJump host1 

Abbiamo un gateway ssh nella nostra networking privata. Se sono al di fuori e desidero una shell remota su una macchina all'interno della networking privata, dovrei ssh nel gateway e da lì alla macchina privata.

Per automatizzare questa procedura, utilizzi il seguente script:

 #!/bin/bash ssh -f -L some_port:private_machine:22 [email protected] "sleep 10" && ssh -p some_port [email protected] 

Che cosa sta succedendo:

  1. Stabilire un tunnel per il protocollo ssh (port 22) alla macchina privata.
  2. Solo se questo è successo, ssh nella macchina privata usando il tunnel. (l'operatore && assicura questo).
  3. Dopo aver chiuso la session privata ssh, voglio anche chiudere il tunnel ssh. Questo è fatto tramite il trucco "sonno 10". Di solito, il primo command ssh si chiuderà dopo 10 secondi, ma durante questo tempo il secondo command ssh avrà stabilito una connessione utilizzando il tunnel. Di conseguenza, il primo command ssh mantiene aperto il tunnel fino a quando le due condizioni seguenti sono soddisfatte: il sonno 10 è terminato e il tunnel non è più utilizzato.

Dopo aver letto le cose sopra e incollando tutto insieme, ho creato il seguente script Perl (salvo come mssh in / usr / bin e renderlo eseguibile):

 #!/usr/bin/perl $iport = 13021; $first = 1; foreach (@ARGV) { if (/^-/) { $args .= " $_"; } elsif (/^((.+)@)?([^:]+):?(\d+)?$/) { $user = $1; $host = $3; $port = $4 || 22; if ($first) { $cmd = "ssh ${user}${host} -p $port -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; $args = ''; $first = 0; } else { $cmd .= " -L $iport:$host:$port"; push @cmds, "$cmd -f sleep 10 $args"; $cmd = "ssh ${user}localhost -p $iport -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; $args = ''; $iport ++; } } } push @cmds, "$cmd $args"; foreach (@cmds) { print "$_\n"; system($_); } 

Uso:

Per accedere a HOSTC tramite HOSTA e HOSTB (stesso utente):

 mssh HOSTA HOSTB HOSTC 

Per accedere a HOSTC tramite HOSTA e HOSTB e utilizzare i numbers di port SSH non predefiniti e diversi utenti:

 mssh [email protected]:1234 [email protected]:1222 [email protected]:78231 

Per accedere a HOSTC tramite HOSTA e HOSTB e utilizzare l'inoltro X:

 mssh HOSTA HOSTB HOSTC -X 

Per accedere alla port 8080 su HOSTC tramite HOSTA e HOSTB:

 mssh HOSTA HOSTB -L8080:HOSTC:8080 

Questa risposta è simile a kynan, in quanto riguarda l'utilizzo di ProxyCommand. Ma è più conveniente usare IMO.

Se avete installato netcat nelle vostre macchine di hop puoi aggiungere questo snippet al tuo ~ / .ssh / config:

 Host *+* ProxyCommand ssh $(echo %h | sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p /') nc $(echo %h | sed 's/^.*+//;/:/!s/$/ %p/;s/:/ /') 

Poi

 ssh -D9999 host1+host2 -l username 

farà quello che hai chiesto.

Sono venuto qui a cercare il posto originale in cui ho letto questo trucco. Farò un link quando lo trovo.

OpenSSH v7.3 in avanti support un interruttore -J e un'opzione ProxyJump che permettono uno o più host di salto separati da virgole, quindi è ansible farlo ora:

 ssh -J [email protected],[email protected],...,[email protected] [email protected] 

Davvero, credo che dovresti dare un'occhiata qui:

http://sshmenu.sourceforge.net/articles/transparent-mulithop.html

 ssh -L 9999:host2:80 -R 9999:localhost:9999 host1 

-L 9999: host2: 80

Metti a bind a localhost: 9999 e qualsiasi pacchetto inviato a localhost: 9999 inoltra a host2: 80

-R 9999: localhost: 9999

Significa qualsiasi pacchetto ricevuto da host1: 9999 inoltro di nuovo a localhost: 9999

si dovrebbe essere in grado di utilizzare l'inoltro di port per accedere a un servizio su host2 da localhost . Qui si trova una buona guida. Estratto:

Ci sono due tipi di inoltro di porte: inoltro locale e remoto. Sono anche chiamati tunnel in output e in ingresso. L'inoltro di port locale inoltra il traffico verso una port locale a una port remota specificata.

Ad esempio, se si esegue il command

 ssh2 -L 1234:localhost:23 [email protected] 

tutto il traffico che entra nella port 1234 sul client verrà inoltrato alla port 23 sul server (host). Si noti che localhost verrà risolto dal server sshdserver dopo che la connessione è stata stabilita. In questo caso localhost si riferisce quindi al server (host) stesso.

L'inoltro della port remota fa il contrario: inoltra il traffico che arriva ad una port remota ad una port locale specificata.

Ad esempio, se si esegue il command

 ssh2 -R 1234:localhost:23 [email protected] 

tutto il traffico che entra nella port 1234 sul server (host) verrà inoltrato alla port 23 sul client (localhost).

Nel tuo cast, sostituisci localhost nell'esempio con host2 e host con host1 .

Se è ansible eseguire SSH in entrambe le macchine, dare un'occhiata alla direttiva ProxyCommand di ssh. Ciò vi permetterà di passare direttamente da localhost a host2 (in un semplice command se si utilizzano chiavi pubbliche !!). Allora puoi fare tutto quello che vuoi con host2.

http://www.statusq.org/archives/2008/07/03/1916/

In questa risposta vorrei passare attraverso un esempio concreto. È sufficiente sostituire i nomi host, i nomi utente e le password dei computer.

Dichiarazione problema

Supponiamo che abbiamo la seguente topologia di networking:

 our local computer <---> server 1 <---> server 2 

Per concnetworkingzza, supponiamo di avere i nomi di host, i nomi utente e le password dei seguenti computer:

 LocalPC <---> hostname: mit.edu <---> hec.edu username: bob username: john password: dylan123 password: doe456 

Obiettivo: vogliamo impostare un proxy SOCKS che ascolta la port 9991 di LocalPC modo che each volta che una connessione a LocalPC venga avviata dalla port 9991 passerà attraverso mit.edu poi hec.edu .

Esempio di caso d'uso: hec.edu dispone di un server HTTP accessibile solo su http://127.0.0.1:8001 , per motivi di sicurezza. Vorremmo poter visitare http://127.0.0.1:8001 aprendo un browser web su LocalPC .


Configurazione

In LocalPC , aggiungere in ~/.ssh/config :

 Host HEC HostName hec.edu User john ProxyCommand ssh [email protected] -W %h:%p 

Quindi, nel terminal di LocalPC , eseguire:

 ssh -D9991 HEC 

Ti chiederà la password di bob su mit.edu (cioè, dylan123 ), poi ti chiederà la password di john su hec.edu (cioè doe456 ).

A quel punto, il proxy SOCKS è ora in esecuzione sulla port 9991 di LocalPC .

Ad esempio, se si desidera visitare una pagina web su LocalPC utilizzando il proxy SOCKS, è ansible eseguire Firefox:

immettere qui la descrizione dell'immagine

Alcune osservazioni:

  • in ~/.ssh/config , HEC è il nome della connessione: puoi modificarlo a qualsiasi cosa desideri.
  • Il -D9991 dice a ssh di impostare un proxy SOCKS4 sulla port 9991 .