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

12

¿Cómo puedo mantener un registro local con marca de tiempo de todos los comandos remotos que uso en ssh(se inició el cliente openssh de línea de comandos bash)?

Requisitos:

  • Esencial:

    • 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 o filtra tanto como sea posible
    • Las entradas de contraseña no están registradas o el archivo está encriptado
    • Indica los comandos reales utilizados (después de que se haya completado la tabulación / historial, retrocesos, CTRL+ C, etc.)
  • Agradable tener:

    • También registra comandos en sesiones encadenadas (comandos ingresados ​​durante sesiones remotas ssho su <user>)
    • El inicio y el final de la sesión deben registrarse
    • Un simple bash-Basado, solución que no sea root sería mejor (tal vez una aliaso bashguión envoltorio para el sshcomando?)

Mi nivel de habilidad:

  • No soy nuevo en programación, pero todavía estoy aprendiendo bashy en la "forma de Linux", por lo que agradecería mucho las muestras de código con explicaciones breves.

Posibles estrategias

  • keylogger - Problema: registra las contraseñas, no registra la finalización de la pestaña / historial (consulte la respuesta de Glenn )
  • screencon volcado de desplazamiento una vez por segundo y diffentre ellos para encontrar nuevas líneas de desplazamiento - Problema: ¿cómo se puede implementar de una manera automatizada útil?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile) - Problema: no puede manejar comandos multilínea o historial en sesiones encadenadas, se necesita una limpieza cuidadosa (vea 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 resultar en un registro en ~/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]

O quizás se creará 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.

Oleg
fuente
También debería manejar editores como nano o vim
daisy

Respuestas:

4

Su pregunta me intrigó. Originalmente no iba a dar una respuesta, pero me enganché.

Esto usa expecty es realmente un key logger.

#!/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 las claves ssh, obtendrá la contraseña del usuario en el archivo de registro
  • se frustra al completar la pestaña: si el usuario escribe uptTab(para el uptimecomando), obtendrá "upt \ t" en el archivo de registro, no "tiempo de actividad"
  • captura caracteres en modo "sin procesar": si el usuario es un mal mecanógrafo, obtendrá muchos ^?(caracteres de retroceso) en el archivo de registro.
Glenn Jackman
fuente
Muchas gracias por su respuesta. Es interesante que no parece haber una respuesta fácil para esto, tal vez nativa del cliente ssh. Gracias por explicar las limitaciones; Creo que la finalización de tabulación / el registro de caracteres de retroceso / el registro de contraseña son suficientes para evitar que lo use con frecuencia. También me hizo pensar más en mis prioridades, y aclararé las de la pregunta.
Oleg
La salida del proceso generado puede analizarse para extraer el comando que desea. Necesitaría conocer la solicitud del usuario para que sea más fácil.
Glenn Jackman
Uso mucho la finalización de pestañas. ¿No significa esto que esos comandos no se registrarían?
Oleg
Ah, ya veo lo que estás diciendo. ¿Cómo se analizaría la salida? La solicitud podría ingresarse en algún lugar como una opción de configuración.
Oleg
Agregué la lista de posibles soluciones al final de la pregunta. ssh ... | tee -ai <archivo de registro> funciona bien para registrar la entrada y salida de forma segura, pero no sé cómo agregar marcas de tiempo y / o filtrar la salida en segundo plano.
Oleg
2

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 "agradables" (al menos la mayor parte del tiempo).

Esta respuesta discute por qué registrar sesiones ssh localmente es tan difícil.

Problemas con el script que encontré hasta ahora:

  1. Los comandos multilínea causan problemas:

    • Si navega por 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. Puede evitar esto eliminando del historial de bash cualquier comando multilínea inmediatamente después de su uso.
    • Solo se registra la primera línea de comandos multilínea.
  2. Las sesiones encadenadas (usando ssho sucomandos en 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 deban modificarse para ciertos entornos:

    • Hago trampa convirtiendo caracteres no imprimibles cat -vantes de limpiar. Como resultado, el contenido válido puede eliminarse si alguna vez usa cadenas como ^[[en sus comandos.
    • A veces, obtiene una entrada adicional registrada antes del comando, como si navega por el historial muy rápido. Esto generalmente es seguido por una "^ M" antes del comando real y, por lo tanto, podría eliminarse si se desea.
    • Otros caracteres de control a veces ocurren. Los dejo todos por ahora hasta que sepa cuáles son seguros de eliminar. ^ M, como acabo de mencionar, es útil para detectar entradas registradas no válidas, y ^ C le diría si el comando fue abortado.
    • Es posible que sea necesario modificar la expresión regular del aviso para indicaciones particulares, y podría imaginar que diferentes entornos remotos pueden tener diferentes patrones de caracteres de control.
  4. No se completa el comando ssh bash, como por ejemplo para el nombre de host. Puede obtener la finalización de bash si alias este script sshconalias ssh="sshlog"

Fuente de script e instalación:

Para instalar, pegue lo siguiente en ~ / bin / sshlog y haga ejecutable. Llamada con sshlog <ssh command options>. Opcionalmente alias a '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}

Ejemplo de contenido 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]
Oleg
fuente
0

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


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

En debian debe editar el archivo: /etc/bash.bashrc y en centos el archivo: / etc / bashrc

Si desea iniciar el registro de 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 de centos.

De ahora en adelante, cada comando de cada sesión ssh se registrará en / var / log / syslog en un sistema debian y en / var / log / messages en un sistema centos.

En caso de que desee registrarlos en un archivo separado y no desordenar con 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 el rsyslogd según sea necesario.

Por ejemplo, en un sistema Debian edite el archivo /etc/rsyslog.conf : cambie 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

Strimpak
fuente
Esta pregunta es específicamente sobre el problema de registrar sesiones ssh en el lado del equipo iniciador / local / cliente, sin tener que (recordar / permitir) configurar cada servidor remoto o tener que descargar manualmente los registros de todos los servidores remotos que conecte a. Creo que su respuesta, si bien no responde a esta pregunta, sería útil para alguien interesado en mejorar la auditoría de su servidor y tal vez debería pasar a una pregunta más relevante.
Oleg
0

¿Qué tal 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: rastrear niños bifurcados
  • -ff: registrar cada niño por separado en ssh_log.PID
  • -s8192: aumenta el límite de registro de cadenas (si es necesario)
  • -T -ttt: sellado en microsegundos en segundos desde la época
  • -p N: adjuntar a pid N
Anul
fuente