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


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

ssh -D9999 username@example.com

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

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

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


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


272
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

138
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


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

ssh -D 9999 -J host1 host2

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


2
2017-11-21 11:06





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

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

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

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 bob@mit.edu -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
2018-03-18 20:13