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.