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

Туннелирование данных по SSH довольно прямолинейно:

ssh -D9999 [email protected]

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

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

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

284 голоса | спросил Mala 16 Jam1000000amSat, 16 Jan 2010 08:58:48 +030010 2010, 08:58:48

13 ответов


269

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

  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 на 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.

ответил Mika Fischer 18 Jam1000000amMon, 18 Jan 2010 00:31:56 +030010 2010, 00:31:56
137

Существует отличный ответ, объясняющий использование 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

Update

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

Host host2
  ProxyJump host1
ответил kynan 1 PM00000090000002731 2010, 21:10:27
20

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

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

#! /Bin /Баш
ssh -f -L some_port: private_machine: 22 пользователь @ шлюз «sleep 10» & & & & ssh -p some_port private_user @ localhost

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

  1. Установите туннель для протокола ssh (порт 22) на частную машину.
  2. Только если это успешно, ssh в частную машину, используя туннель. (этот & operater обеспечивает это).
  3. После закрытия приватной сессии ssh я хочу, чтобы туннель ssh тоже закрывался. Это делается с помощью трюка «sleep 10». Обычно первая команда ssh закрывается через 10 секунд, но в течение этого времени вторая команда ssh установит соединение с использованием туннеля. В результате первая команда ssh удерживает туннель открытым до тех пор, пока не будут выполнены следующие два условия: сон 10 завершен, и туннель больше не используется.
ответил Bernhard Kausler 24 Jpm1000000pmSun, 24 Jan 2010 21:47:37 +030010 2010, 21:47:37
16

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

#! /USR /бен /Perl

$ iport = 13021;
$ first = 1;

foreach (@ARGV) {
  если (/^ - /) {
    $ 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";
  система ($ _);
}

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

Для доступа к HOSTC через HOSTA и HOSTB (тот же пользователь):

mssh HOSTA HOSTB HOSTC

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

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

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

mssh HOSTA HOSTB HOSTC -X

Для доступа к порту 8080 на HOSTC через HOSTA и HOSTB:

mssh HOSTA HOSTB -L8080: HOSTC: 8080
ответил Bob Muller 11 Jpm1000000pmWed, 11 Jan 2012 15:02:06 +040012 2012, 15:02:06
16

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

ssh -J jumpuser1 @ jumphost1, jumpuser2 @ jumphost2, ..., jumpuserN @ jumphostN user @ host
ответил nikolay 10 PM000000120000003431 2016, 12:11:34
8

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

Если у вас есть 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 имя пользователя

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

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

ответил silviot 13 MarpmWed, 13 Mar 2013 13:57:28 +04002013-03-13T13:57:28+04:0001 2013, 13:57:28
4
ssh -L 9999: host2: 80 -R 9999: localhost: 9999 host1
  

-L 9999: host2: 80

Средство связывается с localhost: 9999 и любым пакетом, отправленным на localhost: 9999 пересылает его на host2: 80

  

-R 9999: localhost: 9999

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

ответил chinmaya 19 Jam1000000amTue, 19 Jan 2010 05:03:35 +030010 2010, 05:03:35
2

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

  

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

     

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

ssh2 -L 1234: localhost: 23 username @ host
     

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

     

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

     

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

ssh2 -R 1234: localhost: 23 username @ host
     

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

В вашем литье замените localhost в примере с помощью host2 и host с помощью host1.

ответил fideli 16 Jam1000000amSat, 16 Jan 2010 09:34:17 +030010 2010, 09:34:17
2

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

ssh -D 9999 -J host1 host2

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

ответил Cheryl 21 22017vEurope/Moscow11bEurope/MoscowTue, 21 Nov 2017 14:06:21 +0300 2017, 14:06:21
1

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

Описание проблемы

Предположим, что мы имеем следующую сетевую топологию:

наш локальный компьютер <---> сервер 1 <---> сервер 2

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

LocalPC <---> имя хоста: mit.edu <---> hec.edu
                          имя пользователя: bob имя пользователя: john
                          пароль: dylan123 пароль: 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
    Пользователь 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:

 введите описание изображения здесь>> </a> </p>

<p> Некоторые замечания: </p>

<ul>
<li> in <code>~ /.ssh /config</code>, <code>HEC</code> - это имя соединения: вы можете изменить его на все, что хотите. </li>
<li> <code>-D9991</code> сообщает <code>ssh</code>, чтобы установить прокси SOCKS4 на порт <code>9991</code>. </li>
</ul></div>
					 
						<div class=

ответил Franck Dernoncourt 18 MarpmSat, 18 Mar 2017 23:13:02 +03002017-03-18T23:13:02+03:0011 2017, 23:13:02
0

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

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

ответил 19 Jam1000000amTue, 19 Jan 2010 04:35:00 +030010 2010, 04:35:00
0

Вариант 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

    # Туннель от localhost до host1 и от host1 до host2
    # вы можете связать их с host3 ... hostn
    ssh -tt -L $ local_host_port: localhost: $ host1_port $ host1_user @ $ host1 \
    ssh -tt -L $ host1_port: localhost: $ host2_port $ host2_user @ $ host2
ответил Yordan Georgiev 5 +03002017-10-05T11:43:30+03:00312017bEurope/MoscowThu, 05 Oct 2017 11:43:30 +0300 2017, 11:43:30
0

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

localhost $ ssh -D 9999 host1
host1 $ ssh -L 8890: localhost: 8890 host2

, где host2: 8890 работает в Jupyter Notebook.

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

Итак, теперь у меня есть ноутбук на host2, доступный Firefox на localhost: 8890 на моей машине.

ответил amarion 26 J000000Thursday18 2018, 08:24:38

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132