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

10

Como posso manter um registro local com registro de data e hora de todos os comandos remotos que uso em ssh (cliente opensh da linha de comando iniciado por 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 a cada vez e não interfere significativamente no uso do ssh)
  • Alta prioridade:

    • 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 o término da tabulação / histórico, backspaces, CTRL + C , etc ... foram processados)
  • É bom ter:

    • Também registra comandos em sessões encadeadas (comandos inseridos durante as sessões ssh ou su <user> remotas)
    • Início e fim da sessão devem ser registrados
    • Uma solução simples, não raiz, baseada em bash seria melhor (talvez um script de wrapper alias ou bash para o comando ssh ?)

Meu nível de habilidade:

  • Eu não sou novo em programar, mas ainda estou aprendendo bash e o "modo Linux", então amostras de código com breves explicações seriam muito apreciadas.

Estratégias possíveis

  • keylogger - Problema: registra senhas, não registra log / conclusão do histórico (veja resposta de glenn )
  • screen com rolagem de dumping uma vez por segundo e diff entre eles para encontrar novas linhas de rolagem - Problema: como isso pode ser implementado de uma forma útil e automatizada?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile) - Problema: não pode manipular comandos de múltiplas linhas ou histórico em sessões encadeadas, limpeza cuidadosa necessária (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 em ~/logs/ssh.log , como:

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, um log separado seja criado para cada sessão com a linha de comando usada para iniciar a sessão na parte superior do arquivo.

    
por Oleg 18.06.2014 / 02:18

4 respostas

4

Fiquei intrigado com a sua pergunta. Eu não ia dar uma resposta, mas fiquei viciado.

Isso usa expect e é realmente um criador 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 tiver configurado as chaves ssh, receberá a senha do usuário no arquivo de log
  • é anulado pela conclusão da tabulação: se o usuário digitar u p t Tab (para o uptime command), você obterá "upt \ t" no arquivo de log, não "uptime"
  • ele captura caracteres no modo "raw": se o usuário for um mau datilógrafo, você obterá muitos ^? (caracteres de retrocesso) no arquivo de log.
por 19.06.2014 / 03:31
2

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

Esta resposta discute por que registrar sessões ssh localmente é tão difícil.

Problemas com o script que encontrei até agora:

  1. Os comandos multilinha causam problemas:

    • Se você percorrer um item de várias linhas no histórico remoto (com as teclas para cima / para baixo), ele registrará um item de histórico em vez do último comando. Você pode evitar isso por excluir do histórico do bash qualquer comando de múltiplas linhas imediatamente após eles são usados.
    • Apenas a primeira linha de comandos de múltiplas linhas é registrada.
  2. Sessões encadeadas (usando os comandos ssh ou su no final remoto) fazem com que a rolagem do histórico registre comandos passados por rolagem em vez dos comandos reais usados

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

    • Eu trapaceio convertendo caracteres não imprimíveis com cat -v antes de limpar. Como resultado, o conteúdo válido pode ser removido se você usar strings como ^[[ em seus comandos.
    • Às vezes, você recebe uma entrada extra antes do comando, como se você paginasse o histórico com muita rapidez. Isso geralmente é seguido por um "^ M" antes do comando real e, portanto, pode ser removido, se desejado.
    • Outros caracteres de controle às vezes ocorrem. Estou deixando todos eles por enquanto até saber quais são seguros para remover. ^ M como acabei de mencionar é útil para detectar entradas inválidas, e ^ C diria se o comando foi cancelado.
    • O regex de prompt pode precisar ser modificado para prompts específicos, e eu poderia imaginar que diferentes ambientes remotos podem ter padrões de caracteres de controle diferentes.
  4. Nenhum comando ssh com conclusão completa, como por exemplo hostname. Você pode obter o bash completion se você alias este script para ssh com alias ssh="sshlog"

Origem e instalação do script:

Para instalar, cole o seguinte em ~ / bin / sshlog e torne 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]
    
por 30.06.2014 / 03:08
0

Eu tenho uma resposta menos complicada, e certamente não é um keylogger. Eu não entendo o seu ponto de ser independente do log do servidor (isso significa que todas as ações precisam ser levadas para o servidor e todos os logs são do lado do servidor), e assim eu pensei que uma boa idéia é passar para o sistema bashrc 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ê quiser iniciar o registro da sessão em que está, precisará fornecer o arquivo que editou, por exemplo, executar:


source /etc/bash.bashrc

em um sistema debian ou


source /etc/bashrc
em um sistema centos.

De agora em diante, cada comando, de cada sessão ssh será registrado em / var / log / syslog em um sistema debian, e em / var / log / messages em um sistema centos.

Caso você queira registrá-los em um arquivo separado e não interferir em outros arquivos de registro, 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 configure o rsyslogd conforme necessário.

Por exemplo, em um sistema Debian, edite o arquivo /etc/rsyslog.conf : mude 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

execute então:

touch /var/log/history.log && /etc/init.d/rsyslog restart
    
por 18.07.2014 / 16:14
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 , awk etc.

  • -f : trace bifurcado
  • -ff : registra cada filho separadamente para ssh_log.PID
  • -s8192 : aumenta o limite de registro de string (se necessário)
  • -T -ttt : microssegundo em segundos desde a época
  • -p N : anexar ao pid N
por 04.06.2015 / 11:29