Большинство системных администраторов так или иначе мониторящих оборудование компании, знакомы с пакетом smstools, зачастую используемого лишь для отправки SMS сообщений о состоянии инфраструктуры. Оборотной стороной медали является необходимость удалённого управления инфраструктурой предприятия при недоступности VPN подключения или нахождении вне зоны доступа в интернет. Ранее описанные способы управления безусловно имеют право на жизнь, но рассчитаны на управление одним сервером и не предоставляют возможности безопасного выполнения команд. Ниже по тексту я предлагаю вашему вниманию рабочий механизм безопасного подтверждения выполнения sms команд внутри локальной сети.
Согласно правилу «Правильно настроенная система в обслуживании не нуждается», правильные сисадмины не перенастраивают стабильно работающее оборудование ограничиваясь только установкой обновлений.
Но в работе серверов бывают моменты когда вешается какой-нить процесс обеспечивающий работу сетевых шар и RPC, скажем LanManServer(в простонародии server), причём вешается не сам процесс, а какая-то его ветка. В итоге мы имеем сервер, который нельзя перезапустить через удалённое управление или корректно погасить.
Почти все современные сервера имеют на борту IPMI и возможность управления питанием. Отсюда и будем строить наш функционал. Если ваши сервера дополнительно мониторятся через nagios или аналогичные пакеты, то в большинстве случаев у вас используется nrpe -Nagios Remote Plugin Executor, а это значит у вас есть независимый от системных служб механизм по управлению сервером. Достаточно в конфиге NSClient++ прописать часто используемые команды типа reboot, shutdown, stop_server, start_server и удалённо делать с сервером необходимые действия.
В старом конфиге клиента вызов внешних скриптов расположен в разделе "[External Scripts]", в новом "[/settings/external scripts/scripts]". Текстовка в обоих случаях одинаковая.
текстовка скриптов
s_reboot.cmd
s_shutdown.cmd
start_server.cmd
stop_server.cmd
Это базовый список команд которые можно использовать удалённо. Можно вызывать остановку или поднятие сервиса передавая в аналогичный скрипт аргументы. Например передёрнуть IIS.
Вызов команды обычно прост и выглядит как
С nrpe вроде бы разобрались, теперь нужно обслужить IPMI.
Для диалога с IPMI системой сервера можно воспользоваться пакетом ipmitool, который представляет собой интерфейс доступа к управлению ipmi из командной строки.
Основной набор команд который нам необходим, относится к разделу «power», а именно
Можно еще почитать температурные сенсоры, скорость вращения вентиляторов, но это нам не особо нужно.
С основным набором команд разобрались.
В связи с тем, что последнее время появилось некоторое количество сервисов позволяющих подделать номер отправителя смс — обычная проверка номера отправителя стала недостаточно надёжной.
Пересылка прямого пароля в сообщении тоже вещь ненадёжная, т.к. перехват сообщения позволит получить полный доступ к вашей системе управления. Что же делать?
Выход на удивление прост. OTP (One Time Passwords). С точки зрения простоты использования и отсутствии зависимости генерируемых паролей от времени оптимальным решением будет использование OPIE.
Если у вас есть несколько системных администраторов или инженеров обслуживающих сервера, то выдавать каждому пароль и начальный вектор инициализации будет не совсем корректным. Для обслуживания серверов уместно выдать каждому список паролей из различных блоков.
А в случае использования блоков паролей можно точно утверждать чьей рукой был выключен или перезагружен сервер. С точки зрения использования системы «в одно лицо», для Android телефонов, целесообразнее будет установить пакет OTPDroid для онлайн генер��ции паролей. Прекрасен он тем, что в буфер обмена сразу копируется значение сгенерированного пароля и трёх нажатий хватает для копипаста пароля в sms.
Вы спросите «А как же двойное использование одного и того же пароля ?»
Ответ прост: «Нужно просто контролировать и вести список использованных последовательностей прилетевших в смс»
Первым делом в конфигурационном файле smsd необходимо добавить вызов обработчика событий.
Программа обработки представляет собой обычный shell скрипт.
Немного комментариев о файле обработчика smsevent
В начале файла задаются основные переменные о нахождении файла конфигурации, программ проверки и управления, а также OPIE параметры для проверки паролей.
В конфигурационном файле вы задаёте телефоны и список доступных им команд, список адресов серверов, логины и пароли IPMI для различных хостов, темплейты выполняемых команд.
В блоке темплейтов команд второй аргумент имеет значение 0 или 1 и либо пропускает проверку OPIE для команды, либо проверяет OPIE.
Самый простой смс запрос пришлёт обратно поочередно 2 sms с результатами проверки доступности хостов:
Запрос вида отправит хост 192.168.55.2 в перезагрузку путём эмуляции кнопки RESET, а хост 192.168.54.5 выключит штатным образом:
Все выполняемые посредством sms действия пишутся в расширенный лог smsd.
В общем-то, всё. Редактируете под себя конфиг, настраиваете сервера на приём команд и можно ехать с телефоном на отдых. Если вдруг что повиснет, выстрел прямой наводкой посредством sms сделает своё дело.
PS: Скрипт немного сыроват, но как говорится «совершенству нет предела!».
Начнём с того «Зачем это нужно?»
Согласно правилу «Правильно настроенная система в обслуживании не нуждается», правильные сисадмины не перенастраивают стабильно работающее оборудование ограничиваясь только установкой обновлений.
Но в работе серверов бывают моменты когда вешается какой-нить процесс обеспечивающий работу сетевых шар и RPC, скажем LanManServer(в простонародии server), причём вешается не сам процесс, а какая-то его ветка. В итоге мы имеем сервер, который нельзя перезапустить через удалённое управление или корректно погасить.
Что можно с этой проблемой сделать ?
Почти все современные сервера имеют на борту IPMI и возможность управления питанием. Отсюда и будем строить наш функционал. Если ваши сервера дополнительно мониторятся через nagios или аналогичные пакеты, то в большинстве случаев у вас используется nrpe -Nagios Remote Plugin Executor, а это значит у вас есть независимый от системных служб механизм по управлению сервером. Достаточно в конфиге NSClient++ прописать часто используемые команды типа reboot, shutdown, stop_server, start_server и удалённо делать с сервером необходимые действия.
В старом конфиге клиента вызов внешних скриптов расположен в разделе "[External Scripts]", в новом "[/settings/external scripts/scripts]". Текстовка в обоих случаях одинаковая.
reboot=scripts\s_reboot.cmd shutdown=scripts\s_shutdown.cmd stop_server=scripts\stop_server.cmd start_server=scripts\start_server.cmd
текстовка скриптов
s_reboot.cmd
@echo "Reboot initiated" @start cmd /c shutdown -r -f -t 00 @exit 0
s_shutdown.cmd
@echo "Shutdown initiated" @start cmd /c shutdown -s -f -t 00 @exit 0
start_server.cmd
@start cmd /c net start server @if %ERRORLEVEL% EQU 0 goto ok @echo Some problem with service start @exit 1 :ok @echo Service started @exit 0
stop_server.cmd
@start cmd /c net stop server /y @if %ERRORLEVEL% EQU 0 goto ok @echo Some problem with service stop @exit 1 :ok @echo Service stopped @exit 0
Это базовый список команд которые можно использовать удалённо. Можно вызывать остановку или поднятие сервиса передавая в аналогичный скрипт аргументы. Например передёрнуть IIS.
Вызов команды обычно прост и выглядит как
/usr/local/libexec/nagios/check_nrpe2 -H <HOST> -c <command> -a <arguments>
С nrpe вроде бы разобрались, теперь нужно обслужить IPMI.
Для диалога с IPMI системой сервера можно воспользоваться пакетом ipmitool, который представляет собой интерфейс доступа к управлению ipmi из командной строки.
Основной набор команд который нам необходим, относится к разделу «power», а именно
ipmitool -H <host> -U <username> -P <password> power status - узнать состояние питания на сервере ipmitool -H <host> -U <username> -P <password> power up - включить сервер ipmitool -H <host> -U <username> -P <password> power off - выключить питание ipmitool -H <host> -U <username> -P <password> power reset - эмулировать нажатие клавиши reset
Можно еще почитать температурные сенсоры, скорость вращения вентиляторов, но это нам не особо нужно.
С основным набором команд разобрались.
Как обеспечить безопасность управления ?
В связи с тем, что последнее время появилось некоторое количество сервисов позволяющих подделать номер отправителя смс — обычная проверка номера отправителя стала недостаточно надёжной.
Пересылка прямого пароля в сообщении тоже вещь ненадёжная, т.к. перехват сообщения позволит получить полный доступ к вашей системе управления. Что же делать?
Выход на удивление прост. OTP (One Time Passwords). С точки зрения простоты использования и отсутствии зависимости генерируемых паролей от времени оптимальным решением будет использование OPIE.
Почему OPIE ?
Если у вас есть несколько системных администраторов или инженеров обслуживающих сервера, то выдавать каждому пароль и начальный вектор инициализации будет не совсем корректным. Для обслуживания серверов уместно выдать каждому список паролей из различных блоков.
# opiekey -5 -n 5 5 habrahabr Using the MD5 algorithm to compute response. Reminder: Dont use opiekey from telnet or dial-in sessions. Enter secret pass phrase: 1: JIG RIFT BODE OLGA RICK JAG 2: RIM HIVE BANG LIMA HELL OMEN 3: BULB MOD CARR BANK MOS SET 4: GARB BAWL MANY HAL GLOW FEED 5: FAWN EDGY MEET SHUT LIKE TIME # opiekey -5 -n 5 25 habrahabr Using the MD5 algorithm to compute response. Reminder: Dont use opiekey from telnet or dial-in sessions. Enter secret pass phrase: 21: MAIN HOFF JAM OATH SMOG LIED 22: FUND DENY BYTE BOLT NIBS EASY 23: SLY COAT FLEA CAGE MAE COAL 24: SURE LEFT HULK CLAN SHUN DAR 25: GRAB LIE CLAN FLAK MEL ROSE
А в случае использования блоков паролей можно точно утверждать чьей рукой был выключен или перезагружен сервер. С точки зрения использования системы «в одно лицо», для Android телефонов, целесообразнее будет установить пакет OTPDroid для онлайн генер��ции паролей. Прекрасен он тем, что в буфер обмена сразу копируется значение сгенерированного пароля и трёх нажатий хватает для копипаста пароля в sms.
Вы спросите «А как же двойное использование одного и того же пароля ?»
Ответ прост: «Нужно просто контролировать и вести список использованных последовательностей прилетевших в смс»
Как всё это заставить работать вместе ?
Первым делом в конфигурационном файле smsd необходимо добавить вызов обработчика событий.
eventhandler = /usr/local/etc/smshandlers/smsevent
Программа обработки представляет собой обычный shell скрипт.
Далее пойдёт много shell кода smsevent
#!/bin/sh NRPETOOL="/usr/local/libexec/nagios/check_nrpe2" IPMITOOL="/usr/local/bin/ipmitool" FPINGTOOL="/usr/local/sbin/fping" PARAMFILE="/usr/local/etc/smshandlers/param.list" OPIEKEYBIN="/usr/bin/opiekey" OPIESEED="HABROPIEProc" OPIEPASS="StrongOPIEPassword" OPIEUSEDSEED="/var/tmp/used.opie" SMSDOUTSPOOL="/var/spool/sms/outgoing" if [ ! -f ${OPIEUSEDSEED} ]; then echo "#USED SEEDS FILE. Do not EDIT" > ${OPIEUSEDSEED} fi if [ ! -w ${OPIEUSEDSEED} ]; then echo "file ${OPIEUSEDSEED} is not writable" exit fi if [ ! -r ${PARAMFILE} ]; then echo "file ${PARAMFILE} is not readable" exit fi IFS=" " FOUNDNUM="" NUMBER="" # search any properties search (){ # $1 - section [name] from param.list # $2 - search string in section SECTION=$1 SEARCHSTR=$2 shift shift OLDIFS=${IFS} IFS=" " [ "X"${SEARCHSTR} == "X" ] && exit for i in ${PARAMS}; do # search section definition if [ `echo ${i} | grep -e "^\["` ]; then CURSECTION=${i} continue fi if [ "${CURSECTION}" == "["${SECTION}"]" ]; then if [ `echo ${i} | grep -e "^\b${SEARCHSTR}\b:"` ]; then echo ${i} break fi fi done IFS=${OLDIFS} } cut_message_body (){ # split sms file to parts # BSD buggy "grep -m 1 -A 10 -e '^$'" replacement # FILE=$1 NULLSTR=0 for i in `cat -e $1`; do if [ "X"${i} == "X\$" ]; then NULLSTR=1 continue fi if [ ${NULLSTR} -eq 1 ]; then echo ${i} fi done } process_command () { CMD=$1 shift CMDPARAM=$* oIFS=$IFS IFS=" " for host in ${CMDPARAM}; do HOSTACCOUNT=$( search hosts "${host}" ) if [ "X"${HOSTACCOUNT} != "X" ]; then ACCOUNT=`echo ${HOSTACCOUNT} | cut -d ":" -f 2-` LOGINPW=$( search logins "${ACCOUNT}" ) if [ "X"${ACCOUNT} != "X" ]; then if [ "${ACCOUNT}" != "null" ]; then USER=`echo ${LOGINPW} | cut -d ":" -f 2` PASSWORD=`echo ${LOGINPW} | cut -d ":" -f 3` else USER="USER" PASSWORD="PASSWORD" fi else echo "ACCOUNT ${ACCOUNT} NOT FOUND!" break fi else echo "HOST ${host} NOT FOUND!" continue fi opierequired=$( search commands_template "${CMD}" | cut -d ":" -f 2 ) commandtemplate=$( search commands_template "${CMD}" | \ cut -d ":" -f 3- | sed \ -e "s@\%HOST\%@${host}@g" \ -e "s@\%FPING\%@${FPINGTOOL}@g" \ -e "s@%IPMITOOL%@${IPMITOOL}@g" \ -e "s@%CHECK_NRPE%@${NRPETOOL}@g" \ -e "s@%USER%@${USER}@g" \ -e "s@%PASSWORD%@${PASSWORD}@g" ) if [ "${opierequired}" -eq "1" ]; then if [ "${OPIERES}" == "True" ]; then echo "OPIE Success" res=$( eval ${commandtemplate} ) sendsms ${NUMBER} ${host} ${res} else echo "OPIE Failed" sendsms ${NUMBER} ${host} "OPIE Challenge failed" fi else res=$( eval ${commandtemplate} ) sendsms ${NUMBER} ${host} ${res} fi done IFS=$oIFS } sendsms () { NM=$1 shift TMPFILE=`mktemp ${SMSDOUTSPOOL}/smscmd.XXXXXX` || exit 1 echo "To: ${NM}" >> ${TMPFILE} echo >> ${TMPFILE} echo "$*" >> ${TMPFILE} } opiecheck () { OPIESEQ=`echo $* | cut -d " " -f 1 | sed -e 's/[^0-9]//g'` OPIESTR=`echo $* | cut -d " " -f 2-` if [ "X"${OPIESEQ} == "X" ]; then echo "OPIE SEQUENCE FOR NUMBER ${NUMBER} IS NOT SET!" OPIERES="False" break fi if [ `grep "^${OPIESEQ}$" ${OPIEUSEDSEED}` ]; then echo "USED OPIE SEQUENCE ${OPIESEQ} DETECTED" OPIERES="False" sendsms ${NUMBER} "OPIE SEQUENCE ${OPIESEQ} ALREADY USED" exit 1 else echo ${OPIESEQ} >> ${OPIEUSEDSEED} fi OPIEGEN=`echo ${OPIEPASS} | ${OPIEKEYBIN} -5 -a ${OPIESEQ} ${OPIESEED} 2>/dev/null` if [ "X"${OPIESTR} != "X"${OPIEGEN} ]; then OPIERES="False" else OPIERES="True" fi } parse_commands () { for command in $*; do command=`echo ${command} | sed -e 's/\$$//g' -e 's/^\#//g'` CURCOMMAND=`echo ${command} | cut -d " " -f 1` CMDPARAM=`echo ${command} | cut -d " " -f 2-` case "${CURCOMMAND}" in "OPIE") opiecheck ${CMDPARAM} continue ;; *) if [ `echo ${FOUNDNUM} | cut -d : -f 2 | grep "\b${CURCOMMAND}\b"` ]; then TMPMSG="ALLOWED COMMAND FOR NUMBER "${NUMBER}" - COMMAND: "${CURCOMMAND}" ARGS "${CMDPARAM} echo ${TMPMSG} process_command ${CURCOMMAND} ${CMDPARAM} else TMPMSG="DISALLOWED COMMAND FOR NUMBER "${NUMBER}" - COMMAND: "${CURCOMMAND}" ARGS "${CMDPARAM} echo ${TMPMSG} fi ;; esac done } PARAMS=`cat ${PARAMFILE} | grep -E -v '^#'` if [ $1 == "RECEIVED" ]; then FILENAME=$2 NUMBER=`grep 'From:' ${FILENAME} | sed -e 's/^From\:\ //g' -e 's/[^0-9]//g;'` FOUNDNUM=$( search phones ${NUMBER} ) if [ "X"${FOUNDNUM} != "X" ]; then commands=$( cut_message_body ${FILENAME} ) parse_commands ${commands} fi elif [ $1 == "SENT" ]; then echo $@ else echo "UNKNOWN STATUS $@" fi
Немного комментариев о файле обработчика smsevent
В начале файла задаются основные переменные о нахождении файла конфигурации, программ проверки и управления, а также OPIE параметры для проверки паролей.
Немного конфигурационного файла param.list
# --------------------------------------- # # ALLOWED PHONES # PHONENUMBER:COMMAND,COMMAND,COMMAND # --------------------------------------- [phones] 79030000000:RESET,PWROFF,PWRON,REBOOT,SHUTDOWN,STOPSERVER,STARTSERVER,ALIVE,PWRSTAT 79160000000:ALIVE,PWRSTAT 79020000000:PWRON,STARTSERVER,ALIVE # --------------------------------------- # # HOST LIST # REAL_IP:IPMI_USER # --------------------------------------- [hosts] 192.168.55.2:ADMSM 192.168.54.2:null 192.168.55.5:ADMDEF 192.168.54.5:null # --------------------------------------- # # IPMI LOGINS # IPMI_ACCOUNT:IPMI_NAME:IPMI_PASSWORD # --------------------------------------- [logins] ADMSM:ADMIN:PW1234 ADMDEF:ADMIN:ADMIN ADMIBM:USERID:USERID # --------------------------------------- # # COMMANDS TEMPLATE # COMMAND:OPIE_CHECK:COMMAND_TEXT # --------------------------------------- [commands_template] RESET:1:%IPMITOOL% -H %HOST% -U %USER% -P %PASSWORD% power reset PWROFF:1:%IPMITOOL% -H %HOST% -U %USER% -P %PASSWORD% power off PWRON:0:%IPMITOOL% -H %HOST% -U %USER% -P %PASSWORD% power on PWRSTAT:0:%IPMITOOL% -H %HOST% -U %USER% -P %PASSWORD% power status REBOOT:1:%CHECK_NRPE% -H %HOST% -p 5666 -c reboot SHUTDOWN:1:%CHECK_NRPE% -H %HOST% -p 5666 -c shutdown STOPSERVER:1:%CHECK_NRPE% -H %HOST% -p 5666 -c stop_server STARTSERVER:0:%CHECK_NRPE% -H %HOST% -p 5666 -c start_server ALIVE:0:%FPING% %HOST%
В конфигурационном файле вы задаёте телефоны и список доступных им команд, список адресов серверов, логины и пароли IPMI для различных хостов, темплейты выполняемых команд.
В блоке темплейтов команд второй аргумент имеет значение 0 или 1 и либо пропускает проверку OPIE для команды, либо проверяет OPIE.
Самый простой смс запрос пришлёт обратно поочередно 2 sms с результатами проверки доступности хостов:
ALIVE 192.168.54.2 192.168.54.5
Запрос вида отправит хост 192.168.55.2 в перезагрузку путём эмуляции кнопки RESET, а хост 192.168.54.5 выключит штатным образом:
OPIE 1 COT NORM TILL JILL MOST MESH RESET 192.168.55.2 SHUTDOWN 192.168.54.5
Все выполняемые посредством sms действия пишутся в расширенный лог smsd.
В общем-то, всё. Редактируете под себя конфиг, настраиваете сервера на приём команд и можно ехать с телефоном на отдых. Если вдруг что повиснет, выстрел прямой наводкой посредством sms сделает своё дело.
PS: Скрипт немного сыроват, но как говорится «совершенству нет предела!».
