O SSH pergunta a senha uma vez, reutiliza a senha até que o tempo limite termine

3

Como posso resolver este problema? Eu tenho um script bash (em Ubuntu Server), fazendo várias conexões SSH, executa algumas transferências remotas, como rsync várias vezes.

Meu problema é que eu gostaria de evitar a inserção de senha várias vezes. Mas eu não quero usar a troca de chave pública SSH, porque se alguém tiver a chave, será capaz de conectar o computador remoto.

Eu gostaria do seguinte:

  • O SSH deve perguntar a senha quando eu iniciar o script bash
  • reutilize a senha, por isso, não solicite a senha novamente até o tempo limite
  • quando o tempo limite acabar, peça novamente a senha.

Algo semelhante, como o sudo está funcionando, apenas com ssh.

Alguma ideia de como resolver isso?

EDIT1:

Eu encontrei um novo recurso SSH chamado ssh multiplexing. Talvez usando isso eu possa alcançar o objetivo que eu quero.

link

Isso funcionaria?

    
por klor 31.03.2017 / 18:00

4 respostas

0

Parece que encontrei a solução perfeita para as minhas necessidades:

Reutilizando a sessão ssh para comandos repetidos de rsync

#!/bin/bash

# Create ssh-mux (SSH multiplex) dir only if not exists
[[ ! -d dir ]] || mkdir ~/.ssh/ssh-mux

apache_site_path_source="/var/www/source_site"
apache_site_path_target="/var/www/target_site"

# Solution: Start SSH multiplexing session (works fine)
# https://unix.stackexchange.com/questions/50508/reusing-ssh-session-for-repeated-rsync-commands
sudo ssh -nNf -o ControlMaster=yes -o ControlPath="~/.ssh/ssh-mux/%L-%r@%h:%p" [email protected]

sudo rsync -av --progress -e 'ssh -l root -p 22 -o "ControlPath=~/.ssh/ssh-mux/%L-%r@%h:%p"' 192.168.0.1:${apache_site_path_source}/. ${apache_site_path_target}/;
printf "\n\n\n\n\n\n"
sudo rsync -av --progress -e 'ssh -l root -p 22 -o "ControlPath=~/.ssh/ssh-mux/%L-%r@%h:%p"' 192.168.0.1:${apache_site_path_source}/. ${apache_site_path_target}/;
printf "\n\n\n\n\n\n"
sudo rsync -av --progress -e 'ssh -l root -p 22 -o "ControlPath=~/.ssh/ssh-mux/%L-%r@%h:%p"' 192.168.0.1:${apache_site_path_source}/. ${apache_site_path_target}/;
printf "\n\n\n\n\n\n"

# Finish SSH multiplexing session
sudo ssh -O exit -o ControlPath="~/.ssh/ssh-mux/%L-%r@%h:%p" [email protected]

Essa solução solicita a senha apenas uma vez e, em seguida, realiza o rsync três vezes sem solicitar a senha novamente. Cada rsync reutiliza a conexão SSH usando a multiplexação SSH.

Poderia ser possível alterar a configuração do SSH e armazenar as configurações de multiplexação do SSH, mas usando essa solução não há necessidade de alterar a configuração do servidor, o script funciona como está.

    
por 05.04.2017 / 19:30
3

(Repostando meu comentário como uma resposta por solicitação de klor ).

Não é o que você quer ouvir, mas é para isso que serve a autenticação baseada em chave. Contanto que você insira uma senha em sua chave privada, ela não é menos segura que a autenticação por senha.

Você pode usar ssh-agent para evitar a necessidade de inserir a frase secreta todas as vezes, e a opção -t para ssh-agent fornecerá o comportamento de tempo limite desejado.

# start a shell under ssh-agent with a 5-minute timeout for keys loaded with ssh-add
ssh-agent -t 300 /bin/bash

# add your key(s) to the agent; ssh-add will prompt for passphrase, if one is set
ssh-add

# do some stuff
ssh remote.server cat /some/file
rsync file1 file2 [email protected]:/some/directory

# after 300 seconds, timeout reached, run ssh-add again to re-add your keys
ssh-add

Seu script precisará de alguma lógica para determinar quando o tempo limite ocorre. Uma maneira seria executar ssh e rsync com -o BatchMode=yes , o que evitará métodos de autenticação interativos, portanto, se a chave não puder mais ser usada, ssh será encerrado em vez de solicitar uma senha. Você pode usar o código de saída para determinar se precisa executar ssh-add novamente; $? deve ser definido como 255 neste caso.

Você ainda precisa descobrir como alimentar a senha para ssh-add , porque ela não oferece uma maneira de aceitá-la de maneira programática. A menos que seu script peça para você digitá-lo manualmente, você provavelmente precisará usar expect para essa parte, e isso significará a codificação da frase secreta em algum lugar.

    
por 31.03.2017 / 20:49
0

Implementação do comentário de James Sneeringer como um script de perfil.

# This script must be sourced to be useful. For example, if you name this script 
# ~/.bash_autossh, at the end of .bashrc, source $HOME/.bash_autossh
# Tested in bash & zsh
# MIT license, if you need a license.

# An absolute path to a private key:
AUTOLOADSSHID=$HOME/.ssh/id_ecdsa
# Timeout is in seconds, optional:
SSHID_TIMEOUT=60

auto_init_ssh_agent() {
  if [ "${SSH_AGENT_PID}x" = "x" ] || \
     [ "${SSH_AUTH_SOCK}x" = "x" ] || \
     ps -p "${SSH_AGENT_PID}" >& /dev/null || \
     [ ! -e "${SSH_AUTH_SOCK}" ]; then
    # There are problems with the agent, initialize a new agent.
    # Agents started this way should be manually stopped with ssh-agent -k
    source <(ssh-agent -s)
  fi
  if ! ssh-add -l | grep "${AUTOLOADSSHID}" >/dev/null; then
    # The autoload key is not present, try to load it.
    SSH_ADDTL_ARGS=()
    if [ "${SSHID_TIMEOUT}x" != "x" ]; then
      SSH_ADDTL_ARGS+=( -t "${SSHID_TIMEOUT}" )
    fi
    # This may ask for a password, as appropriate
    ssh-add "${SSH_ADDTL_ARGS[@]}" "${AUTOLOADSSHID}"
    unset SSH_ADDTL_ARGS
  fi
}

_autossh() {
  args=( "$@" )
  auto_init_ssh_agent
  ssh "${args[@]}"
}

alias autossh=_autossh

Depois, você pode executar o comando autossh myserver e ele inicializará automaticamente um agente, se não estiver disponível. O alias é impedir a chamada acidental de uma função interativa de um script.

Problematicamente, em sistemas que não iniciam automaticamente um agente com a sessão WM, isso pode sujar sua máquina com processos ssh-agent, talvez seja necessário ssh-agent -k finalizar ou killall ssh-agent . Alguns scripts adicionais podem ser necessários se você quiser compartilhar um único agente ssh em uma sessão de login inteira ou em várias sessões de processo.

    
por 31.03.2017 / 20:49
-1

Eu normalmente diria para você experimentar expect , mas neste caso eu acho melhor usar sshpass , é muito fácil de instalar e usar, aqui eu posto alguns casos de uso

sshpass -p<pass> ssh <args> sshpass -pfoobar ssh -o StrictHostKeyChecking=no user@host command_to_run

divirta-se:)

EDIT 1

em um script

#!/bin/bash
read -p "give me the password" pass
sshpass -p"$pass" ssh -o StrictHostKeyChecking=no user@host command_to_run
    
por 31.03.2017 / 20:20