Таъмини худкор Yealink T19 + китоби суроғаҳои динамикӣ

Вақте ки ман барои кор ба ин ширкат омадам, ман аллакай якчанд пойгоҳи додаҳои дастгоҳҳои IP, якчанд серверҳо бо ситорача ва патч дар шакли FreeBPX доштам. Илова бар ин, аналогии PBX Samsung IDCS500 мувозӣ кор мекард ва дар маҷмӯъ системаи асосии алоқа дар ширкат буд, IP телефония танҳо барои шӯъбаи фурӯш кор мекард. Ва ҳама чиз ҳамин тавр пухтан мебуд, аммо як рӯзи хуб фармон дода шуд, ки ҳама ба IP-телефония гузаранд, мӯҳлатҳо мувофиқа карда шуданд, таҷҳизот харидорӣ карда шуданд ва нақшаи интиқоли корхона ба асри 21 амалӣ карда шуд.
Аввалин чизе, ки дар чунин вазъ боиси нигаронӣ мегардад, шумораи зуд афзоишёбандаи телефонҳо мебошад, ки бояд бо ягон роҳ идора карда шаванд, чизи дуюм, ки хеле ташвишовар буд, дафтарчаи телефонӣ буд. Агар Менеҷери Endpoint метавонад дар версияи аввал ба мо кӯмак кунад (воқеан, он аз версияҳои охирини FreePBX бурида шуда буд), пас баъзе саволҳо бо китоб пайдо шуданд:

  • Аввалан, чӣ тавр дурустии онро таъмин кардан мумкин аст, вақте ки ҷойгиршавӣ / моеъи корбарон доимо тағир меёбад?
  • Дуюм, чӣ гуна телефонҳоро комилан шахси ғайриманқул кардан мумкин аст. Ва ҳар дафъа номи тамосро пур накунед?

Мушкилот ҷолиб буд, ҳалли он дер наёфт. Ҳоло ман рӯйхати пурраро медиҳам, ва баъд мо онро бо тартиб дида мебароем.

from scapy.all import sniff
from scapy.layers.inet import IP
import mysql.connector
import ldap
import getpass
import tftpy
import requests
import os
import time
from string import replace

def conn_ldap(login):
    ad = ldap.initialize('ldap://***.local')
    ad.simple_bind_s('voip@***.local', 'password')
    basedn = 'OU=IT,DC=***,DC=LOCAL'
    basedn_user = 'OU=***,OU=***,DC=***,DC=LOCAL'
    scope = ldap.SCOPE_SUBTREE
    filterexp = "(&(sAMAccountName=" + login + ")(ObjectClass=person))"
    filterexp2 = "(&(ObjectClass=organizationUnit))"
    attrlist = ['cn']
    attrlist2 = ['OU']
    search = ad.search_s(basedn, scope, filterexp, attrlist)
    adname = search[0][1]['cn'][0].decode('utf-8')
    if adname == ' ':
        search = ad.search_s(basedn_user, scope, filterexp2, attrlist2)
        for i in range(1, len(search)+1):
            group = search[i][1]['ou'][0]
            basedn_user2 = 'OU='+group+','+basedn_user
            search = ad.search_s(basedn_user2, scope, filterexp, attrlist)
            adname = search[0][1]['cn'][0].decode('utf-8')
            if adname != ' ':
                return adname
        adname = search[0][1]['cn'][0].decode('utf-8')
    ad.unbind_s()
    return adname


def tftp_file_change(config,place,adname,current_account,current_account_password):

    client = tftpy.TftpClient("192.168.0.3", 69)
    client.download('template.cfg', place)
    fileread = open(place, 'r')
    line = fileread.readlines()
    fileread.close()
    line[5] = (('account.1.label = ').encode('utf-8') + adname.encode('utf-8') + 'n')
    line[2] = (('account.1.auth_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[3] = (('account.1.display_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[6] = (('account.1.password = ').encode('utf-8') + current_account_password[0][0] + 'n')
    filewrite = open(place, 'w')
    for i in line:
      filewrite.write(i)
    filewrite.close()
    print place
    print config
    client.upload(config,place)


def get_phone_inform(ipaddr):
    fileconf = requests.get('http://admin:admin@'+ipaddr+'/servlet?phonecfg=get[&accounts=1]')
    conf = fileconf.text.split('|')
    current_account = conf[2]
    return current_account


def sniff_frame():
    pcapf = sniff(count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060")
    if len(pcapf) == 0:
        exit()
    frame = pcapf[0]
    macaddr = frame.src
    print macaddr[:8]
    if macaddr[:8] != '80:5e:c0':
        exit()
    ipaddr = frame[0][IP].src
    return macaddr, ipaddr


def conn_mysql(query,fquery,macaddr,qwery2):
    connect = mysql.connector.connect(host='192.168.0.3', database='voip', user='voip_wr', password='***')
    cursor = connect.cursor()
    cursor.execute(fquery)
    state = cursor.fetchall()
    state = bool(state[0][0])
    if state == True:
        cursor.execute(qwery2)
        connect.commit()
        connect.close()
    else:
        cursor.execute(query)
        connect.commit()
        connect.close()


def check_account(current_account):
    connect = mysql.connector.connect(host='192.168.0.3', database='asterisk', user='voip_wr', password='***')
    cursor = connect.cursor()
    qwery = 'select data from sip where id=' + current_account + ' and keyword="secret";'
    cursor.execute(qwery)
    password = cursor.fetchall()
    if password == ' ':
        exit()
    else:
        return password


if __name__ == '__main__':
    macaddr, ipaddr = sniff_frame()
    current_account = get_phone_inform(ipaddr)
    current_account_password = check_account(current_account)
    macaddr = macaddr.replace(':', '')
    ipaddr = ipaddr.decode('utf-8')
    adname = conn_ldap(getpass.getuser())
    query = 'INSERT INTO station (mac, ip, name, number) VALUES (' + '"' + macaddr + '",' + '"' + ipaddr + '",' + '"' + adname + '",' + '"' + get_phone_inform(ipaddr) + '"' + ')'
    qwery2 = 'UPDATE station SET ip=' + '"' + ipaddr + '"' + ', name=' + '"' + adname + '"' + ', number=' + '"' + get_phone_inform(ipaddr) + '"' + ' WHERE mac=' + '"' + macaddr + '"'
    fquery = 'SELECT EXISTS(SELECT mac FROM voip.station WHERE mac=' + '"' + macaddr + '")'
    query = query.encode('utf-8')
    fquery = fquery.encode('utf-8')
    config = macaddr + '.cfg'
    place = os.path.expanduser("~") + "" + "AppDataLocal" + config
    conn_mysql(query,fquery,macaddr,qwery2)
    tftp_file_change(config,place,adname,current_account,current_account_password)
    requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=AutoP')
    requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=Reboot')

Барнома дар компютери корбар кор мекунад ва ба шарте кор мекунад, ки компютер ба шабака тавассути телефон пайваст бошад, зеро Yealink T19 наметавонад ҳамчун дарвоза кор кунад.

Аввалан, мо бояд фаҳмем, ки оё он пайваст аст? ва телефони мо чӣ mac ва ip дорад.

def sniff_frame():
    pcapf = sniff(count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060")
    if len(pcapf) == 0:
        exit()
    frame = pcapf[0]
    macaddr = frame.src
    print macaddr[:8]
    if macaddr[:8] != '80:5e:c0':
        exit()
    ipaddr = frame[0][IP].src
    return macaddr, ipaddr

Дар ин ҷо мо функсияи sniff-ро аз чаҳорчӯбаи scapy истифода мебарем, бо ёрии он мо бастаи udp-и пешакӣ муайяншударо мегирем, 70 сония интизор мешавем ва агар чизе нагирем, мо берун мешавем.

count=1, timeout=70, filter="dst host 192.168.0.3 and port 5060"

Сипас, мо боварӣ ҳосил мекунем, ки дастгоҳ воқеан Yealink аст ва арзишҳои заруриро бармегардонем (ip ва mac).

Бо истифода аз дархости махсус, мо ҳисоби ҷорӣро дар телефон пайдо мекунем. Барои ин, конфигуратсияи ҷорӣ аз телефон зеркашӣ карда мешавад ва таҳлил карда мешавад.

def get_phone_inform(ipaddr):
    fileconf = requests.get('http://admin:admin@'+ipaddr+'/servlet?phonecfg=get[&accounts=1]')
    conf = fileconf.text.split('|')
    current_account = conf[2]
    return current_account

Рамзи ин ҳисобро пайдо кунед. Барои ин мо ба ҷадвали asterisk.sip ва майдони маълумот дар он муроҷиат мекунем.

def check_account(current_account):
    connect = mysql.connector.connect(host='192.168.0.3', database='asterisk', user='voip_wr', password='***')
    cursor = connect.cursor()
    qwery = 'select data from sip where id=' + current_account + ' and keyword="secret";'
    cursor.execute(qwery)
    password = cursor.fetchall()
    if password == ' ':
        exit()
    else:
        return password

Хуб, барои марҳилаи ниҳоӣ мо ба ldap AD пайваст мешавем ва бо истифода аз sAMAccountName, ки тавассути функсия гирифта шудааст getpass.getuser() cn-и корбари ҷорӣро гиред (ки одатан номи пурраи корбарро дар бар мегирад).

def conn_ldap(login):
    ad = ldap.initialize('ldap://***.local')
    ad.simple_bind_s('voip@***.local', 'password')
    basedn = 'OU=***,DC=***,DC=LOCAL'
    basedn_user = 'OU=***,OU=***,DC=***,DC=LOCAL'
    scope = ldap.SCOPE_SUBTREE
    filterexp = "(&(sAMAccountName=" + login + ")(ObjectClass=person))"
    filterexp2 = "(&(ObjectClass=organizationUnit))"
    attrlist = ['cn']
    attrlist2 = ['OU']
    search = ad.search_s(basedn, scope, filterexp, attrlist)
    adname = search[0][1]['cn'][0].decode('utf-8')
    if adname == ' ':
        search = ad.search_s(basedn_user, scope, filterexp2, attrlist2)
        for i in range(1, len(search)+1):
            group = search[i][1]['ou'][0]
            basedn_user2 = 'OU='+group+','+basedn_user
            search = ad.search_s(basedn_user2, scope, filterexp, attrlist)
            adname = search[0][1]['cn'][0].decode('utf-8')
            if adname != ' ':
                return adname
        adname = search[0][1]['cn'][0].decode('utf-8')
    ad.unbind_s()
    return adname

Мо ба ҷадвали қаблан сохташуда дар базаи маълумот пайваст мешавем (ман онро дар он ҷо офаридаам) ва ҳама чизеро, ки мо омӯхтаем, дохил мекунем: ip, mac, номи корбар.

def conn_mysql(query,fquery,macaddr,qwery2):
    connect = mysql.connector.connect(host='192.168.0.3', database='voip', user='voip_wr', password='***')
    cursor = connect.cursor()
    cursor.execute(fquery)
    state = cursor.fetchall()
    state = bool(state[0][0])
    if state == True:
        cursor.execute(qwery2)
        connect.commit()
        connect.close()
    else:
        cursor.execute(query)
        connect.commit()
        connect.close()

Мо метавонем дар ин ҷо таваққуф кунем, зеро мо аллакай як китоби суроғаҳои динамикӣ офаридаем, шумо метавонед пурсед, аммо ман пештар рафтам ва ба таври худкор таъмин кардани дастгоҳҳоро дар ин ҷо илова кардам.

Барои ин, конфигуратсияи шаблон аз сервери қаблан танзимшудаи tftp зеркашӣ карда мешавад, ки мо дар он тағиротҳои худро ворид мекунем ва онро ҳамчун mac.cfg захира мекунем. Яъне, барои Yealink ду намуди конфигуратсия вуҷуд дорад, яке глобалӣ ва дуюм ба телефони мушаххас дахл дорад ва бояд шакли mac_phone.cfg бошад.

Пас аз ҳама тағирот дар файл ва захира кардани он ба сервери tftp, мо ба телефон фармон медиҳем, ки дастгоҳро таъмин ва аз нав оғоз кунад.

def tftp_file_change(config,place,adname,current_account,current_account_password):

    client = tftpy.TftpClient("192.168.0.3", 69)
    client.download('template.cfg', place)
    fileread = open(place, 'r')
    line = fileread.readlines()
    fileread.close()
    line[5] = (('account.1.label = ').encode('utf-8') + adname.encode('utf-8') + 'n')
    line[2] = (('account.1.auth_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[3] = (('account.1.display_name = ').encode('utf-8') + current_account.encode('utf-8') + 'n')
    line[6] = (('account.1.password = ').encode('utf-8') + current_account_password[0][0] + 'n')
    filewrite = open(place, 'w')
    for i in line:
      filewrite.write(i)
    filewrite.close()
    print place
    print config
    client.upload(config,place)

requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=AutoP')
requests.get('http://admin:admin@'+ipaddr+'/cgi-bin/ConfigManApp.com?key=Reboot')

Пас аз бозоғозкунии дастгоҳ, мо номи пурраи худро дар экрани телефон пайдо мекунем + китоби суроғаҳои ҳамеша дуруст пуршуда дар шакли пойгоҳи додаҳо, пас танҳо илова кардани XML ва каме PHP барои динамикӣ намоиш додани мундариҷа аст. Чунин мисолҳо зиёданд, ҳатто худи YEALINK низ доранд.

PS: Барои миқёспазирии бештар, шумо метавонед танзимоти асосиро (тағйирёбандаҳо) ба файли алоҳида интиқол диҳед.

Манбаъ: will.com

Илова Эзоҳ