Автопровижининг Cisco SPA504g и Asterisk. Часть 2. Настройка DHCP-сервера и Apache

В первой части мы установили MySQL и собрали Астериск из исходников с поддержкой res_config_mysql (Asterisk Realtime Architecture)

Настройка DHCP-сервера

У меня в двух рабочих средах развёрнуты разные DHCP-серверы, покажу настройки для трёх самых (имхо) популярных: Windows Server DHCP, Mikrotik, DNSMasq

Windows Server 2012R2 DHCP Server

image

В DHCP-менеджере добавляем новую опцию к нашему DHCP-диапазону, с номером 66 (Boot Server Host Name) и следующим содержимым
http://<server ip>/cisco.php?mac=$MA&sn=$SN

Mikrotik RouterOS v6.x

/ip dhcp-server option add code=66 name=tftp value="'http://<server ip>/cisco.php\?mac=\$MA&sn=\$SN'" /ip dhcp-server network set dhcp-option=tftp 0

DNSMasq

в dnsmasq.conf
dhcp-option=66,"http://<server ip>/cisco.php\?mac=$MA&sn=$SN"

Установка и настройка Apache + PHP

Можно было обойтись и thttpd, и lighttpd, и даже nginx’ом, но я больше люблю старого доброго индейца.

[root@asterisk ~]# yum install httpd php php-mysql -y [root@asterisk ~]# chkconfig httpd on [root@asterisk ~]# vi /etc/php.ini 

и в разделе Date устанавливаем date.timezone = Europe/Moscow (или свою временную зону, если не в Московском часовом поясе), иначе будет куча предупреждений.

Esc -> :wq -> Enter [root@asterisk ~]# echo "<?php phpinfo(); ?>">/var/www/html/index.php 

И открываем браузером адрес http://<ip сервера>/ для проверки работы Апача и PHP.

Создаём скрипт автовыдачи XML для SPA504G

Скачиваем и распаковываем в /var/www/html прошивки 7.5.2b и 7.5.5 для SPA504G, а также языковые XML’ки для русского языка:

[root@asterisk ~]# cd /var/www/html/ [root@asterisk html]# wget http://zztopper.ru/cisco.tar.gz [root@asterisk html]# tar fzx cisco.tar.gz [root@asterisk html]# rm cisco.tar.gz 

Создаём cisco.php

[root@asterisk html]#  nano cisco.php 

<?php  //---------------------------------Тут объявляем переменные  //-------Данные MySQL $mysrv = 'localhost'; $mydb = 'asterisk'; $myuser = 'asterisk'; $mypass = 'mypass'; $table = 'tbl_sip_conf';  $server = 'SERVERIP'; //IP сервера с апачем и астериском $dns = 'DNSIP';  // IP DNS-сервера $enable_vlan = 'No'; // Использовать VLAN'ы $voice_vlan = 1; // VLAN для телефонии  $pc_vlan = 1; // Access VLAN для сквозного PC-порта $adminpass = '7654321'; //Пароль для Web-морды телефона $textlogo = 'LOGO'; //Текстовое лого  $tz = 'GMT+04:00'; //Часовой пояс $dialplan = '(1xxS0|911S0|1xxxS0|2xxxxxxS0|8xxxxxxxxxx|7xxxxxxxxxx)'; //Строка диалплана $label = 'Yellow Pages'; //Подпись для кнопки Line 4 для адресной книги $use4line = 1; // Использовать ли кнопку Line 4 для адресной книги //---------------------------------Дальше сам скрипт, не трогаем без нужды  function randomPassword() {     $alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";     $pass = array(); //remember to declare $pass as an array     $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache     for ($i = 0; $i < 10; $i++) {         $n = rand(0, $alphaLength);         $pass[] = $alphabet[$n];     }     return implode($pass); //turn the array into a string }   $mac = isset($_GET['mac'])?$_GET['mac']:"000000000000";  $sn = isset($_GET['sn'])?$_GET['sn']:"0000000";  $link = new mysqli($mysrv,$myuser,$mypass,$mydb); if ($link->connect_error) {     die('Connect Error (' . $link->connect_errno . ') '             . $link->connect_error); }  $query = 'set names utf8;';  $link->query($query);  $query = 'SELECT * FROM `'.$table.'` WHERE `macaddress`="'.$mac.'"';  $result = $link->query($query);  if (!$result).     die("Ошибка: ".$link->error);  if ($result->num_rows == 1).  {     while ($myrow = $result->fetch_array(MYSQLI_ASSOC))     {       $phone=$myrow["name"];       $pass=$myrow["secret"];       $name=$myrow["defaultuser"];     }.     $result->close();.  }else  {  $query="SELECT MAX(name) FROM `".$table."`";  $result = $link->query($query);  while ($myrow = $result->fetch_array(MYSQLI_NUM))  {     $phone=$myrow[0];  }     $phone++;  $result->close();                                                                                                $pass=randomPassword();     $name="Unidentified Phone #".$phone;  $query="INSERT INTO `".$table."` (`defaultuser`,`macaddress`,`secret`,`name`, `serial`) VALUES ('".$name."', '".$mac."', '".$pass."', '".$phone."', '".$sn."');";  $result=$link->query($query);  }  $host="SPA".strtoupper($mac); ?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <flat-profile xmlns="http://www.sipura.net/xsd/SPA50x-30x-SIP" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sipura.net/xsd/SPA5 <Enable_VLAN ua="rw"><?php echo $use_vlan ?></Enable_VLAN> <VLAN_ID ua="rw"><?php echo $voice_vlan?></VLAN_ID> <Enable_PC_Port_VLAN_Tagging ua="na">No</Enable_PC_Port_VLAN_Tagging> <Enable_CDP ua="na">Yes</Enable_CDP> <Enable_LLDP-MED ua="na">Yes</Enable_LLDP-MED> <PC_Port_VLAN_ID ua="na"><?php echo $pc_vlan ?></PC_Port_VLAN_ID> <Resync_On_Reset>Yes</Resync_On_Reset> <Resync_Periodic>60</Resync_Periodic> <Admin_Passwd ua="na"><?php echo $adminpass ?></Admin_Passwd> <SPCP_Auto-detect ua="na">No</SPCP_Auto-detect> <Domain ua="rw">aton.local</Domain> <Primary_DNS ua="rw">$dns</Primary_DNS> <Debug_Level ua="na">0</Debug_Level> <Primary_NTP_Server ua="na">ru.pool.ntp.org</Primary_NTP_Server> <Profile_Rule ua="na">http://<?php echo $server?>/cisco.php?mac=$MA&sn=$SN</Profile_Rule> <Key_System_Auto_Discovery ua="na">No</Key_System_Auto_Discovery> <G722_Enable_1_ ua="na">Yes</G722_Enable_1_> <L16_Enable_1_ ua="na">No</L16_Enable_1_> <G726-16_Enable_1_ ua="na">No</G726-16_Enable_1_> <G726-24_Enable_1_ ua="na">No</G726-24_Enable_1_> <G726-32_Enable_1_ ua="na">No</G726-32_Enable_1_> <G726-40_Enable_1_ ua="na">No</G726-40_Enable_1_> <Enable_IP_Dialing_1_ ua="na">No</Enable_IP_Dialing_1_> <Use_Remote_Pref_Codec_1_ ua="na">Yes</Use_Remote_Pref_Codec_1_> <Text_Logo ua="na"><?php echo $textlogo ?></Text_Logo> <Time_Zone ua="na"><?php echo $tz ?></Time_Zone> <Upgrade_Rule ua="na">( $SWVER lt 7.5.2b )? http://<?php echo $server ?>/spa50x-30x-7-5-2b.bin | http://<?php echo $server ?>/spa50x-30x-7-5-5.bin </Upgrade_Rule> <HostName ua="rw"><?php echo $host ?></HostName> <Phone-UI-readonly ua="na">Yes</Phone-UI-readonly> <Phone-UI-user-mode ua="na">Yes</Phone-UI-user-mode> <Proxy_1_ ua="na"><?php echo $server ?></Proxy_1_> <Display_Name_1_ ua="na"><?php echo $name ?></Display_Name_1_> <User_ID_1_ ua="na"><?php echo $phone ?></User_ID_1_> <Password_1_ ua="na"><?php echo $pass ?></Password_1_> <Dial_Plan_1_ ua="na"><?php echo $dialplan ?></Dial_Plan_1_> <Station_Name ua="na"><?php echo $phone ?></Station_Name> <Date_Format>day/month</Date_Format>                                                                              <Time_Format ua="rw">24hr</Time_Format>          <Station_Display_Name ua="na"><?php echo $name ?></Station_Display_Name> <Server_Type ua="na">Asterisk</Server_Type> <Language_Selection ua="na">Russian</Language_Selection> <Dictionary_Server_Script ua="na">serv=http://<?php echo $server?>/;d0=English;x0=spa50x_30x_en_v755.xml;d1=Russian;x1=spa50x_30x_ru_v755.xml</Dictionary_Server_Script> <Default_Character_Encoding ua="na">UTF-8</Default_Character_Encoding> <Locale ua="na">ru-RU</Locale> <!-- Vertical Service Activation Codes --> <Call_Return_Code ua="na"></Call_Return_Code> <Blind_Transfer_Code ua="na"></Blind_Transfer_Code> <Call_Back_Act_Code ua="na"></Call_Back_Act_Code> <Call_Back_Deact_Code ua="na"></Call_Back_Deact_Code> <Cfwd_All_Act_Code ua="na"></Cfwd_All_Act_Code> <Cfwd_All_Deact_Code ua="na"></Cfwd_All_Deact_Code> <Cfwd_Busy_Act_Code ua="na"></Cfwd_Busy_Act_Code> <Cfwd_Busy_Deact_Code ua="na"></Cfwd_Busy_Deact_Code> <Cfwd_No_Ans_Act_Code ua="na"></Cfwd_No_Ans_Act_Code> <Cfwd_No_Ans_Deact_Code ua="na"></Cfwd_No_Ans_Deact_Code> <CW_Act_Code ua="na"></CW_Act_Code> <CW_Deact_Code ua="na"></CW_Deact_Code> <CW_Per_Call_Act_Code ua="na"></CW_Per_Call_Act_Code> <CW_Per_Call_Deact_Code ua="na"></CW_Per_Call_Deact_Code> <Block_CID_Act_Code ua="na"></Block_CID_Act_Code> <Block_CID_Deact_Code ua="na"></Block_CID_Deact_Code> <Block_CID_Per_Call_Act_Code ua="na"></Block_CID_Per_Call_Act_Code> <Block_CID_Per_Call_Deact_Code ua="na"></Block_CID_Per_Call_Deact_Code> <Block_ANC_Act_Code ua="na"></Block_ANC_Act_Code> <Block_ANC_Deact_Code ua="na"></Block_ANC_Deact_Code> <DND_Act_Code ua="na"></DND_Act_Code> <DND_Deact_Code ua="na"></DND_Deact_Code> <Secure_All_Call_Act_Code ua="na"></Secure_All_Call_Act_Code> <Secure_No_Call_Act_Code ua="na"></Secure_No_Call_Act_Code> <Secure_One_Call_Act_Code ua="na"></Secure_One_Call_Act_Code> <Secure_One_Call_Deact_Code ua="na"></Secure_One_Call_Deact_Code> <Paging_Code ua="na"></Paging_Code> <Call_Park_Code ua="na"></Call_Park_Code> <Call_Pickup_Code ua="na"></Call_Pickup_Code> <Call_UnPark_Code ua="na"></Call_UnPark_Code> <Group_Call_Pickup_Code ua="na"></Group_Call_Pickup_Code> <Media_Loopback_Code ua="na"></Media_Loopback_Code> <Referral_Services_Codes ua="na"></Referral_Services_Codes> <Feature_Dial_Services_Codes ua="na"></Feature_Dial_Services_Codes> <XML_Directory_Service_Name ua="na">Address Book</XML_Directory_Service_Name> <XML_Directory_Service_URL ua="na">http://<?php echo $server ?>/directory.php</XML_Directory_Service_URL> <?php if ($use4line==1){ ?> <Extension_4_ group="Phone/Line_Key_4">Disabled</Extension_4_> <Short_Name_4_ group="Phone/Line_Key_4"><?php echo $label ?></Short_Name_4_> <Share_Call_Appearance_4_ group="Phone/Line_Key_4">private</Share_Call_Appearance_4_>    <Extended_Function_4_ group="Phone/Line_Key_4">fnc=xml;url=http://<?php echo $server ?>/directory.php</Extended_Function_4_> <?php } ?> </flat-profile> 

Тут же сделаем PHP-файл для адресной книги:

nano directory.php 

<?php  //-------Данные MySQL $mysrv = 'localhost'; $mydb = 'asterisk'; $myuser = 'asterisk'; $mypass = 'mypass'; $table = 'tbl_sip_conf';  $mysqli = new mysqli($mysrv,$myuser,$mypass,$mydb); if ($mysqli->connect_error) {     die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error); } $mysqli->query("set names utf8"); $query = 'SELECT * from `'.$table.'` ORDER BY `defaultuser` ASC'; $result=$mysqli->query($query); while ($row = $result->fetch_assoc()){ $phones[] = $row['name']; $names[] = $row['defaultuser']; } $mysqli->close();  ?> <?xml version="1.0" encoding="utf-8" ?> <CiscoIPPhoneDirectory>    <Title>Каталог</Title>    <Prompt>Выберите номер</Prompt> <?php foreach($phones as $k=>$v){?>    <DirectoryEntry>      <Name><?php echo $names[$k]." - ".$v;?></Name>      <Telephone><?php echo $v;?></Telephone>    </DirectoryEntry> <?php } ?> </CiscoIPPhoneDirectory>  

Кратко подытожим

Таким образом, у нас сейчас телефон при подключении к сети получает IP-адрес и DHCP-опцию 66 от DHCP-сервера, после чего идёт на адрес, указанный в опции 66, за персональным конфигом. Если версия его прошивки меньше, чем 7.5.2b, то он обновляется на неё, если нет — то на 7.5.5 (актуальная в момент написания поста).
После чего пытается регистрироваться на сервере Астериска с логином-паролем из БД.
Если в БД ранее телефон с этим MAC-адресом не появлялся — создаётся запись «Unidentified phone #xxxx’, и телефон так же регистрируется на Астериске с этой записью.

Еще на четвёртую кнопку выбора линии я повесил вызов XML-каталога с адресной книгой, каковую скрипт сгенерит на лету прямо из таблицы пиров в БД.

В третьей части мы накидаем простенький веб-интерфейс для редактирования/создания/удаления номеров из таблицы.

Комментарии и пожелания — велком, очень жду!

ссылка на оригинал статьи http://habrahabr.ru/post/214235/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *