Входы Выходы Пользователей SSH auth.log Debian Ubuntu В целом тут неплохо все работает
и
Входы Выходы Пользователей SSH Auth journalctl Alt Linux тут мне не совсем все нравится как работает. Например выходы не всегда работают нужно закрывать вручную, не отображает IP адрес подключившегося была идея совместить 2 строки в одну через внешний скрипт запроса по времени и брать полные данные, но там не все так хорошо.
Решил попробовать другими способами взять
СКАЧАТЬ Рабочий Входы на Линукс + authlinuxlld.sh
Код: Выделить всё
lsof -n -a -itcp -stcp:established -c sshd
-n — не пытаться преобразовывать ip-адреса в доменные имена (может значительно ускорить работу)
-a — применить логическую операцию «и» («and»)
-itcp — показать tcp-сокеты
-stcp:established — показать tcp-сокеты, находящиеся в состоянии «established»
-c sshd — показать процессы, запущенные из бинарных файлов, имена которых начинаются строкой sshd
почему два фильтры -itcp и -c sshd вместо одного -itcp:22?
потому что в этом случае в вывод попадут и процессы ssh, запущенные локально и подключившиеся к 22-ым портам каких-нибудь машин. к тому же, в случае, если ваш sshd слушает и/или порт(ы), отличный(е) от 22-го, то такие соединения просто не попадут в вывод.
Пример вывода:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 2608 root 3u IPv4 361287 0t0 TCP 192.168.175.36:ssh->192.168.175.8:57577 (ESTABLISHED)
sshd 5429 root 3u IPv4 386680 0t0 TCP 192.168.175.36:ssh->192.168.180.130:49835 (ESTABLISHED)
Код: Выделить всё
netstat -tnpa | grep 'ESTABLISHED.*sshd'
Вывод:
Нет пользователя
Код: Выделить всё
ss -o state established '( dport = :ssh or sport = :ssh )'
Netid Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp 0 272 192.168.175.36:ssh 192.168.180.130:49835 timer:(on,057ms,0)
tcp 0 0 192.168.175.36:ssh 192.168.175.8:57577 timer:(keepalive,76min,0)
Эти 2 команды выше показывают подключение по сети ssh.
КТО
Код: Выделить всё
who
user :0 Jun 16 07:58 (:0)
root pts/0 Jun 16 10:41 (192.168.175.8)
root pts/1 Jun 16 11:48 (192.168.180.130) вход одновременно
root pts/2 Jun 16 11:48 (192.168.180.130) вход одновременно
user pts/3 Jun 16 11:51 (:0) терминал под root
user pts/4 Jun 16 12:03 (192.168.175.8) терминал под root
Код: Выделить всё
who -H
ИМЯ ЛИНИЯ ВРЕМЯ PID КОММЕНТАРИЙ ВЫХОД
root - pts/0 2022-06-17 08:22 . 25180 (192.168.175.8)
pts/3 2022-04-05 16:08 28927 id=ts/3 терминал=0 выход=0
pts/1 2022-06-01 16:44 29415 id=ts/1 терминал=0 выход=0
pts/2 2022-04-12 12:29 23964 id=ts/2 терминал=0 выход=0
информации о пользователях, которые подключены к системе
-a (--all) — включает в себя все основные опции.
- b (--boot) — показывает время загрузки операционной системы.
-d (--dead) — выводит перечень зомби-процессов. (кто вышел)
- H (--heading) — никак не влияет на получаемую информацию, зато добавляет колонкам заголовки и помогает понять что где находится.
-m — показать пользователя, который сейчас работает в терминале.
-r — вывести текущий уровень запуска (runinit);
-t — показать последнее изменение системных часов;
-s — вывести только имя, терминальную сессию и время.
-q — вывести количество авторизованных пользователей.
-T — данные о терминальной сессии.
-u — показать активных пользователей.
--ips — вместо названия хостов показывает ips.
--lookup — используется в сочетании с --ips, выводит данные, которые основываются на сохраненном IP, если он доступен, а не на названии хоста
В состав опции -a входят опции -b, -d, --login, -p, -r, -t, -T, -u
Попытка №1
Сперва возникла идея с таким ключом заббикс
system.run["who -a|tail -n +3"]
на разных осях выходило разное количество строк и бывало в разном порядке убрать 3 строки в начале не всегда помогало!
Ключ с выводом шапки столбцов
system.run["who -aH"]
Ну и не посредственно ключ с выбранными нужными нам строками и их содержанием
system.run["who -dsTu"] Триггер
Имя: SSH auth {HOST.NAME1} {ITEM.VALUE}
Важность: Информационная
Выражение
{SSH-Local Auth Linux Test:system.run["who -dsTu"].iregexp([0-9]+)}=1 and
{SSH-Local Auth Linux Test:system.run["who -dsTu"].iregexp(выход|exit)}=0 and
{SSH-Local Auth Linux Test:system.run["who -dsTu"].diff(0)}=1
Выражение восстановления
{SSH-Local Auth Linux Test:system.run["who -dsTu"].iregexp(выход|exit)}=1
Множественный
Все проблемы если значения тегов совпадают
Тег совпадения who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}
Описание
Пользователь Авторизовался в системе
Auth who {ITEM.VALUE}
Имя тега who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}
Попытка №2
С данными все не плохо, но использовать их для триггера в частности для множественного срабатывания не вариант.
Пилим скрипт внешней проверки
Ключ authlinux.sh[{HOST.CONN},{$HOST.PORTS}] Из скрипта сделать вывод в видело лога со штампом даты времени
в некоторых случаях месяц выходит текстом , где то на русском. так же если после перезагрузки или включения никто не входил пустая переменная.
authlinux.sh
Код: Выделить всё
#!/bin/bash
# 17.06.2022
# Автор Мамзиков Артём Андреевич
IP=$1
PORT=${2:-10050}
HOSTHOST=$3
# На основе команды who будем формировать лог/журнал для передачи в заббикс
#authlist=`zabbix_get -s $IP -p $PORT -k system.run["who -a|tail -n +3"]`
authlist=`zabbix_get -s $IP -p $PORT -k system.run["who -dsTu"]`
# Если вывод пустой (после включения или перезагрузки)
currentd=`date "+%m-%d %H:%M"`
if [[ "$authlist" == "" ]]; then echo $currentd $IP no-logged &&exit 1;fi
#Обработаем построчно
IFS=$'\n'
for strokami in $authlist;do
# Для распознавания строки, строка которая не содержит выход|exit добавим auth
strauth=$(echo $strokami|grep -Eiv 'exit|выход'|sed 's/$/ auth/g')
if [[ "$strauth" != "" ]]; then strokami=$strauth ;fi
# Штампа времени y: Год (0001-9999); M: Месяц (01-12); d: День (01-31); h: Час (00-23); m: Минута (00-59); s: Секунда (00-59); p-заменители могут быть чем угодно
cutdate=$(echo "${strokami}"|sed 's/\s\+/ /g'|grep -oe '....[0-9][0-9].[0-9][0-9]:[0-9][0-9]'|sed 's|^-||')
# Преобразуем в нижний регистр (формат)
shopt -s nocasematch
# Переведем текстовый формат месяца в числовой, где он приходит текстом
case $cutdate in
*янв*|*jan*)
nummount="01"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*фев*|*feb*)
nummount="02"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*мар*|*mar*)
nummount="03"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*апр*|*arp*)
nummount="04"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*ма*|*may*)
nummount="05"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*июн*|*jun*)
nummount="06"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*июл*|*jul*)
nummount="07"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*авг*|*aug*)
nummount="08"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*сен*|*sep*)
nummount="09"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*окт*|*oct*)
nummount="10"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*ноя*|*nov*)
nummount="11"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
*дек*|*dec*)
nummount="12"
timestamp=$(echo $cutdate|sed "s/^[A-Za-zA-Яа-я]\+ /$nummount-/g")
json=$(echo $timestamp $IP "${strokami}")
;;
# Если уже числовой без изменений
*)
json=$(echo $cutdate $IP "${strokami}")
esac
shopt -u nocasematch
#zabbix_sender -z 127.0.0.1 -p 10051 -s "${HOSTHOST}" -k authlinux -o "$json" #Вывод построчно
# Формируем список
jsons=$jsons$st"${json}"
st="\n"
done
echo -e $jsons #Вывод логом
Код: Выделить всё
./authlinux.sh 192.168.175.33 10050
04-13 10:58 192.168.403.77 pts/1 2022-04-13 10:58 10424 id=ts/1 терминал=0 выход=0
Код: Выделить всё
./authlinux.sh 192.168.185.29 10050
Код: Выделить всё
./authlinux.sh 192.168.185.29 10050
06-16 10:06 192.168.185.23 pts/0 2022-06-16 10:06 313765 id=ts/0 терминал=0 выход=0
Код: Выделить всё
./authlinux.sh 192.168.409.8 10050
Триггер
SSH auth {HOST.NAME1} {ITEM.VALUE}
Важность: Информационная
Выражение
{SSH-Local Auth Linux Test:authlinux.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].iregexp(auth)}=1 and
{SSH-Local Auth Linux Test:authlinux.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].iregexp(выход|exit)}=0 and
{SSH-Local Auth Linux Test:authlinux.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].diff(0)}=
Выражение восстановления
{SSH-Local Auth Linux Test:authlinux.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].iregexp(выход|exit)}=1
Множественный
Все проблемы если значения тегов совпадают
Тег совпадения who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}
Описание
Пользователь Авторизовался в системе
Auth who {ITEM.VALUE}
Имя тега who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}
Попытка №3
Далее попытка передавать все построчно, через траппер немного переделав скрипт
Ключ authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}] authlinuxtrap.sh
Код: Выделить всё
#!/bin/bash
# 21.06.2022
# Автор Мамзиков Артём Андреевич
IP=$1
PORT=${2:-10050}
HOSTHOST=$3
# На основе команды who будем формировать лог/журнал для передачи в заббикс
#authlist=`zabbix_get -s $IP -p $PORT -k system.run["who -a|tail -n +3"]`
authlist=`zabbix_get -s $IP -p $PORT -k system.run["who -dsTu"]`
# Если вывод пустой (после включения или перезагрузки)
if [[ "$authlist" == "" ]]; then echo "no-logged" &&exit 1;fi
#Обработаем построчно
IFS=$'\n'
for strokami in $authlist;do
# Для распознавания строки, строка которая не содержит выход|exit добавим auth
strauth=$(echo $strokami|grep -Eiv 'exit|выход'|sed 's/$/ auth/g')
if [[ "$strauth" != "" ]]; then strokami=$strauth ;fi
# Преобразуем в нижний регистр (формат)
shopt -s nocasematch
#Вывод построчно
zabbix_sender -z 127.0.0.1 -p 10051 -s "${HOSTHOST}" -k authlinuxtrap -o ""${strokami}"" > /dev/null
shopt -u nocasematch
# Формируем список
jsons=$jsons$st"${strokami}"
st="\n"
done
#zabbix_sender -z 127.0.0.1 -p 10051 -s "${HOSTHOST}" -k authlinuxtrap -o ""${jsons}"" > /dev/null
echo -e $jsons #Вывод логом
#echo "1"
Триггер
SSH auth {HOST.NAME1} {ITEM.VALUE}
Важность: Информационная
Выражение
{SSH-Local Auth Linux Test:authlinuxtrap.iregexp(auth)}=1 and
{SSH-Local Auth Linux Test:authlinuxtrap.iregexp(выход|exit|no-logged)}=0 and
{SSH-Local Auth Linux Test:authlinuxtrap.diff(0)}=1
Выражение восстановления
{SSH-Local Auth Linux Test:authlinuxtrap.iregexp(auth)}=0 and
{SSH-Local Auth Linux Test:authlinuxtrap.iregexp(выход|exit|no-logged)}=1
Множественный
Все проблемы если значения тегов совпадают
Тег совпадения who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}{{ITEM.VALUE}.iregsub("(no-logged.*)", "\1")}
Описание
Пользователь Авторизовался в системе
Auth who {ITEM.VALUE}
Имя тега
who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}
{{ITEM.VALUE}.iregsub("(no-logged.*)", "\1")}
Еще 2 триггера прямо на элемент со скрипта authlinuxtrap.sh
Триггер
Test SSH auth {HOST.NAME1} {ITEM.VALUE}
Важность: Информационная
Выражение
{SSH-Local Auth Linux Test:authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].str(auth)}=1 and
{SSH-Local Auth Linux Test:authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].str(выход|exit|no-logged)}=0 and
{SSH-Local Auth Linux Test:authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].diff(0)}=1
Выражение восстановления
{SSH-Local Auth Linux Test:authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].str(auth)}=0 and
{SSH-Local Auth Linux Test:authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].str(выход|exit|no-logged)}=1
Множественный
Все проблемы если значения тегов совпадают
Тег совпадения who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}{{ITEM.VALUE}.iregsub("(no-logged.*)", "\1")}
Описание
Пользователь Авторизовался в системе
Auth who {ITEM.VALUE}
Имя тега
who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}
{{ITEM.VALUE}.iregsub("(no-logged.*)", "\1")}
Без выражения восстановления на закрытие только выражение и тег
Триггер
Test2 SSH auth {HOST.NAME1} {ITEM.VALUE}
Важность: Информационная
Выражение
{SSH-Local Auth Linux Test:authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].str(auth)}=1 and
{SSH-Local Auth Linux Test:authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].str(выход|exit|no-logged)}=0 and
{SSH-Local Auth Linux Test:authlinuxtrap.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}].diff(0)}=1
Множественный
Все проблемы если значения тегов совпадают
Тег совпадения who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}{{ITEM.VALUE}.iregsub("(no-logged.*)", "\1")}
Описание
Пользователь Авторизовался в системе
Auth who {ITEM.VALUE}
Имя тега
who{{ITEM.VALUE}.iregsub("[0-9]+:[0-9]+.* ([0-9]+).*(\(|id)", "\1")}
{{ITEM.VALUE}.iregsub("(no-logged.*)", "\1")}
Итого мы уже получили с 3х попыток 4 элемента данных 2 скрипта 5 триггеров Все в целом работает, ИД входа проставляется в тег закрытие происходит при совпадении тегов на выход, данные время вид сессии пользователь ip все получаем.
Но так как данные идут построчно кругом это считаются разные данные а не одна и таже строка что вызывает бесконечное открытие новых триггеров! даже если мы скидываем разом берется либо верхняя строка либо искомая строка из всех строк первая по совпадению, опять же в некоторых строках пишется время с момента входа и оно меняется данные отличаются и все теже множественные срабатывания.
Проблема закрытия если было 5 пользователей и выполнили перезагрузку тега на выход нет.
Можно принимать 1 строку самую новую по ней открывать и закрывать но это не совсем точно если за интервал опроса например 1 минуту вошли сразу несколько покажет только одного.
Глобальная Корреляция так же не подходит так как нужно указать конкретное значения тега, а у нас оно получается в момент открытия триггера, по имени тега не вариант.
В итоге сделал чрез правило обнаружения, на строки входа создается элемент с триггером и выходит в ошибку через 35 секунд после обнаружения нет данных. История не хранится, элемент удаляется вместе с триггером сразу же как перестает обнаруживаться
есть запаздывание 2-4 минуты если пользователь зашел и вышел за 1 минуту быстрее всего не покажет. Остается история проблем.
Так же можно включит обычный элемент для лога истории если необходимо.
Правило обнаружения
Имя: Обнаружение пользователей выполнивших вход в ОС
Тип: Внешняя проверка
Ключ: authlinuxlld.sh[{HOST.CONN},{$HOST.PORTS},{HOST.HOST}
Интервал обновления: 1m
Период сохранения потерянных ресурсов: 0d
Описание:
На основе вывода команды who -dsTu
Найденные пользователи сразу будут выводить триггер в ошибку, после пропадания в списке обнаружения пользователя, пропадание триггера.
Активировано: V
Прототип элемента данных
Имя: Auth-User: {#STAUTH}
Тип: Zabbix траппер
Ключ: authuser["{#AUTHID}"]
Тип информации: Целое числовое
Период хранения истории: 1h
Период хранения динамики изменения: 0d
Группы элементов данных: Авторизация ssh
Описание: Временный элемент, создается пока пользователь {#AUTHUSER} находится в ОС Linux .
Создать активированным: V
Прототип триггера
Имя: Auth-User: {#STAUTH}
Важность: Информационная
Выражение:
{SSH-Local Auth Linux Test:authuser["{#AUTHID}"].last()}=1 or
{SSH-Local Auth Linux Test:authuser["{#AUTHID}"].nodata(35)}=1
Описание:
Триггер создается пока пользователь: {#AUTHUSER} находится в ОС Linux .
{#STAUTH}
Создать активированным: V
Скрипт: authlinuxlld.sh
Код: Выделить всё
#!/bin/bash
# 21.06.2022
# Автор Мамзиков Артём Андреевич
IP=$1
PORT=${2:-10050}
HOSTHOST=$3
# На основе команды who будем формировать лог/журнал для передачи в заббикс
authlist=`zabbix_get -s $IP -p $PORT -k system.run["who -dsTu"]|sed 's/\s\+/ /g'`
#Обработаем построчно
IFS=$'\n'
for strokami in $authlist;do
# Выбираем строки авторизации, кроме строк выхода
strauth=$(echo $strokami|grep -Eiv 'exit|выход')
# Получим ID сессии для ключа (так как в строке $strauth меняется время с момента входа и создается новый элемент)
idsession=$(echo $strokami|sed -E 's|.*[0-9]+:[0-9]+ ||'|sed 's|^[A-Za-zA-Яа-я]\+ ||'|sed 's/(.*\|id.*//'|tr -d ' '|grep -oe '[0-9]\+')
# Пользователь
authuser=$(echo $strauth|awk '{print $1}')
if [[ "$strauth" != "" ]]; then
# Формируем список
JSON=$JSON"$SEP\n{\"{#AUTHID}\":\"$idsession\",\"{#AUTHUSER}\":\"$authuser\", \"{#STAUTH}\":\"$strauth\"}"
SEP=", "
fi
done
# Выводим результат в json
JSON="["$JSON"\n]"
echo -e "${JSON}"
# Для того чтоб ввести триггер сразу в ошибку нужно передать данные в элемент сразу после обнаружения, еще раз цикл(
#Обработаем построчно
#IFS=$'\n'
#for strokami in $authlist;do
# Выбираем строки авторизации, кроме строк выхода
#strauth=$(echo $strokami|grep -Eiv 'exit|выход')
#idsession=$(echo $strokami|sed -E 's|.*[0-9]+:[0-9]+ ||'|sed 's|^[A-Za-zA-Яа-я]\+ ||'|sed 's/(.*\|id.*//'|tr -d ' '|grep -oe '[0-9]\+')
#if [[ "$strauth" != "" ]]; then
# Отправка через траппер
#zabbix_sender -z 127.0.0.1 -p 10051 -s "${HOSTHOST}" -k authuser[\""${idsession}"\"] -o "1" > /dev/null
#fi
#done