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

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

Como posso manter um registro local com carimbo de data e hora de todos os comandos remotos que uso ssh(cliente openssh da linha de comando iniciado por meio de 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 múltiplas sessões simultâneas com vários usuários e hosts.
    • Não intrusivo (não há necessidade de 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 tanto quanto possível
    • As entradas de senha não são registradas ou o arquivo está criptografado
    • Indica os comandos reais usados ​​(após a conclusão da tabulação/histórico, backspaces, CTRL+ C, etc... terem sido processados)
  • Bom ter:

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

Meu nível de habilidade:

  • Não sou novo em programação, mas ainda estou aprendendo basho "jeito Linux", então exemplos de código com breves explicações seriam muito apreciados.

Estratégias possíveis

  • registrador de teclas-- Problema: registra senhas, não registra conclusão de guia/histórico (vejaresposta de Glenn)
  • screencom scrollback despejando uma vez por segundo e diffentre eles para encontrar novas linhas de scrollback-- Problema: como isso pode ser implementado de uma forma automatizada e útil?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile)- Problema: não é possível lidar com comandos multilinha ou histórico em sessões encadeadas, é necessária uma limpeza cuidadosa (veja minha resposta)
  • Uma combinação de alguns dos itens 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 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.

Responder1

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

Isso usa expecte é realmente um keylogger.

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

  • ele é anexado a um arquivo com o destino ssh no nome
  • é um key logger: se você não configurou chaves ssh, você obtém a senha do usuário no arquivo de log
  • é frustrado pela conclusão da tabulação: se o usuário digitar uptTab(para o uptimecomando), você obterá "upt\t" no arquivo de log, não "uptime"
  • ele captura caracteres no modo "bruto": se o usuário for um digitador ruim, você obterá muitos ^?(caracteres de retrocesso) no arquivo de log.

Responder2

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

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

Problemas com o script que encontrei até agora:

  1. Comandos multilinha causam problemas:

    • Se você percorrer um item de múltiplas linhas no histórico remoto (com as teclas para cima/para baixo), ele registrará um item do histórico em vez do comando mais recente. Você pode evitar issoexcluindo do histórico do bashquaisquer comandos multilinha imediatamente após serem usados.
    • Somente a primeira linha dos comandos multilinhas é registrada.
  2. Sessões encadeadas (usando comandos sshou suna extremidade remota) fazem com que a rolagem do histórico registre comandos passados ​​​​pela rolagem em vez dos comandos reais usados

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

    • Eu trapaceio convertendo caracteres não imprimíveis cat -vantes de limpar. Como resultado, o conteúdo válido pode ser removido se você usar strings como ^[[em seus comandos.
    • Às vezes, você obtém entradas extras registradas antes do comando, como se você folheasse o histórico muito rapidamente. Geralmente é seguido por um "^M" antes do comando real e, portanto, pode ser removido, se desejado.
    • Às vezes ocorrem outros caracteres de controle. Estou deixando todos eles por enquanto até saber quais são seguros para remover. ^M, como acabei de mencionar, é útil para detectar entradas registradas inválidas e ^C informaria se o comando foi abortado.
    • O prompt regex pode precisar ser modificado para prompts específicos, e posso imaginar que diferentes ambientes remotos podem ter diferentes padrões de caracteres de controle.
  4. Nenhuma conclusão do comando ssh, como para o nome do host. Você pode obter a conclusão do bash se você usar o alias deste script sshcomalias ssh="sshlog"

Fonte 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 registro:

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]

Responder3

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 grepetc.awk

  • -f: rastrear crianças bifurcadas
  • -ff: registre cada filho separadamente emssh_log.PID
  • -s8192: aumente o limite de registro de strings (se necessário)
  • -T -ttt: carimbo de microssegundos em segundos desde a Época
  • -p N: anexar ao pidN

Responder4

Tenho uma resposta menos complicada e certamente não é um keylogger. Não entendi o que você quer dizer sobre 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 ideia seria passar para todo o sistema bashrc um comando prompt 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 quiser iniciar o registro da sessão em que você está, você deve obter 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, todos os comandos de todas as sessões ssh serão registrados em/var/log/syslogem um sistema debian, e em/var/log/mensagensem um sistema centos.

Caso você queira registrá-los em um arquivo separado e não bagunçar 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 configure o rsyslogd conforme necessário.

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

informação relacionada