Сторожевой таймер на 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 поставил 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.
-q
- отключит вывод сообщений в консоль (ошибки всё равно будут отображаться).
-O /dev/null
- отбрасывает" содержимое (не сохраняет).
Чтобы сообщение приходило один раз добавим файл флаг (FLAG_FILE).
Переменные IP и PORT будем "забирать" из запроса (пример будет ниже, в sheduled tasks)
Оптимизируем скрипт, добавив функцию send_message.
Эмоджи галочка и крестик заколдируем в URL-encoded:
Если интернет-подключение не работает, то пинг не пройдёт, поэтому добавим функцию 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.