Управляем сервером посредством СМС: различия между версиями

Материал из support.qbpro.ru
imported>Vix
(Новая страница: «Началось все с того, что я откопал в полке с железками USB модем huaweiE1550, купленный мной прош…»)
 
imported>Vix
Нет описания правки
 
Строка 279: Строка 279:


* [https://habrahabr.ru/post/114912/ взято тут...]
* [https://habrahabr.ru/post/114912/ взято тут...]
* Дополнительно (с)
''Чтобы в лог сыпался баланс и уровень сигнала, в конфиге smstools надо написать (для МТС):''
regular_run_cmd = AT+CUSD=1,"#100#";
regular_run_cmd = AT+CSQ
regular_run_interval = 86400
regular_run_logfile = /var/log/smsd_regular_run.log

Текущая версия от 17:04, 14 февраля 2016

Началось все с того, что я откопал в полке с железками USB модем huaweiE1550, купленный мной прошлым летом для организации резервного канала Интернет. Проработал он тогда недолго и за ненадобностью был убран в «закрома» до лучших времен. Первое что сделал, разлочил его для работы с МТС (так уж сложилось исторически, что я предпочитаю именно этого оператора). Изначально в голову пришла идея отправки смс с предупреждениями от Nagios, вместо почты. Бегло пробежавшись по Интернетам, наткнулся на smsd демона для отправки/приемки смс-ок из пакета smstools. После прочтения документации по этому зверю, в голову пришла идея о том, что можно принимать сообщения с нужных телефонов, с командами для сервера. Так и родилась идея «Управлять сервером посредством СМС», которая может применяться для чего угодно: перезагрузить сервер, выключить его, перезапустить демона, сбросить кеш, открыть порт на фаерволе для удаленного подключения по ssh.

Настраиваем модем

Для начала необходимо подружить наш модем и Linux (кстати, я использую Centos 5.5). Втыкаем модем в один из свободных usb-портов. Первое, с чем приходится столкнуться, это то что модем определяется как CD-ROM, а с CD-ROM-а как известно смс-ки не отправишь и тем более не получишь. Для того чтоб это дело нам поправить, необходимо всего лишь скормить модему эту команду: AT^U2DIAG=0 (0 – только modem, 1 – modem + cd-rom, 255 – modem + cd-rom + cardreader, 256 – modem + cardreader). Если у вас есть под рукой компьютер, с установленной Windows, то открывайте HyperTerminal, подключайтесь к модему, вводите команду: AT^U2DIAG=0 и пропускайте следующий шаг.

Итак, заставляем модем быть модемом, а не каким-то CD-ROM-ом под Linux. Для начала необходимо поставить пакеты usb_modeswitch и minicom yum --enablerepo=rpmforge install usb_modeswitch minicom, затем создаем/правим /etc/usb-modeswitch.conf

DefaultVendor = 0x12d1
DefaultProduct = 0x1446
MessageEndPoint = "0x01"
MessageContent = "55534243000000000000000000000011060000000000000000000000000000"

И перетыкаем модем в другой порт, необходимо подождать 5-10 секунд (необходимо чтоб модем определился как CD-ROM) и от root-а запускаем usb_modeswitch и видим примерно следующие:

Looking for target devices ...
No devices in target mode or class found
Looking for default devices ...
Found default devices (1)
Accessing device 004 on bus 007 ...
Using endpoints 0x01 (out) and 0x81 (in)
Inquiring device details; driver will be detached ...
Looking for active driver ...
OK, driver found ("usb-storage")
OK, driver "usb-storage" detached

SCSI inquiry data (for identification)
-------------------------
Vendor String: HUAWEI
Model String: Mass Storage
Revision String: 2.31
-------------------------

USB description data (for identification)
-------------------------
Manufacturer: HUAWEI Technology
Product: HUAWEI Mobile
Serial No.: not provided
-------------------------
Setting up communication with interface 0 ...
Trying to send the message to endpoint 0x01 ...
OK, message successfully sent
Device is gone, skipping any further commands
-> Run lsusb to note any changes. Bye.

Должны появится новые устройства ttyUSB

ls /dev | grep ttyUSB:
ttyUSB0
ttyUSB1
ttyUSB2

Запускаем minicom –s настраиваем последовательный порт на работу с /dev/ttyUSB0, Выходим из настроек, запускается терминал, затем необходимо отдать команду AT^U2DIAG=0 и получить в ответ ok

Процедура превращения модема в модем закончена, преступаем к установке/настройке smstools.

Smstools

Как ни странно, в огромных репозитариях rpmforge не нашлось места такому наиполезнейшему пакету как smstools. Но не беда, на просторах Интернета и на сайте производителя её достаточно. Я нашел пакет: smstools-3.0.10-4.el5.i386.rpm и «воспользовался» им rpm –i smstools-3.0.10-4.el5.i386.rpm. Настраиваем smstools, файл /etc/sms.conf:

devices = huaweiE1550
logfile = /var/log/smsd.log
loglevel = 2

[huaweiE1550]
device = /dev/ttyUSB0
baudrate = 115200
rtscts = no
init = at+cpms="sm","sm",""
incoming = yes
incoming = high

настройки примерно понятные, запускаем демона, service smsd start и проверяем сие чудо: smssend 9128141111 ‘test message’ (не понимает кириллицу, необходимо конвертировать в UCS-2BE, в рамках этой статьи рассматривать не буду) и ждать смс-ки на мобильник. Если заветное сообщение не пришло, ставим в конфиге loglevel = 7 и идем за бубном. У меня поднялось все с первого раза.

smsctrl daemon

Итак разговаривать мы умеем, необходимо научиться слушать! Если отправить смс-ку на номер симки в модеме, через некоторое время smsd создаст файл в /var/spool/sms/incoming/huaweiE1550.* примерно следующего содержания:

From: 79128141111
From_TOA: 91 international, ISDN/telephone
From_SMSC: 79126313431
Sent: 11-03-02 08:05:46
Received: 11-03-02 08:08:09
Subject: huaweiE1550
IMSI: 2500XXXXXXXXXXX
Report: no
Alphabet: ISO
UDH: false

Test message

Соответственно эти файлики мы и будем проверять на наличие команд для управления сервером. Для этого два способа 1-й небольшой демон на bash-е, 2-й встроеный обработчик событий в smsd.

1-й способ

#!/bin/sh
# SMSCtrl
# chkconfig: - 55 45
# description: Sms control, Egor N. Zuskin, 2011, http://www.it2k.ru/projects/smsctrl

. /etc/rc.d/init.d/functions

DAEMON=smsctrl
REFRESH_TIME=15

COMMAND_CHAR="#"
INCOMING_DIR=/var/spool/sms/incoming
ALLOW_PHONES="79128141111 79128141112"
SEND_BACK_REPORT=YES

to_log(){
       text=$1
       export LANG=en_EN
       log_date=`date "+%b %d %H:%M:%S "`
       log_host=`hostname -s`
       echo "$log_date $log_host $DAEMON: $text" >> /var/log/$DAEMON.log
}

start() {
       echo -n "Starting $DAEMON: "
       $0 --daemon && success || failure
       RETVAL=$?
       echo
       [ $RETVAL = 0 ] && touch /var/lock/subsys/$DAEMON
       to_log "Starting ..."
       return $RETVAL
}

stop() {
       # Stop daemon.
       echo -n "Shutting down $DAEMON: "
       killproc $0
       RETVAL=$?
       to_log "Stopping ..."
       echo
       [ $RETVAL = 0 ] && rm -f /var/lock/subsys/$DAEMON
}

run() {
   for File in $(ls $INCOMING_DIR); do
       Allow=0
       for Phone in $ALLOW_PHONES; do
           cat $INCOMING_DIR/$File | grep "From: $Phone" > /dev/null 2>&1
           [ $? -eq 0 ] && Allow=1
       done;
       [ $Allow -eq 0 ] && continue

       cat $INCOMING_DIR/$File | grep "$COMMAND_CHAR"
       [ $? -ne 0 ] && continue

       FromPhone=`cat $INCOMING_DIR/$File | grep "From:" | cut -d " " -f2`

       command=`cat $INCOMING_DIR/$File | grep "$COMMAND_CHAR" | cut -d "$COMMAND_CHAR" -f2`
       to_log "Incoming command: $command from $FromPhone"
       out=`$command`

       if [ "$SEND_BACK_REPORT" = "YES" ]; then
           smssend $FromPhone "$out"
           to_log "Send sms to $FromPhone: $out"
       fi
       rm -f $INCOMING_DIR/$File
       to_log "Deleting file $INCOMING_DIR/$File"
   done
}

daemon() {
       exec >/dev/null
       exec 2>/dev/null
       (
       trap "" TERM
       while [ true ]; do
           run
           sleep $REFRESH_TIME;
       done;
       )&
}


case "$1" in
   --daemon)
         daemon
         ;;
   run)
         run
         ;;
   start)
         start
         ;;
   stop)
         stop
         ;;
   restart)
         $0 stop
         $0 start
         exit $?
         ;;
   status)
         status $DAEMON
         echo
         ;;
   *)
         echo "Usage: $DAEMON {start|stop|restart|status|run}"
         exit 1
 esac

 exit 0



COMMAND_CHAR="#" – Признак команды
INCOMING_DIR=/var/spool/sms/incoming – Директория для входящих смс-ок
ALLOW_PHONES="79128141111 79128141112" – Номера с которых разрешены команды
SEND_BACK_REPORT=YES – Отправлять вывод смс-ой обратно

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

Сохраняем демона в /etc/init.d/smsctrl, chkconfig --add smsctrl, service smsctrl start

2-й способ

Дописываем в /etc/smsd.conf:
eventhandler = /root/bin/sms_event.sh
создаем /root/bin/sms_events.sh
#!/bin/bash

COMMAND_CHAR="#"
ALLOW_PHONES="79128141111 79128141112"
SEND_BACK_REPORT=YES

[ "$1" = "RECEIVED" ] || exit 0

to_log(){
   text=$1
   export LANG=en_EN
   log_date=`date "+%b %d %H:%M:%S "`
   log_host=`hostname -s`
   echo "$log_date $log_host $text" >> /var/log/smsctrl.log
}

File=$2

Allow=0
for Phone in $ALLOW_PHONES; do
   cat $File | grep "From: $Phone" > /dev/null 2>&1
   [ $? -eq 0 ] && Allow=1
done;
[ $Allow -eq 0 ] && exit 0

cat $INCOMING_DIR/$File | grep "$COMMAND_CHAR"
[ $? -ne 0 ] && exit 0

FromPhone=`cat $File | grep "From:" | cut -d " " -f2`

command=`cat $File | grep "$COMMAND_CHAR" | cut -d "$COMMAND_CHAR" -f2`
to_log "Incoming command: $command from $FromPhone"
out=`$command`

if [ "$SEND_BACK_REPORT" = "YES" ]; then
   smssend $FromPhone "$out"
   to_log "Send sms to $FromPhone: $out"
fi
rm -f $File
to_log "Deleting file $File"


Проверка

Создаем файлик /root/bin/test.sh следующего содержания:

#!/bin/bash

ls –la /etc | grep $1


Затем берем в руки телефон и посылаем смс с текстом #/root/bin/test.sh sms на заветный номер и смотрим в лог tail –f /var/log/smsctrl.log, если все хорошо — в ответ прилетит смс-ка вида: smsd.conf

Заключение

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

  • Дополнительно (с)

Чтобы в лог сыпался баланс и уровень сигнала, в конфиге smstools надо написать (для МТС):

regular_run_cmd = AT+CUSD=1,"#100#";
regular_run_cmd = AT+CSQ
regular_run_interval = 86400
regular_run_logfile = /var/log/smsd_regular_run.log