Registro local com registro de data e hora de todos os comandos ssh?

12

Como posso manter um registro local com registro de data e hora de todos os comandos remotos em que uso ssh(o cliente openssh da linha de comando é iniciado bash)?

Requisitos:

  • Essencial:

    • 100% do lado do cliente sem depender do log do servidor
    • Configurado ou instalado por usuário com logs armazenados no diretório inicial do usuário.
    • Suporte para distinguir entre várias sessões simultâneas com vários usuários e hosts.
    • Não intrusivo (não é necessário ativá-lo todas as vezes e não interfere significativamente no uso do ssh)
  • Prioridade máxima:

    • A saída não é registrada ou filtrada o máximo possível
    • As entradas de senha não são registradas ou o arquivo é criptografado
    • Indica os comandos reais usados ​​(após a conclusão da guia / histórico, backspaces, CTRL+ C, etc ... foram processados)
  • Bom ter:

    • Também registra comandos em sessões encadeadas (comandos inseridos durante sessões remotas sshou su <user>)
    • O início e o fim da sessão devem ser registrados
    • Uma bashsolução simples , sem raiz, seria a melhor (talvez um script aliasou bashwrapper para o sshcomando?)

Meu nível de habilidade:

  • Eu não sou novo em programação, mas ainda estou aprendendo bashe do "jeito Linux", portanto, exemplos de código com breves explicações seriam muito apreciados.

Estratégias possíveis

  • keylogger - Problema: registra senhas, não registra a conclusão da guia / histórico (consulte a resposta de glenn )
  • screencom dumping de scrollback uma vez por segundo e diffentre eles para encontrar novas linhas de scrollback - Problema: como isso pode ser implementado de uma maneira automatizada útil?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile) - Problema: não é possível manipular comandos de múltiplas linhas ou histórico em sessões encadeadas, é necessária uma limpeza cuidadosa (veja minha resposta)
  • Uma combinação de algumas das opções acima

Um exemplo

A seguinte sessão SSH:

user@local:~$ ssh user@remote
Last login: Tue Jun 17 16:34:23 2014 from local
user@remote:~$ cd test
user@remote:~/test$ ls
a  b
user@remote:~/test$ exit

Pode resultar em um log ~/logs/ssh.logcomo:

2014-06-17 16:34:50   [user@remote - start]
2014-06-17 16:34:51   [user@remote] cd test
2014-06-17 16:34:52   [user@remote] ls
2014-06-17 16:34:53   [user@remote] exit
2014-06-17 16:34:53   [user@remote - end]

Ou talvez seja criado um log separado para cada sessão com a linha de comando usada para iniciar a sessão na parte superior do arquivo.

Oleg
fonte
Ele também deve lidar com editores como nano ou vim
daisy

Respostas:

4

Fiquei intrigado com sua pergunta. Originalmente, eu não daria uma resposta, mas fiquei viciado.

Isso usa expecte é realmente um registrador de chaves.

#!/usr/bin/expect -f

proc log {msg} {
    puts $::fh "[timestamp -format {%Y-%m-%d %H:%M:%S}]: $msg"
}

set ssh_host [lindex $argv 0]
set ::fh [open "sshlog.$ssh_host" a]

log "{session starts}"

spawn ssh $ssh_host

interact {
    -re "(.)" {
        set char $interact_out(1,string)
        if {$char eq "\r"} {
            log $keystrokes
            set keystrokes ""
        } else {
            append keystrokes $char
        }
        send -- $char
    }
    eof
}

log "{session ends}"

Notas:

  • anexa a um arquivo com o destino ssh no nome
  • é um registrador de chaves: se você não configurou chaves ssh, obtém a senha do usuário no arquivo de log
  • isso é frustrado pela conclusão da guia: se o usuário digitar uptTab(para o uptimecomando), você receberá "upt \ t" no arquivo de log, não "uptime"
  • ele pega caracteres no modo "bruto": se o usuário for um datilógrafo ruim, você receberá muitos ^?(caracteres de backspace) no arquivo de log.
Glenn Jackman
fonte
Muito obrigado pela sua resposta. É interessante que não parece haver uma resposta fácil para isso, talvez nativa do cliente ssh. Obrigado por explicar as limitações; Acho que a conclusão da guia / registro de caracteres de backspace / registro de senha são suficientes para me impedir de usar isso com frequência. Também me fez pensar mais sobre minhas prioridades e vou esclarecer as que estão em questão.
Oleg
A saída do processo gerado pode ser analisada para extrair o comando desejado. Você precisaria saber o prompt do usuário para facilitar.
Glenn Jackman
Eu uso muito a conclusão de guias. Isso não significa que esses comandos não seriam registrados?
Oleg
Ah, entendo o que você está dizendo. Como a saída seria analisada? O prompt pode ser inserido em algum lugar como uma opção de configuração.
Oleg
Adicionei a lista de possíveis soluções na parte inferior da pergunta. ssh ... | tee -ai <logfile> funciona bem para registrar entrada e saída com segurança, mas não sei como adicionar registros de data e hora e / ou filtrar a saída em segundo plano.
Oleg
2

Atualmente, estou usando o script bash abaixo. Tem muitos problemas, mas é a única solução que encontrei que atende a todos os requisitos, prioridades e "bom ter" (pelo menos na maioria das vezes).

Esta resposta discute por que o registro local de sessões ssh é tão difícil.

Problemas com o script que encontrei até agora:

  1. Comandos de várias linhas causam problemas:

    • Se você percorrer um item de várias linhas no histórico remoto (com teclas para cima / para baixo), ele registrará um item do histórico em vez do comando mais recente. Você pode evitar isso excluindo do histórico do bash qualquer comando com várias linhas imediatamente após serem usados.
    • Somente a primeira linha de comandos com várias linhas é registrada.
  2. Sessões encadeadas (usando sshou sucomandos na extremidade remota) fazem com que a rolagem do histórico grave os comandos passados ​​por rolagem, em vez dos comandos reais usados

  3. As expressões regulares podem ser aprimoradas e podem precisar ser modificadas para determinados ambientes:

    • Eu trapaceio convertendo caracteres não imprimíveis cat -vantes da limpeza. Como resultado, o conteúdo válido pode ser removido se você usar seqüências de caracteres como ^[[em seus comandos.
    • Às vezes, você obtém entrada extra registrada antes do comando, como se você paginasse o histórico muito rapidamente. Isso geralmente é seguido por um "^ M" antes do comando real e, portanto, pode ser removido, se desejado.
    • Às vezes, outros caracteres de controle ocorrem. Estou deixando todos eles por enquanto até saber quais são seguros para remover. ^ M, como acabei de mencionar, é útil para detectar entrada registrada inválida e ^ C diria se o comando foi abortado.
    • O regex de prompt pode precisar ser modificado para prompts específicos, e eu poderia imaginar que diferentes ambientes remotos podem ter diferentes padrões de caracteres de controle.
  4. Nenhuma conclusão do bash do comando ssh, como para nome do host. É possível obter a conclusão do bash se você aliasar esse script sshcomalias ssh="sshlog"

Origem e instalação do script:

Para instalar, cole o seguinte em ~ / bin / sshlog e torne o executável. Ligue com sshlog <ssh command options>. Opcionalmente, alias para 'ssh' no arquivo .bashrc do usuário.

#!/bin/bash
# A wrapper for the ssh command that produces a timestamped log of all ssh commands
declare -r logfile=~/logs/ssh.log
declare -r description="sshlog-${$} ${@}"
declare -r TAB=$'\t'

logdir=`dirname ${logfile}`
[ -d ${logdir} ] || mkdir "${logdir}";

clean_control_chars() {
    while IFS= read -r line; do
        # remove KNOWN control characters. Leave the rest for now.
        # line=$(echo "${line}" | sed 's/\^\[\[K//g')  # unkown control character: ^[[K
        # line=$(echo "${line}" | sed 's/\^\[\[[0-9]\+[P]//g')  # these are generated by up/down completion - e.g. ^[[2P
        line=$(echo "${line}" | sed 's/\^\[\[[0-9]*[A-Z]//g')  # all other ^[[..
        # replay character deletions (backspaces)
        while [[ $(echo "${line}" | grep -E --color=never '.\^H') != "" ]]; do
            line=$(echo "${line}" | sed 's/.\^H//')
        done
        # remove common control characters
        line=$(echo "${line}" | sed 's/\^M$//')  # remove end of line marker from end
        line=$(echo "${line}" | sed 's/^\^G//g')  # remove start marker from start
        # remove ^G from other locations - possibly a good idea
        # line=$(echo "${line}" | sed 's/\^G//g')
        # remove all other control characters - not recommended (many like ^C and ^M indicate which section was processed/ ignored)
        # line=$(echo "${line}" | sed 's/\^[A-Z]//g')
        echo ${line};
    done
}

filter_output() {
    while IFS= read -r line; do
        # convert nonprinting characters and filter out non-prompt (in Ubuntu 14.04 tests, ^G indicates prompt start)
        line=$(echo "${line}" | cat -v | grep -Eo '[\^][G].*[\$#].*')
        [[ ${line} != "" ]] && echo "${line}"
    done
}

format_line() {
    while IFS= read -r line; do
        raw=${line};
        line=$(echo "${line}" | clean_control_chars);
        prompt=$(echo "${line}" | grep -Po '^.*?(\$|#)[\s]*')
        command=${line:${#prompt}}
        timestamp=`date +"%Y-%m-%d %H:%M:%S %z"`
        echo -e "${timestamp}${TAB}${description}${TAB}${prompt}${TAB}${command}"
    done
}

echo "Logging ssh session: ${description}"
echo "[START]" | format_line >> ${logfile}
/usr/bin/ssh "$@" | tee >(filter_output | format_line >> ${logfile})
echo "[END]" | format_line >> ${logfile}

Exemplo de conteúdo de log:

2014-06-29 23:04:06 -0700   sshlog-24176 remote [START]
2014-06-29 23:04:12 -0700   sshlog-24176 remote oleg@remote:~$  cd test
2014-06-29 23:04:13 -0700   sshlog-24176 remote oleg@remote:~/test$     ls
2014-06-29 23:04:14 -0700   sshlog-24176 remote oleg@remote:~/test$     exit
2014-06-29 23:04:14 -0700   sshlog-24176 remote [END]
Oleg
fonte
0

Eu tenho uma resposta menos complicada e certamente não sou um keylogger. Não entendo seu ponto de ser independente do log do servidor (isso significa que todas as ações precisam ser executadas no servidor e todos os logs são logs do lado do servidor) e, portanto, pensei que uma boa idéia é passar para o bashrc em todo o sistema um comando rápido como:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -t "$USER[$$] $SSH_CONNECTION")'

No debian você deve editar o arquivo: /etc/bash.bashrc e no centos o arquivo: / etc / bashrc

Se você deseja iniciar o logon da sessão em que está, precisa originar o arquivo que editou, por exemplo, execute:


source /etc/bash.bashrc

em um sistema debian ou


source /etc/bashrc
em um sistema de centos.

A partir de agora, todos os comandos, todas as sessões ssh serão registradas em / var / log / syslog em um sistema debian e em / var / log / messages em um sistema centos.

Caso deseje registrá-los em um arquivo separado e não mexer com outros arquivos de log, você pode usar:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
em vez do exemplo PROMPT_COMMAND anterior e, em seguida, configure o rsyslogd conforme necessário.

Por exemplo, em um sistema Debian, edite o arquivo /etc/rsyslog.conf : altere a linha:


.;auth,authpriv.none           -/var/log/syslog
para

.;auth,authpriv.none,local6           -/var/log/syslog
e adicione a seguinte linha ao final do arquivo:

local6.info                     /var/log/history.log

então execute:

touch /var/log/history.log && /etc/init.d/rsyslog restart

strimpak
fonte
Esta pergunta é especificamente sobre o problema de registrar sessões ssh no lado do computador inicial / local / cliente, sem precisar (lembrar / ser permitido) configurar cada servidor remoto ou fazer o download manual dos logs de todos os servidores remotos que você conectar para. Eu acho que sua resposta, embora não responda a essa pergunta, seria útil para alguém interessado em melhorar a auditoria do servidor e talvez devesse ser movida para uma pergunta mais relevante.
21414 Oleg
0

Que tal strace -o /tmp/ssh_log -ff -s8192 -T -ttt -fp $(pidof sshd)? Isso registra todas as sessões ssh. Você pode precisar de uma ferramenta para analisar o log posteriormente ou apenas usar grep, awketc.

  • -f: rastrear crianças bifurcadas
  • -ff: registre cada filho separadamente para ssh_log.PID
  • -s8192: aumentar o limite de log de string (se necessário)
  • -T -ttt: carimbo de microssegundos em segundos desde a época
  • -p N: anexar ao pid N
Anul
fonte