Questão Wrapper SSH que tenta vários parâmetros de conexão


Eu estou procurando um wrapper SSH (ou opção SSH, se houvesse um), que pode tentar se conectar a vários endereços IP sequencialmente até que um deles tenha sucesso. Por exemplo 10.0.0.1, então my_machine.example.com e finalmente my_machine.example.com -J me@other_machine.example.com.

Existe alguma ferramenta que faz isso?


1


origem




Respostas:


Este é o meu objetivo geral ssh embrulho. Nenhuma opção nem endereço é codificado. A única coisa que você pode precisar ajustar é o caminho para o seu ssh executável na linha 3 (você pode usar executable=ssh, Eu escolhi o caminho completo). Você encontrará meu código completo abaixo.

Vamos dizer que você salvou como sshmt ("ssh, multi target") onde seu $PATH aponta para, feito executável com chmod. Então familiarize-se com a sintaxe:

sshmt -h

Excerto:

USO

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

SINOPSE

Invoca ssh comando com o primeiro conjunto de argumentos ARGS   e argumentos comuns COMMON. Se este comando retornar   status de saída de 255 e o segundo conjunto de argumentos ARGS   existe, então o segundo ssh será invocado com estes   Novo ARGS e COMMON; então o terceiro e assim por diante.

No seu caso de exemplo, você quer invocá-lo assim:

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

ou melhor, com alguns tempos limite convenientes:

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

Para executar remotamente df -h de uma maneira direta, invoque:

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

mas você não quer se repetir, então use isso:

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

Tubos devem funcionar também:

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"

Na prática, você pode querer definir um alias:

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

depois faça o login com

myssh

ou executar um comando como

myssh uptime

Este é o código. Toda a sua lógica apenas analisa a linha de comando realmente.

#!/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 "$@"

1





Tanto quanto eu sei, não existe esse recurso embutido. No entanto, isso pode ser facilmente roteirizado:

#!/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

Com o seguinte .ssh/config Arquivo:

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

Nota essa conexão pode levar muito tempo, por exemplo, no caso do uso da configuração proxyjump. Na verdade, a conexão pode ocorrer após dois tempos limite.


1





Acontece que algo semelhante a isso pode ser feito facilmente usando ProxyCommand opção em ssh config. No meu caso de uso, ignorei o requisito de conexão com o 10.0.0.1 primeiro e terminei com isso:

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

Ao combinar isso com as conexões principais (ControlMaster, ControlPath e ControlPersist) esta técnica faz 95% do que eu queria em primeiro lugar e é muito rápida em conexões repetidas (a primeira é sempre um pouco lenta se tiver que passar pelo salto).


0