python3使用libpcap給ESL命令添加日誌記錄

操作系統 :CentOS 7.6_x64
FreeSWITCH版本 :1.10.9
python版本:3.9.12
libpcap版本:1.11.0b7
 
FreeSWITCH的ESL模塊用起來很方便,可以控制FreeSWITCH實現具體業務需求,但該模塊沒有提供ESL命令執行日誌,不便於排查問題,本文展示一種使用python3基於libpcap實現ESL命令執行日誌的方法,並提供示例代碼及相關資源下載途徑。

一、背景描述

日常開發過程中觀察到:通過ESL發送給FreeSWITCH的命令,在freeswitch.log中找不到記錄。
查看代碼發現,確實沒有相關記錄(mod_event_socket.c文件):
static void *SWITCH_THREAD_FUNC api_exec(switch_thread_t *thread, void *obj)

分析後發現,大概有以下幾個方法:

  • 1、通過修改FreeSWITCH源代碼實現
文件: mod_event_socket.c
入口: api_exec

可通過switch_log_printf函數來實現。

  • 2、使用tcpdump抓取
因EventSocket模塊使用的是基於TCP的文本協議,且未加密,默認端口8021,可以通過tcpdump抓取event socket服務端口獲取命令記錄。

 示例如下:

tcpdump tcp dst port 8021 -w test1.pcap
  • 3、使用python3基於libpcap實現
底層原理和tcpdump一樣,只是基於libpcap使用python3進行實現,會靈活很多,這也是本文終點描述的方法,具體實現在後續展開。

二、具體實現

本文基於python3.9.12實現,CentOS 7環境編譯及使用python3.9.12,可參考這篇文章:
https://www.cnblogs.com/MikeZhang/p/centos7-install-py39-20220704.html

關鍵點如下:
1、實時抓取網卡數據

可基於libpcap實時抓取網卡數據,具體可參考我之前寫的文章:

https://www.cnblogs.com/MikeZhang/p/pythonUseLibpcap20221029.html

2、解析IP頭獲取源地址
需要獲取發送ESL命令機器的源地址以便排查問題,IP數據包裏面包含有源地址,python中解析IP頭的示例如下:

ipInfo = struct.unpack('!BBHHHBBH4s4s',bytes(p[14:34]))
srcIp = socket.inet_ntoa(ipInfo[-2])
dstIp = socket.inet_ntoa(ipInfo[-1])

3、解析TCP頭獲取具體數據
具體的ESL命令在TCP的數據部分保存,可通過解析TCP頭獲取ESL數據的起始下標,進而獲取數據,示例如下:

tcpInfo = struct.unpack('!HHLLBBH',bytes(p[34:50]))
tcpHdrLen = (tcpInfo[4] >> 4) * 4
offset = 34 + tcpHdrLen
data = bytes(p[offset:tlen])

4、使用logging模塊進行記錄
可使用python自帶的日誌模塊記錄ESL命令記錄,並進行存盤,便於後續查看。

示例如下:

logger.info("(%s,%s)" % (srcIp,data))

logger可在main函數中實現,指定具體的存盤文件,如果只是想控制檯查看,則可以這樣實現:

logger = logging.getLogger()

...

logging.basicConfig(
    level=logging.DEBUG, # DEBUG,INFO,WARNING,ERROR,CRITICAL
    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
    datefmt='%a, %d %b %Y %H:%M:%S'
)

基於上述關鍵點,可以實現ESL命令的日誌記錄,示例如下(eslLogTest1.py):

完整代碼可從如下渠道獲取:

關注微信公衆號(聊聊博文,文末可掃碼)後回覆 20231125 獲取。

三、運行效果

可使用ESL發送命令,然後用python腳本進行記錄。發送ESL命令可使用ESL庫,python3.9.12版本的ESL編譯及使用,可參考這篇文章:
https://www.cnblogs.com/MikeZhang/p/py39esl-20230424.html

也可直接使用socket,示例如下(sendcmd1.py):
import socket,time

def doCmd(sock,cmd):
    print(cmd)
    sock.send(cmd + b'\r\n\r\n')

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
sock.connect(('192.168.137.32', 8021))  
sock.send(b'auth ClueCon\r\n\r\n')
doCmd(sock,b'bgapi originate user/1000 &echo')
time.sleep(10)
doCmd(sock,b'bgapi hupall')
發送命令後,使用python實時記錄的運行效果如下:

運行效果視頻可從如下渠道獲取:

關注微信公衆號(聊聊博文,文末可掃碼)後回覆 2023112501 獲取。

四、資源獲取

本文涉及資源,可以從如下途徑獲取:

 關注微信公衆號(聊聊博文,文末可掃碼)後回覆 20231125 獲取。

好,就這麼多了,希望對你有幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章