Переадресация трафика SSH через промежуточную машину


110

SSH туннелирование меня очень смущает. Мне интересно, могу ли я сделать это в Linux.

У меня 3 машины ..

A. My local machine at home.
B. Machine at work that I can SSH into (middle man).
C. My desktop at work that I can only SSH into from machine B.

Так что я могу SSH от A -> B и от B -> C, но не от A -> C.

Есть ли способ настроить SSH-туннель от A до B, поэтому, когда я запускаю другие SSH-команды, они просто работают с моей локальной машины A? Я в основном пытаюсь клонировать git-репозиторий с работы на дом (и я не могу установить git на компьютер B).

Кроме того, после настройки .. Как бы я также отключил его?


я полагаю, что где-то есть дублирующий вопрос, но мое поисковое фу сегодня слабое.
Квик-кихот



Если вы используете Linux на компьютере A, используйте инструмент под названием sshuttle, который позволяет вам выборочно пересылать весь трафик для C через туннель A-> B (при условии, что C виден из B).
joat

Ответы:


128

Поместите это в свой .ssh/configфайл на hostA (подробнее см. Man 5 ssh_config ):

# .ssh/config on hostA:
Host hostC
    ProxyCommand ssh hostB -W %h:%p

Теперь следующая команда автоматически туннелирует через hostB

hostA:~$ ssh hostC

Возможно, вы захотите добавить такие параметры, как -oCiphers=arcfourи, -oClearAllForwardings=yesчтобы ускорить процесс, так как упаковка sshвнутри sshвычислительно дороже, и дополнительные усилия и оболочка не должны быть такими же безопасными, когда они туннелируют уже зашифрованный трафик.


Если вы используете OpenSSH ранее, чем 5.3, -Wопция недоступна. В этом случае вы можете реализовать вышеизложенное с помощью netcat ( nc):

ProxyCommand ssh hostB nc %h %p  # or netcat or whatever you have on hostB

1
Это великолепно! Спасибо. Это решает проблему, с которой я сталкиваюсь последние 2 дня: hostC находится за брандмауэром и располагает данными, к которым я хочу получить доступ с hostA, ноутбука, который может быть в любой точке мира. hostB также находится за тем же межсетевым экраном, что и hostC, но у него есть открытый для всего мира порт SSH. Таким образом я могу ssh из hostC -> hostB. Я установил обратный SSH-туннель между hostC и hostB, поэтому я также могу ssh из hostB -> hostC (пересылается через localhost). С твоей уловкой я могу перейти от hostA -> hostC! Он работает без проблем с SCP и Fugu на OSX! Спасибо!
AndyL

-WВариант следует использовать вместо ncопции.
vy32

Какой SSH должен поддерживать -W, только один на hostA (источник) или также на hostB (средний компьютер)?
gioele

Для информации, если у вас есть несколько хостов, к которым вам нужно подключиться через один и тот же сервер hostB, можно объявить несколько Host hostCстрок выше, ProxyCommandчтобы было очень легко получить доступ к нескольким хостам через промежуточный сервер.
Fduff

7

Редактировать: это неправильный подход. Вместо этого смотрите ответ Эфимента . Этот ответ будет работать, но потенциально менее безопасен и определенно менее удивителен.

Похоже, вы хотите решение, подобное следующему:

ssh -L localhost:22:machinec:22 machineb

Это даст вам оболочку machineb. Оставь это в покое. сверните окно терминала.

Теперь, когда вы устанавливаете ssh-соединение с localhost, вы на самом деле будете подключены machinecчерез machineb. Когда вы закончите с туннелем, просто закройте терминал, в котором вы выполнили вышеуказанную команду.

Обратите внимание, что вам понадобятся привилегии суперпользователя для запуска команды.


+1 Спасибо Уэсли. Это настоящий ssh-туннельный ответ. Вот статья об этом: securityfocus.com/infocus/1816
Ларри К

3
В целом, это довольно плохо ... но мне приходилось делать это с древними версиями OpenSSH или других клиентов ssh. Вы можете выбрать какой-нибудь высокий порт, например, 8022: таким образом, он не мешает работе службы ssh на локальном хосте и не требует запуска с правами root. Просто добавьте -p 8022в ваши команды ssh. С помощью git все очень просто: используйте URI ssh://localhost:8022/path/to/repo.git.
Эфимент

3

Похоже, вам нужен псевдоним оболочки на A, который вызывает ssh на C

  1. Я предполагаю, что на A, вы можете набрать ssh me @ b "ssh me @ c hostname" и получить обратно "C"
  2. Сделайте псевдоним sshc, который расширяет sshc foo в ssh me @ b "ssh me @ c foo"
  3. Для точного синтаксиса создания псевдонима, обратитесь к superuser.com

1
Возможно, вам придется добавить -tк внешним параметрам ssh, если вы хотите интерактивную оболочку, так как sshпредполагается, -Tчто ей дана команда.
Эфимент

1

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

ssh -J <user>@<hostB> <user>@<hostC>

Опции -J для прыжка .


0

Если ваш работодатель предоставляет VPN, я бы рекомендовал использовать его вместо этого.

Таким образом, вам не придется специально настраивать какие-либо приложения (даже ssh), и вы сможете увидеть любую машину за брандмауэром. Кроме того, весь ваш трафик будет зашифрован программным обеспечением VPN, что повысит безопасность любого непреднамеренно или намеренно незашифрованного трафика.


6
Иногда именно из-за VPN нам нужны эти уловки ...
Луи

0

Ясс Еще одно простое решение

ssh -f -L 2222:HostC_IP_or_Name:22 userOnB@hostB sleep 10 &&
    ssh -o HostKeyAlias=HostC -p 2222 userOnC@localhost
  • Первая команда открывает ssh-соединение с HostB и сообщает HostB о переадресации соединений с localhost: 2222 на HostC: 22 .
  • -fпараметр указывает SSH переходить в фоновый режим после установления соединения
  • Вторая команда просто открывает клиентское соединение с localhost: 2222
  • Опция HostKeyAlias не требуется, но может помочь предотвратить подключение к неправильному хосту
  • Примечание: команда sleep 10необходима для поддержания соединения до тех пор, пока вторая команда ssh не использует перенаправленный порт. Тогда первый ssh закроется, когда второй ssh покинет перенаправленный порт.

Теперь вы можете запустить последующие сеансы SSH:

ssh -o HostKeyAlias=HostC -p 2222 userOnC@localhost

Вариант:

ssh -f -L 2222:HostC_IP_or_Name:22 userOnB@hostB sleep 10 &&
    ssh -M -S ~/.ssh/ssh_HostC22userOnC.sock -o HostKeyAlias=HostC -p 2222 userOnC@localhost

последующие сеансы ssh могут быть открыты с помощью команды:

ssh -S ~/.ssh/ssh_HostC22userOnC.sock userOnC@localhost

Основное преимущество использования параметров -M и -S состоит в том, что между HostA и HostC открыто только одно соединение, последующий сеанс не будет проходить проверку подлинности и будет выполняться намного быстрее.


0

Особый случай, смешанные платформы NIX:

  hostA (linux) -> HostB (solaris) -> HostC (linux)

Если вам нужно приложение X на hostC, а промежуточный переход - на коробке Solaris ... в этом случае я нашел netcat (nc), необходимый для ProxyCommand, примерно так:

hostA: ~ $ vi .ssh / config:

Host hostC
    ProxyCommand ssh hostB nc% h% p #, где nc - это netcat

Затем работает автоматическое туннелирование:

hostA: ~ $ ssh hostC

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.