Техника
March 4

Сторожевой таймер на OpenWrt

Я сделал из старого роутера watchdog (сторожевой таймер), который делает пинг порта каждую минуту и в случае неудачи отправляет сообщение в чат Телеграм.

Зачем? У меня есть веб-сервер и хотелось бы знать если он "отвалится", чтобы принять меры.

Есть готовые решения? Да. Полно. Только бесплатная версия отправит е-мейл, а вот чтобы в Телеграм уведомление - это только через вебхуки и всегда платно.

Роутер и прошивка

У меня завалились два претендента - это D-link Dir-300 (B5) и Asus RT-N14U.

На Dir-300 ставим прошивку OpenWrt 15.05.

Сразу скажу почему Dir-300 не подошел. Всего лишь 228Кб памяти, из которых половину заняла система. Сильно урезанная прошивка имеет проблемы с безопасностью: wget не работает с ssl (https), ssh не поддерживает современные методы шифрования. Передавать свой API токен от Telegram не зашифровав через мужика-по-середине (Man-In-The-Middle attack) так себе идея.

ASUS RT-N14U

На Asus RT-N14U поставил OpenWrt 24.10. На борту устройства почти 58Мб памяти. Под дополнительные пакеты осталось чуть меньше 9Мб. Пойдет.

Telegram бот

Через @BotFather создаем своего бота и получаем token для HTTP API запросов.

Узнаем свой идентификатор (user ID) через бота @getmyid_bot - это будет наш chat_id.

Теперь можно отправлять уведомления через вебхук:

https://api.telegram.org/bot{token}/sendMessage?chat_id={chat_id}&text=""

Скрипт

Написал bash-скрипт для OpenWrt.

Для пинга порта использую netcat.

Ключи для wget:

-q - отключит вывод сообщений в консоль (ошибки всё равно будут отображаться).

-O /dev/null - отбрасывает" содержимое (не сохраняет).

Чтобы сообщение приходило один раз добавим файл флаг (FLAG_FILE).

Переменные IP и PORT будем "забирать" из запроса (пример будет ниже, в sheduled tasks)

Оптимизируем скрипт, добавив функцию send_message.

Эмоджи галочка и крестик заколдируем в URL-encoded:

  • (галочка) → %E2%9C%85
  • (крестик) → %E2%9D%8C

Если интернет-подключение не работает, то пинг не пройдёт, поэтому добавим функцию check_internet - для проверки интернет-соединение и добавим проверку подключения перед отправкой сообщения.

Вот мой скрипт:

#!/bin/sh

TOKEN="1111:AAAA"
CHAT_ID="11111"

IP="$1"
PORT="$2"
FLAG_FILE="/tmp/ping_failed_${IP}_${PORT}"
BASE_URL="https://api.telegram.org/bot${TOKEN}/sendMessage"

send_message() {
    local MESSAGE="$1"
    wget -q --post-data="chat_id=${CHAT_ID}&text=${MESSAGE}" --header="Content-Type: application/x-www-form-urlencoded" -O /dev/null "$BASE_URL"
}

check_internet() {
    ping -q -c 1 -W 1 8.8.8.8 > /dev/null 2>&1
    return $?
}

if ! nc -z -w3 "$IP" "$PORT"; then

    if [ ! -f "$FLAG_FILE" ]; then

        if check_internet; then

            send_message "%E2%9D%8C Ping server $IP on port $PORT failed"

            touch "$FLAG_FILE"

        fi

    fi

else

    if [ -f "$FLAG_FILE" ]; then

        send_message "%E2%9C%85 Ping server $IP on port $PORT available"

        rm -f "$FLAG_FILE"

    fi

fi

Закинул в директорию /root/scripts/portmonitor.sh

Применил права на выполнение скрипта

chmod +x portmonitor.sh

Настраиваем OpenWrt

Ставим необходимые пакеты

В OpenWrt нужно поставить пакет netcat, потому что весит всего лишь 15 Кб.

opkg update
opkg install netcat
В busybox уже есть netcat, но он "урезан". Поэтому если столкнетесь с тем, что netcat не работает с ключами -z -w , то удалите пакет netcat (opkg remove netcat) и поставьте заново - это должно помочь.

Ставим пакеты ca-bundle (125.16 KiB) и ca-certificates (135.90 KiB), чтобы wget мог проверять сертификаты SSL.

opkg install ca-bundle ca-certificates

Если места не хватает для ca-bundle и ca-certificates, то можно выполнить wget с ключом no-check-certificate

wget --no-check-certificate

Так сертификаты проверятся не будут, но это не безопасно.

Ставим таймер

Просто через веб-интерфейс OpenWrt (system > Scheduled Tasks) добавил настройку для cron. Передаем скрипту IP и PORT.

* * * * * /root/scripts/portmonitor.sh 1.1.1.1 80

Все "звездочки" будут запускать скрипт каждую минуту. Вариантов настройки таймеров для cron очень много, если что.

По умолчанию в OpenWrt отключен cron. Включаем и добавляем автозапуск.

/etc/init.d/cron start
/etc/init.d/cron enable

Мой сторожевой пёс роутер поступил на службу. Каждую минуту обнюхивает порт, а если что-то не так - лает в Telegram.