Как я могу SSH к машине A через B в одной команде?

103

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

Вот что я делаю сейчас:

  1. Войти в другой университетский компьютер, скажем, компьютер B

    (Эта машина B доступна через SSH с моего домашнего компьютера.)

  2. Используйте SSH на B для подключения к A.

Есть ли способ сделать это быстрее? Используя только одну команду ssh.

nikosdi
источник
связанные: ssh через несколько хостов
Тревор Бойд Смит

Ответы:

97

Да, используя ProxyCommandв вашей конфигурации SSH.

Создайте файл конфигурации SSH в своем домашнем каталоге (если вы не хотите делать это для всей системы) ~/.ssh/config,:

Host unibroker          # Machine B definition (the broker)
Hostname 12.34.45.56    # Change this IP address to the address of the broker
User myusername         # Change this default user accordingly 
                        # (`user@unibroker` can overwrite it)

Host internalmachine    # Machine A definition (the target host)
ProxyCommand ssh -q unibroker nc -q0 hostname.or.IP.address.internal.machine 22

Теперь вы можете связаться с машиной A напрямую, используя

ssh user@internalmachine

Также обратите внимание, что теперь у вас есть одно целевое имя хоста SSH, вы можете использовать его и в других приложениях. Например:

  • SCP для копирования файлов.

    scp somefile user@internalmachine:~/
    
  • В ваших приложениях с графическим интерфейсом:

    использовать sftp://user@internalmachine/в качестве местоположения для просмотра на машине.

    На основе KDE (Dolphin): использование fish://user@internalmachine/

Примечания

Измените hostname.or.IP.address.internal.machineи порт ( 22) на машину, к которой вы хотите подключиться, как если бы вы были с unibrokerмашины.

В зависимости от версии netcat на хосте unibroker, эта -q0опция должна быть опущена. Что касается аутентификации; вы в основном настраиваете два SSH-соединения со своей рабочей станции. Это означает, что как хост unibroker, так и хост internalmachine проверяются / аутентифицируются один за другим (как для пар ключей / паролей, так и для проверки ключа хоста).

объяснение

Такой подход к использованию ProxyCommandи «netcat» является лишь одним из способов сделать это. Мне это нравится, потому что мой SSH-клиент общается напрямую с целевым компьютером, чтобы я мог проверить ключ хоста с моего клиента и использовать аутентификацию с открытым ключом, не используя другой ключ в брокере.

Каждый Hostопределяет начало нового раздела хоста. Hostnameявляется целевым именем хоста или IP-адресом этого хоста. Userэто то, что вы бы предоставили в качестве пользователя ssh user@hostname.

ProxyCommandбудет использоваться в качестве трубы для целевой машины. Используя SSH для первой машины и напрямую настраивая простой «netcat» ( nc) для цели оттуда, это в основном просто открытый текст на внутреннюю машину от посредника между ними. Эти -qопции , чтобы заглушить любой выход (только личное предпочтение).

Убедитесь, что Netcat установлены на брокере (обычно доступен по умолчанию в Ubuntu) - либо Netcat-OpenBSDУстановите netcat-openbsd или Netcat-традиционногоУстановить netcat-традиционный .

Обратите внимание, что вы все еще используете SSH с шифрованием дважды здесь. Пока канал netcat является открытым текстом, ваш SSH-клиент на вашем ПК настроит другой зашифрованный канал с конечным целевым компьютером.

gertvdijk
источник
4
Мне пришлось удалить опцию -q0, поскольку она не поддерживалась машиной, которую я использовал. Кроме этого, все это работало. Это фантастический совет. Огромное спасибо. :)
Джерри
Я столкнулся с проблемой, ваш ответ работает нормально для меня из терминала, но я не могу сделать это с помощью графического интерфейса пользователя, он говорит: необработанное сообщение об ошибке, истекло время ожидания при входе в систему.
Vikash B
@VikashB Ну, это действительно должно работать. Попробуйте создать НОВЫЙ вопрос, чтобы справиться с вашей конкретной ситуацией.
gertvdijk
Я сделал вот такой вопрос: askubuntu.com/questions/688567/…
Викаш Б
1
В дополнение к мудрому слову @gertvdijk есть замечательная вики-книга на тему прокси-серверов ssh и хостов переходов, которая может служить бесценным справочным материалом.
Трэвис Кларк
51

Хоп за один раз

Очевидной альтернативой подходу ProxyCommand, который я представил в своем другом ответе, было бы «переключение» непосредственно на целевой компьютер:

ssh -t user@machineB ssh user@machineA

Обратите внимание -tна первую sshкоманду. Без него это не получится

Pseudo-terminal will not be allocated because stdin is not a terminal.
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
Permission denied, please try again.
[...]

Это заставит выделяться настоящий TTY

Недостатком этого является то, что теперь вся конфигурация, проверка и аутентификация происходят на компьютере B, что мне действительно не нравится в моей ситуации по соображениям безопасности. Мне нравится моя пара ключей на моем собственном ПК, и я проверяю и проверяю конечную целевую машину с моего собственного ПК. Кроме того, вы можете использовать только интерактивную оболочку для SSH, поэтому это не касается других инструментов, таких как SCP или вашего файлового менеджера с графическим интерфейсом.

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

gertvdijk
источник
Почему бы не получить один ответ как с «One Off», так и с постоянными решениями?
скромно
5
@demure Вот как работают сайты StackExchange ... Смотрите: Каков официальный этикет на ответ на вопрос дважды? говорит: «Лучше опубликовать два разных ответа, чем поместить их в один ответ». , И я не считаю это одним и тем же решением. Постоянный / временно не то, что делает этот подход по-другому, на мой взгляд.
gertvdijk
Другие руководства говорят, что, кроме того, следует использовать ключ -A, но указывают, что это имеет значение для безопасности. Знаете ли вы, что значит пересылать или нет соединение с агентом аутентификации?
Диагональ
@gertvdijk супер ниндзя здесь! у вас есть лучшие два решения. Я никогда не видел этого раньше. очень круто. Это лучше, чем создание одного мега длинного решения с N решениями (что я обычно вижу).
Тревор Бойд Смит
Это гораздо удобнее, чем настраивать конфигурацию, которая будет препятствовать другим ssh.
Нихил Саху
37

Вы можете использовать параметр -Jкомандной строки:

ssh -J user@machineB user@machineA

От man ssh:

-J [user@]host[:port]
     Connect to the target host by first making a ssh connection to
     the jump host and then establishing a TCP forwarding to the
     ultimate destination from there.  Multiple jump hops may be
     specified separated by comma characters.  This is a shortcut to
     specify a ProxyJump configuration directive.

Он был представлен в OpenSSH версии 7.3 (выпущен в августе 2016 года). Это доступно в Ubuntu 16.10 и позже.

Эрик Шёлунд
источник
3
+1, потому что это работает, даже если вам нужно указать ключевой файл для machineA
Горе
1
+1, это лучшая версия по сравнению с моим ответом ProxyCommand, если все ваши хосты используют версию OpenSSH достаточно недавно.
gertvdijk
В этом случае сервер OpenSSH должен быть установлен на компьютерах A и B? Я правильно понял?
Михаил
17

Попробуйте использовать

Host <visible hostname alias>
        Controlmaster auto
        User <user>
        hostname <visible hostname>
        port <port>
        IdentityFile ~/.ssh/<id file>

Host <private LAN hostname alias>
     ProxyCommand ssh -q -W <private LAN hostname>:<private LAN port> <visible hostname alias>

в вашем ~ / .ssh / config и делайте все это за один раз с ключами, находящимися только на вашем компьютере.

Справка по SSH
источник
1
Это более чисто, чем введение netcat в смесь. Кроме того, закрытый ключ SSH также не должен существовать на Bкомпьютере.
danemacmillan
1

Это очень полезное предложение. Потратив несколько часов, я нашел эту заметку и подтвердил, что она работает именно так, как задокументировано. Для подключения через MachineA к MachineB с удаленного компьютера C:

Например: [xuser @ machineC ~] ssh -t MachineA ssh MachineB

«-T» имеет решающее значение, ssh не работает, если его нет. Вам будет предложено дважды, сначала для пароля на MachineA, затем второй раз для MachineB. Также обратите внимание, что это предполагает, что у вас есть пользователь "xuser", определенный на всех трех машинах. Если нет, просто используйте синтаксис ssh: "yuser @ MachineA ...". Также обратите внимание, что при желании вы можете использовать точечные четырехточечные IP-адреса. Это полезно, если вы соединяетесь через частную локальную сеть, которая использует IP-адреса, не представленные миру. не в вашем локальном файле хоста или в любом DNS. Чтобы получить файл с MachineB на удаленный machineC, вы можете перейти с MachineB на MachineA, а затем с MachineA на удаленный machineC. (Например, удаленный компьютер C может пропинговать MachineA, но не MachineB.) Предостережение: Я тестировал с Fedora и WindowsXP, MachineA - это XP-box с ICS (Internet Connection Sharing), в то время как MachineB и удаленный machineC являются блоками Fedora-Linux. Это предложение решило ключевую проблему для меня - т.е. ограниченный, контролируемый удаленный доступ к моей локальной сети. Также обратите внимание, что когда вы «выходите из системы» из MachineB, вы должны видеть два «Соединение с xxx.xxx.xxx.xxx закрыто». Сообщения.

Mcl
источник
Если вы установили и настроили аутентификацию с открытым ключом, вам не нужно беспокоиться о вводе паролей. Но -tвсе еще требуется.
Фелипе Альварес,
@FelipeAlvarez Вам все равно придется беспокоиться о вводе второго пароля, если вы не доверяете машине B иметь беспарольный вход в систему A!
Майкл
1

ProxyCommand - это чистое решение для случая, когда вы разрешаете доступ к оболочке в обеих системах. Мы хотели предоставить удаленным пользователям доступ к внутренней машине (A) через посредника (B), но без предоставления пользователю доступа к оболочке B для повышения безопасности. Это сработало:

Заменить оболочку входа

Замените оболочку входа в систему (используйте chsh) для extuserброкера следующим сценарием (хранится в файле):

#!/bin/sh   # this is essential to avoid Exec format error
ssh internaluser@A

При условии, что в extuser @ B для удаленного пользователя не задан пароль для входа в систему и в internaluser @ A для extuser @ B, выполнение следующей команды приведет к тому, что удаленный пользователь будет напрямую переведен в A

ssh extuser@B

Совет : Создайте необходимую настройку без пароля для входа в систему authorized_keys в extuser @ B, прежде чем переходить на пользовательскую оболочку входа. После внесения изменений, поскольку эта учетная запись недоступна кому-либо через оболочку, только sudoer @ B может внести изменения в файл author_keys, отредактировав его напрямую.

sudo vi ~extuser/.ssh/authorized_keys
sudo touch ~extuser/.hushlogin

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

Sunthar
источник
Очень интересный подход. Однако основными недостатками этого являются: 1) Использование ограничено стандартным использованием SSH (без поддержки SFTP / SCP). 2) Пользователь не может выбрать другой целевой хост, кроме одного (поскольку он жестко задан в оболочке входа в систему). 3) Проверка ключа хоста не может быть выполнена с рабочей станции до конечного целевого хоста (поскольку используется двоичный файл SSH посредника). , 4) Закрытые ключи для доступа пользователей к конечному целевому хосту находятся у брокера, а не у пользователя. Это позволяет выдавать себя за пользователя администратором (что обычно невозможно).
gertvdijk
Все верно, спасибо за разработку. Однако основная цель - предоставить ssh доступ доверенного пользователя к S без входа в систему B. Поскольку только администратор может добавить открытый ключ доверенного пользователя на B (через sudo, без входа в систему), это уже означает, что пользователь имеет ( admin) доступ к закрытому ключу extuser @ B (не для доверенного пользователя снаружи), и он настроил его, в первую очередь!
Сунтар
1

Вы имеете в виду, что вам нужно несколько перемычек :)

Недавно я столкнулся с этой проблемой с jumper1 jumper2 и моей последней машиной, что касается моего sol

локальный скрипт:

#!/bin/bash
sshpass -p jumper1Passwd ssh -t jumper1@jumper1IP ./Y00.sh

Затем на 1-й перемычке (которая является моим маршрутизатором) я поместил скрипт с именем Y00.sh:

ssh -tt jumper2@jumper2 -i ~/.ssh/id_rsa sshpass -p finalPassWord ssh -tt final@final

Вы можете заменить их своим IP и паролями, удачи!

Z-Y00
источник