Задача:
Собирать информацию о действиях пользователя (аудита) в консоли Linux, а именно вводимых им командах и выводимой на экран информации.
Предлагаемое решение:
screen по умолчанию для всех пользователей в Linux с логированием
Необходимые условия:
- Полное логирование всех пользователей в консоли, включая вывод информации процессами, чтобы можно было оценить почему пользователь принял то или иное решение
- Без возможности отключения логирования
- Раз уж выбрали screen — максимально используем его возможности (открытие новых окон, отключение по ^a + d, оставляя рабочие процессы запущенными и другие удобства)
- Максимальное удобство — не должно быть каких-либо несовместимостей с приложениями
- В случае использования пользователями, не знакомыми с screen — сделать работу максимально знакомой и близкой к обычной командной оболочке (shell)
Возможные варианты:
1) Предложенный на Хабре вариант. Рабочий, но есть несколько моментов:
- По-хорошему надо было бы указать shell пользователя в /etc/shells
- screen как таковой не работает. Иначе говоря дополнительные окна не открываются
- Логирование отключается банальным ^a + H (заглавная)
2) Тут тоже предложены варианты, но это больше сырые заготовки
Итак, приступим:
Имеется 2 возможных варианта использования screen для нашей задачи:
- Использование родной командной оболочки (shell), а затем вызывать screen автоматически скриптом
- Использование screen как командную оболочку пользователя
Судя по цитатам по ссылке, второй вариант нехорош по
...It then becomes hard to do anything with your account other than log in. Also, your sysadmin probably doesn't have screen in /etc/shells...
Создаём скрипт для запуска screen, чтобы при запуске командной оболочки bash (ведь у вас bash, правда?) все пользователи использовали этот файл и загружались в screen по умолчанию с включённым логированием. При выходе из screen – сессия закрывается:
vi /usr/local/bin/get_in.sh#!/bin/sh SCREEN=/usr/bin/screen KILL=/bin/kill ## Check if we are already in screen ($STY is set) if [ -z "$STY" ]; then $SCREEN -LARR -S Shared -c /etc/screenrc ## Force SHELL close on exit - we don't want to allow users to escape logging outside screen $KILL -SIGHUP $PPID fi
Что мы имеем:
-L — направить весь лог в файл (куда именно — см. директиву logfile в файле /etc/screenrc ниже)
-A — Адаптировать размеры окон к размеру текущего терминала. Взято отсюда.
-RR — Переподключить сессию и, если необходимо, отсоединить (detach) её или создать заново. Используется первая сессия, если больше чем одна доступна. В случае отключения по ^a + d, при повторном входе откроется эта же сессия этого же пользователя.
-c — мы чётко указываем, какой конфигурационный файл использовать, чтобы избежать возможности отключения логирования и переназначения опций пользователями, к примеру созданием файла в ~/.screenrc.
-S — Назначаем сессии понятное имя. У каждого пользователя может быть одно и то же имя.
Делаем скрипт исполняемым:
chmod 0755 /usr/local/bin/get_in.shДелаем так, чтобы все использовали этот скрипт. Для этого в конец файла /etc/bash.bashrc добавляем строку:
/usr/local/bin/get_in.shКорректируем файл /etc/screenrc:
## Выбираем, хотим ли мы видеть заметку о правообладателях во время запуска. По умолчанию включено (on), как вы заметили. startup_message off # default: on ## Отключаем визуальный сигнал - включается обычное "пикание" как в shell vbell off ## Размер буфера прокрутки увеличиваем до 4096. Значение по умолчанию - 100. defscrollback 4096 # default: 100 ## Устанавливаем командную оболочку (shell), которая будет использоваться при создании новых окон. Переназначает значение переменной окружения $SHELL. Если команда начинается с символа '-' , то командная оболочка будет запущена как login-shell. defshell -/bin/bash ## Влияет на копирование текста комадной ^a+[ . crlf off # default: off ## Добавляет симпатичную строку состояния внизу экрана. caption always "%{= kg} %H | %{kc}%?%-w%?%{kY}%n*%f %t%?(%u)%?%{= kc}%?%+w%? %=|%{kW} %l %{kw}| %{kc}%{-b}%D, %m/%d/%Y | %{kW}%{+b}%c %{wk}" ## Set terminal cap info termcapinfo xterm* 'hs:ts=\E]0;:fs=\007:ds=\E]0;\007' hardstatus off ## Отключаем возможность отключения логирования из самой сессии screen (^a + H) bind H ## Устанавливаем расположение и именование лог-файлов logfile /var/log/screen/$USER@%H-%Y%m%d-%c:%s.log ## By default, screen uses an 8-color terminal emulator. Use the following line to enable more colors, which is useful if you are using a more-capable terminal emulator: term screen-256color ## Устанавливает функцию записи отметок времени в лог-файл logtstamp on
Не забываем создать директорию для логов:
mkdir /var/log/screen
chmod 0777 /var/log/screen
Этим мы добиваемся, что все команды будут логироваться в лог-файлы вида:
/var/log/screen/user@server-20130716-19:52:34.log
В Debian, чтобы в screen работало автозавершение команд (bash_completion), необходимо раскомментировать в /etc/bash.bashrc:
# enable bash completion in interactive shells if [ -f /etc/bash_completion ] && ! shopt -oq posix; then . /etc/bash_completion fi
Уважаемый 1ex подсказал решение, как с помощью wrapper-а для ssh логировать команды, выполняемые без входа в интерактивный режим bash вида: ssh user@host «ls -l». Для этого необходимо:
в /etc/ssh/sshd_config указать ссылку на обработку wrapper-ом:
ForceCommand /etc/ssh/hook.sh
Затем создать сам wrapper /etc/ssh/hook.sh:
#!/bin/sh if [ ! -z "${SSH_ORIGINAL_COMMAND}" ]; then echo "User "${USER}" remotely runs a command: ${SSH_ORIGINAL_COMMAND}" >> /var/log/screen/$USER@`hostname`-`date +%Y%m%d-%H:%M:%S`-command.log bash -c "$SSH_ORIGINAL_COMMAND" else cat /etc/motd ${SHELL} fi
Не забыть сделать его исполняемым:
chmod +x /etc/ssh/hook.sh
Этим мы добиваемся, чтобы все такие команды (и только команды — без информации, что выводится на экране) логировались в ту же директорию и будут дополнены суффиксом "-command":
/var/log/screen/user@server-20130717-12:47:53-command.log
Ну вот и всё. Теперь при подключении все пользователи (включая root — будьте осторожны, если потеряете возможность входа!) будут работать в screen, который запускается из bash. При выходе из screen, родительский bash закрывается и соединение прерывается. Если необходимо оставить работать процессы в фоне, то для выхода используем ^a+d. При следующем подключении эта сессия подключится автоматически.
Для дальнейшего изучения:
- Так как в логи пишется вывод команд — они могут занимать большое количество места. Необходимо предусмотреть методы сжатия для уменьшения объёма/трафика
- Лучшее место для логов — удалённая машина и далее обработку производить там, так как логи на локальной машине создаются с uid/guid пользователя и могут быть им удалены/изменены. Предполагается использование syslog.
- Возможно, есть методы обойти screen и, соответственно, логирования при этой конфигурации. Хотелось бы услышать их и внести изменения
Используемые источники:
- http://habrahabr.ru/sandbox/65904/
- http://superuser.com/questions/52297/use-gnu-screen-as-login-shell
- https://spaces.seas.harvard.edu/display/USERDOCS/How+to+use+%27screen%27+for+remote+shell+sessions
- http://www.linuxjournal.su/?p=3495
- http://www.howtoforge.com/options-for-user-auditing-on-linux-platforms
Update:
1) По замечанию joneleth пути изменены на жёсткие:
Абзац:
Заменён на:SCREEN=`which screen` KILL=`which kill`
SCREEN=/usr/bin/screen KILL=/bin/kill
На данный момент существуют 2 метода обхода логирования команд:
Уважаемый 1ex подсказал решение с помощью wrapper-а для ssh. Теперь все команды такого типа логируются. Изменения в текст внесены.
2) Подсказана ForeverYoung: команда screen -X log отключает логирование.
Возможности отключить эту особенность пока что нету, поэтому необходимо применять административные меры к пользователям, кто запускает эту команду (сама эта команда всё равно будет записана в лог).
Лучшие решения приветствуются.
ИТОГИ:
Как выяснилось screen не совсем предназначен для решения такого рода задач, а именно принудительного логирования команд и их вывода без возможности отключения логирования. Это приводит к тому, что приходится дополнительно править другие файлы.
Как порекомендовал уважаемый amarao для решения такого рода задач лучше посмотреть на другие решения:
а) сниффинга всего трафика, проходящего через псевдотерминалы (более серьёзно). kiltumподсказал conspy. Slipeer предложил Snoopy Logger.
б) систем аудита (SELinux/Apparmor/etc), которые будут записывать реально всё выполняемое.
Но эти решения выходят за рамки данной статьи.
Считаю, что несмотря на недостатки, использование screen для логирования действий пользователей и выводимой на экран информации в Linux оправдано, ввиду несложности реализации, а главное — простоты чтения логов (в отличие от auditd, напимер).

