Penyediaan otomatis Yealink T19 + buku alamat dinamis

Nalika aku teka kanggo bisa kanggo perusahaan iki, Aku wis sawetara database piranti IP, sawetara server karo tanda bintang lan tembelan ing wangun FreeBPX. Kajaba iku, analog PBX Samsung IDCS500 makarya ing podo karo lan, ing umum, iku sistem komunikasi utama ing perusahaan, IP telephony makarya mung kanggo departemen sales. Lan kabeh bakal terus masak kaya iki, nanging ing sawijining dina, dekrit diwenehake kanggo nransfer kabeh wong menyang IP telephony, tenggat wektu disepakati, peralatan dituku lan rencana kanggo nransfer perusahaan menyang abad 21st wiwit dileksanakake.
Wangsulan: Bab ingkang pisanan sing wiwit sumelang ing kahanan kaya mengkono iku nomer akeh pesawat telpon sing perlu kanggo ngatur piye wae, bab kapindho sing banget kuwatir ana buku telpon. Yen Manajer Endpoint bisa nulungi kita karo sing pisanan (sing, kanthi cara, dipotong saka versi paling anyar saka FreePBX), banjur ana sawetara pitakon babagan buku kasebut:

  • Kaping pisanan, kepiye njamin akurasi nalika lokasi / fluiditas pangguna terus ganti?
  • Sareh, carane rampung depersonalize telpon. Lan ora isi jeneng kontak saben wektu?

Masalah kasebut menarik, solusi kasebut ora suwe teka. Saiki aku bakal menehi dhaptar lengkap, banjur kita bakal katon ing 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 kasebut mlaku ing komputer pangguna lan bisa digunakake yen komputer disambungake menyang jaringan liwat telpon, amarga Yealink T19 ora bisa digunakake minangka gateway.

Pisanan, kita kudu ngerti apa disambungake? lan apa mac lan ip telpon kita duwe.

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

Kene kita nggunakake fungsi sniff saka framework scapy, karo bantuan kita nampa paket udp predetermined, ngenteni 70 detik lan yen kita ora nyekel apa-apa, kita metu.

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

Sabanjure, kita priksa manawa piranti kasebut pancen Yealink lan ngasilake nilai sing dibutuhake (ip lan mac).

Nggunakake panjalukan khusus, kita ngerteni akun saiki ing telpon. Kanggo nindakake iki, konfigurasi saiki diundhuh saka telpon lan diurai.

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

Temokake sandhi kanggo akun iki. Kanggo nindakake iki, kita nguripake tabel asterisk.sip lan kolom data ing.

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

Inggih, kanggo tahap pungkasan kita nyambung menyang ldap AD lan nggunakake sAMAccountName sing dipikolehi liwat fungsi kasebut getpass.getuser() njupuk cn pangguna saiki (sing biasane ngemot jeneng lengkap pangguna).

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

Kita nyambung menyang tabel sing wis digawe ing database (aku nggawe ana) lan ketik kabeh sing kita sinau, yaiku: 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()

Kita bisa mandheg ing kene, amarga kita wis nggawe buku alamat dinamis, sampeyan bisa uga takon, nanging aku luwih maju lan nambahake piranti kanthi otomatis ing kene.

Kanggo nindakake iki, konfigurasi cithakan diundhuh saka server tftp sing wis dikonfigurasi, ing ngendi kita nggawe owah-owahan lan disimpen minangka mac.cfg. Yaiku, kanggo Yealink ana rong jinis konfigurasi, siji global, lan nomer loro ditrapake kanggo telpon tartamtu lan kudu wangun mac_phone.cfg

Sawise kabeh owah-owahan ing file lan nyimpen maneh menyang server tftp, kita menehi printah kanggo telpon kanggo panentu lan urip maneh piranti.

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

Sawise reboot piranti, kita entuk jeneng lengkap ing layar telpon + buku alamat sing tansah diisi kanthi bener ing wangun database, banjur mung nambah XML lan PHP sethithik kanggo nampilake isi kanthi dinamis. Ana akeh conto kasebut, malah YEALINK dhewe duwe.

PS: Kanggo skalabilitas sing luwih gedhe, sampeyan bisa mindhah setelan utama (variabel) menyang file sing kapisah.

Source: www.habr.com

Add a comment