Как настроить ярлык для соединения SSH через туннель SSH


22

Производственные серверы моей компании (FOO, BAR ...) расположены за двумя шлюзовыми серверами (A, B). Чтобы подключиться к серверу FOO, мне нужно открыть ssh-соединение с сервером A или B с моим именем пользователя JOHNDOE, затем из A (или B) я могу получить доступ к любому производственному серверу, открывающему соединение SSH со стандартным именем пользователя (назовем его Webby).

Итак, каждый раз, когда я должен сделать что-то вроде:

ssh johndoe@a
...
ssh webby@foo
...
# now I can work on the server

Как вы можете себе представить, это хлопотно, когда мне нужно использовать scpили если мне нужно быстро открыть несколько соединений.

Я настроил ключ ssh, а также я использую .ssh / config для некоторых ярлыков.

Мне было интересно, могу ли я создать какую-то конфигурацию ssh для того, чтобы напечатать

ssh foo

и пусть SSH открывает / пересылает все соединения для меня. Является ли это возможным?

редактировать

Ответ womble - именно то, что я искал, но, похоже, сейчас я не могу использовать netcat, потому что он не установлен на сервере шлюза.

weppos:~ weppos$ ssh foo -vv
OpenSSH_5.1p1, OpenSSL 0.9.7l 28 Sep 2006
debug1: Reading configuration data /Users/xyz/.ssh/config
debug1: Applying options for foo
debug1: Reading configuration data /etc/ssh_config
debug2: ssh_connect: needpriv 0
debug1: Executing proxy command: exec ssh a nc -w 3 foo 22
debug1: permanently_drop_suid: 501
debug1: identity file /Users/xyz/.ssh/identity type -1
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type 'Proc-Type:'
debug2: key_type_from_name: unknown key type 'DEK-Info:'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /Users/xyz/.ssh/id_rsa type 1
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type 'Proc-Type:'
debug2: key_type_from_name: unknown key type 'DEK-Info:'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /Users/xyz/.ssh/id_dsa type 2
bash: nc: command not found
ssh_exchange_identification: Connection closed by remote host

Ответы:


36

В качестве более конкретной версии ответа Кайла, вы хотите поместить в свой ~/.ssh/configфайл:

host foo
  User webby
  ProxyCommand ssh a nc -w 3 %h %p

host a
  User johndoe

Затем, когда вы запустите "ssh foo", SSH попытается выполнить SSH johndoe@a, запустить netcat( nc), а затем выполнить SSH, чтобы webby@fooпройти через этот туннель. Магия!

Конечно, для этого необходимо установить netcat на сервере шлюза; Этот пакет доступен для всех основных дистрибутивов и ОС.


Превосходно! Я пытался понять это, я никогда раньше не сталкивался с такой ситуацией. Я буду держать свой ответ там, на случай, если он может помочь кому-то еще с менее определенной ситуацией в будущем.
Кайл Брандт

Я обновил свой оригинальный вопрос, включая подробный вывод моего соединения. Кажется, я не могу использовать netcat. Должен ли он быть доступен по умолчанию?
Симона Карлетти

Не всегда, у вас есть возможность установить его? Вы могли бы сделать это и с помощью telnet, я никогда не пробовал этого ...
Кайл Брандт

Вы также можете загрузить netcat в свой домашний каталог и скомпилировать его там. Затем вы можете просто использовать полный путь в прокси-команде, например / home / userName / bin / nc
Кайл Брандт,

Я только что проверил настройки системы. В Ubuntu netcat, по-видимому, доступен по умолчанию, к сожалению, серверы шлюзов работают на OpenSUSE. Я собираюсь рассмотреть возможность установки netcat на серверах шлюза тоже.
Симона Карлетти

7

Вы можете использовать директиву ProxyCommand в вашем файле ~ / .ssh / config, например, для использования netcat в качестве реле:

host server2
    ProxyCommand ssh server1 nc server2 22

Вы бы просто использовать 'ssh server2'. Информация man-страницы для этой директивы находится в man ssh_config


5

Я предпочитаю другой подход, который поддерживает предварительно аутентифицированный туннель к серверу шлюза. В ~/.ssh/config:

Host a
    ControlMaster auto
    ControlPath ~/.ssh/control-master/%r@%h:%p

Тогда в .bashrc:

s () {
        if ( ssh -O check a 2>&1 > /dev/null 2>&1 )
        then
                ssh -t a ssh $1
        else
                if [[ -S ~/.ssh/control-master/insyte@a:22 ]]
                then
                        echo "Deleting stale socket..."
                        rm ~/.ssh/control-master/insyte@a:22
                fi
                echo "Opening master session..."
                if ssh -Nf a
                then
                         ssh -t a ssh $1
                fi
        fi
 }

Итак, чтобы подключиться к foo:

s foo

При первом подключении он аутентифицирует вас по «а» и открывает постоянный фоновый туннель ssh. Последующие вызовы «s» будут открываться практически мгновенно через предварительно авторизованный туннель.

Работает отлично.


2

Этот тип функциональности существует в более новых версиях OpenSSH и может использоваться

ssh -W server2 server1

Где server2ваш пункт назначения и server1ваш прокси-сервер. Вы можете сделать это проще, используя ProxyCommandопцию в вашей конфигурации ssh, например:

host = *.example.com
user = packs
port = 22
ProxyCommand ssh -W %h:%p server1

Похоже, что для этого вам нужен OpenSSH 5.4+ во всех трех местах: на рабочем столе, посредник, пункт назначения. (Ну первое и последнее, конечно).
Стив Беннетт

@SteveBennett: я уже давно пользуюсь этим методом, он отлично работает. Мне пришлось вернуться к методу netcat на нескольких системах RHEL5, что раздражало.
Скотт Пак

2

Когда netcatнедоступен на прокси, попробуйте этот трюк:

host foo
  User webby      
  ProxyCommand ssh a 'exec 3<>/dev/tcp/foo/22; cat <&3 & cat >&3;kill $!'

host a
  User johndoe

Тогда вы должны быть в состоянии ssh foo.

Также, если у вас есть последняя версия ssh на (то есть, с -Wкомандой для переадресации стандартного ввода и вывода), вы можете использовать:

host foo
  User webby
  ProxyCommand ssh -W foo:%p a

host a
  User johndoe

Наконец, просто потому, что я нахожу это классным (а не потому, что он будет работать в вашем конкретном случае из-за различий в именах пользователей), сообщение в блоге друга указывает, как сделать такие вещи динамическими и рекурсивно связывать прокси-серверы SSH (наряду с некоторыми вещами это плохо работает)

host */*
  ProxyCommand ssh ${$(dirname %h)/\%%/@} nc ${$(basename %h)#*%%} %p

А потом ssh machine1/machine2должен дать вам скорлупу machine2, проложенную через туннель machine1.

Интересно, если использовать пользовательские sedкоманды вместо dirnameи basenameне может решить проблему с разными именами пользователей?


2

Это может быть достигнуто, делая ssh -At johndoe@a ssh webby@foo. Команда -Aпересылает ваш ssh-агент (так что вы можете избежать повторной аутентификации на прокси-сервере), в то время -tкак на прокси-сервере существует терминал. Следующая функция bash может быть полезна:

ssh-bounce () {
    local cmd=""
    for i in "$@"; do
        cmd+="ssh -At $i "
    done
    $cmd
}

Это, безусловно, самое простое решение. Теперь ему просто нужно еще 35 голосов. (Кстати, -А ничего не делает для меня.)
Стив Беннетт

0
weppos:~ weppos$ ssh foo -vv
[..]
bash: nc: command not found

Netcat не установлен на a. Когда вы запускаете ssh host "command arg", commandвыполняется на host, а не на локальном компьютере.


Да, я знаю. Это именно то, что я сообщил в комментарии к ответу Womble. :)
Симона Карлетти

0

Начиная с OpenSSH 7.3 (2016-08-01), ProxyJumpопция и соответствующий -Jфлаг командной строки были доступны, чтобы позволить более простое косвенное обращение через один или несколько бастионов SSH или «переход хостов».

Это устраняет зависимость от внешней ncкоманды, найденной в решении Womble .

ssh -J johndoe@a webby@foo 

установит SSH-соединение с вашей рабочей станции на сервер шлюза aкак пользователь johndoe и туннелирует сеанс SSH для размещения foo для пользователя Webby через него.

Чтобы упростить создание определений хостов для вашего ~/.ssh/configи для вас, вы можете просто выполнитьssh foo

Host a
    User johndoe

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