scp файлы через промежуточный хост

У меня есть доступ к 3 машинам, A, B и C. Единственные возможные (ssh) соединения:

A -> B
B <-> C

Мне нужно получить файлы из A в C, чтобы я мог просмотреть файлы из A в B, а затем скопировать их из B в C. Однако B не имеет много места на диске, так что это не вариант. Есть ли способ scp файлы из A в C через B? Обратите внимание, что у меня нет доступа с правами root ни на одной из машин, поэтому не думайте, что я могу настроить какие-либо постоянные туннели, но исправьте меня, если я ошибаюсь!

4 ответа

Решение

ProxyJump

Новое в OpenSSH 7.3:

A$ scp -oProxyJump=B thefile C:destination

(За кулисами, это просто использует ProxyCommand и ssh -W .)

ProxyCommand

Обновлено, чтобы включить -W из других ответов:

A$ scp -oProxyCommand="ssh -W %h:%p B" thefile C:destination

Если у A установлен очень старый SSH-клиент (без -W поддержка), или если B настроен на запрет перенаправления TCP (но все еще разрешает команды оболочки), используйте альтернативы:

A$ scp -oProxyCommand="ssh B socat stdio tcp:%h:%p" thefile C:destination
A$ scp -oProxyCommand="ssh B nc %h %p" thefile C:destination

трубы

A$ tar cf - thefile anotherfile | ssh B "ssh C \"cd destination && tar xvf -\""
A$ (echo thefile; echo anotherfile) | cpio -o | ssh B "ssh C \"cd destination && cpio -i\""

Только для одного файла:

A$ ssh B "ssh C \"cd destination && cat > thefile\"" < thefile

"Туннель" через Б

A$ ssh -f -N -L 4567:C:22 B
(continues running in background)

A$ scp -P 4567 thefile localhost:destinationPath

Когда вы закончите, не забудьте убить ранее начатый ssh процесс (который упал на фон из-за -f -N ).

  • -f Запрашивает ssh перейти в фоновый режим непосредственно перед выполнением команды. Это полезно, если ssh собирается запрашивать пароли или парольные фразы, но пользователь хочет сделать это в фоновом режиме. Это подразумевает -n.
  • -N Не выполняйте удаленную команду. Это полезно только для переадресации портов.

Обратный "туннель" через B к A

Не всегда работает, хотя:

A$ ssh -f -N -R 4567:localhost:22 B
(now you can reach A from B, by using localhost:4567)

B$ scp -P 4567 localhost:thefile C:destination
  • -R Указывает, что соединения с данным портом TCP или сокетом Unix на удаленном (серверном) хосте должны перенаправляться на данный хост и порт или сокет Unix на локальной стороне.

Версии scp с начала 2011 года и позже могут иметь опцию "-3":

 -3      Copies between two remote hosts are transferred through the local
         host.  Without this option the data is copied directly between
         the two remote hosts.  Note that this option disables the
         progress meter.

Если у вас есть это, вы можете просто запустить:

B$ scp -3 A:file C:file

Почти все уже сказано, но вот моя последняя копейка: я использую вариант ProxyCommand без nc ни soc, На основе прокси-серверов OpenSSH и Jumphost Cookbook я создал следующую конфигурацию:

  1. Итак, у нас есть следующие игроки:

    • HOME_HOST: это откуда мы копируем файл на целевой хост
    • HOP_HOST: мы копируем через этот хост (зарегистрирован как HOP_USER)
    • TARGET_HOST: это наш пункт назначения (аутентифицированный как TARGET_USER)
  2. Сначала я добавил свой локальный открытый ключ от моего домашнего хоста .ssh/id_dsa.pubв .ssh/authorized_keys на обоих прыжках и целевых хостах. Да, один и тот же открытый ключ от домашнего хоста для них обоих. Обычно вы ожидаете, что это открытый ключ HOP, который вы должны добавить к TARGET.

  3. Потом я подправил .ssh/config немного добавив следующую запись:

    Host TARGET_HOST
       User TARGET_USER
       ProxyCommand ssh -W %h:%p HOP_USER@HOP_HOST
    
  4. После этого операция копирования так же проста, как: scp FILE TARGET_HOST:, Он отображает двойные баннеры как с узла, так и с узла, но работает.

Конечно, вы можете использовать выше для ssh непосредственно к цели: ssh TARGET_HOST, Работает с scp и ssh.

Другим более общим вариантом может быть утилита sshuttle, которая выглядит как своего рода прозрачный прокси (vpn over ssh). Так что в вашем случае A-> B<->C это позволяет подключиться к каждому узлу в сети C: A->B-[CDEFG]. Ему не нужен админ, но он требует Python 2.7 (3.5 тоже хорошо), что не всегда то, что мы имеем. Это стоит попробовать.

ssh -L 4321:hostC:22 youruser@hostB

в другой оболочке:

scp -P 4321 localfile youruser@127.0.0.1

Это использует переадресацию портов. Единственным ограничением здесь является то, что хост B должен быть настроен для разрешения переадресации портов. В противном случае это должно работать нормально.

В пути объяснения, -L а также -R позволяют перенаправлять порты. В -L первый указанный порт - это порт ssh, который начнет слушать на исходной машине (хост A), и он перенаправит все, что получит через этот порт через ваше соединение SSH, на хост B, а затем направит его на хост C на порт 22.

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

Я немного испортил синтаксис. Это настраивает форварда на вашей локальной машине.

Ответ Grawity ProxyCommand работал для меня, но, поскольку я менее знаком с SSH, потребовались некоторые эксперименты. Я думал, что просто изложу ответ Гравити более подробно, чтобы помочь другим новичкам в SSH, таким как я. Вот определения для более явного обозначения:

Машина A: машина, на которой вы находитесь

Сервер B: userB@ip.address.for.B (сервер перехода или промежуточный сервер)

Сервер C: userC@ip.address.for.C (удаленный сервер, на который вы хотите скопировать)

ProxyCommnad

    A$ scp -oProxyCommand="ssh -W %h:%p userB@ip.address.for.B" thefile userC@ip.address.for.C:destination

Конкретный пример

Итак, для конкретного примера, скажем, у вас есть доступ к серверу с IP 0.0.1.2 с учетной записью пользователя с именем bar (Сервер C). Но чтобы добраться до него, нужно сначала войти на сервер с IP 0.0.1.1 с именем пользователя foo (Сервер Б). Теперь вы хотите скопировать файл baz.txt расположен на вашем текущем компьютере (машина A) к серверу 0.0.1.2"s /home/bar/ каталог. Чтобы использовать вышеупомянутый ProxyCommand для этого примера, вы должны выполнить следующее:

    A$ scp -oProxyCommand="ssh -W %h:%p foo@0.0.1.1" baz.txt bar@0.0.1.2:/home/bar/

Вы также можете с легкостью скопировать файл с сервера C, изменив его порядок и место назначения. Так, например, если baz.txt был уже на сервере 0.0.1.2 находится в /home/bar/ тогда вы можете скопировать его на свой компьютер, используя:

    A$ scp -oProxyCommand="ssh -W %h:%p foo@0.0.1.1" bar@0.0.1.2:/home/bar/baz.txt /destination/path/on/A

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

Начиная с v7.3 OpenSSH поддерживает -J. Чтобы отправить в C из A в A:

tar cf - file1 file_n | ssh -J userB@B:Bport userB@C -p Cport 'tar -C destDir xvf -'
  • Используйте столько прыжков, сколько хотите, с ssh -J вариант.
  • Опустить -C чтобы оставить файлы в домашней папке.
  • Отправляйте сразу любые файлы (текстовые или двоичные).
  • При необходимости сжимаем поток tar -z или ssh -C.

Вдохновленный на Florian Фида и Дэна Garthwaite в ответах.

Другие вопросы по тегам