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


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

ssh -D9999 username@example.com

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

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

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


284
2018-01-16 05:58


Источник


Для чего вы его использовали? Я хочу использовать его для прокси-сервера socks. Это будет работать? - prongs
Да, вы должны иметь возможность использовать туннелированное соединение как прокси-сервер SOCKS, если только host2 отказывает в пересылке - Mala
Я думал о создании обертки над SSH, который установил бы это, используя многократное использование ProxyCommand. - Pavel Šimerda
@prongs Вам удалось использовать это для прокси SOCKS (все эти годы назад)? - Drux


Ответы:


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

  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 сам.


269
2018-01-17 21:31



вариант 3 был тем, что я искал, спасибо! - Mala
Я хочу сделать это так. Какой из них лучше? Я попробовал сначала, но это не сработало. Я установил прокси-сервер в моем браузере localhost: 1234, но не повезло. :( пожалуйста помоги.. - prongs
@prongs попробуйте вариант 3 - Mala
есть способ переслать мой открытый ключ с localhost, через туннель хоста 1, на host2? - Noli
@Noli Если вы используете ssh-agent (который вам нужен), вы можете переслать его через соединения, используя -A опция ssh. - 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

137
2017-08-01 17:10



Есть ли способ сделать это условно? Я только хочу делать это иногда. Кроме того, это специально для команд, но я ищу что-то для всего порта 22 (ssh, sftp и т. Д.). - Stephane
@Stephane, что вы подразумеваете под специально для команд? Ваша конфигурация SSH используется любым использованием ssh, в том числе git, sftp и т. д. afaik. - kynan
@Stephane Я не знаю, как это сделать условно (например, только когда вы находитесь за пределами сети целевого хоста). Я установил эту опцию для всех рассматриваемых узлов в блоке конфигурации, а затем (un) прокомментировал строку по мере необходимости. Не идеально, но он работает. - kynan
@Stephane уверен: ssh -F /path/to/altconfig, Помните, что это игнорирует всю систему /etc/ssh/ssh_config, - kynan
Простой способ сделать настройки «условными» - это определить два разных хоста в .ssh / config, которые имеют одинаковое имя хоста. Подключитесь к хост-туннелю, если хотите туннель, и host2, когда вы этого не сделаете. - Steve Bennett


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

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

#!/bin/bash
ssh -f -L some_port:private_machine:22 user@gateway "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 завершен и туннель больше не используется.

20
2018-01-24 18:47



Очень умно!!! ЛЮБИТЬ ЭТО! - Hendy Irawan


Прочитав выше и склеив все вместе, я создал следующий скрипт 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 user1@HOSTA:1234 user2@HOSTB:1222 user3@HOSTC:78231

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

mssh HOSTA HOSTB HOSTC -X

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

mssh HOSTA HOSTB -L8080:HOSTC:8080

16
2018-01-11 11:02



это круто - Mala
Я серьезно не могу вас поблагодарить, этот сценарий облегчает мою жизнь на ежедневной основе. Единственное, что я изменил, это добавить int (rand (1000)) в iport, чтобы одновременно запускать несколько экземпляров. Я определенно должен тебе пиво. - Mala
Это работает очень хорошо. Дальнейшим улучшением будет разрешение HOSTB, HOSTC и т. Д., Используя localhost's / etc / hosts и ~ / .ssh / config - Steve Bennett
Также я второй комментарий Малы. Без рандомизированного порта, если вы затем попытаетесь mssh HOSTA HOSTD вы на самом деле окажетесь в HOSTB (и, возможно, не поймете ...) - Steve Bennett


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

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 Это ускорит получение firefox с host2 на localhost. - Jaur


Этот ответ похож на 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
2018-03-13 09:57



Я считаю, что это является причиной трюка: wiki.gentoo.org/wiki/SSH_jump_host - slm
@slm да, вот и все! Благодаря! - silviot


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


4
2018-01-19 02:03



Блестящий, самый простой ответ, чтобы создать туннель, чтобы вы могли получить доступ к приложению на хосте2 непосредственно с localhost: 9999 - dvtoever
После этого ответа я получаю channel 3: open failed: administratively prohibited: open failed  сообщение об ошибке. - Franck Dernoncourt


вы должны иметь возможность использовать переадресацию портов для доступа к службе на 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,


2
2018-01-16 06:34



согласно этой статье соединение будет закреплено только до средней машины (host1). Есть ли способ убедиться, что все это остается в безопасности? - Mala
Я никогда не пробовал этого, но если host1 и host2 являются серверами ssh, вы можете настроить туннель от host1 до host2, а затем настроить туннель от localhost до host1 для той же службы (получение локального и удаленного порты вправо). Я не знаю, возможно ли это в одной команде из localhost. - fideli