Локальное ведение журнала всех команд ssh с метками времени?


12

Как я могу сохранить локальную метку времени всех удаленных команд, которые я использую ssh(клиент openssh из командной строки запускается bash)?

Требования:

  • Essential:

    • 100% на стороне клиента, не полагаясь на ведение журнала на сервере
    • Сконфигурированный или установленный для пользователя с журналами, сохраненными в домашнем каталоге пользователя.
    • Поддержка различения нескольких одновременных сеансов с различными пользователями и хостами.
    • Ненавязчивый (не нужно активировать его каждый раз и не сильно мешает использованию ssh)
  • Высокий приоритет:

    • Либо вывод не зарегистрирован или отфильтрованы в максимально возможной степени
    • Либо записи пароля не зарегистрированы, либо файл зашифрован
    • Указывает фактические используемые команды (после завершения табуляции / истории, возвраты, CTRL+ Cи т.д ...)
  • Хорошо бы иметь:

    • Также регистрирует команды в связанных сессиях (команды, введенные во время удаленных sshили su <user>сессий)
    • Начало и конец сеанса должны быть зарегистрированы
    • bashЛучше было бы использовать простое решение без полномочий root (возможно, сценарий aliasили bashоболочка для sshкоманды?)

Мой уровень мастерства:

  • Я не новичок в программировании, но я все еще учусь bashи "способ Linux", поэтому примеры кода с краткими пояснениями будут наиболее цениться.

Возможные стратегии

  • Кейлоггер - Проблема: регистрирует пароли, не регистрирует вкладку / историю завершения (см . ответ Гленна )
  • screenс выгрузкой прокрутки один раз в секунду и diffмежду ними для поиска новых строк прокрутки - Проблема: как это можно реализовать полезным автоматическим способом?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile) - Проблема: не может обрабатывать многострочные команды или историю в связанных сессиях, необходима тщательная очистка (см. Мой ответ)
  • Сочетание некоторых из вышеперечисленных

Пример

Следующая сессия 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

Может привести к записи в журнале, ~/logs/ssh.logнапример:

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]

Или, возможно, для каждого сеанса будет создан отдельный журнал с командной строкой, используемой для запуска сеанса в верхней части файла.


Он также должен обрабатывать редактор как нан или VIM
ромашка

Ответы:


4

Я был заинтригован вашим вопросом. Изначально я не собирался давать ответ, но меня зацепило.

Это использует, expectи это действительно ключ регистратор.

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

Заметки:

  • он добавляется в файл с адресом ssh в имени
  • это регистратор ключей: если вы не настроили ssh-ключи, вы получите пароль пользователя в файле журнала.
  • это мешает завершению табуляции: если пользователь наберет uptTab(для uptimeкоманды), вы получите «upt \ t» в файле журнала, а не «uptime»
  • он захватывает символы в «сыром» режиме: если пользователь плохо печатает, вы получите много ^?(символов возврата) в файле журнала.

Большое спасибо за ответ. Интересно, что на этот вопрос нет простого ответа, возможно, родного для клиента ssh. Спасибо за объяснение ограничений; Я думаю, что завершение табуляции / регистрация символов возврата / возврата достаточно для того, чтобы я не мог использовать это часто. Это также заставило меня больше думать о моих приоритетах, и я проясню те, которые в этом вопросе.
Олег

Выходные данные порожденного процесса можно проанализировать, чтобы извлечь нужную команду. Вам нужно знать подсказку пользователя, чтобы сделать это проще.
Гленн Джекман

Я часто использую завершение табуляции. Не означает ли это, что эти команды не будут зарегистрированы?
Олег

Ах, я понимаю, что вы говорите. Как будет проанализирован вывод? Приглашение может быть введено где-то в качестве параметра конфигурации.
Олег

Я добавил список возможных решений в нижней части вопроса. SSH ... | tee -ai <logfile> хорошо работает для безопасного ввода и вывода, но я не знаю, как добавить временные метки и / или отфильтровать вывод в фоновом режиме.
Олег

2

В настоящее время я использую скрипт bash ниже. У него много проблем, но это единственное найденное мной решение, которое учитывает все требования, приоритеты и «приятно иметь» (по крайней мере, большую часть времени).

В этом ответе обсуждается, почему локальная регистрация сессий ssh ​​так сложна.

Проблемы со сценарием, которые я обнаружил до сих пор:

  1. Многострочные команды вызывают проблемы:

    • Если вы пролистаете многострочный элемент в удаленной истории (с помощью клавиш вверх / вниз), он запишет элемент истории вместо последней команды. Вы можете избежать этого, удалив из истории bash любые многострочные команды сразу после их использования.
    • Регистрируется только первая строка многострочных команд.
  2. Связанные сеансы (использование sshили suкоманды на удаленном конце) вызывают прокрутку истории для записи команд с прокруткой вместо фактических используемых команд

  3. Регулярные выражения могут быть улучшены и могут нуждаться в изменении для определенных сред:

    • Я обманываю, преобразовывая непечатаемые символы cat -vперед очисткой. В результате допустимый контент может быть удален, если вы когда-либо будете использовать строки, как ^[[в ваших командах.
    • Иногда вы получаете дополнительный зарегистрированный ввод перед командой, например, если вы просматриваете историю очень быстро. Это обычно сопровождается "^ M" перед фактической командой и, таким образом, может быть удалено при желании.
    • Другие управляющие символы иногда встречаются. Я оставляю их всех пока, пока не узнаю, какие из них безопасно удалить. ^ M, как я только что упомянул, полезен для обнаружения неверного зарегистрированного ввода, и ^ C сообщит вам, была ли команда прервана.
    • Может быть необходимо изменить регулярное выражение для конкретных приглашений, и я мог бы предположить, что разные удаленные среды могут иметь разные шаблоны управляющих символов.
  4. Нет завершения команды ssh, например, для имени хоста. Вы можете получить завершение оргии , если псевдоним этого скрипта sshсalias ssh="sshlog"

Сценарий источника и установки:

Чтобы установить, вставьте следующее в ~ / bin / sshlog и сделайте исполняемым. Позвони с sshlog <ssh command options>. При желании псевдоним 'ssh' в файле .bashrc пользователя.

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

Пример содержимого журнала:

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

У меня есть менее сложный ответ, и, конечно, не кейлоггер. Я не понимаю, как вы независимы от журналов сервера (это означает, что все действия должны выполняться на сервере, а все журналы - это журналы на стороне сервера), и поэтому я подумал, что хорошей идеей является переход к общесистемному bashrc. Подсказка:


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

В Debian вы должны отредактировать файл: /etc/bash.bashrc, а в centos файл: / etc / bashrc

Если вы хотите начать регистрацию для сеанса, в котором вы находитесь, вам нужно найти файл, который вы отредактировали, например, выполнить:


source /etc/bash.bashrc

в системе Debian или


source /etc/bashrc
в системе сентос.

С этого момента каждая команда каждого сеанса ssh будет записываться в / var / log / syslog в системе debian и в / var / log / messages в системе centos.

Если вы хотите записать их в отдельный файл и не связываться с другими файлами журнала, вы можете использовать:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
вместо предыдущего примера PROMPT_COMMAND, а затем настройте rsyslogd при необходимости.

Например, в системе Debian отредактируйте файл /etc/rsyslog.conf : измените строку:


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

.;auth,authpriv.none,local6           -/var/log/syslog
и добавьте следующую строку в конец файла:

local6.info                     /var/log/history.log

затем выполните:

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


Этот вопрос конкретно касается проблемы регистрации сеансов SSH на стороне инициирующего / локального / клиентского компьютера, без необходимости (запоминания / разрешения) настраивать каждый удаленный сервер или необходимости вручную загружать журналы со всех подключенных удаленных серверов. к. Я думаю, что ваш ответ, хотя и не отвечает на этот вопрос, будет полезен для тех, кто заинтересован в улучшении аудита своего сервера, и, возможно, его следует перенести на более актуальный вопрос.
Олег

0

Как насчет strace -o /tmp/ssh_log -ff -s8192 -T -ttt -fp $(pidof sshd)? Это регистрирует все сеансы SSH. Вам может понадобиться инструмент для последующего анализа журнала, или просто использовать grepи awkт. Д.

  • -f: след разветвленных детей
  • -ff: регистрировать каждого ребенка отдельно ssh_log.PID
  • -s8192: увеличить лимит регистрации строк (при необходимости)
  • -T -ttt: микросекундная штамповка в секундах с начала эпохи
  • -p N: прикрепить к пиду N
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.