company_banner

PiAlert V1 на страже безопасности серверов

Автор оригинала: Nick
  • Перевод
Однажды у меня появилась идея. Эта идея воплотилась в проекте PiAlert. Узнать о том, что это такое, вы можете из этого видео. Если рассказать о PiAlert в двух словах, то окажется, что это устройство, на котором, если происходят попытки вторжения на серверы, загораются разноцветные лампочки. Система подсчитывает общее количество таких событий. Я, в основном, наблюдал за попытками подключения к 22 (SSH) порту моих серверов. Обычно эти события являются результатом деятельности ботов. За сутки на одном из моих VPS, где была включена обычная система входа в него, было зафиксировано 1633 попытки вторжения. На ещё одном сервере, где применялся вход в систему без пароля, с использованием SSH-ключа, было зафиксировано 9 атак. Один раз была обнаружена попытка несанкционированного входа в панель управления WordPress-проекта. В вышеупомянутом видео показано испытание системы до её вывода в рабочий режим.

А вот — несколько снимков.


PiAlert в действии


Выключенное устройство, вид спереди


Выключенное устройство, вид сбоку

Должен сказать, что то, что у меня получилось, в лучшем случае можно назвать альфа-версией устройства. Код проекта и модель для 3D-печати корпуса я выложил в общий доступ в надежде на то, что если мой проект кого-то заинтересует, мне помогут его улучшить для всеобщего блага.

Обзор проекта


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

tail -n 80 -f /var/log/apache2/error.log
tail -n 80 -f /var/log/apache2/access.log
tail -n 80 -f /var/log/auth.log

Интересно наблюдать за тем, к каким страницам пытаются обратиться неизвестно откуда взявшиеся боты, или за тем, в какие учётные записи они пытаются войти через SSH. А ещё всё это напоминает хакерские фильмы. Тогда я подумал, что мог бы создать что-то, выглядящее гораздо привлекательнее окна терминала. В этот момент и родился проект, о котором я тут рассказываю.

Результаты наблюдения за попытками входа в систему в последнее время изменились. Случилось это после того, как я внедрил более строгую процедуру входа. А именно, количество попыток войти в систему сильно снизилось. Это стало очевидным после того, как созданная мной система наблюдения за серверами проработала 24 часа. Ниже я об этом расскажу.

Этот материал включает в себя три раздела. В первом речь идёт об аппаратном обеспечении, во втором — о настройке серверов, в третьем — о программах для Raspberry Pi.

Аппаратное обеспечение


Моё устройство собрано из следующих компонентов:


Вот схема подключения.


Схема подключения компонентов к плате

Для подключения к Raspberry Pi светодиодной панели Blinkt! были использованы соединительные провода DuPont. С одной стороны я их обрезал и припаял к соответствующим выводам 40-контактного GPIO-порта панели. Я не мог подключить его напрямую к плате, так как мне ещё нужно было подключить к ней дисплей.

Для того чтобы заставить панель работать мне понадобилось немало времени. Поначалу я думал, что мой экземпляр страдает от плохих соединений в коннекторе. И мне, чтобы с этим разобраться, пришлось, идя путём проб и ошибок, потратить гораздо больше времени, чем мне хотелось бы на это тратить. После того, как я обратился в Pimoroni через Twitter, оказалось, что ранние версии Blinkt! используют для 5V пин №2, а не №4, как показано на pinout.xyz. Я, правда, пока это не выяснил, в спешке заказал ещё одну светодиодную панель Blinkt!, на тот случай, если моя оказалась бы нерабочей. А теперь, после того, как удалось запустить первую, мне надо подумать над новым проектом, в котором можно было бы использовать вторую.

Все эти компоненты я разместил в корпусе, который я спроектировал в Tinkercad. Корпус был напечатан на моём 3D-принтере Ender 3 Pro. Корпус у меня получился, но я так и не смог додуматься до того, как сделать его части такими, чтобы они или плотно входили бы друг в друга, или крепились бы друг к другу защёлками. В итоге я сформировал на одной из частей корпуса пару столбиков, рассчитанных на винты M5, которые я использовал для сборки готового устройства. Эти столбики размещены по краям, так, чтобы в корпусе хватило бы места для Raspberry Pi.

Для печати корпуса я использовал PLA-пластик неизвестного производителя (температура печати — 217°C, величина заполнения — 10%). Я применял обычные настройки, которые подобрал после просмотра различных видео на YouTube.


Результаты нескольких попыток печати корпуса


Сборка корпуса

Создать прилично выглядящую переднюю панель корпуса мне удалось лишь с девятой попытки. Каждый раз, когда я её печатал, оказывалось, что что-то надо слегка переместить, или что где-то, пусть и немного, надо что-то подправить. Я пользовался Tinkercad лишь несколько раз, редактируя модель, и мне пришлось практически сначала начинать работу над ней. Я хотел закрепить светодиодную панель Blinkt! с использованием защёлок, но после нескольких неудачных попыток отказался от этой идеи и решил вопрос с помощью клеевого пистолета (люблю я эту штуку!). Им же я, в итоге, закрепил и дисплей, и саму плату Raspberry Pi. Завершая работу над корпусом, я решал вопрос, касающийся размещения в нём платы. Поначалу я никак плату в корпусе не закреплял, но из-за этого подключение к ней USB-кабеля превратилось в настоящее приключение. В итоговом варианте корпуса (если вообще можно говорить о том, что какой-то его вариант будет «итоговым») мне хотелось бы избавиться от винтов, от отверстий для них и от столбиков внутри корпуса, и найти способ соединения частей корпуса, например, с помощью защёлок. Если кто-то хочет поучаствовать в работе над корпусом и всё в нём поменять — милости прошу! А мне ещё хочется закрыть переднюю панель корпуса чем-то вроде полупрозрачного стекла или куска акрила. Это придало бы устройству законченный вид, скрыв слишком «технические» детали.

Плата Raspberry Pi, на которой основан этот проект, уже использовалась в другом проекте, в котором нужно было, чтобы 40-пиновый GPIO-порт был бы смонтирован с обратной стороны платы. Это, как оказалось, стало плюсом. Плата намертво закреплена в корпусе, в других проектах я её, вероятно, использовать уже не буду. Поэтому некоторые пины я согнул для того чтобы лучше всё разместить в корпусе.


Всё поместилось!

В конце у меня возникла ещё одна идея, которая заключается в том, что мне следует оснастить устройство хотя бы парой кнопок. Может, даже не выводить их наружу, а просто скрыть их где-то в корпусе. Одна нужна для переключения между разными типами зафиксированных атак и для вывода их количества. А вторая должна, коротким нажатием, выключать дисплей, а длинным — аккуратно завершать работу Raspberry Pi. Если нужно, к моему устройству всегда можно подключиться по SSH, а если мне очень понадобится, я могу создать URL-маршрут, вызывающий команду sudo halt.

Настройка серверов


Я, когда после вышеупомянутого происшествия занимался усилением защиты серверов и наладкой мониторинга, проверил, чтобы на них была бы установлена программа fail2ban. Это — замечательный FOSS-проект. Fail2ban наблюдает за логами на сервере и записывает сведения о чём-то таком, что, в нормальных условиях, происходить не должно, вроде множественных неудачных попыток входа на сервер по SSH. Далее, программа банит IP-адрес, с которого исходят подозрительные запросы, делая это в том случае, если речь идёт о потенциально серьёзной проблеме, или если некие события повторяются в течение заранее заданного промежутка времени. По умолчанию fail2ban наблюдает за SSH-трафиком, но программу можно настроить и так, чтобы она присматривала и за чем-то другим, вроде количества ошибок 404 или числа неудачных попыток входа в панель администратора WordPress-проекта.

Fail2ban позволяет создавать собственные действия, вызываемые при возникновении различных событий. Оказалось, что это сложнее, чем нечто вроде простого выполнения curl-запроса, поэтому я, в итоге, обратился за помощью на GitHub. Мне, что бы я ни делал, не удавалось заставить систему работать так, как надо. Для того чтобы вам было легче решить похожую задачу, расскажу о том, как мне, в итоге, удалось всё настроить. А именно, речь идёт об использовании fail2ban на сервере, основанном на Debian.

Создадим файл jail.local и добавим в него следующее:

[sshd]
enabled = true
port = ssh
banaction = pinotifyred[myhost="SCRIPTHOSTSERVER"]

Здесь SCRIPTHOSTSERVER надо заменить на подходящий URL (например — на dev.testing:8080). Обратите внимание на то, что в начале этого URL нет сведений о протоколе, в конце нет пути, адрес не должен завершаться косой чертой.

В результате окажется, что в нашем распоряжении останутся обычные действия, связанные с SSHD, программа продолжит банить подозрительные IP-адреса, но мы ещё и сможем создавать дополнительные действия. К сожалению, нельзя просто описать команду, которая будет здесь выполняться (в этом и заключалась моя проблема). Вместо этого нужно сообщить системе о том, какое именно действие требуется выполнить. Действие вызывается из файла, хранящегося в папке action.d. Имена .conf-файлов в этой папке соответствуют именам действий (в нашем случае это pinotifyred.conf). Вот как выглядят такие файлы:

[Definition]
# отправка get-запроса вроде "http://example.com/red"

actionban = curl --fail "http://<my-host>/red" >> /dev/null

[Init]
# это надо переписать в jail-файл в виде параметра действия:
my-host = SCRIPTHOSTSERVER

Тут, опять же, надо поменять SCRIPTHOSTSERVER на подходящий URL (вроде dev.testing:8080), придерживаясь тех же правил, о которых шла речь выше, в описании файла jail.local.

Код вызывает действие и меняет переменную my-host. Мне не удалось заставить всё это работать без такой переменной.

Этот код выполняет необходимую команду. В нём объявлены некоторые переменные, которые нужны для работы fail2ban. Кроме того, то, как это всё настраивается, означает, что у нас имеется возможность отправлять curl- или wget-запросы с разными параметрами. Среди этих параметров, например, могут быть сведения о том, какой именно IP был забанен, и о том, когда именно это произошло. Поэтому если вам хочется получать более подробные сведения об атаках, чем, как в моём случае, лишь данные об их количестве, вы можете этим воспользоваться. А именно, чтобы это сделать, вы можете разместить в папке action.d файл примерно такого содержания:

[Definition]
#отправляет get-запрос вроде "http://example.com/ban.php?jail=sshd&ip=192.0.2.100":

actionban = curl -G --data-urlencode "jail=%(name)s" --data-urlencode "ip=" --fail "http://<my-host>/ban.php"

[Init]
# это надо переписать в jail-файл в виде параметра действия:
my-host = SCRIPTHOSTSERVER

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

Программы для Raspberry Pi


Буду честен: мой код — это полный бардак. Он написан на Python 3 человеком (мной), который не знает Python, но умеет искать ответы на вопросы в интернете. Это, дополненное общими знаниями в области программирования, позволило мне написать программу на Python.

Я не будут тут рассказывать о подготовке Raspberry Pi к работе по SSH, так как об этом уже много кто рассказывал. Код, о котором идёт речь, размещён на GitHub. Он представлен парой файлов. Первый файл — это pialert.py, он запускается при загрузке системы. Второй файл, tm1637.py, это библиотека, которую я взял из этого материала с сайта RaspberryTips.

Моя Python-программа работает как HTTP-сервер (знаю, она — не для продакшна, но, всё же, речь идёт о простом домашнем проекте), прослушивающий все запросы. Это — однопоточная программа, поэтому если запросов будет очень много, она, скорее всего, с ними не справится. Программа ожидает поступления URL, и если он в ней зарегистрирован, она выполняет действие. Действие — это включение светодиода на Blinkt!, выполняемое в стиле «Larson Scanner», и увеличение показателя счётчика. От URL зависит выбор цвета светодиодов.

Я использую 4 цвета:

  1. Синий — указывает на атаку, совершённую на мой WordPress-сайт.
  2. Красный — SSH-атака на сервер A.
  3. Фиолетовый — SSH-атака на сервер B.
  4. Зелёный — URL-атака на сервер C.

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

В моём коде не обрабатываются ошибки, не контролируется возможное переполнение счётчика. Программа, кроме прочего, показывает мне, что даже моя домашняя сеть постоянно подвергается атакам в виде запросов по особым URL. Атакующие пытаются получить доступ к сети через любую обнаруженную ими уязвимость (из-за этого возникают исключения, но программу это не останавливает).

Одна из последних задач, которую мне нужно было решить в ходе работы над проектом, заключалась в настройке Raspberry Pi. А именно, мне было нужно, чтобы плата, сразу после загрузки, запускала бы скрипт, и чтобы потом всё просто работало. Решается эта задача путём редактирования файла /etc/rc.local. Я, пользуясь редактором vi, добавил в файл команду, которая обычно используется для запуска программ:

python3 /home/pi/PiAlert/pialert.py &

После этого мне осталось решить лишь одну задачу. Она заключалась в том, чтобы обеспечить бесперебойный доступ моих VPS к Raspberry Pi, который находился в домашней сети, за файрволом, и обладал динамическим IP-адресом. Я мог бы воспользоваться Dynamic DNS, или любым другим из бесчисленного множества существующих сервисов. Однако некто из Reddit-сообщества selfhosted создал бесплатный сервис freemyip.com, который решает именно ту задачу, которую мне нужно было решить. И решает он её хорошо. Сервис пока не пользуется особой популярностью, и я уверен, что он, в силу бесплатности, не будет долго оставаться таким, какой он есть. Но учитывая то, как просто с ним работать, я бы с удовольствием за это заплатил. Я обнаружил в том же сообществе ещё один интересный сервис, sliceport.com. Его я тоже когда-нибудь попробую.

Итоги



Демонстрация работы устройства

PiAlert — это устройство, которое нельзя сравнивать с какой-нибудь крутейшей хакерской штукой из фильмов. Его цель — напоминать о том, что каждый день тысячи ботов пытаются получить доступ к чему-то такому, к чему у них доступа быть не должно. Созданное мной устройство просто переносит сведения о подобных попытках в реальный мир, напоминая нам о них. Оно, кроме того, получилось довольно симпатичным.

Что ещё хорошего я могу сказать о PiAlert? Устройство выглядит нейтрально и является весьма гибким. Если я решу, что оно, в его существующем виде, мне больше не нужно, я могу переписать код и превратить его в часы. Или могу сделать из него счётчик посещений страниц моего сайта. На самом деле — есть масса вариантов использования RGB-светодиодов и дисплея, способного выводить 4 цифры. Кроме того, устройство у меня получилось компактное. Оно стоит передо мной на столе когда я пишу код и напоминает мне о том, что в мире есть люди, которые занимаются нехорошими делами. PiAlert для работы нужно совсем немного энергии, поэтому устройство вполне может работать от батарей. Его можно разместить где угодно в доме, главное — чтобы оно могло бы подключиться к WiFi-сети. Там оно будет просто делать своё дело. А если мне понадобится другая сеть — достаточно будет подключиться к Raspberry Pi по SSH или создать новый файл wpa_supplicant.conf в /boot.

В итоге хочу отметить, что мой код, конечно, выглядит не очень. Его можно и нужно отрефакторить. Если я когда-нибудь подучу Python — я это тут же сделаю. Корпус тоже можно улучшить и я, опять же, если освою какую-нибудь программу для 3D-моделирования, поработаю над корпусом. Но, если не брать это в расчёт, могу сказать, что я счастлив тем, что у меня получилось.

Планируете ли вы сделать устройство, напоминающее PiAlert?
RUVDS.com
VDS/VPS-хостинг. Скидка 10% по коду HABR

Комментарии 9

    +1
    Мне почему-то подумалось, что эту идею можно развить.
    Взять старый андроид-смартфон, написать для него простенькое приложение, в котором разные атаки будут разными символами по экрану стекать в зависимости от разных вариантов атаки и разных айпишников как код из Матрицы.
      +1
      Мне казалось, что пытаться взломать будут любой общедоступный сервис, любую админку, любой ssh.
      Если грамотно настроить какой-нибудь вменяемый аналог fail2ban, то и алертер не нужен. а вот алерт о том, что на сервер вошли-таки, было бы неплохо иметь, но с подробностями. например чтобы в телегу приходило уведомление о любом логине в систему, всегда можно точно знать, что происходит и отследить проблемы.
      Но выглядит интересно, мне нравится.
        +1
        Как выглядят попытки взлома, когда на индикатор никто не смотрит? ;)
        Заголовок спойлера
        Точно так же. А поскольку на индикатор чаще не смотрят, чем смотрят — большинство попыток останутся какабы незамеченными.
        Забавно, но бесполезно.
          +1
          А если просто отправлять сообщение на почту/в телеграмм? Как верно здесь подметили эта цветомузыка будет гореть вечно. У меня в fail2ban только по ssh в среднем 15 адресов заблокированных висит.
            +1
            А если просто отправлять сообщение на почту/в телеграмм?


            Зачем? Что нужно делать, увидев это сообщение? Срочно выключать сервер? Срочно менять все пароли? Переносить сервер на другой адрес/порт? Продолжать наблюдение? ;)
              0
              Можно будет составить некоторую картину развития атаки, если заранее продумать какие данные записывать в сообщении. Всяко информативнее моргания светодиодами. Плюс некое свидетельство канарейки — если перестали приходить сообщения, возможно что-то произошло с сервером:)
                0
                Так можно случайно изобрести IDS, а если повезет, то и IPS. Хотя зачем ее изобретать, если готовых решений — вагон?
                  0
                  может и вагон. Но лично я против всяких IDS по причине, «им тоже нужен сервер и за ним нужно следить». Потому только затруднить подбор пароля при помощи fail2ban/iptables, ну и дублирование логов куда-нибудь.
                    0

                    Fail2ban это уже по сути IPS, очень простая по сути.

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

          Самое читаемое