Yealink T19 + ပြောင်းလဲနေသော လိပ်စာစာအုပ်ကို အလိုအလျောက် စီမံဆောင်ရွက်ပေးခြင်း။

ကျွန်ုပ်သည် ဤကုမ္ပဏီအတွက် အလုပ်လုပ်လာသောအခါတွင်၊ ကျွန်ုပ်တွင် IP ကိရိယာများ၏ ဒေတာဘေ့စ်အချို့၊ ခရေပွင့်ပါသော ဆာဗာများစွာနှင့် FreeBPX ပုံစံ patch တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ ထို့အပြင်၊ analogue PBX Samsung IDCS500 သည် အပြိုင်အလုပ်လုပ်ပြီး ယေဘူယျအားဖြင့် ကုမ္ပဏီရှိ အဓိကဆက်သွယ်ရေးစနစ်ဖြစ်သည်၊ IP တယ်လီဖုန်းသည် အရောင်းဌာနအတွက်သာ အလုပ်လုပ်သည်။ အားလုံးက ဒီပုံစံအတိုင်း ဆက်ပြီး ချက်ပြုတ်နေပေမယ့် တစ်နေ့မှာ လူတိုင်း 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')

ပရိုဂရမ်သည် အသုံးပြုသူ၏ကွန်ပြူတာပေါ်တွင်အလုပ်လုပ်ပြီး ကွန်ပြူတာသည် ဖုန်းမှတစ်ဆင့် ကွန်ရက်သို့ချိတ်ဆက်ထားသောကြောင့် 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

ဤနေရာတွင် ကျွန်ုပ်တို့သည် ကြိုတင်သတ်မှတ်ထားသော udp ပက်ကတ်ကို လက်ခံရရှိကာ ၎င်း၏အကူအညီဖြင့် scapy framework မှ sniff လုပ်ဆောင်ချက်ကို အသုံးပြုပြီး 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

ကျွန်ုပ်တို့သည် ဒေတာဘေ့စ်ရှိ ကြိုတင်ဖန်တီးထားသော ဇယားတစ်ခုသို့ ချိတ်ဆက်ကာ (ထိုနေရာတွင် ကျွန်ုပ်ဖန်တီးခဲ့သည်)၊ အိုင်ပီ၊ မက်ခ်၊ အသုံးပြုသူအမည်၊ ကျွန်ုပ်တို့ လေ့လာခဲ့သမျှအားလုံးကို ထည့်သွင်းပါ။

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

ကျွန်ုပ်တို့သည် ဤနေရာတွင် ရပ်တန့်နိုင်သည်၊ အကြောင်းမှာ ကျွန်ုပ်တို့သည် ပြောင်းလဲနေသော လိပ်စာစာအုပ်ကို ဖန်တီးထားပြီးဖြစ်သောကြောင့်၊ သင်သည် မေးကောင်းမေးနိုင်သော်လည်း၊ ကျွန်ုပ်သည် ဤနေရာတွင် စက်ပစ္စည်းများ၏ အလိုအလျောက် စီမံဆောင်ရွက်ပေးခြင်းကို ထပ်ထည့်လိုက်ပါသည်။

၎င်းကိုလုပ်ဆောင်ရန်၊ ကျွန်ုပ်တို့၏ပြောင်းလဲမှုများပြုလုပ်ပြီး ၎င်းကို mac.cfg အဖြစ်သိမ်းဆည်းရန်အတွက် ကြိုတင်ပြင်ဆင်ထားသော tftp ဆာဗာမှ ပုံစံပလိတ်ဖွဲ့စည်းမှုပုံစံကို ဒေါင်းလုဒ်လုပ်ထားသည်။ ဆိုလိုသည်မှာ 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- ပိုမိုကြီးမားသော အရွယ်အစားအတွက်၊ သင်သည် ပင်မဆက်တင်များ (ကိန်းရှင်များ) ကို သီးခြားဖိုင်တစ်ခုသို့ ရွှေ့နိုင်သည်။

source: www.habr.com

မှတ်ချက် Add