Registrazione locale e timestamp di tutti i comandi ssh?


12

Come posso conservare un registro locale, con data e ora di tutti i comandi remoti che uso in ssh(client openssh da riga di comando avviato bash)?

Requisiti:

  • Essenziale:

    • 100% lato client senza fare affidamento sulla registrazione del server
    • Configurato o installato per utente con i log memorizzati nella home directory dell'utente.
    • Supporto per la distinzione tra più sessioni simultanee con vari utenti e host.
    • Non invadente (non è necessario attivarlo ogni volta e non interferisce in modo significativo con l'utilizzo di ssh)
  • Priorità alta:

    • L'output non viene registrato o filtrato il più possibile
    • Le voci della password non sono registrate o il file è crittografato
    • Indica i comandi effettivamente utilizzati (dopo che sono stati elaborati il completamento della scheda / cronologia, i backspaces, CTRL+ C, ecc ...)
  • Bello avere:

    • Registra anche i comandi in sessioni concatenate (comandi immessi durante il telecomando ssho le su <user>sessioni)
    • L'inizio e la fine della sessione devono essere registrati
    • Una soluzione semplice bash, non root, sarebbe la migliore (forse uno script aliaso bashwrapper per il sshcomando?)

Il mio livello di abilità:

  • Non sono nuovo nella programmazione, ma sto ancora imparando bashe il "modo Linux", quindi i campioni di codice con brevi spiegazioni sarebbero apprezzati.

Possibili strategie

  • keylogger - Problema: registra le password, non registra il completamento della scheda / cronologia (vedi la risposta di glenn )
  • screencon lo scrollback che scarica una volta al secondo e difftra di loro per trovare nuove righe di scrollback - Problema: come può essere implementato in un modo automatizzato utile?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile) - Problema: impossibile gestire comandi multilinea o cronologia in sessioni concatenate, è necessaria un'attenta pulizia (vedere la mia risposta)
  • Una combinazione di alcuni dei precedenti

Un esempio

La seguente sessione 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

Potrebbe risultare in un registro ~/logs/ssh.logcome ad esempio:

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]

Oppure, forse verrà creato un registro separato per ogni sessione con la riga di comando utilizzata per avviare la sessione nella parte superiore del file.


Dovrebbe anche gestire editor come nano o vim
daisy,

Risposte:


4

Sono stato incuriosito dalla tua domanda. Inizialmente non avevo intenzione di dare una risposta, ma mi sono appassionato.

Questo utilizza expected è davvero 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}"

Appunti:

  • si aggiunge a un file con la destinazione ssh nel nome
  • è un registratore di chiavi: se non hai impostato le chiavi ssh, ottieni la password dell'utente nel file di registro
  • è sventato dal completamento della scheda: se l'utente digita uptTab(per il uptimecomando), otterrai "upt \ t" nel file di registro, non "uptime"
  • prende i caratteri in modalità "raw": se l'utente ha una cattiva dattilografia, otterrai molti ^?(caratteri backspace) nel file di registro.

Grazie mille per la tua risposta. È interessante notare che non sembra esserci una risposta facile per questo, forse nativo per il client SSH. Grazie per aver spiegato i limiti; Penso che il completamento della scheda / la registrazione dei caratteri del backspace / la registrazione della password siano sufficienti per impedirmi di usarlo spesso. Mi ha anche fatto riflettere di più sulle mie priorità e chiarirò quelle nella domanda.
Oleg,

L'output del processo generato può essere analizzato per estrarre il comando desiderato. Dovresti conoscere il prompt dell'utente per renderlo più semplice.
Glenn Jackman,

Uso molto il completamento delle schede. Questo non significa che quei comandi non sarebbero stati registrati?
Oleg,

Ah, capisco cosa stai dicendo. Come verrebbe analizzato l'output? Il prompt potrebbe essere inserito da qualche parte come opzione di configurazione.
Oleg,

Ho aggiunto l'elenco delle possibili soluzioni in fondo alla domanda. ssh ... | tee -ai <logfile> funziona bene per registrare input e output in modo sicuro, ma non so come aggiungere timestamp e / o filtrare l'output in background.
Oleg,

2

Attualmente sto usando lo script bash di seguito. Ha molti problemi, ma è l'unica soluzione che ho trovato che affronta tutti i requisiti, le priorità e i "simpatici" (almeno la maggior parte delle volte).

Questa risposta spiega perché la registrazione locale delle sessioni ssh è così difficile.

Problemi con lo script che ho trovato finora:

  1. I comandi multilinea causano problemi:

    • Se si sfoglia un elemento su più righe nella cronologia remota (con i tasti su / giù), verrà registrato un elemento della cronologia anziché l'ultimo comando. Puoi evitarlo eliminando dalla cronologia bash tutti i comandi multilinea immediatamente dopo che sono stati utilizzati.
    • Viene registrata solo la prima riga di comandi multilinea.
  2. Le sessioni concatenate (utilizzando ssho sucomandi all'estremità remota) causano lo scorrimento della cronologia per registrare i comandi passati anziché i comandi effettivi utilizzati

  3. Le espressioni regolari possono essere migliorate e potrebbe essere necessario modificarle per determinati ambienti:

    • Imbroglio convertendo i caratteri non stampabili con cat -vprima della pulizia. Di conseguenza, il contenuto valido può essere rimosso se si utilizzano stringhe come ^[[nei comandi.
    • A volte ricevi un ulteriore input registrato prima del comando, come se sfogli la cronologia molto velocemente. Questo è generalmente seguito da una "^ M" prima del comando effettivo e quindi può essere rimosso se desiderato.
    • A volte si verificano altri personaggi di controllo. Li sto lasciando tutti dentro per ora fino a quando non so quali sono sicuri da rimuovere. ^ M come ho appena menzionato è utile per rilevare input registrati non validi e ^ C ti direbbe se il comando è stato interrotto.
    • Potrebbe essere necessario modificare il prompt regex per richieste particolari e potrei immaginare che ambienti remoti diversi possano avere schemi di caratteri di controllo diversi.
  4. Nessun completamento bash del comando ssh, come per hostname. È possibile ottenere il completamento bash se si alias questo script sshconalias ssh="sshlog"

Fonte e installazione dello script:

Per installare, incollare quanto segue in ~ / bin / sshlog e rendere eseguibile. Chiama con sshlog <ssh command options>. Facoltativamente alias di 'ssh' nel file .bashrc dell'utente.

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

Esempio di contenuto del 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]

0

Ho una risposta meno complicata, e sicuramente non un keylogger. Non capisco il tuo punto di essere indipendente dal registro del server (questo significa che tutte le azioni devono essere intraprese sul server e tutti i registri sono registri sul lato server), e quindi ho pensato che una buona idea sia passare a tutto il sistema bashrc un comando rapido come:


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

In debian dovresti modificare il file: /etc/bash.bashrc e in centos il file: / etc / bashrc

Se si desidera avviare la registrazione per la sessione in cui ci si trova, è necessario eseguire il sorgente del file che è stato modificato, ad esempio eseguire:


source /etc/bash.bashrc

in un sistema debian o


source /etc/bashrc
in un sistema centos.

D'ora in poi, ogni comando, di ogni sessione ssh verrà registrato su / var / log / syslog su un sistema debian e su / var / log / message su un sistema centos.

Nel caso in cui si desideri registrarli su un file separato e non fare confusione con altri file di registro, è possibile utilizzare:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
invece dell'esempio PROMPT_COMMAND precedente e quindi configurare rsyslogd secondo necessità.

Ad esempio in un sistema Debian modificare il file /etc/rsyslog.conf : cambiare la riga:


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

.;auth,authpriv.none,local6           -/var/log/syslog
e aggiungi la seguente riga alla fine del file:

local6.info                     /var/log/history.log

quindi eseguire:

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


Questa domanda riguarda in particolare il problema della registrazione delle sessioni ssh sul lato del computer di avvio / locale / client, senza dover (ricordare / essere autorizzato) a configurare ciascun server remoto o scaricare manualmente i registri da tutti i server remoti a cui ci si connette per. Penso che la tua risposta, sebbene non risponda a questa domanda, sarebbe utile a qualcuno interessato a migliorare il controllo del proprio server e dovrebbe forse essere spostato in una domanda più pertinente.
Oleg,

0

Che ne dici strace -o /tmp/ssh_log -ff -s8192 -T -ttt -fp $(pidof sshd)? Questo registra tutte le sessioni ssh. Potrebbe essere necessario uno strumento per analizzare il registro successivamente, o semplicemente utilizzare grep, awkecc.

  • -f: traccia bambini biforcuti
  • -ff: registra ogni bambino separatamente su ssh_log.PID
  • -s8192: aumenta il limite di registrazione delle stringhe (se necessario)
  • -T -ttt: timbratura in microsecondi in pochi secondi dall'epoca
  • -p N: allega a pid N
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.