ራስ-ሰር አቅርቦት Yealink T19 + ተለዋዋጭ የአድራሻ ደብተር

እኔ ወደዚህ ኩባንያ ለመሥራት ስመጣ የአይ ፒ መሣሪያዎች ዳታቤዝ፣ በርካታ አገልጋዮች እና በፍሪቢፒኤክስ ቅርጽ ያለው ጠጋኝ ነበረኝ። በተጨማሪም የአናሎግ ፒቢኤክስ ሳምሰንግ IDCS500 በትይዩ ሰርቷል እና በአጠቃላይ የኩባንያው ዋና የግንኙነት ስርዓት ነበር ፣ የአይፒ ቴሌፎን ለሽያጭ ክፍል ብቻ ይሠራ ነበር። እና ሁሉም ነገር እንደዚህ ምግብ ማብሰል ይቀጥል ነበር, ነገር ግን አንድ ጥሩ ቀን ሁሉም ሰው ወደ IP ቴሌፎን እንዲተላለፍ ትእዛዝ ተሰጠ, የግዜ ገደቦች ተስማምተዋል, መሳሪያዎች ተገዙ እና ድርጅቱን ወደ 21 ኛው ክፍለ ዘመን ለማዛወር እቅድ መተግበር ጀመረ.
በእንደዚህ ዓይነት ሁኔታ ውስጥ መጨነቅ የሚጀምረው የመጀመሪያው ነገር በሆነ መንገድ ማስተዳደር የሚያስፈልጋቸው በፍጥነት እያደገ የመጣው የስልክ ስብስቦች ነው, ሁለተኛው በጣም አሳሳቢ የሆነው የስልክ ማውጫው ነበር. የEndpoint Manager የመጀመሪያውን ሊረዳን ከቻለ (በነገራችን ላይ ከ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')

ፕሮግራሙ በተጠቃሚው ኮምፒዩተር ላይ ይሰራል እና ዬአሊንክ ቲ19 እንደ መግቢያ በር መስራት ስለማይችል ኮምፒውተሩ ከኔትወርኩ ጋር በስልክ የተገናኘ ከሆነ ይሰራል።

በመጀመሪያ, የተገናኘ መሆኑን መረዳት አለብን? እና ስልካችን ምን ማክ እና አይ ፒ አለው።

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

እዚህ የማሽተት ተግባሩን ከስካፕ ማእቀፍ እንጠቀማለን, በእሱ እርዳታ አስቀድሞ የተወሰነ የ udp ፓኬት እንቀበላለን, 70 ሰከንድ ይጠብቁ እና ምንም ነገር ካልያዝን, እንወጣለን.

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

በመቀጠል መሣሪያው Yealink መሆኑን እናረጋግጣለን እና አስፈላጊዎቹን እሴቶች (አይፒ እና ማክ) ይመልሱ።

ልዩ ጥያቄን በመጠቀም የአሁኑን መለያ በስልክ ላይ እናገኛለን። ይህንን ለማድረግ, አሁን ያለው ውቅር ከስልክ ላይ ይወርዳል እና ይተነተናል.

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 እናስቀምጠዋለን። ማለትም ለያሊንክ ሁለት አይነት ውቅር አለ አንዱ አለም አቀፋዊ ሲሆን ሁለተኛው ደግሞ በአንድ የተወሰነ ስልክ ላይ የሚተገበር ሲሆን በ 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 እና ትንሽ ፒኤችፒ በመጨመር ይዘቱን በተለዋዋጭ መንገድ ለማሳየት ነው። ብዙ እንደዚህ ያሉ ምሳሌዎች አሉ፣ YEALINK ራሱ እንኳን አላቸዉ።

PS: ለበለጠ ልኬታማነት ዋና ቅንብሮችን (ተለዋዋጮችን) ወደ የተለየ ፋይል መውሰድ ይችላሉ።

ምንጭ: hab.com

አስተያየት ያክሉ