¿Registro local con marca de tiempo de todos los comandos ssh?

¿Registro local con marca de tiempo de todos los comandos ssh?

¿Cómo puedo mantener un registro local con marca de tiempo de todos los comandos remotos que uso ssh(el cliente openssh de línea de comandos iniciado a través de bash)?

Requisitos:

  • Básico:

    • 100% del lado del cliente sin depender del registro del servidor
    • Configurado o instalado por usuario con registros almacenados en el directorio de inicio del usuario.
    • Soporte para distinguir entre múltiples sesiones simultáneas con varios usuarios y hosts.
    • No intrusivo (no es necesario activarlo cada vez y no interfiere significativamente con el uso de ssh)
  • Alta prioridad:

    • Cualquiera de las salidas no se registra ni se filtra tanto como sea posible
    • Las entradas de contraseña no se registran o el archivo está cifrado
    • Indica los comandos reales utilizados (después de que se hayan procesado la tabulación/historial, retrocesos, CTRL+ C, etc.)
  • Agradable tener:

    • También registra comandos en sesiones encadenadas (comandos ingresados ​​durante sshsesiones remotas su <user>)
    • El inicio y el final de la sesión deben registrarse
    • Lo mejor sería una bashsolución simple basada en -no root (¿quizás un script contenedor aliaso para el comando?)bashssh

Mi nivel de habilidad:

  • No soy nuevo en la programación, pero todavía estoy aprendiendo bashel "estilo Linux", por lo que agradecería mucho los ejemplos de código con explicaciones breves.

Posibles estrategias

  • registrador de teclas-- Problema: registra contraseñas, no registra la finalización de la pestaña/historial (consultela respuesta de glenn)
  • screencon desplazamiento hacia atrás una vez por segundo ydiff entre ellos para encontrar nuevas líneas de desplazamiento hacia atrás-- Problema: ¿cómo se puede implementar esto de una manera útil y automatizada?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile)-- Problema: no puedo manejar comandos multilínea o historial en sesiones encadenadas, se necesita una limpieza cuidadosa (ver mi respuesta)
  • Una combinación de algunos de los anteriores.

Un ejemplo

La siguiente sesión 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

Podría generar un registro como ~/logs/ssh.logpor ejemplo:

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]

O quizás se cree un registro separado para cada sesión con la línea de comando utilizada para iniciar la sesión en la parte superior del archivo.

Respuesta1

Me intrigó tu pregunta. Originalmente no iba a dar una respuesta pero me enganché.

Esto utiliza expecty es realmente un registrador de claves.

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

  • se agrega a un archivo con el destino ssh en el nombre
  • es un registrador de claves: si no ha configurado claves ssh, obtiene la contraseña del usuario en el archivo de registro
  • se frustra al completar con tabulación: si el usuario escribe uptTab(para el uptimecomando), obtendrá "upt\t" en el archivo de registro, no "uptime"
  • captura caracteres en modo "sin formato": si el usuario escribe mal, obtendrá muchos ^?(caracteres de retroceso) en el archivo de registro.

Respuesta2

Actualmente estoy usando el script bash a continuación. Tiene muchos problemas, pero es la única solución que he encontrado que aborda todos los requisitos, prioridades y "es bueno tener" (al menos la mayor parte del tiempo).

esta respuestaanaliza por qué es tan difícil registrar sesiones ssh localmente.

Problemas con el script que encontré hasta ahora:

  1. Los comandos multilínea causan problemas:

    • Si hojea un elemento de varias líneas en el historial remoto (con las teclas arriba/abajo), registrará un elemento del historial en lugar del último comando. Puedes evitar esto aleliminando del historial de bashcualquier comando multilínea inmediatamente después de su uso.
    • Sólo se registra la primera línea de comandos multilínea.
  2. Las sesiones encadenadas (usando comandos ssho suen el extremo remoto) hacen que el desplazamiento del historial registre los comandos pasados ​​desplazados en lugar de los comandos reales utilizados.

  3. Las expresiones regulares se pueden mejorar y es posible que sea necesario modificarlas para determinados entornos:

    • Hago trampa al convertir caracteres no imprimibles cat -vantes de limpiar. Como resultado, es posible que se elimine contenido válido si alguna vez utiliza cadenas como ^[[en sus comandos.
    • A veces obtienes entradas registradas adicionales antes del comando, como si hojeas el historial muy rápido. Esto generalmente va seguido de una "^M" antes del comando real y, por lo tanto, se puede eliminar si se desea.
    • A veces aparecen otros personajes de control. Los dejaré todos por ahora hasta que sepa cuáles es seguro eliminar. ^M, como acabo de mencionar, es útil para detectar entradas registradas no válidas, y ^C le indicará si el comando fue cancelado.
    • Es posible que sea necesario modificar la expresión regular del mensaje para mensajes particulares, y me imagino que diferentes entornos remotos pueden tener diferentes patrones de caracteres de control.
  4. No se completa bash con el comando ssh, como por ejemplo para el nombre de host. Puede completar bash si asigna un alias a este script sshconalias ssh="sshlog"

Fuente del script e instalación:

Para instalar, pegue lo siguiente en ~/bin/sshlog y hágalo ejecutable. Llamar con sshlog <ssh command options>. Opcionalmente, alias 'ssh' en el archivo .bashrc del usuario.

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

Contenido de registro de ejemplo:

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]

Respuesta3

Qué tal si strace -o /tmp/ssh_log -ff -s8192 -T -ttt -fp $(pidof sshd)? Esto registra todas las sesiones ssh. Es posible que necesite una herramienta para analizar el registro posteriormente, o simplemente usar grep, awketc.

  • -f: trazar niños bifurcados
  • -ff: registre a cada niño por separado enssh_log.PID
  • -s8192: aumenta el límite de registro de cadenas (si es necesario)
  • -T -ttt: estampado de microsegundos en segundos desde la Época
  • -p N: adjuntar al pidN

Respuesta4

Tengo una respuesta menos complicada y seguramente no un keylogger. No entiendo su punto de ser independiente del registro del servidor (esto significa que todas las acciones deben realizarse en el servidor y todos los registros son registros del lado del servidor), por lo que pensé que una buena idea es pasar a bashrc en todo el sistema. un comando rápido como:


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

En debian deberías editar el archivo: /etc/bash.bashrc y en centos el archivo: /etc/bashrc

Si desea comenzar a iniciar sesión en la sesión en la que se encuentra, debe obtener el archivo que ha editado, por ejemplo ejecutar:


source /etc/bash.bashrc

en un sistema debian o


source /etc/bashrc
en un sistema centos.

De ahora en adelante, cada comando de cada sesión ssh se registrará en/var/log/syslogen un sistema Debian, y en/var/log/mensajesen un sistema centos.

En caso de que desee registrarlos en un archivo separado y no alterar otros archivos de registro, puede usar:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
en lugar del ejemplo PROMPT_COMMAND anterior y luego configure rsyslogd según sea necesario.

Por ejemplo, en un sistema Debian edite el/etc/rsyslog.confarchivo: cambiar la línea:


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

.;auth,authpriv.none,local6           -/var/log/syslog
y agregue la siguiente línea al final del archivo:

local6.info                     /var/log/history.log

luego ejecuta:

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

información relacionada