python如何實時獲取tcpdump輸出
一、背景
今天有個小需求,要確認客戶端有沒有往服務(wù)端發(fā)送udp包,但為了減輕工作量,不想每次到機器上手動執(zhí)行tcpdump抓包命令。
于是就寫了個腳本來釋放人力。
二、代碼實現(xiàn)
整個腳本我還加了一些其他功能:時間戳、發(fā)送端IP提取,數(shù)據(jù)包分析,數(shù)據(jù)持久化等。這里都先去掉,僅記錄下簡單的實時獲取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)
輸出如下(實時):
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)于手動執(zhí)行了 sudo tcpdump -tt -l -nn -c 5 -i enp4s0 udp port 514 or 51414 這條命令。
注意參數(shù)-l很重要(行顯)。
三、代碼實現(xiàn)(更新)
上面的代碼能實現(xiàn)tcpdump的功能,但是有一個問題:沒有做超時保護。即當(dāng)程序執(zhí)行時間過長時kill該進程(這里使用ctrl+c的方式)。
要實現(xiàn)這個功能有很多種方案,例如定時器+多線程等,這里僅演示一種方案,代碼如下:
# -*- 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ù)超時時間(seconds,進程運行超過該時間,kill該進程)
: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如何實時獲取tcpdump輸出的詳細內(nèi)容,更多關(guān)于python獲取tcpdump輸出的資料請關(guān)注腳本之家其它相關(guān)文章!
- Android端TCP長連接的性能優(yōu)化教程分享
- Java多線程實現(xiàn)TCP網(wǎng)絡(luò)Socket編程(C/S通信)
- java實現(xiàn)基于TCP協(xié)議網(wǎng)絡(luò)socket編程(C/S通信)
- Springboot+TCP監(jiān)聽服務(wù)器搭建過程圖解
- Python使用socket_TCP實現(xiàn)小文件下載功能
- Python使用socket模塊實現(xiàn)簡單tcp通信
- 從Linux源碼看Socket(TCP)Client端的Connect的示例詳解
- Java利用TCP協(xié)議實現(xiàn)客戶端與服務(wù)器通信(附通信源碼)
- TCP性能調(diào)優(yōu)實現(xiàn)原理及過程解析
相關(guān)文章
python email smtplib模塊發(fā)送郵件代碼實例
本篇文章給大家分享了python email smtplib模塊發(fā)送郵件的相關(guān)代碼分享,有需要的朋友參考學(xué)習(xí)下。2018-04-04
python如何修改PYTHONPATH環(huán)境變量
這篇文章主要介紹了python如何修改PYTHONPATH環(huán)境變量問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
使用python繪制人人網(wǎng)好友關(guān)系圖示例
這篇文章主要介紹了使用python繪制人人網(wǎng)好友關(guān)系圖示例,需要的朋友可以參考下2014-04-04
Python+redis通過限流保護高并發(fā)系統(tǒng)
這篇文章主要介紹了Python+redis通過限流保護高并發(fā)系統(tǒng),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04

