python如何實(shí)時(shí)獲取tcpdump輸出
一、背景
今天有個(gè)小需求,要確認(rèn)客戶端有沒有往服務(wù)端發(fā)送udp包,但為了減輕工作量,不想每次到機(jī)器上手動(dòng)執(zhí)行tcpdump抓包命令。
于是就寫了個(gè)腳本來釋放人力。
二、代碼實(shí)現(xiàn)
整個(gè)腳本我還加了一些其他功能:時(shí)間戳、發(fā)送端IP提取,數(shù)據(jù)包分析,數(shù)據(jù)持久化等。這里都先去掉,僅記錄下簡單的實(shí)時(shí)獲取tcpdump輸出功能。
代碼如下:
# -*- coding: utf-8 -*- # !/usr/bin/env python # sudo tcpdump -tt -l -nn -c 5 -i enp4s0 udp port 514 or 51414 import subprocess cmd = ['sudo', 'tcpdump', '-tt', '-l', '-nn', '-c', '5', '-i', 'enp4s0', 'udp', 'port', '514', 'or', '51414'] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) while True: line = proc.stdout.readline() line = line.strip() if not line: print('tcpdump finished...') break print(line)
輸出如下(實(shí)時(shí)):
wenyuanblog@localhost:/home/test/script# python tcpdump_udp.py tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on enp4s0, link-type EN10MB (Ethernet), capture size 262144 bytes 1499774951.124178 IP 192.168.10.210.41974 > 192.168.10.251.514: UDP, length 139 1499774953.125664 IP 192.168.10.210.54995 > 192.168.10.251.51414: UDP, length 139 1499774956.128498 IP 192.168.10.210.56748 > 192.168.10.251.514: UDP, length 139 1499774958.129918 IP 192.168.10.210.53883 > 192.168.10.251.51414: UDP, length 139 1499774961.132921 IP 192.168.10.210.58803 > 192.168.10.251.514: UDP, length 139 5 packets captured 6 packets received by filter 0 packets dropped by kernel tcpdump finished...
以上代碼相當(dāng)于手動(dòng)執(zhí)行了 sudo tcpdump -tt -l -nn -c 5 -i enp4s0 udp port 514 or 51414
這條命令。
注意參數(shù)-l很重要(行顯)。
三、代碼實(shí)現(xiàn)(更新)
上面的代碼能實(shí)現(xiàn)tcpdump的功能,但是有一個(gè)問題:沒有做超時(shí)保護(hù)。即當(dāng)程序執(zhí)行時(shí)間過長時(shí)kill該進(jìn)程(這里使用ctrl+c的方式)。
要實(shí)現(xiàn)這個(gè)功能有很多種方案,例如定時(shí)器+多線程等,這里僅演示一種方案,代碼如下:
# -*- coding: utf-8 -*- # !/usr/bin/env python # sudo tcpdump -tt -l -nn -c 50 -i enp4s0 udp port 514 or 51414 import subprocess import signal import time import os import re import json class CmdServer: def __init__(self, cmd, timeout=120): ''' :param cmd: 執(zhí)行命令(列表形式) :param timeout: 任務(wù)超時(shí)時(shí)間(seconds,進(jìn)程運(yùn)行超過該時(shí)間,kill該進(jìn)程) :param taskname: 任務(wù)名稱(根據(jù)該任務(wù)名稱記錄命令輸出信息) ''' self.cmd = cmd self.timeout = timeout self.base_path = reduce(lambda x, y: os.path.dirname(x), range(1), os.path.abspath(__file__)) self.output_path = os.path.join(self.base_path, 'data.json') self.udp_flow_list = [] self.begin_time = int(time.time()) # 執(zhí)行tcpdump任務(wù) def run(self): if os.path.exists(self.output_path): with open(self.output_path, 'r') as f: self.udp_flow_list = json.load(f) proc = subprocess.Popen(self.cmd, stdout=subprocess.PIPE) stdout = '' while proc.poll() == None: current_time = int(time.time()) if current_time - self.begin_time >= self.timeout: print('tcpdump timeout...') proc.send_signal(signal.SIGINT) stdout = proc.stdout.read() if proc.poll() is not None and not stdout: print('tcpdump finished...') stdout = proc.stdout.read() stdout_list = stdout.split('\n') if stdout_list: self._merge_data(stdout_list) self._save_data() # 數(shù)據(jù)合并(新增/更新) def _merge_data(self, stdout_list): for line in stdout_list: line = line.strip() if not line: continue timestamp = int(float(line.split('IP')[0].strip())) * 1000 # 源 src_ip_port_list = re.findall(r'IP(.+?)>', line) if not src_ip_port_list: continue src_ip_port_str = src_ip_port_list[0].strip() src_ip = '.'.join(src_ip_port_str.split('.')[0:4]) # 目的 dst_ip_port_list = re.findall(r'>(.+?):', line) if not dst_ip_port_list: continue dst_ip_port_str = dst_ip_port_list[0].strip() dst_port = dst_ip_port_str.split('.')[-1] # 新增/更新latest_timestamp src_item = filter(lambda x: src_ip == x['src_ip'], self.udp_flow_list) if src_item: src_item[0]['dst_port'] = dst_port src_item[0]['latest_timestamp'] = timestamp else: self.udp_flow_list.append(dict( src_ip=src_ip, dst_port=dst_port, latest_timestamp=timestamp )) # 保存數(shù)據(jù) def _save_data(self): # 寫入文件 with open(self.output_path, 'w') as f: json.dump(self.udp_flow_list, f, encoding="utf-8", ensure_ascii=False) if __name__ == '__main__': cmd = ['sudo', 'tcpdump', '-tt', '-l', '-nn', '-c', '5', '-i', 'enp4s0', 'udp', 'port', '514', 'or', '51414'] cmd_server = CmdServer(cmd, 10) cmd_server.run()
四、總結(jié)
比較簡單,僅僅是記錄下。
以上就是python如何實(shí)時(shí)獲取tcpdump輸出的詳細(xì)內(nèi)容,更多關(guān)于python獲取tcpdump輸出的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Android端TCP長連接的性能優(yōu)化教程分享
- Java多線程實(shí)現(xiàn)TCP網(wǎng)絡(luò)Socket編程(C/S通信)
- java實(shí)現(xiàn)基于TCP協(xié)議網(wǎng)絡(luò)socket編程(C/S通信)
- Springboot+TCP監(jiān)聽服務(wù)器搭建過程圖解
- Python使用socket_TCP實(shí)現(xiàn)小文件下載功能
- Python使用socket模塊實(shí)現(xiàn)簡單tcp通信
- 從Linux源碼看Socket(TCP)Client端的Connect的示例詳解
- Java利用TCP協(xié)議實(shí)現(xiàn)客戶端與服務(wù)器通信(附通信源碼)
- TCP性能調(diào)優(yōu)實(shí)現(xiàn)原理及過程解析
相關(guān)文章
詳解如何將Pandas運(yùn)行結(jié)果導(dǎo)出為CSV格式文件
在數(shù)據(jù)分析與處理的世界里,Pandas?是一個(gè)不可或缺的工具,它提供了強(qiáng)大的數(shù)據(jù)處理功能,讓我們能夠輕松地清洗、轉(zhuǎn)換和分析數(shù)據(jù),本文將帶領(lǐng)大家了解如何使用?Pandas?將運(yùn)行結(jié)果導(dǎo)出為?CSV?文件,并通過實(shí)際案例進(jìn)行深入探討2024-05-05tensorflow 報(bào)錯(cuò)unitialized value的解決方法
今天小編就為大家分享一篇tensorflow 報(bào)錯(cuò)unitialized value的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-02-02詳解用python自制微信機(jī)器人,定時(shí)發(fā)送天氣預(yù)報(bào)
這篇文章主要介紹了用python自制微信機(jī)器人,定時(shí)發(fā)送天氣預(yù)報(bào),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03如何使用python對(duì)圖片進(jìn)行批量壓縮詳解
對(duì)于圖片強(qiáng)行被定義高和寬會(huì)變形,我們希望圖片被改變大小后,比例保持不變,完成對(duì)圖片的壓縮,下面這篇文章主要給大家介紹了關(guān)于如何使用python對(duì)圖片進(jìn)行批量壓縮的相關(guān)資料,需要的朋友可以參考下2022-07-07python中函數(shù)返回多個(gè)結(jié)果的實(shí)例方法
在本篇文章里小編給大家整理了一篇關(guān)于python中函數(shù)返回多個(gè)結(jié)果的實(shí)例方法,有興趣的朋友們可以學(xué)習(xí)下。2020-12-12