python如何实时获取tcpdump输出
作者:文渊 发布时间:2021-05-05 14:41:36
标签:python,tcpdump
一、背景
今天有个小需求,要确认客户端有没有往服务端发送udp包,但为了减轻工作量,不想每次到机器上手动执行tcpdump抓包命令。
于是就写了个脚本来释放人力。
二、代码实现
整个脚本我还加了一些其他功能:时间戳、发送端IP提取,数据包分析,数据持久化等。这里都先去掉,仅记录下简单的实时获取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...
以上代码相当于手动执行了 sudo tcpdump -tt -l -nn -c 5 -i enp4s0 udp port 514 or 51414
这条命令。
注意参数-l很重要(行显)。
三、代码实现(更新)
上面的代码能实现tcpdump的功能,但是有一个问题:没有做超时保护。即当程序执行时间过长时kill该进程(这里使用ctrl+c的方式)。
要实现这个功能有很多种方案,例如定时器+多线程等,这里仅演示一种方案,代码如下:
# -*- 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: 执行命令(列表形式)
:param timeout: 任务超时时间(seconds,进程运行超过该时间,kill该进程)
:param taskname: 任务名称(根据该任务名称记录命令输出信息)
'''
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())
# 执行tcpdump任务
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()
# 数据合并(新增/更新)
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
))
# 保存数据
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()
四、总结
比较简单,仅仅是记录下。
来源:https://www.wenyuanblog.com/blogs/python-realtime-tcpdump.html
0
投稿
猜你喜欢
- 传统Python语言的主要控制结构是for循环。然而,需要注意的是for循环在Pandas中不常用,因此Python中for循环的有效执行并
- 前言在大多数介绍 Buffer 的文章中,主要是围绕数据拼接和内存分配这两方面的。比如我们使用fs模块来读取文件内容的时候,返回的就是一个
- 1. 引言在本文中,我们将研究从列表中选择随机元素的不同实现方法。在日常项目中,我们经常会遇到这种情形,比如随机从多种数据增强策略中选择一种
- 前言本文主要给大家介绍了关于django配置连接数据库及原生sql语句的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介
- 用js实现一个砖头在页面,但鼠标点击拖动时,砖头在页面上形成拖拉效果:刚开始时:鼠标点击拖动后:实现代码:<html> <
- 目标在本节中,将学习根据立体图像创建深度图基础在上一节中,看到了对极约束和其他相关术语等基本概念。如果有两个场景相同的图像,则可以通过直观的
- 1. 背景在软件需求、开发、测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,要么需要手动制造一些数据。
- 本文实例讲述了Python使用matplotlib绘制多个图形单独显示的方法。分享给大家供大家参考,具体如下:一 代码import nump
- 本文实例讲述了Python挑选文件夹里宽大于300图片的方法。分享给大家供大家参考。具体分析如下:这段代码需要用到PIL库。代码如下所示:i
- 前言很多时候开发者需要删除文件。可能是他错误地创建了文件,或者不再需要该文件。无论出于何种原因,都有一些方法可以通过Python来删除文件,
- 前言此专栏为python与R语言对比学习的文章;以通俗易懂的小实验,带领大家深入浅出的理解两种语言的基本语法,并用以实际场景!感谢大家的关注
- for 循环本系列前面 “探索 Python,第 5 部分:用 Python 编程” 一文讨论了 if 语句和 while 循环,讨论了复合
- 示例from optparse import OptionParser[...]def main():
- OpenCVOpenCV 是计算机视觉领域最受欢迎的开源库,起初它由 C/C ++ 编写,现在用 Python 也能使用。OpenCV 可以
- ERROR 1819 (HY000): Your password does not satisfy the current policy
- 今天闲来无聊无意间看到了百度股票,就想着用python爬一下数据,于是就找到了东方财经网,结合这两个网站,写了一个小爬虫,数据保存在文件中,
- 看了上一篇内容之后,相信对K近邻算法有了一个清晰的认识,今天的内容——手写数字识别是对上一篇内容的延续,这里也是为了自己能更熟练的掌握k-N
- 本文实例讲述了python处理图片之PIL模块简单使用方法。分享给大家供大家参考。具体实现方法如下:#!/usr/bin/env pytho
- 本文实例为大家分享了python实现多张图片垂直合并的具体代码,供大家参考,具体内容如下# coding: utf-8 # image_me
- 概述Web环境我们假设为Apache。在编译PHP的时候,为了能够让Apache支持PHP,我们会生成一个mod_php5.so的模块。Ap