Pull to refresh

Управляем сервером посредством СМС

Reading time 6 min
Views 40K
Началось все с того, что я откопал в полке с железками 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 порт для входящих подключений. Я думаю, это не единственное применение, достаточно включить немного воображения.

Полезные ссылки для настройки huaweiE1550 и smsd
1: SMSTools 3 — шлюз для отправки SMS
2: Нужна статья про смс-центр с модемом Huawei E1550?
3: Как «приручить» МТС-модем Huawei E1550

Спасибо за внимание, с нетерпением жду Ваших комментариев.

UPD По замечанию моего хорошего друга, дополнил реализацию обработки водящих смс сообщений средствами smsd.
Tags:
Hubs:
+52
Comments 33
Comments Comments 33

Articles