Управляем сервером посредством СМС
Началось все с того, что я откопал в полке с железками 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 порт для входящих подключений. Я думаю, это не единственное применение, достаточно включить немного воображения.