Jak połączyć SSH z maszyną A za pośrednictwem B w jednym poleceniu?

103

Chcę uzyskać dostęp do komputera, powiedzmy komputer A, który jest oparty na sieci mojej uczelni. Jednak ten komputer jest dostępny tylko przez wewnętrzną sieć uniwersytetu, więc nie mogę używać SSH do tego komputera bezpośrednio z domu.

Oto co teraz robię:

  1. Zaloguj się do innego komputera uniwersyteckiego, powiedzmy komputer B

    (Ta maszyna B jest dostępna przez SSH z mojego komputera domowego.)

  2. Użyj SSH na B, aby połączyć się z A.

Czy istnieje sposób, aby to zrobić szybciej? Używanie tylko jednego polecenia ssh.

nikosdi
źródło
powiązane: ssh przez wiele hostów
Trevor Boyd Smith

Odpowiedzi:

97

Tak, używając ProxyCommandw konfiguracji SSH.

Utwórz plik konfiguracyjny SSH w swoim katalogu domowym (chyba że chcesz zrobić to dla całego systemu) ~/.ssh/config:

Host unibroker          # Machine B definition (the broker)
Hostname 12.34.45.56    # Change this IP address to the address of the broker
User myusername         # Change this default user accordingly 
                        # (`user@unibroker` can overwrite it)

Host internalmachine    # Machine A definition (the target host)
ProxyCommand ssh -q unibroker nc -q0 hostname.or.IP.address.internal.machine 22

Teraz możesz bezpośrednio dotrzeć do maszyny A.

ssh user@internalmachine

Zauważ też, że teraz masz dla niego pojedynczą nazwę docelową hosta SSH, możesz jej używać również w innych aplikacjach. Na przykład:

  • SCP do kopiowania plików.

    scp somefile user@internalmachine:~/
    
  • W aplikacjach GUI:

    użyj sftp://user@internalmachine/jako lokalizacji do przeglądania na maszynie.

    Oparte na KDE (Dolphin): użyj fish://user@internalmachine/

Notatki

Zmień hostname.or.IP.address.internal.machinei port ( 22) na maszynie, do której chcesz dotrzeć, tak jakbyś z unibrokermaszyny.

W zależności od wersji netcata na hoście unibrokera -q0opcję tę należy pominąć. W odniesieniu do uwierzytelnienia; w zasadzie konfigurujesz dwa połączenia SSH ze stacji roboczej. Oznacza to, że zarówno host unibrokera, jak i host maszyny wewnętrznej są weryfikowane / uwierzytelniane jeden po drugim (zarówno dla pary kluczy / hasła, jak i weryfikacji klucza hosta).

Wyjaśnienie

Takie podejście z użyciem ProxyCommandi „netcat” jest tylko jednym ze sposobów na to. Podoba mi się to, ponieważ mój klient SSH komunikuje się bezpośrednio z maszyną docelową, dzięki czemu mogę zweryfikować klucz hosta od mojego klienta i mogę korzystać z uwierzytelniania mojego klucza publicznego bez używania innego klucza w brokerze.

Każdy Hostokreśla początek nowej sekcji hosta. Hostnameto docelowa nazwa hosta lub adres IP tego hosta. Userjest to, co podasz jako część użytkownika ssh user@hostname.

ProxyCommandbędzie używany jako rura do maszyny docelowej. Poprzez użycie SSH do pierwszego komputera i bezpośrednie skonfigurowanie ncstamtąd prostego „netcat” ( ) do celu, jest to po prostu zwykły tekst przekazywany do wewnętrznego komputera od brokera pomiędzy nimi. Te -qopcje są do milczenia żadnego wyjścia (tylko osobiste preferencje).

Upewnij się, że na brokerze jest zainstalowany program Netcat (zwykle dostępny domyślnie w systemie Ubuntu) - netcat-openbsdZainstaluj netcat-openbsd lub netcat-traditionalZainstaluj netcat-traditional .

Pamiętaj, że nadal używasz SSH z szyfrowaniem dwa razy tutaj. Podczas gdy kanał Netcat jest zwykłym tekstem, twój klient SSH na twoim komputerze skonfiguruje inny zaszyfrowany kanał z ostateczną maszyną docelową.

gertvdijk
źródło
4
Musiałem usunąć opcję -q0, ponieważ nie była obsługiwana przez komputer, którego używałem. Poza tym wszystko działało. To jest FANTASTYCZNA wskazówka. Dziękuję bardzo. :)
Gerry
Wystąpił problem, twoja odpowiedź działa dobrze dla mnie z terminala, ale nie jestem w stanie tego zrobić za pomocą GUI SFTP, mówi: nieobsługiwany komunikat o błędzie, przekroczony limit czasu podczas logowania.
Vikash B
@VikashB Cóż, to naprawdę powinno działać. Zastanów się nad utworzeniem NOWEGO pytania, aby poradzić sobie z określoną sytuacją.
gertvdijk
Zrobiłem tutaj pytanie: askubuntu.com/questions/688567/…
Vikash B
1
Aby uzupełnić mądre słowo @gertvdijk, istnieje świetna wikibook na temat serwerów proxy ssh i hostów skoków, które mogą służyć jako nieocenione odniesienie.
Travis Clarke
51

Wskakuj za jednym razem

Oczywistą alternatywą dla podejścia ProxyCommand, które podałem w mojej innej odpowiedzi, byłoby „przeskakiwanie” bezpośrednio do maszyny docelowej:

ssh -t user@machineB ssh user@machineA

Zwróć uwagę -tna pierwsze sshpolecenie. Bez tego zawiedzie:

Pseudo-terminal will not be allocated because stdin is not a terminal.
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
Permission denied, please try again.
[...]

Wymusi to przydzielenie prawdziwego TTY

Minusem tego jest to, że teraz cała konfiguracja, weryfikacja i uwierzytelnianie odbywa się na komputerze B, co tak naprawdę nie lubię w mojej sytuacji ze względów bezpieczeństwa. Podoba mi się moja para kluczy na własnym komputerze oraz uwierzytelnianie i weryfikacja docelowej maszyny na własnym komputerze. Ponadto można używać interaktywnej powłoki tylko dla SSH, więc nie będzie to obsługiwać innych narzędzi, takich jak SCP lub menedżer plików GUI.

Ze wszystkich wyżej wymienionych powodów zdecydowanie zalecam podejście ProxyCommand , ale w przypadku szybkiego połączenia działa to dobrze.

gertvdijk
źródło
Dlaczego nie odpowiedzieć na jedno pytanie zarówno w przypadku rozwiązań jednorazowych, jak i stałych?
demure
5
@demure Tak działają strony StackExchange ... Zobacz: Jaka jest oficjalna etykieta podwójnego odpowiadania na pytanie? mówi „Lepiej jest opublikować dwie różne odpowiedzi niż połączyć je w jedną odpowiedź”. . I nie uważam tego za to samo rozwiązanie. Moim zdaniem stałe / tymczasowe nie jest tym, co wyróżnia to podejście.
gertvdijk
Inne przewodniki mówią, że należy dodatkowo użyć przełącznika -A, ale wskazują, że ma to wpływ na bezpieczeństwo. Czy wiesz, co to znaczy przekazywać, czy nie, połączenie agenta uwierzytelniania?
Przekątna
@gertvdijk super ninja tutaj! masz dwa najlepsze rozwiązania. nigdy wcześniej tego nie widziałem. Super fajne. o wiele lepsze niż tworzenie jednego mega długiego rozwiązania z rozwiązaniami N (co zwykle widzę).
Trevor Boyd Smith
Jest to o wiele wygodniejsze niż konfigurowanie konfiguracji, która utrudni również działanie innych ssh.
Nikhil Sahu
37

Możesz użyć -Jopcji wiersza poleceń:

ssh -J user@machineB user@machineA

Od man ssh:

-J [user@]host[:port]
     Connect to the target host by first making a ssh connection to
     the jump host and then establishing a TCP forwarding to the
     ultimate destination from there.  Multiple jump hops may be
     specified separated by comma characters.  This is a shortcut to
     specify a ProxyJump configuration directive.

Został wprowadzony w wersji OpenSSH 7.3 (wydanej w sierpniu 2016 r.). Jest dostępny w wersji Ubuntu 16.10 i nowszych.

Erik Sjölund
źródło
3
+1, ponieważ działa to nawet wtedy, gdy trzeba podać plik klucza dla maszyny A
Żal
1
+1, jest to lepsza wersja w porównaniu z moją odpowiedzią ProxyCommand, jeśli na wszystkich hostach uruchomiona jest wersja OpenSSH wystarczająco niedawno.
gertvdijk
Czy serwer OpenSSH powinien być zainstalowany na obu maszynach A i B? Czy mam rację rozumianą?
Michaił
17

Spróbuj użyć

Host <visible hostname alias>
        Controlmaster auto
        User <user>
        hostname <visible hostname>
        port <port>
        IdentityFile ~/.ssh/<id file>

Host <private LAN hostname alias>
     ProxyCommand ssh -q -W <private LAN hostname>:<private LAN port> <visible hostname alias>

w ~ / .ssh / config i zrób to wszystko jednym strzałem z kluczami znajdującymi się tylko na twoim komputerze.

Pomoc SSH
źródło
1
Jest to czystsze niż wprowadzanie netcat do miksu. Ponadto prywatny klucz SSH również nie musi istnieć na Bkomputerze.
danemacmillan
1

To bardzo pomocna sugestia. Po wielu godzinach gadania znalazłem tę notatkę i potwierdziłem, że działa ona dokładnie tak, jak zostało to udokumentowane. Aby połączyć się przez MachineA z MachineB, ze zdalnego komputera C:

np .: [xuser @ machineC ~] ssh -t MachineA ssh MachineB

„-T” jest krytyczne, ssh zawiedzie, jeśli nie jest obecne. Zostaniesz dwukrotnie zapytany, najpierw o hasło na MachineA, a następnie drugi raz na MachineB. Zauważ też, że zakłada się, że na wszystkich trzech komputerach zdefiniowano użytkownika „xuser”. Jeśli nie, po prostu użyj składni ssh: „yuser @ MachineA ...”. Zauważ też, że możesz użyć kropkowanych quad surowych adresów IP, jeśli chcesz. Jest to przydatne, jeśli łączysz się przez prywatną sieć lokalną, która korzysta z adresów IP nie narażonych na świat - tj. nie w lokalnym pliku hosta ani w żadnym DNS. Aby pobrać plik z MachineB, na zdalną maszynę C, możesz scpować z MachineB na MachineA, a następnie z MachineA na zdalną maszynę C. (Np. Zdalna maszyna C może pingować MachineA, ale nie MachineB.) Zastrzeżenie: Testowałem z Fedorą i WindowsXP, MachineA to XP-box z ICS (Udostępnianie połączenia internetowego), podczas gdy MachineB i zdalna maszyna C są pudełkami Fedory-Linux. Ta sugestia rozwiązała dla mnie kluczowy problem - tj. ograniczony, monitorowany zdalny dostęp do mojej zdalnej witryny LAN. Uwaga: po „wylogowaniu” z MachineB powinieneś zobaczyć dwa „Połączenie z xxx.xxx.xxx.xxx zamknięte”. wiadomości.

Mcl
źródło
Jeśli skonfigurujesz i skonfigurujesz uwierzytelnianie za pomocą klucza publicznego, nie musisz martwić się o podanie hasła. Ale -tnadal jest wymagany.
Felipe Alvarez
@FelipeAlvarez Nadal musisz się martwić o wpisanie drugiego hasła, jeśli nie ufasz maszynie B, aby mieć hasło bez logowania do A!
Michael
1

ProxyCommand to czyste rozwiązanie w przypadku, gdy pozwalasz na dostęp do powłoki w obu systemach. Chcieliśmy zapewnić zdalnym użytkownikom dostęp do komputera wewnętrznego (A) za pośrednictwem brokera (B), ale bez umożliwienia użytkownikowi dostępu do powłoki B w celu zwiększenia bezpieczeństwa. To działało:

Zamień powłokę logowania

Zastąp powłokę logowania (użyj chsh) dla extuserbrokera następującym skryptem (przechowywanym w pliku):

#!/bin/sh   # this is essential to avoid Exec format error
ssh internaluser@A

Pod warunkiem, że nie skonfigurowano hasła logowania w extuser @ B dla użytkownika zdalnego i w internaluser @ A dla extuser @ B, wówczas wykonanie następującego polecenia spowoduje bezpośrednie przejście użytkownika zdalnego do A

ssh extuser@B

Wskazówka : Przed przejściem do niestandardowej powłoki logowania należy utworzyć niezbędną konfigurację logowania bez hasła za pomocą autoryzowanych kluczy w extuser @ B. Po zmianie, ponieważ to konto jest niedostępne dla nikogo przez powłokę, tylko sudoer @ B może dokonać zmian w pliku autoryzowanych_kluczy, edytując je bezpośrednio.

sudo vi ~extuser/.ssh/authorized_keys
sudo touch ~extuser/.hushlogin

Ostatnim wierszem jest wyłączenie wyświetlania banera logowania z B, aby zdalny użytkownik miał przejrzysty dostęp do A.

Sunthar
źródło
Bardzo ciekawe podejście. Jednak głównymi wadami tego są: 1) Wykorzystanie jest ograniczone do standardowego użycia SSH (brak obsługi SFTP / SCP). 2) Użytkownik nie może wybrać innego hosta docelowego innego niż pojedynczy (ponieważ jest zakodowany na stałe w powłoce logowania) 3) Weryfikacji klucza hosta nie można przeprowadzić ze stacji roboczej do ostatecznego hosta docelowego (od momentu użycia pliku binarnego SSH brokera) . 4) Klucze prywatne dla użytkowników, aby uzyskać dostęp do docelowego hosta docelowego, znajdują się w brokerze, a nie z użytkownikiem. Pozwala to na personifikację użytkownika przez administratora (co zwykle nie jest możliwe).
gertvdijk
Wszystkie punkty są prawdziwe, dziękuję za opracowanie. Jednak głównym celem jest zapewnienie zaufanemu użytkownikowi dostępu ssh do A bez logowania do B. Ponieważ tylko administrator może dodać klucz publiczny zaufanego użytkownika na B (poprzez sudo, bez logowania), oznacza to już, że użytkownik ma ( admin) dostęp do klucza prywatnego extuser @ B (nie zaufanego użytkownika na zewnątrz) i skonfigurował go, po pierwsze!
Sunthar
1

Masz na myśli, że potrzebujesz kilku zworek :)

Ostatnio spotkałem ten problem z jumper1 jumper2 i moją maszyną końcową, tak jak w przypadku mojego sola

skrypt lokalny:

#!/bin/bash
sshpass -p jumper1Passwd ssh -t jumper1@jumper1IP ./Y00.sh

następnie na 1. zworce (która jest moim routerem) umieściłem skrypt o nazwie Y00.sh:

ssh -tt jumper2@jumper2 -i ~/.ssh/id_rsa sshpass -p finalPassWord ssh -tt final@final

Możesz je zastąpić swoim adresem IP i hasłami, powodzenia!

Z-Y00
źródło