Comment puis-je conserver un logging horodaté local de toutes les commands distantes que j'utilise dans ssh
(client openssh en command line lancé par bash
)?
Exigences:
Essentiel:
Haute priorité:
Agréable d'avoir:
ssh
ou su <user>
distantes) bash
basique non root serait la meilleure (peut-être un script d'encapsulage alias
ou bash
pour la command ssh
?) Mon niveau de compétence:
bash
et la "manière Linux", donc les exemples de code avec de brèves explications seraient très appréciés. Stratégies possibles
screen
avec scrollback dumping une fois par seconde et diff
entre eux pour find de nouvelles lignes de défilement – Problème: comment cela peut-il être mis en œuvre de manière automatisée et utile? ssh "$@" | tee >(some_cleaner_function >> $logfile)
ssh "$@" | tee >(some_cleaner_function >> $logfile)
– Problème: impossible de gérer les commands multilignes ou l'historique des sessions chaînées, nettoyage soigné nécessaire (voir ma réponse) Un exemple
La session SSH suivante:
user@local:~$ ssh user@remote Last login: Tue Jun 17 16:34:23 2014 from local user@remote:~$ cd test user@remote:~/test$ ls ab user@remote:~/test$ exit
Peut résulter en un journal à ~/logs/ssh.log
comme:
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, peut-être un journal distinct sera créé pour chaque session avec la command line utilisée pour démarrer la session en haut du file.
J'ai été insortinggué par votre question. Je ne voulais pas donner de réponse à l'origine mais je me suis accroché.
Cela utilise expect
et c'est vraiment un enregistreur key.
#!/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,ssortingng) if {$char eq "\r"} { log $keystrokes set keystrokes "" } else { append keystrokes $char } send -- $char } eof } log "{session ends}"
Remarques:
uptime
), vous obtiendrez "upt \ t" dans le file journal, pas "uptime" ^?
(caractères de return arrière) dans le file journal. J'utilise actuellement le script bash ci-dessous. Il y a beaucoup de problèmes, mais c'est la seule solution que j'ai trouvée qui réponde à toutes les exigences, à toutes les priorités et à tous les aspects de la vie (au less la plupart du time).
Cette réponse explique pourquoi la journalisation des sessions ssh localement est si difficile.
Problèmes avec le script que j'ai trouvé jusqu'à présent:
Les commands multilignes provoquent des problèmes:
Les sessions chaînées (en utilisant les commands ssh
ou su
sur l'extrémité distante) provoquent le défilement de l'historique pour save les commands défilées au lieu des commands réelles utilisées
Les expressions régulières peuvent être améliorées et peuvent devoir être modifiées pour certains environnements:
cat -v
avant le nettoyage. Par conséquent, le contenu valide peut être supprimé si vous utilisez des strings comme ^[[
dans vos commands. Pas d'achèvement de la command ssh bash, comme pour le nom d'hôte. Vous pouvez get la complétion bash si vous aliasez ce script avec ssh
avec alias ssh="sshlog"
Source du script et installation:
Pour l'installer, collez ce qui suit dans ~ / bin / sshlog et faites un exécutable. Appelez avec les sshlog <ssh command options>
. Optionellement alias à 'ssh' dans le file .bashrc de l'user.
#!/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 - eg ^[[2P line=$(echo "${line}" | sed 's/\^\[\[[0-9]*[AZ]//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/\^[AZ]//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}
Exemple de contenu de journal:
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]
Que diriez-vous de strace -o /tmp/ssh_log -ff -s8192 -T -ttt -fp $(pidof sshd)
? Ceci journalise toutes les sessions ssh. Vous pouvez avoir besoin d'un outil pour parsingr le journal ultérieurement, ou simplement utiliser grep
, awk
etc.
-f
: trace des enfants fourchus -ff
: consigne chaque enfant séparément dans ssh_log.PID
-s8192
: augmente la limite de consignation des strings (si nécessaire) -T -ttt
: microseconde en quelques secondes depuis l'époque -p N
: joindre à pid N
J'ai une réponse less compliquée, et sûrement pas un keylogger. Je n'obtiens pas votre point d'être indépendant du journal du server (cela signifie que toutes les actions doivent être sockets sur le server et tous les journaux sont des journaux côté server), et j'ai donc pensé qu'une bonne idée est de passer à bashrc une command rapide comme:
PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -t "$USER[$$] $SSH_CONNECTION")'
Dans debian, vous devez éditer le file: /etc/bash.bashrc et en centos le file: / etc / bashrc
Si vous souhaitez démarrer la journalisation de la session, vous devez générer le file que vous avez édité, par exemple:
source /etc/bash.bashrc
dans un système debian ou
source /etc/bashrc
dans un système centos.
A partir de maintenant, chaque command de chaque session ssh sera enregistrée dans / var / log / syslog sur un système debian, et dans / var / log / messages sur un système centos.
Si vous voulez les save sur un file séparé et ne pas gâcher avec d'autres files journaux, vous pouvez utiliser:
PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
à la place de l'exemple précédent de PROMPT_COMMAND, puis configurez le rsyslogd selon les besoins.
Par exemple, sur un système Debian, éditez le file /etc/rsyslog.conf : changez la ligne:
. ;auth,authpriv.none -/var/log/syslog
à
. ;auth,authpriv.none,local6 -/var/log/syslog
et ajoutez la ligne suivante à la fin du file:
local6.info /var/log/history.log
puis exécutez:
touch /var/log/history.log && /etc/init.d/rsyslog restart