Выявление сессий по ключу SSH: различия между версиями

Материал из ALT Linux Wiki
Нет описания правки
Нет описания правки
 
(не показано 36 промежуточных версий этого же участника)
Строка 1: Строка 1:
Когда к одному логину на сервере приходится давать доступ нескольким персоналиям (например, нескольким разработчикам к логину <code>webmaster</code> для работы с сайтом), хотелось бы понимать, кто именно, откуда и когда входил.
=Входы=
Когда к одному логину на сервере приходится давать доступ нескольким персоналиям (например, разным разработчикам к логину <code>webmaster</code> для работы с сайтом), хотелось бы понимать, кто именно, откуда и когда входил.


И это далеко не столь сложно, как может представляться, поскольку в журнал SSHd сыплются в т.ч. сообщения формата:
И это далеко не столь сложно, как может представляться, поскольку в журнал SSHd сыплются в т.ч. сообщения формата:
Строка 6: Строка 7:
</pre>
</pre>
В то же время, чек-суммы ключей для допущенных пользователей…
В то же время, чек-суммы ключей для допущенных пользователей…
*можно извлечь из файла {{path|~/.ssh/authorized_keys}} командой {{cmd|ssh-keygen -E SHA256 -lf ~/.ssh/authorized_keys}}, где они хранятся в виде <pre>ssh-<алгоритм> <публичный ключ> <его владелец></pre>
*можно получить командой {{cmd|ssh-keygen -E SHA256 -lf ~/.ssh/authorized_keys}} из указанного в ней файла, где они хранятся в виде: <pre>ssh-<алгоритм> <публичный ключ> <его владелец></pre>
*и сопоставить их со входами этих пользователей.
*и сопоставить их со входами этих пользователей.
Набросал для этих целей скриптец:
Набросал для этих целей скриптец:
Строка 15: Строка 16:
#!/bin/bash
#!/bin/bash


UNIT=sshd # в некоторых дистрибутивах этот юнит не содержит "d".
USER=${1:-admin} # умолчальный юзер, если не задан иной.
KEYS=`eval echo ~$USER`/.ssh/authorized_keys # ключ-файл.
UNIT=ssh
 
case `awk -F= '/^NAME/{gsub("\"","");print $2}' /etc/os-release` in
    ALT*) UNIT+=d;;
esac


case $LANG in
case $LANG in
     ru*)printf "  Дата    Время  Логин      IP-адрес        Чей ключ\n";;
     ru*)printf "  Дата    Время  Логин      Откуда          Чей ключ\n";;
     *)  printf "  Date      Time  Login      IP address     Key owner\n"
     *)  printf "  Date      Time  Login      Where from     Key owner\n"
esac
esac


while read LOGINS; do
## В старых линуксах лучше делать так:
     LINE=($LOGINS)
readarray -t LOGINS < <(journalctl -o short-iso -u $UNIT | \
awk '/Accepted publickey/{sub("ROOT USER","");print $1,$7,$9,$14}')
 
for ((i=0;i<${#LOGINS[@]};i++)); do
     LINE=(${LOGINS[$i]})
     DATE=${LINE[0]%+*}
     DATE=${LINE[0]%+*}
    LOGIN=${LINE[1]}
     OWNER=`ssh-keygen -E SHA256 -lf $KEYS | grep "${LINE[3]}" | cut -d' ' -f3`
    IP=${LINE[2]}
     printf "${DATE/T/ } %-10s %-15s $OWNER\n" ${LINE[1]} ${LINE[2]}
     OWNER=`ssh-keygen -E SHA256 -lf ~/.ssh/authorized_keys | grep "${LINE[3]}" | cut -d' ' -f3`
done
     printf "${DATE/T/ } %-10s %-15s %s\n" $LOGIN $IP $OWNER
done <<<`journalctl -o short-iso -u $UNIT | awk '/Accepted publickey/{print $1,$7,$9,$14}'`
</source>
</source>
|}
|}
Вывод выглядит так:
<pre>
    Дата    Время  Логин      Откуда          Чей ключ
год-мес-день ЧЧ:ММ:СС логин      ип.ад.ре.с      владелец@ключа
...
год-мес-день ЧЧ:ММ:СС логин      ип.ад.ре.с      владелец@ключа
</pre>
=Выходы=
Куда сложней обстоит дело с завершением таких сеансов ввиду перманентной долбёжки ботами, войти которые не могут (не только ввиду отключённого парольного доступа, но их ещё и {{cmd|fail2ban}} за настырность блокирует), однако выходить после неудач вынуждены — что журналируется, забивая выходы «честных бродяг».
Посему длительность сессии приходится прикидывать наугад, выявляя глазами логауты, ближайшие под логином по ключу.
Можно ещё поискать {{cmd|awk '/Received disconnect/'}} по совпадающим адресу и номеру порта, но сколько времени займёт такой поиск — угадать крайне затруднительно.
=Обратная связь=
*[https://t.me/gbIMoBou @gbIMoBou]
*[[Участник:Дым#Заметки|Другие статьи]]
{{Category navigation|title=Системному администратору|category=Admin|sortkey={{SUBPAGENAME}}}}
[[Категория:Admin]]

Текущая версия от 14:06, 29 сентября 2023

Входы

Когда к одному логину на сервере приходится давать доступ нескольким персоналиям (например, разным разработчикам к логину webmaster для работы с сайтом), хотелось бы понимать, кто именно, откуда и когда входил.

И это далеко не столь сложно, как может представляться, поскольку в журнал SSHd сыплются в т.ч. сообщения формата:

<дата> <время> <хост назначения> <демон[пид]> Accepted publickey for <логин> from <IP-адрес> port <номер> ssh2: <алгоритм ключа> <контрольная сумма ключа>

В то же время, чек-суммы ключей для допущенных пользователей…

  • можно получить командой ssh-keygen -E SHA256 -lf ~/.ssh/authorized_keys из указанного в ней файла, где они хранятся в виде:
    ssh-<алгоритм> <публичный ключ> <его владелец>
  • и сопоставить их со входами этих пользователей.

Набросал для этих целей скриптец:

/usr/local/bin/sswho  
#!/bin/bash

USER=${1:-admin} # умолчальный юзер, если не задан иной.
KEYS=`eval echo ~$USER`/.ssh/authorized_keys # ключ-файл.
UNIT=ssh

case `awk -F= '/^NAME/{gsub("\"","");print $2}' /etc/os-release` in
    ALT*) UNIT+=d;;
esac

case $LANG in
    ru*)printf "   Дата     Время   Логин      Откуда          Чей ключ\n";;
    *)  printf "   Date      Time   Login      Where from      Key owner\n"
esac

## В старых линуксах лучше делать так:
readarray -t LOGINS < <(journalctl -o short-iso -u $UNIT | \
awk '/Accepted publickey/{sub("ROOT USER","");print $1,$7,$9,$14}')

for ((i=0;i<${#LOGINS[@]};i++)); do
    LINE=(${LOGINS[$i]})
    DATE=${LINE[0]%+*}
    OWNER=`ssh-keygen -E SHA256 -lf $KEYS | grep "${LINE[3]}" | cut -d' ' -f3`
    printf "${DATE/T/ } %-10s %-15s $OWNER\n" ${LINE[1]} ${LINE[2]}
done

Вывод выглядит так:

     Дата     Время   Логин      Откуда          Чей ключ
год-мес-день ЧЧ:ММ:СС логин      ип.ад.ре.с      владелец@ключа
...
год-мес-день ЧЧ:ММ:СС логин      ип.ад.ре.с      владелец@ключа

Выходы

Куда сложней обстоит дело с завершением таких сеансов ввиду перманентной долбёжки ботами, войти которые не могут (не только ввиду отключённого парольного доступа, но их ещё и fail2ban за настырность блокирует), однако выходить после неудач вынуждены — что журналируется, забивая выходы «честных бродяг».

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

Можно ещё поискать awk '/Received disconnect/' по совпадающим адресу и номеру порта, но сколько времени займёт такой поиск — угадать крайне затруднительно.

Обратная связь