1

Я ищу обертку SSH (или опцию SSH, если таковая была), которая может попытаться подключиться к нескольким IP-адресам последовательно, пока один из них не будет успешным. Например, 10.0.0.1 , затем my_machine.example.com и, наконец, my_machine.example.com -J me@other_machine.example.com .

Есть ли инструмент, который делает это?

3 ответа3

1

Насколько я знаю, такой встроенной функции нет. Однако это может быть легко написано:

#!/bin/bash

usage ()
{
    echo "usage:"
    echo "  $0 MYHOST"
    echo "or"
    echo "  $0 IP DNS PROXYJUMP"
}

if [[ $# -eq 1 ]]; then
    host="$1"

    ssh ${host}_ip && exit 0
    ssh ${host}_dns && exit 0
    ssh ${host}_proxyjump && exit 0
    exit 1
else if [[ $# -eq 3 ]]; then
    ip="$1"
    dns="$2"
    proxy="$3"

    ssh "$ip" && exit 0
    ssh "$dns" && exit 0
    ssh "$dns" -J "$proxy" && exit 0
    exit 1
else
    echo "Illegal number of argument"
    usage
    exit 1
fi

Со следующим файлом .ssh/config :

Host MYHOST_ip
  Hostname 10.0.0.1

Host MYHOST_dns
  Hostname my_machine.example.com

Host MYHOST_proxyjump
  Hostname my_machine.example.com
  ProxyJump me@other_machine.example.com

Обратите внимание, что подключение может занять много времени, например, в случае использования конфигурации proxyjump. На самом деле соединение может произойти через 2 таймаута.

1

Это моя универсальная ssh оболочка. Ни опция, ни адрес не прописаны. Единственное, что вам может понадобиться настроить - это путь к исполняемому файлу ssh в строке 3 (вы можете использовать executable=ssh , я выбрал полный путь). Вы найдете мой полный код ниже.

Допустим, вы сохранили его как sshmt («ssh, multi target»), куда указывает ваш $PATH , и сделали его исполняемым с помощью chmod . Затем ознакомьтесь с синтаксисом:

sshmt -h

Выдержка:

ИСПОЛЬЗОВАНИЕ

sshmt [-v] ARGS [+[N] ARGS]... [-- COMMON]
sshmt -h

СИНТАКСИС

Вызывает команду ssh с первым набором аргументов ARGS и общими аргументами COMMON . Если эта команда возвращает состояние выхода 255 и существует второй набор аргументов ARGS , то второй ssh будет вызван с этими новыми ARGS и COMMON ; потом третий и тд.

В вашем примере вы хотите вызвать его так:

sshmt 10.0.0.1 + my_machine.example.com + my_machine.example.com -J me@other_machine.example.com

или лучше с некоторыми удобными таймаутами:

sshmt 10.0.0.1 +2 my_machine.example.com +3 my_machine.example.com -J me@other_machine.example.com +5

Чтобы удаленно выполнить df -h простым способом, вызовите:

sshmt 10.0.0.1 df -h +2 my_machine.example.com df -h +3 my_machine.example.com -J me@other_machine.example.com df -h +5

но вы не хотите повторяться, так что используйте вместо этого:

sshmt 10.0.0.1 +2 my_machine.example.com +3 my_machine.example.com -J me@other_machine.example.com +5 -- df -h

Трубы также должны работать:

echo 123 | sshmt 10.0.0.1 +2 my_machine.example.com +3 my_machine.example.com -J me@other_machine.example.com +5 -- sh -c "cat > /tmp/foo"

На практике вы можете определить псевдоним:

alias myssh='sshmt 10.0.0.1 +2 my_machine.example.com +3 my_machine.example.com -J me@other_machine.example.com +5 --'

затем войдите с

myssh

или выполнить команду как

myssh uptime

Это код. Вся его логика просто анализирует командную строку.

#!/usr/bin/env bash

executable=/usr/bin/ssh
exename="${executable##*/}"
myname="${0##*/}"
declare -a args
declare -a seq_opts
declare -a common_opts

main () {
  split_opts "$@"
  process_seq "${seq_opts[@]}" "+"
  exit 255
}

split_opts () {
  while [ $# -ne 0 ]; do
    if [ "$1" = "--" ]; then
      shift
      common_opts=("$@")
      break
    else
      seq_opts=("${seq_opts[@]}" "$1")
      shift
    fi
  done
}

process_seq() {
  if [ "$*" = "+" ] || [ "$1" = "-h" ]; then
    print_help; exit 0
  fi

  while [ $# -ne 0 ]; do
    if [ "${1:0:1}" != "+" ]; then
      args=("${args[@]}" "$1")
    else
      timeout="${1:1}"
      [[ "$timeout" =~ ^[0-9]*$ ]] || print_error
      if [ "${#args[*]}" -ne 0 ]; then
        printf '%s\n' "${myname}: trying ${args[*]}" >&2
        "$executable" ${timeout:+-o ConnectTimeout=$timeout} "${args[@]}" "${common_opts[@]}"
        status=$?
        [ $status -ne 255 ] && exit $status
        args=()
      fi
    fi
    shift
  done
}

print_error() {
  cat >&2 << EOF
${myname}: error parsing command line
Try '$myname -h' for more information.
EOF
  exit 254
}

print_help() {
  cat << EOF
USAGE

    $myname [-v] ARGS [+[N] ARGS]... [-- COMMON]
    $myname -h

SYNOPSIS

Invokes \`${exename}' command with the first set of arguments ARGS
and common arguments COMMON. If this command returns
exit status of 255 and the second set of arguments ARGS
exists, then the second \`ssh' will be invoked with these
new ARGS and COMMON; then the third and so on.

Empty set of arguments is discarded without invoking \`ssh'.
Successful invocation of \`ssh' stops parsing the command
line and makes the script exit.

OPTIONS

    -h     print this help and exit (must be the first option)
    +, +N  execute \`ssh' with preceding ARGS and COMMON

N, if given, specifies timeout for \`ssh' invoked with
immediately preceding ARGS. This is just a convenient
alternative for \`-o ConnectTimeout=N'.

The final set of arguments may or may not have a terminating \`+'.

EXIT STATUS

The exit status is 254 in case of an error while parsing
the command line; 255, if none of \`${exename}' managed
to connect; or an exit status of successfully connected
\`${exename}' otherwise.

EXAMPLES

To try 10.0.0.1 and, if failed, the alternative address:
    $myname 10.0.0.1 + my_machine.example.com

To execute \`df -h' with timeouts:
    $myname 10.0.0.1 +3 my_machine.example.com +5 -- df -h

LICENCE
        Creative Commons CC0.
EOF
}

main "$@"
0

Оказывается, что-то довольно похожее на это можно сделать довольно легко, используя параметр ProxyCommand в конфигурации ssh. В моем случае я пропустил требование сначала подключиться к 10.0.0.1 и в итоге получил следующее:

Host my_machine.example.com
    ProxyCommand nc "%h" "%p" || ssh -W "%h:%p" me@other_machine.example.com

Комбинируя это с мастер-соединениями (ControlMaster , ControlPath и ControlPersist), этот метод в первую очередь выполняет 95% от того, что я хотел, и очень быстр при повторных соединениях (первое всегда немного медленное, если нужно пройти через переход ).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .