ServerAdmin.ru
28.8K subscribers
294 photos
34 videos
13 files
2.62K links
Авторская информация о системном администрировании.

Информация о рекламе: @srv_admin_reklama_bot
Автор: @zeroxzed

Второй канал: @srv_admin_live
Сайт: serveradmin.ru
Download Telegram
​​Информационный пост на тему ssh и его возможностей по туннелированию трафика. С помощью ssh подключения можно совершать очень много простых, полезных и неочевидных вещей. Иногда это очень удобно. Я рассмотрю два примера, которые сам регулярно использую. Для их реализации вам необходим обычный ssh доступ к какому-то серверу в интернете.

SOCKS-прокси через ssh. Вы можете без проблем поднять у себя на компьютере локальный socks прокси с использованием удаленного сервера. Для этого локально подключитесь к серверу по ssh примерно таким образом:

ssh -D 3128 root@95.145.142.226

Дальше идёте в любой браузер в настройки прокси и указываете там в параметрах для socks 5 свой локальный socks сервер: localhost, порт 3128. Дальше можете сразу же проверить, какой внешний ip адрес будет показывать ваш браузер. В общем случае это должен быть ip адрес сервера, к которому вы подключились по ssh.

Для подобного подключения подойдет современный windows terminal, который уже имеет встроенный ssh клиент. То есть подключиться проще простого и ничего особо настраивать не надо. На самом сервере, к примеру, можно быстро поднять adguard и использовать его как собственный блокировщик рекламы. При этом не придется замусоривать локальную машину для установки блокировщиков, которые точно не известно, что делают на вашем компе.

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

Переадресация портов через ssh. Это тоже очень простая и полезная история. С помощью ssh можно удаленный порт переадресовать себе локально.

ssh  -L 8181:127.0.0.1:8080 root@95.145.142.226

В данном случай я удаленный порт 8080, который слушает только localhost (127.0.0.1) переадресовал себе локально на порт 8181. Тут важно не перепутать удаленную и локальную машины. 127.0.0.1:8080 - это удалённый сервер, к которому мы подключились по ssh, а 8181 локальный порт на машине, с которой происходит подключение к серверу.

С помощью этой переадресации можно локально получить доступ к порту, который закрыт для удаленных подключений. Обычно локальные mysql клиенты используют такие подключения. Но не обязательно. Можно банально какой-то веб сервер запустить на сервере, закрыв к нему доступ из интернета, а подключаться к нему со своего компа через ssh. Так можно закрывать какие-то панели управления от посторонних глаз.

#ssh #полезности
​​Ранее я уже рассказывал о полезных возможностях ssh. Речь была о SOCKS-прокси и переадресации портов через ssh. Сейчас расскажу о том, как настроить полноценный vpn туннель с помощью подключения по ssh.

Сразу отвечу на вопрос, зачем это вообще нужно, если есть куча других способов настроить vpn. Все дело в простоте и времени настройки. Обычно на сервере уже есть настроенный openssh сервер, так что ничего дополнительно устанавливать не надо. Берёте любой линукс сервер или виртуальную машину и организовываете через него vpn канал.

Для начала вам нужно включить параметр в конфиге /etc/ssh/sshd_config:
PermitTunnel yes
и перезапустить службу sshd.

Далее с клиента подключаетесь к серверу по ssh со следующими ключами:
ssh -p 22777 -w3:3 root@111.222.333.444

w3:3 - имена tun интерфейсов, которые будут созданы на клиенте и сервере (в данном случае tun3). Обращаю внимание, что подобное подключение напрямую из Windows работать не будет. Я для этого подключаюсь через WSL.

После подобного ssh подключения, на сервере и клиенте поднимаются tun3 интерфейсы и фактически vpn канал уже создан. Дальше вам нужно вручную назначить им ip адреса и можно передавать информацию по зашифрованному vpn каналу поверх ssh подключения. Что-то вроде этого надо сделать:
server: ip a add 10.20.0.1/30 dev tun3
server: ip link set dev tun3 up
client: ip a add 10.20.0.2/30 dev tun3
client: ip link set dev tun3 up

Я взял подсеть 10.20.30.0 с маской 30, где всего 2 ip адреса и объединил клиента и сервера в рамках это подсети. Теперь можно пинговать по этим адресам друг друга с сервера или клиента.

Дальше есть разные варианты, как использовать это подключение. Если вы с клиента захотите увидеть локальную сеть за сервером, то на самом сервере нужно будет настроить ip_forward и nat для tun интерфейса, а на клиенте добавить маршрут в эту локалку через vpn канал. Всё точно так же, как и на других vpn туннелях.

Если тема заинтересовала без проблем нагуглите пошаговую инструкцию. Я просто дал информацию о том, что так можно сделать. Как-то объединял по быстрому два филиала через такой туннель. Автоматизировал всё через обычные bash скрипты. Один сервер стоял на базе какой-то готовой сборки с веб панелью управления. И всё это дремучей версии, непонятно кем и как настроенный. Я не захотел туда лазить, разбираться и что-то ставить дополнительно. Просто настроил vpn поверх ssh и закрыл вопрос.

#ssh #vpn
Есть небольшая утилита для организации vpn подключения через ssh - sshuttle. Она есть в стандартных репозиториях популярных дистрибутивов. В Centos живет в репозитории epel. Также присутствует в pip, так как написана на python.

https://github.com/sshuttle/sshuttle
https://sshuttle.readthedocs.io/en/stable/usage.html

Установка:
# dnf install sshuttle
# apt install sshuttle
# pip install sshuttle

Её удобство в простоте и функциональности. VPN соединение организуется поверх SSH. Покажу на примерах:
# sshuttle -r user@1.2.3.4 0/0

Выражение 0/0 эквивалентно маске 0.0.0.0/0, то есть весь трафик отправляем в этот туннель. Будьте аккуратны, когда начнёте тестировать. Вас отключит от текущего ssh соединения. Можете сразу же проверить, через какой ip вы выходите в интернет:
# curl ifconfig.me/ip

Должны увидеть внешний ip ssh сервера, к которому подключились. С помощью sshuttle удобно подключаться к jump host и дальше на целевое устройство. Допустим, на какое-то устройство или сервер (ip - 2.2.2.2) можно подключиться только через конкретный сервер (ip - 3.3.3.3). Используем для подключения sshuttle.
# sshuttle -r user@3.3.3.3 2.2.2.2/32

После подобного подключения у вас будет создан маршрут к 2.2.2.2/32 через ssh сервер 3.3.3.3. Дальше можете со своей машины подключиться к 2.2.2.2.

Во время тестов я столкнулся с ошибкой: fatal: server died with error code 255. Подключение по ssh осуществлялось, а потом sshuttle падал. Решил вот так:

# sshuttle -r user@1.2.3.4 -x 1.2.3.4 0/0

Если используется нестандартный ssh порт, то указать его следует так:

# sshuttle -r user@1.2.3.4:22334 0/0

Для использования ключа при ssh подключении, добавьте следующие опции:

# sshuttle -r user@1.2.3.4 0/0 --ssh-cmd "ssh -i ~/.ssh/id_rsa"

Если что-то пойдёт не так, включите подробное логировние через ключ -vvvv. Увидите, какие правила sshuttle добавляет в firewall и как прописывает маршруты. Там никакой магии, всё наглядно.

В Windows через WSL2 тоже работает, что весьма удобно. Данной заметки достаточно, чтобы начать пользоваться программой, так что смело добавляйте в закладки.

#vpn #ssh
​​Нередко возникает задача по логированию действий пользователя на сервере. Я нагуглил простое и эффективное решение - log-user-session. Проблема возникла одна - никакого описания, как это настраивается. Даже примера конфига нет в репозитории, хотя в описании упомянуто, что он может существовать.

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

Проверял всё на Debian 11. Устанавливаем:
# apt install autoconf gcc make git
# git clone https://github.com/open-ch/log-user-session
# cd open-ch/log-user-session
# ./autogen.sh
# ./configure
# make
# make install

Убеждаемся, что программа log-user-session появилась в /usr/local/bin/. Для проверки её можно запустить в консоли и посмотреть, начала ли она писать лог вашей сессии в /var/log/user-session.

Дальше я не понял, как заставить утилиту писать логи пользователя. Сначала подумал, что её надо поставить, вместо стандартной shell, но это так не работает. Потом чисто методом тыка решил поискать, как настроить принудительный запуск через sshd и нашёл там подходящий параметр. Надо в sshd_config добавить параметр:
ForceCommand /usr/local/bin/log-user-session

Теперь у каждого пользователя будет запускаться оболочка через log-user-session. Если попытаться её закрыть, то пользователя отключит от ssh. У обычного пользователя нет доступа к логам, так что они скрыть свою деятельность не смогут. Может и есть лазейки, но я не разбирал подробно эту тему.

А вот root сможет посмотреть, изменить логи или удалить. Так что если нужно гарантированно логировать действия root, то логи нужно пересылать на какой-то другой сервер, куда нет доступа с этого.

Заметку имеет смысл сохранить, если есть потребность в таком функционале. Я вообще нигде не нашёл информации по настройке этой программы. Какие вы использовали решения для задачи логирования действий пользователей? По идее, тут наколхозить можно много всяких способов, но решение с log-user-session мне показалось самым простым и эффективным. Она даже вывод MC отображает. Я сначала не понял, когда вывел лог работы пользователя в консоль, что это за сессия MC приехала. Потом сообразил, посмотрев текстовым редактором лог файл.

#security #ssh #linux
​​Вчера рассказал, как с помощью log-user-session можно логировать все действия. Сегодня хочу затронуть ещё одну полезную тему - оповещение о логине по SSH. Я настраиваю это почти везде, где подразумевается не только моё подключение к серверам. Это сильно упрощает контроль за инфраструктурой. Если что-то сломалось и ты видишь, что накануне кто-то подключался к серверу, путь к решению лежит на поверхности. Надо сразу написать и спросить, что делали на сервере, а параллельно посмотреть лог действий пользователя.

Вариантов решения этой задачи может быть много. Есть настроен Zabbix Server, то я делаю через него. Для меня это самое простое. Надо добавить айтем с анализом лог файла авторизаций и сделать триггер, срабатывающий на определённые строки. Если мониторинг развёрнут, то достаточно добавить готовый шаблон и дать Zabbix Agent доступ на чтение соответствующего лога. Обычно это /var/log/auth.log или /var/log/secure. Пример подобного мониторинга можно посмотреть у меня в статье. Она довольно старая, а сам я использую другой шаблон, но идея такая же. Каждый уже сам может доработать под себя.

Если используется система сбора логов, то логично настроить анализ и оповещения через неё. Zabbix не очень приспособлен для работы с логами, но в случае отсутствия централизованной системы сбора, для данной задачи он подойдёт. Не надо только очень сильно его нагружать этими логами и хранить их долго. Они будут лежать в обычной SQL базе.

Если системы мониторинга или сборов логов нет, то можно обойтись возможностями самой ОС. Достаточно установить postfix, настроить отправку почты через какой-то почтовый сервис, чтобы письма не улетали в спам. Настройка легко гуглится, есть и у меня на сайте.

Затем добавляем пользователям в .bash_profile небольшой код. Набросал и проверил прямо сейчас, по ходу написания заметки:

if [ -n "$SSH_CLIENT" ]; then
EMAIL="SSH login to $(hostname)\n
\nDATE: $(date)\n
\nUSER: ${USER} from $(echo $SSH_CLIENT | awk '{print $1}')"
echo -e $EMAIL | mail -s "SSH login to ${USER}@$(hostname) from $(echo $SSH_CLIENT | awk '{print $1}')" userpochta@mail.ru
fi

Пример вывода скрипта в итогом письме можно посмотреть во вложении к посту. Теперь при каждом логине в систему будет срабатывать этот код и отправлять уведомление. Если надо добавить сразу всем пользователям этот код и убрать у всех, кроме root, возможность его изменить, добавьте в файл /etc/profile.

#linux #ssh #security
​​Я как-то раз уже вскользь упоминал о возможности пробрасывать порты через SSH в рамках общей заметки о разных возможностях этого протокола. Сейчас хочу поподробнее остановиться на этом с конкретным примером.

Допустим, у вас есть какой-то веб сервис на удалённом сервере, с которым работаете только вы. Хотя это не обязательно, но для упрощения будем считать, что это так. Вам нужен доступ к этому сервису через интернет, но при этом вы не хотите открывать его через интернет без ограничений. Тогда у вас есть как минимум 2 очевидных решения:

1️⃣ Настроить ограничение на подключение по IP. Это сработает в том случае, если у вас существует список статичных IP адресов, с которых вы подключаетесь, а необходимости подключаться с адресов не из этого списка не возникнет. Тогда всё просто. Настраиваете Firewall и забываете о проблеме. Но для надёжности неплохо было бы настроить мониторинг правил фаревола, так как я неоднократно сталкивался с ситуациями, когда по различным причинам фаервол не работал или необходимые правила в нём не были активны.

2️⃣ Настраиваете VPN туннель и подключаетесь к сервису через него. Тут уже нет ограничений по адресам, но придётся настроить и поддерживать дополнительный сервис, плюс ставить клиента на рабочие машины, с которых будете подключаться.

Рассказываю про третий, наиболее простой вариант. Пробрасываете локальный порт сервиса с сервера к себе на локальную машину с помощью SSH. Данный протокол безопасен и его можно оставлять доступным из интернета, используя авторизацию по сертификатам или сложный пароль. Для надёжности можно прикрыть Fail2ban или чем-то подобным.

Подключаемся с локальной машины по SSH следующим образом:
# ssh -L 8080:127.0.0.1:80 -N -f user@remote.host
8080 - локальный порт машины, с которой подключаемся
127.0.0.1:80 - порт, на котором работает веб сервер, не забудьте его запустить только на localhost, чтобы с других адресов он не был доступен
-N -f - ключи для запуска соединения в фоновом режиме, в WSL оно останется активным даже после закрытия терминала

Теперь можно открыть интерфейс Zabbix через проброшенный порт со своего компьютера: http://127.0.0.1:8080/zabbix/

Не нужно настраивать ни VPN, ни Firewall. На сервере открыт только порт SSH, вы можете подключиться к веб интерфейсу из любого места, где есть возможность использовать SSH соединение.

Все популярные SSH клиенты позволяют настраивать проброс портов и сохранять параметры. Так что достаточно один раз настроить соединение и использовать его. Можно и других людей так же подключать. А создав для каждого из них отдельного пользователя можно получить простой аудит подключений на основе логов SSH.

Берите на вооружение, особенно те, кто не умеет, не хочет, ему не нужно учиться настраивать Firewall, а хочется по-быстрому настроить безопасный доступ к какому-то сервису. Программисты часто грешат тем, что на тестовых серверах вешают базу на внешний интерфейс, чтобы подключаться к ней напрямую. А потом забывают, отключить, поменять дефолтную учётку и т.д. Лично сталкивался с этим и не раз.

Когда соединение станет не нужно, через px axf посмотрите его pid и прибьёте через kill. Подобных подключений можно много открыть на разные локальные порты с разных удалённых серверов.

#linux #ssh
​​Делюсь с вами малоизвестной, но полезной и функциональной находкой. Речь пойдёт про систему централизованного хранения и управления ключами для подключения по SSH к хостам - ssham. Я настроил её и разобрался, как с ней работать. Несмотря на то, что про ssham нет ни одного упоминания в интернете, кроме репозитория программы, она достойна внимания.

Идея ssham следующая. Вы устанавливаете её на любой Linux хост. Потом с её помощью через веб интерфейс управляете настройками подключения к другим хостам.

Для этого вы заходите в веб интерфейс ssham, добавляете туда хосты, пользователей, генерируете ключи. Для всего этого поддерживаются группы. А потом связываете ключи с пользователями, создаёте правила, кому на какой хост можно подключаться с помощью того или иногда ключа. Когда всё настроите, запускаете синхронизацию и ssham сам разложит по хостам нужные сертификаты, для которых настроено разрешение на подключение. Ключи можно как добавлять, так и отзывать/удалять.

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

Копируем репозитоий:
# git clone https://github.com/pacoorozco/ssham.git ssham
# cd ssham
Делаем копию файла с параметрами окружения:
# cp .env.example .env
Заходим в .env и комментируем строку:
#QUEUE_CONNECTION=database
Пока я этого не сделал, у меня не работала синхронизация ключей по хостам. Несколько часов потратил, пока разобрался.

Далее собираем и запускаем образы:
# export DOCKER_SSHAM_UID="$(id -u)"
# docker-compose build
# docker-compose up -d

Устанавливаем в контейнер app зависимости:
# docker-compose exec app composer install
Инициализируем БД и добавляем туда demo данные:
# docker-compose exec app php artisan key:generate 
# docker-compose exec app php artisan migrate:fresh --seed

Дальше идём в веб интерфейс по ip адресу и логинимся под superadmin / superadmin.

Логика работы с ssham следующая. Создаём SSH Key groups, добавляем SSH key и помещаем его в эту группу. Далее создаём Host group, добавляем Host и помещаем его в эту группу. В завершении создаём Rule, где указываем, что созданная SSH Key group имеет доступ к Host group. Или не имеет. Доступ можно как разрешить, так и запретить.

После того, как всё сделали, в Settings смотрим Public key сервера. Его нужно один раз самостоятельно распространить на управляемые хосты, добавив в ./ssh/authorized_keys. После этого идём в консоль сервера, где запущены контейнеры и выполняем синхронизацию:
# docker-compose exec app php artisan ssham:send

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

Исходники

#ssh #devops #управление
Не зря существует поговорка: "Век живи - век учись". Буквально на днях узнал, что есть очень простой способ, как ограничить выполнение каких-то команд при подключении по SSH с аутентификацией через сертификат.

В файл authorized_keys перед самим сертификатом добавляем разрешённую команду:
command="top" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt....

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

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

Я знал, что можно настраивать подобные ограничения через конфиг sshd и настройку ForceCommand, но с authorized_keys всё намного проще, быстрее, нагляднее.

Возникла ещё одна идея, где это может быть удобно. Если сами настраиваете bastion host или jump host, по разному может называться. Суть в том, что только через этот хост можно подключаться к другим серверам. Можно сделать учётки, для которых будет разрешено подключение к какому-то конкретному серверу. А параметры подключения прописать сразу в command. При подключении по ssh на jump host, пользователь сразу окажется на нужном сервере. Сразу готова и система ограничения доступа, и логирования на базе sshd.

Подробнее об этой настройке можно прочитать в документации к sshd.

#ssh
Хочу подкинуть вам идею, которая может когда-нибудь пригодиться. Подключение к NFS серверу можно организовать через проброс портов по SSH и это нормально работает. Когда есть sshfs, может показаться, что в этом нет никакого смысла. Могу привести свой пример, когда мне это пригодилось.

Мне нужно было перекинуть бэкапы виртуалок с внешнего сервера Proxmox домой на мой NFS сервер. Тут вариант либо порты пробрасывать на домашний сервер, но это если у тебя белый IP, либо как раз воспользоваться пробросом портов, подключившись из дома к внешнему серверу по SSH.

Настраивать тут особо ничего не надо. Если NFS сервер уже настроен, то достаточно сделать обратный проброс локального порта 2049 на внешний сервер:

# ssh -R 2049:127.0.0.1:2049 root@server-ip

Если на той стороне уже есть nfs сервер и порт 2049 занят, то можно указать другой. Только надо аккуратно поменять ровно то, что нужно. Я обычно путаюсь в пробросе портов по SSH, так как тут неинтуитивно. Должно быть вот так:

# ssh -R 3049:127.0.0.1:2049 root@server-ip

Останется только на удалённом сервере подмонтировать том:
# mount -t nfs -o port=3049 localhost:/data /mnt/nfs-share

Тут ещё стоит понимать, что nfs и sshfs принципиально разные вещи. Первое — это полноценная сетевая файловая система со своими службами, хранением метаданных и т.д., а второе — реализация доступа к файлам по протоколу SFTP на базе FUSE (Filesystem in Userspace). SFTP обычно используется для разовой передачи файлов. NFS же можно ставить на постоянку. Это стабильное решение (но не через SSH 😀).

#nfs #ssh #fileserver
​​Я уже не однократно затрагивал тему логирования сессий пользователей на Linux сервере. Все способы сильно отличаются друг от друга, так что каждый может выбрать то, что подходит ему больше в конкретной ситуации. Напомню, о чём я уже рассказывал:

◽️snoopy — небольшая библиотека под Linux, которая может логировать не только команды пользователей, но многое другое. Например, команды системных процессов.
◽️log-user-session — программа, которая запускается вместо оболочки пользователя и пропускает через себя все его команды, записывая их в текстовый файл.
◽️PROMPT_COMMAND — логирование в текстовый файл с помощью встроенных возможностей оболочки bash.

Сейчас хочу рассказать о более серьезной программе, которая написана RedHat и интегрирована в их экосистему. Речь пойдёт про Tlog. Под остальные линуксы нужно будет самостоятельно собирать из исходников. Хотя я посмотрел в момент написания статьи, как дела обстоят в Debian, и заметил, что этот пакет в 12-й версии уже в ветке Testing. Так что со временем и для Debian должен появиться пакет.

Tlog умеет хранить сессии пользователей в текстовых файлах через rsyslog, в журнале systemd или в elasticsearch. Формат хранения — json, так что вручную такие логи смотреть не удобно. В комплекте с tlog есть утилита для воспроизведения сохранённой сессии. Причём можно как запись смотреть, так и в режиме реального времени. Если сессии хранятся локально, то за сеансом можно следить в соседней консоли, если в elasticsearch, то подключившись к нему. Посмотреть, как это выглядит на практике можно в демонстрационном ролике.

Tlog в RHEL или Centos, а также всех форках, интегрирован с SSSD и Cockpit. У redhat есть статья с описанием, как это реализовано. Если коротко, то ставим cockpit и tlog. Настраиваем в sssd запись сессии, назначаем группу, для которой она будет работать. Потом пользователей добавляем в эту группу и смотрим записи их сессий через веб интерфейс cockpit. Там это реализовано в виде плеера.

Поддержка elasticsearch реализована с помощью модуля omelasticsearch для rsyslog. То есть логи надо будет сначала в rsyslog положить, а потом он отправит их в elasticsearch. А встроенная поддержка этого дела заключается в том, что потом можно будет просматривать сессии, подключаясь напрямую в elasticsearch. Пример настройки и просмотра показан в репозитории.

В общем, если вам нужно централизованное решение для логирования пользовательских сессий, то Tlog будет лучшим вариантом. С настройкой придётся повозиться, но получится полноценное решение, основанное на пользователях и группах с помощью интеграции с FreeIPA через SSSD. Забыл сразу упомянуть об этом.

Сайт / Исходники / Настройка / Демонстрация

#security #ssh #linux
​​Очень простой и быстрый способ настроить уведомления об успешном SSH подключении к серверу в Telegram. Для этого понадобится свой bot, простенький bash скрипт и изменение конфига PAM для SSH. Будем через него уведомления делать.

Рассказывать про создание бота не буду. Надо создать нового бота, получить его токен. Также понадобится ваш ID. Узнать можно разными способами, например через бота @my_id_bot.

Далее берём простой скрипт:

#!/bin/bash

if [ "$PAM_TYPE" != "close_session" ]; then
  ID=1307682341
  BOT_TOKEN=6327355747:AAEDcFIlhKSIOKS-t2I9ARTdT1usbq2a9W4
  message="$(date +"%Y-%m-%d, %A %R")"$'\n'"SSH Login: $PAM_USER@$(hostname)"
  curl -s --data "text=$message" --data "chat_id=$ID" 'https://api.telegram.org/bot'$BOT_TOKEN'/sendMessage' > /dev/null
fi

Тут мы проверяем переменную PAM_TYPE. Если это что-то отличное от закрытия сессии, то нам подходит. Проверить работу скрипта можно примерно так:

# PAM_TYPE=open_session ./ssh-success.sh

От бота вам должно прийти уведомление в указанном выше формате. Только имени пользователя не будет, потому что переменную PAM_USER не задали.

Копируем этот скрипт в директорию /etc/ssh/ и выставляем минимальные права:
# chown root /etc/ssh/ssh-success.sh
# chmod 100 /etc/ssh/ssh-success.sh

Далее открываем конфиг /etc/pam.d/sshd и добавляем туда:

# Send a login notification to Telegram via ssh-success.sh
session  optional   pam_exec.so seteuid /etc/ssh/ssh-success.sh

На этом всё. Теперь при успешном SSH подключении вы будете получать уведомление в Telegram.

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

Единственное, что мне хотелось бы сделать, но не получилось - вывести в уведомление IP адрес подключившегося пользователя. Я не нашёл в переменных PAM этой информации. А парсить лог ssh подключений не захотелось. Это делает решение неуниверсальным. В представленном виде сообщения будут такие:

2023-08-07, Monday 15:10
SSH Login: root@debian11

Подробная дата (date +"%Y-%m-%d, %A %R"), имя пользователя ($PAM_USER) и имя сервера (hostname). Можете добавить какую-то ещё информацию по своему усмотрению. Если кто-то знает переменную PAM с информацией об адресе подключившегося, подскажите. Я не нашёл такой информации.

#linux #bash #ssh #security
Существует удобный инструмент для поддержания постоянного подключения по SSH - Autossh. Это бесплатная программа, которая есть в стандартных репозиториях популярных дистрибутивов.

# apt install autossh

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

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

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

Сначала просто проверяем соединение:

# autossh -M 0 -N -p 22777 -f -q -i /home/userssh/.ssh/id_rsa \
-o "ExitOnForwardFailure=yes" -o "ServerAliveInterval=30" \
-o "ServerAliveCountMax=3" -R 9033:localhost:22 \
userssh@1.1.1.1

Синтаксис тут один в один как у обычной службы sshd в том, что касается ssh соединения. То есть выполняем стандартный обратный проброс через ssh. Локальный порт 22 пробрасываем на удалённый хост 1.1.1.1 на порт 9033. Опции autossh можете посмотреть в его описании. Не буду на этом подробно останавливаться.

Теперь можно подключиться к внешнему серверу и на нём подключиться к внутреннему серверу:

# ssh -p 9033 root@localhost

Окажетесь на закрытом сервере, на котором запустили autossh.

Теперь сделаем всё красиво, запуская autossh через systemd под отдельной учётной записью. Создаём юнит /etc/systemd/system/autossh.service:

[Unit]
Description=SSH Reverse Tunnel
After=network-online.target

[Service]
Type=forking
User=userssh
ExecStart=/usr/bin/autossh -M 0 -N -p 22777 -f -q -i /home/userssh/.ssh/id_rsa -o "ExitOnForwardFailure=yes" -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" -R 9033:localhost:22 userssh@1.1.1.1
ExecStop=/usr/bin/pkill -9 -u userssh
RestartSec=5
Restart=always

[Install]
WantedBy=multi-user.target

Запускаем и добавляем в автозагрузку:

# systemctl daemon-reload
# systemctl start autossh.service
# systemctl enable autossh.service

Проверяем на внешнем сервере:
# netstat -tulnp | grep 9033
tcp    0   0 127.0.0.1:9033     0.0.0.0:*        LISTEN   19814/sshd: userssh
tcp6    0   0 ::1:9033        :::*          LISTEN   19814/sshd: userssh

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

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

#ssh