Локальна, часова реєстрація всіх команд ssh?


12

Як я можу зберігати локальний запис часу з усіма віддаленими командами, якими я користуюсь ssh(командний рядок, що відкривається клієнтом bash)?

Вимоги:

  • Основні:

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

    • Будь-який вихід не реєструється або відфільтровується максимально
    • Або записи в паролі не реєструються, або файл зашифровано
    • Позначає фактично використовувані команди (після завершення вкладки / історії, обробок назад, CTRL+ Cтощо) були оброблені
  • Добре мати:

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

Мій рівень кваліфікації:

  • Я не новачок у програмуванні, але все ще вчусь bashі "Linux шляху", тому зразки коду з короткими поясненнями були б найбільш вдячні.

Можливі стратегії

  • keylogger - Проблема: реєструє паролі, не записує вкладку / завершення історії (див . відповідь Glenn )
  • 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]

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


Він також повинен працювати з такими редакторами, як nano або vim
daisy

Відповіді:


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"
  • він захоплює символів у режимі "raw": якщо користувач поганий машинописець, ^?у файлі журналу ви отримаєте багато (символи зворотної області).

Дуже дякую за вашу відповідь. Цікаво, що на це не здається простої відповіді, можливо, рідною для ssh-клієнта. Дякую за пояснення обмежень; Я вважаю, що заповнення вкладки / реєстрація символів зворотної області / реєстрація паролів достатньо, щоб не дозволяти мені часто використовувати це. Це також змусило мене більше задуматися над своїми пріоритетами, і я проясню ці питання.
Олег

Вихід із спареного процесу може бути проаналізований для отримання потрібної команди. Вам потрібно буде знати підказку користувача, щоб зробити це простіше.
glenn jackman

Я багато використовую поповнення вкладок. Чи це не означає, що ці команди не були б записані?
Олег

А, я бачу, що ти кажеш. Як би розбирався вихід? Підказку можна десь ввести як варіант конфігурації.
Олег

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

2

Зараз я використовую скрипт bash нижче. У неї багато проблем, але це єдине знайдене нами рішення, яке стосується всіх вимог, пріоритетів та "приємно мати" (принаймні більшу частину часу).

У цій відповіді йдеться про те, чому вести реєстрацію ssh-сеансів на локальному рівні так складно.

Проблеми зі сценарієм, який я знайшов поки що:

  1. Багаторядкові команди викликають проблеми:

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

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

    • Я обманюю, перетворюючи символи, що не друкуються, cat -vперед чищенням. В результаті дійсний вміст може бути видалений, якщо ви коли-небудь використовуватимете рядки, як ^[[у своїх командах.
    • Іноді перед командою ви отримуєте додатковий вхід, наприклад, якщо дуже швидко перегортаєте історію. За цим, як правило, дотримується "^ M" перед фактичною командою, і, таким чином, за бажанням його можна позбавити
    • Інші символи управління іноді трапляються. Я покидаю їх усіх поки що, поки не знаю, які безпечно видалити. ^ M, як я щойно згадував, корисний для виявлення недійсних вхідних даних, і ^ C сказав би вам, чи була команда перервана.
    • Швидкий регулярний вираз може бути змінений для конкретних підказок, і я можу уявити, що різні віддалені середовища можуть мати різні шаблони символів управління.
  4. Немає виконання команди ssh bash, наприклад, для імені хоста. Ви можете отримати завершення оргії , якщо псевдонім цього скрипта 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, а в центсі - файл: / etc / bashrc

Якщо ви хочете почати вести журнал для сеансу, на якому ви перебуваєте, вам потрібно подати файл, який ви відредагували, наприклад виконати:


source /etc/bash.bashrc

в системі debian або


source /etc/bashrc
в системі centos.

Відтепер кожна команда, кожен ssh сеанс буде реєструватися в / var / log / syslog в системі debian та at / 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: прикріпити до pid N
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.