Frage Ein SSH-Tunnel über mehrere Hops


Tunneldaten über SSH sind ziemlich einfach:

ssh -D9999 username@example.com

richtet Port 9999 auf Ihrem ein localhost als ein Tunnel zu example.com, aber ich habe ein spezifischeres Bedürfnis:

  • Ich arbeite lokal an localhost
  • host1 ist zugänglich für localhost
  • host2 akzeptiert nur Verbindungen von host1
  • Ich muss einen Tunnel erstellen von localhost zu host2

Effektiv möchte ich einen "Multi-Hop" SSH-Tunnel erstellen. Wie kann ich das machen? Im Idealfall möchte ich dies tun, ohne Superuser sein zu müssen irgendein der Maschinen.


287
2018-01-16 05:58


Ursprung


Wofür hast du es benutzt? Ich möchte es für SOCKS Proxy verwenden. Wird es funktionieren? - prongs
Ja, Sie sollten in der Lage sein, die getunnelte Verbindung als SOCKS-Proxy zu verwenden, es sei denn host2 verweigert die Weiterleitung - Mala
Ich habe über das Erstellen eines Wrappers über SSH nachgedacht, der das mit multiple Verwendung von ProxyCommand einrichten würde. - Pavel Šimerda
@prongs Haben Sie es geschafft, dies für SOCKS-Proxy (all diese Jahre) zu verwenden? - Drux


Antworten:


Sie haben grundsätzlich drei Möglichkeiten:

  1. Tunnel von localhost zu host1:

    ssh -L 9999:host2:1234 -N host1
    

    Wie oben erwähnt, besteht die Verbindung von host1 zu host2 wird nicht gesichert werden.

  2. Tunnel von localhost zu host1 und von host1 zu host2:

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

    Dies wird einen Tunnel von öffnen localhost zu host1 und ein weiterer Tunnel von host1 zu host2. Allerdings der Hafen 9999 zu host2:1234 kann von jedem benutzt werden host1. Dies kann oder kann kein Problem sein.

  3. Tunnel von localhost zu host1 und von localhost zu host2:

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

    Dies wird einen Tunnel von öffnen localhost zu host1 durch welche der SSH-Dienst läuft host2 kann verwendet werden. Dann wird ein zweiter Tunnel von geöffnet localhost zu host2 durch den ersten Tunnel.

Normalerweise würde ich mit Option 1 gehen. Wenn die Verbindung von host1 zu host2 muss gesichert werden, gehen Sie mit Option 2. Option 3 ist vor allem nützlich, um auf einen Dienst zuzugreifen host2 das ist nur erreichbar von host2 selbst.


272
2018-01-17 21:31



Option 3 war, was ich suchte, danke! - Mala
Ich möchte auf diese Weise surfen. Welches ist das Beste? Ich habe es zuerst versucht, aber es hat nicht funktioniert. Ich setze einen Socks-Proxy in meinem Browser localhost: 1234 aber kein Glück. :( bitte helfen .. - prongs
@prongs versuchen Sie Option 3 - Mala
Gibt es eine Möglichkeit, meinen öffentlichen Schlüssel von localhost über den Tunnel von host 1 auf host2 weiterzuleiten? - Noli
@Noli Wenn Sie ssh-agent verwenden (was Sie tun sollten), können Sie es über die Verbindungen weiterleiten -A Option zu SSH. - Mika Fischer


Da ist ein ausgezeichnete Antwort, die den Gebrauch des erklärt ProxyCommand Konfigurationsanweisung für SSH:

Fügen Sie das zu Ihrem hinzu ~/.ssh/config (sehen man 5 ssh_config für Details):

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

Dann ssh host2 wird automatisch durchtunneln host1 (funktioniert auch mit X11-Weiterleitung etc.).

Dies funktioniert auch für eine ganze Klasse von Hosts, z.B. identifiziert nach Domäne:

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

Aktualisieren

OpenSSH 7.3 führt ein ein ProxyJump Richtlinie, vereinfacht das erste Beispiel zu

Host host2
  ProxyJump host1

138
2017-08-01 17:10



Gibt es einen Weg dies bedingt zu tun? Ich möchte das nur manchmal machen. Dies ist auch speziell für Befehle, aber ich suche etwas für alle von Port 22 (SSH, SFTP, etc). - Stephane
@ Stephane was meinst du mit speziell für Befehle? Ihre SSH-Konfig wird von allem benutzt ssh, einschließlich git, sftp usw. afaik. - kynan
@ Stephane Ich bin mir nicht bewusst, wie Sie dies bedingt aktivieren können (z. B. nur, wenn Sie sich außerhalb des Netzwerks des Zielhosts befinden). Ich stelle diese Option für alle fraglichen Hosts in einem Konfigurationsblock ein und entziehe die Zeile nach Bedarf. Nicht perfekt, aber es funktioniert. - kynan
@ Stephane sicher: ssh -F /path/to/altconfig. Vorsicht, dies wird das System ignorieren /etc/ssh/ssh_config. - kynan
Eine einfache Möglichkeit, Einstellungen "bedingt" vorzunehmen, besteht darin, zwei verschiedene Hosts in .ssh / config zu definieren, die denselben Hostnamen haben. Verbinden Sie sich mit host2-tunnel, wenn Sie den Tunnel möchten, und host2, wenn Sie nicht möchten. - Steve Bennett


Wir haben ein SSH-Gateway in unser privates Netzwerk. Wenn ich draußen bin und eine entfernte Shell auf einer Maschine innerhalb des privaten Netzwerks haben möchte, müsste ich in das Gateway und von dort auf die private Maschine zugreifen.

Um dieses Verfahren zu automatisieren, verwende ich das folgende Skript:

#!/bin/bash
ssh -f -L some_port:private_machine:22 user@gateway "sleep 10" && ssh -p some_port private_user@localhost

Was ist los:

  1. Richten Sie einen Tunnel für das ssh-Protokoll (Port 22) für die private Maschine ein.
  2. Nur wenn das erfolgreich ist, ssh in den privaten Computer, der den Tunnel verwendet. (Der Operator von && stellt dies sicher).
  3. Nach dem Schließen der privaten SSH-Sitzung möchte ich auch den SSH-Tunnel schließen. Dies geschieht über den Trick "Schlaf 10". Normalerweise wird der erste ssh-Befehl nach 10 Sekunden geschlossen, aber während dieser Zeit hat der zweite ssh-Befehl eine Verbindung über den Tunnel hergestellt. Daher hält der erste ssh-Befehl den Tunnel offen, bis die folgenden zwei Bedingungen erfüllt sind: Schlaf 10 ist beendet und der Tunnel wird nicht mehr verwendet.

20
2018-01-24 18:47



Sehr schlau!!! LIEBE ES! - Hendy Irawan


Nachdem ich das obige gelesen und alles zusammengefügt habe, habe ich das folgende Perl-Skript erstellt (speichern Sie es als mssh in / usr / bin und machen Sie es ausführbar):

#!/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($_);
}

Verwendung:

Zugriff auf HOSTC über HOSTA und HOSTB (gleicher Benutzer):

mssh HOSTA HOSTB HOSTC

Um über HOSTA und HOSTB auf HOSTC zuzugreifen und nicht standardmäßige SSH-Portnummern und verschiedene Benutzer zu verwenden:

mssh user1@HOSTA:1234 user2@HOSTB:1222 user3@HOSTC:78231

Um auf HOSTC über HOSTA und HOSTB zuzugreifen und X-Forwarding zu verwenden:

mssh HOSTA HOSTB HOSTC -X

Um über HOSTA und HOSTB auf Port 8080 auf HOSTC zuzugreifen:

mssh HOSTA HOSTB -L8080:HOSTC:8080

16
2018-01-11 11:02



das ist fantastisch - Mala
Ich kann Ihnen nicht genug danken, dieses Skript macht mein Leben jeden Tag einfacher. Das einzige, was ich geändert habe, war, int (rand (1000)) zu iport hinzuzufügen, damit mehrere Instanzen gleichzeitig ausgeführt werden können. Ich schulde dir definitiv ein Bier. - Mala
Das funktioniert wirklich gut. Eine weitere Verbesserung wäre das Auflösen von HOSTB, HOSTC usw. mit localhosts / etc / hosts und ~ / .ssh / config - Steve Bennett
Auch ich hinterlasse Malas Kommentar. Ohne den randomisierten Port, wenn Sie dann versuchen mssh HOSTA HOSTD Sie werden tatsächlich bei HOSTB landen (und vielleicht nicht realisieren ..) - Steve Bennett


OpenSSH v7.3 unterstützt a -J wechseln und a ProxyJump Option, die einen oder mehrere kommaseparierte Sprunghosts erlaubt, also können Sie das jetzt einfach tun:

ssh -J jumpuser1@jumphost1,jumpuser2@jumphost2,...,jumpuserN@jumphostN user@host

16
2017-08-10 09:11



ssh -J user1 @ host1-YC4c arcfour, blowfish-cbc user2 @ host2 firefox -no-remote Dies wird beschleunigen firefox von host2 zu localhost zu bekommen. - Jaur


Diese Antwort ähnelt der von Kynan, da hier ProxyCommand verwendet wird. Aber es ist bequemer, IMO zu verwenden.

Wenn Sie netcat in Ihren Hop-Maschinen installiert haben, können Sie dieses Snippet zu Ihrer ~ / .ssh / config hinzufügen:

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

Dann

ssh -D9999 host1+host2 -l username

werde tun, was Sie gefragt haben.

Ich kam hierher, um nach dem ursprünglichen Ort zu suchen, wo ich diesen Trick lese. Ich poste einen Link, wenn ich ihn finde.


8
2018-03-13 09:57



Ich glaube, das ist der Ursprung des Tricks: wiki.gentoo.org/wiki/SSH_jump_host - slm
@slm ja, das wars! Vielen Dank! - silviot


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

-L 9999: Host2: 80

Means binden an localhost: 9999 und jedes an localhost gesendete Paket: 9999 leitet es an host2: 80 weiter

-R 9999: localhost: 9999

Jedes Paket, das von Host1 empfangen wird: 9999 leitet es zurück an localhost: 9999


4
2018-01-19 02:03



Brilliant, einfachste Antwort, um einen Tunnel zu machen, so dass Sie direkt von localhost: 9999 auf die Anwendung auf host2 zugreifen können - dvtoever
Nach dieser Antwort bekomme ich eine channel 3: open failed: administratively prohibited: open failed  Fehlermeldung. - Franck Dernoncourt


Sie sollten die Port-Weiterleitung verwenden können, um auf einen Dienst zuzugreifen host2 von localhost. Ein guter Führer ist lokalisiert Hier. Auszug:

Es gibt zwei Arten der Portweiterleitung: lokale und entfernte Weiterleitung. Sie werden auch als ausgehende bzw. eingehende Tunnel bezeichnet. Die lokale Portweiterleitung leitet den Datenverkehr von einem lokalen Port zu einem bestimmten entfernten Port weiter.

Zum Beispiel, wenn Sie den Befehl absetzen

ssh2 -L 1234:localhost:23 username@host

Der gesamte Verkehr, der auf dem Client zu Port 1234 gelangt, wird an Port 23 auf dem Server (Host) weitergeleitet. Beachten Sie, dass localhost nach dem Verbindungsaufbau vom sshdserver aufgelöst wird. In diesem Fall verweist localhost daher auf den Server (Host) selbst.

Die Remote-Port-Weiterleitung macht das Gegenteil: Sie leitet den Datenverkehr von einem Remote-Port zu einem bestimmten lokalen Port weiter.

Zum Beispiel, wenn Sie den Befehl absetzen

ssh2 -R 1234:localhost:23 username@host

Der gesamte Verkehr, der auf dem Server (Host) auf Port 1234 ankommt, wird an den Port 23 auf dem Client (localhost) weitergeleitet.

In deiner Besetzung, ersetzen localhost im Beispiel mit host2 und host mit host1.


2
2018-01-16 06:34



laut diesem Artikel wird die Verbindung nur bis zur mittleren Maschine (host1) gesichert. Gibt es eine Möglichkeit sicherzustellen, dass das Ganze sicher bleibt? - Mala
Ich habe das nie ausprobiert, aber wenn Host1 und Host2 beide SSH-Server sind, können Sie möglicherweise einen Tunnel von Host1 zu Host2 einrichten und dann einen Tunnel von Localhost zu Host1 für den gleichen Dienst einrichten (Ihren lokalen und entfernten Server holen) Ports rechts). Ich weiß nicht, ob das in einem Befehl von localhost möglich ist. - fideli


Ich habe was ich getan denken du wolltest damit umgehen

ssh -D 9999 -J host1 host2

Ich werde für beide Kennwörter aufgefordert, dann kann ich localhost: 9999 für einen SOCKS-Proxy zu Host2 verwenden. Es ist das nächste, was ich an das Beispiel denken kann, das Sie an erster Stelle gezeigt haben.


2
2017-11-21 11:06





In dieser Antwort werde ich ein konkretes Beispiel durchgehen. Sie müssen nur die Hostnamen, Benutzernamen und Passwörter der Computer durch Ihre ersetzen.

Problemstellung

Nehmen wir an, wir haben die folgende Netzwerktopologie:

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

Nehmen wir an, dass wir die Hostnamen, Benutzernamen und Passwörter der folgenden Computer haben:

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

Ziel: Wir möchten einen SOCKS-Proxy einrichten, der den Port überwacht 9991 von LocalPC so dass jedes Mal eine Verbindung auf LocalPC wird vom Port initiiert 9991 es geht durch mit.edu dann hec.edu.

Anwendungsbeispiel: hec.edu hat einen HTTP-Server, auf den nur zugegriffen werden kann http://127.0.0.1:8001, aus Sicherheitsgründen. Wir würden gerne besuchen können http://127.0.0.1:8001 indem Sie einen Webbrowser öffnen LocalPC.


Aufbau

Im LocalPC, hinzufügen ~/.ssh/config:

Host HEC
    HostName hec.edu
    User john
    ProxyCommand ssh bob@mit.edu -W %h:%p

Dann im Terminal von LocalPC, Lauf:

ssh -D9991 HEC

Es fragt Sie das Passwort von bob auf mit.edu (d. h. dylan123), dann wird es dir das Passwort von fragen john auf hec.edu (d. h. doe456).

Zu diesem Zeitpunkt läuft der SOCKS-Proxy jetzt auf Port 9991 von LocalPC.

Zum Beispiel, wenn Sie eine Webseite besuchen möchten LocalPC mit dem SOCKS-Proxy können Sie in Firefox tun:

enter image description here

Einige Anmerkungen:

  • im ~/.ssh/config, HEC ist der Name der Verbindung: Sie können sie beliebig ändern.
  • Das -D9991 erzählt ssh Einrichten eines SOCKS4-Proxy für den Port 9991.

1
2018-03-18 20:13





Wenn Sie SSH auf beiden Computern ausführen können, sehen Sie sich die ProxyCommand-Direktive von ssh an. Dadurch können Sie direkt von localhost zu host2 wechseln (mit einem einfachen Befehl, wenn Sie öffentliche Schlüssel verwenden !!). Dann können Sie mit Host2 machen, was Sie wollen.

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


0
2018-01-19 01:35