Provisioning otomatis Yealink T19 + buku alamat dinamis

Nalika kuring sumping ka dianggo pikeun parusahaan ieu, Kuring geus kungsi sababaraha database alat IP, sababaraha server kalawan tanda bintang sarta patch dina bentuk FreeBPX. Salaku tambahan, analog PBX Samsung IDCS500 damel paralel sareng, sacara umum, mangrupikeun sistem komunikasi utama di perusahaan; IP telephony ngan ukur dianggo pikeun jabatan penjualan. Sareng sadayana bakal terus masak sapertos kieu, tapi hiji dinten anu saé parantos masihan kaputusan pikeun nransferkeun sadayana ka IP telephony, deadlines sapuk, alat-alat dibeuli sareng rencana pikeun mindahkeun perusahaan kana abad ka-21 mimiti dilaksanakeun.
Hal kahiji anu mimiti hariwang dina kaayaan sapertos kitu nyaéta jumlah set telepon anu ngembang pesat anu kedah diurus kumaha waé, anu kadua anu pikahariwangeun nyaéta buku telepon. Upami Manajer Endpoint tiasa ngabantosan urang anu munggaran (anu, ku jalan kitu, dipotong tina versi panganyarna tina FreePBX), teras aya sababaraha patarosan anu timbul dina buku:

  • Anu mimiti, kumaha carana mastikeun katepatanana nalika lokasi / fluiditas pangguna terus robih?
  • Bréh, kumaha lengkep depersonalize telepon. Na teu eusian ngaran kontak unggal waktu?

Masalahna pikaresepeun, solusina henteu lami dugi. Ayeuna kuring bakal masihan daptar lengkep, teras urang bakal ningali dina urutan.

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')

program dijalankeun dina komputer pamaké sarta gawéna disadiakeun yén komputer disambungkeun ka jaringan via telepon a, saprak Yealink T19 teu tiasa dianggo salaku gateway a.

Kahiji, urang kudu ngarti naha éta disambungkeun? sareng naon mac sareng ip telepon urang gaduh.

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

Di dieu kami nganggo fungsi sniff tina kerangka scapy, kalayan bantosan na kami nampi pakét udp anu tos ditangtukeun, antosan 70 detik sareng upami urang henteu nyekel nanaon, urang kaluar.

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

Salajengna, kami mastikeun yén alat éta leres-leres Yealink sareng mulangkeun nilai anu diperyogikeun (ip sareng mac).

Ngagunakeun pamundut husus, urang manggihan rekening ayeuna dina telepon. Jang ngalampahkeun ieu, konfigurasi ayeuna diundeur ti telepon tur parsed.

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

Panggihan sandi pikeun akun ieu. Jang ngalampahkeun ieu, urang balikkeun kana tabel asterisk.sip sareng widang data di jerona.

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

Muhun, pikeun tahap ahir urang nyambung ka ldap AD sarta ngagunakeun sAMAccountName diala ngaliwatan fungsi getpass.getuser() nyandak cn tina pamaké ayeuna (anu biasana ngandung ngaran lengkep pamaké).

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

Urang sambungkeun kana tabel anu tos didamel dina pangkalan data (kuring nyiptakeunana di dinya) sareng lebetkeun sadayana anu urang diajar, nyaéta: ip, mac, username.

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()

Urang tiasa lirén di dieu, sabab kami parantos nyiptakeun buku alamat dinamis, anjeun tiasa naroskeun, tapi kuring langkung jauh sareng nambihan alat-alat otomatis di dieu.

Jang ngalampahkeun ieu, hiji konfigurasi template diundeur ti server tftp tos ngonpigurasi, kana nu urang jieun perobahan urang jeung simpen salaku mac.cfg. Nyaéta, pikeun Yealink aya dua jinis konfigurasi, hiji global, sareng anu kadua manglaku ka telepon khusus sareng kedah bentukna mac_phone.cfg.

Saatos sagala parobihan dina file sareng simpen deui ka server tftp, kami masihan paréntah ka telepon pikeun nyayogikeun sareng reboot alat.

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')

Saatos rebooting alat, urang meunang ngaran lengkep urang dina layar telepon + hiji salawasna bener dieusian kaluar buku alamat dina bentuk database a, lajeng sagala anu tetep nyaéta pikeun nambahkeun XML sarta PHP saeutik pikeun dinamis nembongkeun eusi. Aya seueur conto sapertos kitu, bahkan YEALINK sorangan gaduh aranjeunna.

PS: Pikeun skalabilitas anu langkung ageung, anjeun tiasa mindahkeun setélan utama (variabel) kana file anu misah.

sumber: www.habr.com

Tambahkeun komentar