Як SSH обробляти A через B в одній команді?


103

Я хочу отримати доступ до комп'ютера, скажімо, машини A, який базується в мережі мого університету. Однак цей комп'ютер доступний лише через внутрішню мережу університету, тому я не можу використовувати SSH на цьому комп’ютері з дому безпосередньо.

Ось що я зараз роблю:

  1. Увійдіть до іншої університетської машини, скажімо, машини B

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

  2. Використовуйте SSH на B для підключення до А.

Чи є спосіб зробити це швидше? Використовуючи лише одну команду 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

Тепер ви можете дістатися до Machine A безпосередньо

ssh user@internalmachine

Також зауважте, що тепер у вас є одне цільове ім'я хоста SSH, ви можете використовувати це і в інших програмах. Наприклад:

  • SCP для копіювання файлів.

    scp somefile user@internalmachine:~/
    
  • У ваших програмах GUI:

    використовувати sftp://user@internalmachine/як місце для перегляду на пристрої.

    На основі KDE (Дельфін): використання fish://user@internalmachine/

Примітки

Змініть hostname.or.IP.address.internal.machineі порт ( 22) на машину, до якої ви хочете доїхати, як ніби з unibrokerмашини.

Залежно від версій netcat на хості unibroker, -q0параметр повинен бути пропущений. Щодо аутентифікації; ви в основному встановлюєте два SSH-з'єднання зі своєї робочої станції. Це означає, що і хост unibroker, і хост внутрішньої машини перевірені / автентифіковані один за одним (як для підтвердження ключа, / пароля, так і для перевірки ключа хоста).

Пояснення

Такий підхід використання 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 на вашому ПК налаштує ще один зашифрований канал із кінцевою машиною націлення.


4
Мені довелося видалити параметр -q0, оскільки він не підтримувався машиною, якою я користувався. Крім цього, все працювало. Це FANTASTIC порада. Дуже дякую. :)
Джеррі

Я зіткнувся з проблемою, ваша відповідь працює добре для мене з терміналу, але я не в змозі зробити це за допомогою gui sftp, він говорить: непоправлене повідомлення про помилку, вимкнене під час входу в систему.
Vikash B

@VikashB Ну, це справді має працювати. Подумайте про створення НОВОГО питання, щоб вирішити вашу конкретну ситуацію.
gertvdijk

У мене тут питання: askubuntu.com/questions/688567/…
Vikash B

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 або з використанням файлового менеджера GUI.

З усіх вищезазначених причин настійно рекомендую підхід ProxyCommand , але для швидкого підключення це працює чудово.


Чому б не було однієї відповіді як з рішеннями "Один вихід", так і постійними?
деморе

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.

Він був представлений у версії 7.3 OpenSSH (вийшов у серпні 2016 року). Він доступний в Ubuntu 16.10 та пізніших версіях.


3
+1, оскільки це працює, навіть якщо вам потрібно вказати ключовий файл для машиниA
горе

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 та виконайте це за один кадр, за допомогою клавіш, що знаходяться лише на вашому комп'ютері.


1
Це більш чисто, ніж введення тьотки в суміш. Також приватний ключ SSH також не повинен існувати на Bмашині.
danemacmillan

1

Це дуже корисна пропозиція. Протягом багатьох годин возившись, я знайшов цю замітку і підтвердив, що це працює саме так, як це зафіксовано. Для підключення через MachineA до MachineB, від віддаленого machineC:

наприклад: [xuser @ machineC ~] ssh -t MachineA ssh MachineB

"-T" є критичним, ssh виходить з ладу, якщо його немає. Вам буде запропоновано двічі: спочатку про пароль на MachineA, потім вдруге для MachineB. Також зауважте, що це передбачає, що на всіх трьох машинах визначено "xuser" користувача. Якщо ні, просто використовуйте синтаксис ssh: "yuser @ MachineA ...". Також зауважте, що ви можете використовувати крапкові IP-файли з чотиригранними, якщо ви хочете. Це корисно, якщо ви зв’язуєтесь через приватну локальну мережу, яка використовує IP-адреси, не піддані впливу світу - тобто. не у вашому локальному файлі хоста чи будь-якому DNS. Щоб отримати файл від MachineB, до віддаленого machineC, ви можете зробити scp від MachineB до MachineA, потім від MachineA до віддаленого machineC. (Наприклад, віддалений machineC може пінгувати MachineA, але не MachineB.) Caveat: Я тестував Fedora та WindowsXP, MachineA - це ящик XP, на якому працює ICS (Internet Sharing Sharing), тоді як MachineB і віддалений machineC - це коробки Fedora-Linux. Ця пропозиція вирішила для мене ключову проблему - тобто. віддалений доступ до мого віддаленого веб-сайту з обмеженим контролем. Зауважте також, що під час "виходу" з MachineB, ви повинні побачити два "З'єднання до xxx.xxx.xxx.xxx закрите." повідомлення.


Якщо ви налаштували та налаштували аутентифікацію відкритих ключів, вам не потрібно буде турбуватися про введення паролів. Але -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 для віддаленого користувача та у внутрішньому користувачі @ A для extuser @ B, виконання наступної команди безпосередньо переведе віддаленого користувача на A

ssh extuser@B

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

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

Останній рядок - придушити відображення банера для входу з B, тому віддалений користувач має прозорий доступ до A.


Дуже цікавий підхід. Однак основними недоліками цього є: 1) Використання обмежено стандартним використанням SSH (відсутність підтримки SFTP / SCP). 2) Користувач не може обрати інший цільовий хост, окрім одиничного (тому що він жорстко закодований в оболонці входу) 3) Перевірка ключа хоста не може бути виконана від робочої станції до кінцевого цільового хоста (оскільки використання SSH-брокера брокера) . 4) Приватні ключі для доступу користувачів до кінцевого цільового хоста знаходяться у брокера, а не у користувача. Це дозволяє іммініфікувати користувача адміністратором (що зазвичай неможливо).
gertvdijk

Усі пункти правдиві, дякую за детальну розробку. Однак головна мета - забезпечити доступ ssh довіреного користувача до A без входу до B. Оскільки лише адміністратор може додати відкритий ключ довіреного користувача на B (через sudo, без входу), це вже означає, що користувач має ( адміністратор) доступ до приватного ключа extuser @ B (не належить довіреному користувачеві ззовні), і встановив його, в першу чергу!
Сунтар

1

Ви маєте на увазі, що вам потрібно кілька перемичок :)

Нещодавно я зустрів цю проблему з jumper1 jumper2 та моєю остаточною машиною, що стосується мого золя

локальний сценарій:

#!/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 та паролями, удачі!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.