it-swarm-ru.tech

Туннель SSH через несколько переходов

Туннелирование данных по SSH довольно просто:

ssh -D9999 [email protected]

настраивает порт 9999 на вашем localhost в качестве туннеля на example.com, но у меня есть более конкретная потребность:

  • Я работаю локально на localhost
  • Host1 доступен для localhost
  • Host2 принимает соединения только от Host1
  • Мне нужно создать туннель от localhost до Host2

По сути, я хочу, чтобы создать «мульти-хоп» SSH туннель. Как я могу это сделать? В идеале я хотел бы сделать это без необходимости иметь права суперпользователя на любой из машин.

319
Mala

У вас есть три возможности:

  1. Туннель от localhost до Host1:

    ssh -L 9999:Host2:1234 -N Host1
    

    Как отмечалось выше, соединение от Host1 к Host2 не будет защищено.

  2. Туннель от localhost до Host1 и от Host1 до Host2:

    ssh -L 9999:localhost:9999 Host1 ssh -L 9999:localhost:1234 -N Host2
    

    Это откроет туннель от localhost до Host1 и другой туннель от Host1 до Host2. Однако порт 9999 to Host2:1234 может использоваться любым пользователем на Host1. Это может или не может быть проблемой.

  3. Туннель от localhost до Host1 и от localhost до Host2:

    ssh -L 9998:Host2:22 -N Host1
    ssh -L 9999:localhost:1234 -N -p 9998 localhost
    

    Это откроет туннель от localhost до Host1, через который можно использовать службу SSH на Host2. Затем открывается второй туннель от localhost до Host2 через первый туннель.

Как правило, я бы выбрал вариант 1. Если необходимо защитить соединение от Host1 до Host2, перейдите к варианту 2. Вариант 3 в основном полезен для доступа к сервису по Host2, который доступен только из самого Host2.

306
Mika Fischer

Существует отличный ответ, объясняющий использование директивы конфигурации ProxyCommand для SSH :

Добавьте это к своему ~/.ssh/config (подробнее см. man 5 ssh_config):

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

Затем ssh Host2 будет автоматически туннелировать через Host1 (также работает с пересылкой X11 и т.д.).

Это также работает для целого класса хостов, например идентифицируется по домену:

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

Обновление

OpenSSH 7.3 вводит директивуProxyJump, упрощая первый пример для

Host host2
  ProxyJump Host1
149
kynan

OpenSSH v7.3 и выше поддерживает параметр -J и параметр ProxyJump, которые позволяют использовать один или несколько хостов перехода через запятую, поэтому вы можете просто сделать это сейчас:

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

У нас есть один шлюз SSH в нашей частной сети. Если я нахожусь снаружи и хочу использовать удаленную оболочку на машине внутри частной сети, мне придется подключиться через ssh к шлюзу, а оттуда - к частной машине.

Для автоматизации этой процедуры я использую следующий скрипт:

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

Что происходит:

  1. Установите туннель для протокола ssh (порт 22) на частную машину.
  2. Только если это успешно, ssh на частную машину, используя туннель. (Оператор && обеспечивает это).
  3. После закрытия частного ssh-сеанса я хочу, чтобы ssh-туннель тоже закрывался. Это делается с помощью трюка «спать 10». Обычно первая команда ssh закрывается через 10 секунд, но в течение этого времени вторая команда ssh установит соединение с использованием туннеля. В результате первая команда ssh сохраняет туннель открытым, пока не будут выполнены следующие два условия: сон 10 завершен и туннель больше не используется.
21
Bernhard Kausler

Прочитав вышесказанное и склеив все вместе, я создал следующий Perl-скрипт (сохраните его как mssh в/usr/bin и сделайте его исполняемым):

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

Использование:

Чтобы получить доступ к HOSTC через HOSTA и HOSTB (один и тот же пользователь):

mssh HOSTA HOSTB HOSTC

Чтобы получить доступ к HOSTC через HOSTA и HOSTB и использовать номера SSH-портов по умолчанию и разных пользователей:

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

Чтобы получить доступ к HOSTC через HOSTA и HOSTB и использовать X-forwarding:

mssh HOSTA HOSTB HOSTC -X

Чтобы получить доступ к порту 8080 на HOSTC через HOSTA и HOSTB:

mssh HOSTA HOSTB -L8080:HOSTC:8080
18
Bob Muller

Этот ответ похож на kynan, так как включает использование ProxyCommand. Но использовать ИМО удобнее.

Если у вас на компьютерах прыжков установлен netcat, вы можете добавить этот фрагмент в ~/.ssh/config:

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

Затем

ssh -D9999 Host1+Host2 -l username

будет делать то, что вы просили.

Я пришел сюда в поисках оригинального места, где я прочитал этот трюк. Я выложу ссылку, когда найду ее.

8
silviot
ssh -L 9999:Host2:80 -R 9999:localhost:9999 Host1

-L 9999: хост2: 80

Привязка означает localhost: 9999, и любой пакет, отправленный localhost: 9999, перенаправляет его на Host2: 80

-R 9999: локальный хост: 9999

Означает, что любой пакет, полученный Host1: 9999, пересылает его обратно на localhost: 9999

4
chinmaya

Я сделал то, что я думаю / ты хотел сделать с

ssh -D 9999 -J Host1 Host2

Мне предлагается ввести оба пароля, затем я могу использовать localhost: 9999 для SOCKS-прокси для Host2. Это самое близкое, что я могу вспомнить, к примеру, который вы показали в первую очередь.

3
Cheryl

у вас должна быть возможность использовать переадресацию портов для доступа к службе по Host2 из localhost. Хороший гид находится здесь . Выдержка:

Существует два вида переадресации портов: локальная и удаленная. Их также называют исходящими и входящими туннелями соответственно. Переадресация с локального порта перенаправляет трафик, поступающий на локальный порт, на указанный удаленный порт.

Например, если вы выполните команду

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

весь трафик, поступающий на порт 1234 на клиенте, будет перенаправлен на порт 23 на сервере (хост). Обратите внимание, что локальный хост будет разрешен sshdserver после установления соединения. В этом случае localhost, следовательно, относится к самому серверу (хосту).

Переадресация удаленного порта происходит наоборот: он перенаправляет трафик, поступающий на удаленный порт, на указанный локальный порт.

Например, если вы выполните команду

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

весь трафик, который поступает на порт 1234 на сервере (хосте), будет перенаправлен на порт 23 на клиенте (локальный хост).

В своем приведении замените localhost в примере на Host2, а Host на Host1.

2
fideli

В этом ответе я рассмотрю конкретный пример. Вам просто нужно заменить имена компьютеров, имена пользователей и пароли на ваши.

Постановка задачи

Предположим, у нас есть следующая топология сети:

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

Для конкретности предположим, что у нас есть следующие имена компьютеров, имена пользователей и пароли:

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

Цель: мы хотим настроить прокси-сервер SOCKS, который прослушивает порт 9991 из LocalPC, чтобы каждый раз, когда подключение к LocalPC инициировалось из порта 9991, оно проходило через mit.edu, а затем hec.edu.

Пример варианта использования: hec.edu имеет HTTP-сервер, доступный только по http://127.0.0.1:8001 , в целях безопасности. Мы хотели бы иметь возможность посетить http://127.0.0.1:8001 , открыв веб-браузер на LocalPC.


Конфигурация

В LocalPC добавьте ~/.ssh/config:

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

Затем в терминале LocalPC запустите:

ssh -D9991 HEC

Он запросит пароль bob для mit.edu (т.е. dylan123), затем запросит пароль john для hec.edu (т.е. doe456).

В этот момент прокси-сервер SOCKS теперь работает на порту 9991 из LocalPC.

Например, если вы хотите посетить веб-страницу на LocalPC с помощью прокси-сервера SOCKS, вы можете сделать это в Firefox:

 enter image description here

Некоторые замечания:

  • в ~/.ssh/config, HEC - имя соединения: вы можете изменить его на любое другое.
  • -D9991 указывает ssh настроить прокси SOCKS4 на порту 9991.
1
Franck Dernoncourt

Если вы можете использовать SSH на обеих машинах, взгляните на директиву ssh ProxyCommand. Это позволит вам перейти прямо с локального хоста на Host2 (одной простой командой, если вы используете открытые ключи !!). Тогда вы можете делать все, что вы хотите с Host2.

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

0
Andrew

В моем случае я сделал

localhost$ ssh -D 9999 Host1
Host1$ ssh -L 8890:localhost:8890 Host2

где Host2:8890 работает на ноутбуке Jupyter.

Затем я настроил Firefox для использования localhost:9999 в качестве хоста SOCKS.

Так что теперь у меня есть ноутбук, работающий на Host2, доступный Firefox на localhost:8890 на моей машине.

0
amarion

Вариант 2 лучший ответ можно использовать с другими пользователями ssh, отличными от текущего: aka user @ Host

    export local_Host_port=30000
    export Host1_user=xyz
    export Host1=mac-Host
    export Host1_port=30000
    export Host2=192.168.56.115
    export Host2_user=ysg
    export Host2_port=13306

    # Tunnel from localhost to Host1 and from Host1 to Host2
    # you could chain those as well to Host3 ... hostn
    ssh -tt -L $local_Host_port:localhost:$Host1_port [email protected]$Host1 \
    ssh -tt -L $Host1_port:localhost:$Host2_port [email protected]$Host2
0
Yordan Georgiev