python如何实时获取tcpdump输出


Posted in Python onSeptember 16, 2020

一、背景

今天有个小需求,要确认客户端有没有往服务端发送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()

四、总结

比较简单,仅仅是记录下。

以上就是python如何实时获取tcpdump输出的详细内容,更多关于python获取tcpdump输出的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python 返回汉字的汉语拼音
Feb 27 Python
如何高效使用Python字典的方法详解
Aug 31 Python
13个最常用的Python深度学习库介绍
Oct 28 Python
在Pandas中DataFrame数据合并,连接(concat,merge,join)的实例
Jan 29 Python
Python3.4学习笔记之列表、数组操作示例
Mar 01 Python
Python中最大递归深度值的探讨
Mar 05 Python
详解python和matlab的优势与区别
Jun 28 Python
解决os.path.isdir() 判断文件夹却返回false的问题
Nov 29 Python
pytorch实现特殊的Module--Sqeuential三种写法
Jan 15 Python
Python爬虫程序架构和运行流程原理解析
Mar 09 Python
Python通过fnmatch模块实现文件名匹配
Sep 30 Python
python 获取剪切板内容的两种方法
Nov 28 Python
基于python实现复制文件并重命名
Sep 16 #Python
详解python程序中的多任务
Sep 16 #Python
python实现简单的tcp 文件下载
Sep 16 #Python
实现Python3数组旋转的3种算法实例
Sep 16 #Python
Python私有属性私有方法应用实例解析
Sep 15 #Python
PyQt5多线程防卡死和多窗口用法的实现
Sep 15 #Python
PyQt5结合matplotlib绘图的实现示例
Sep 15 #Python
You might like
PHP中的extract的作用分析
2008/04/09 PHP
PHP上传文件时自动分配路径的方法
2015/01/09 PHP
Laravel中Facade的加载过程与原理详解
2017/09/22 PHP
laravel5.6中的外键约束示例
2019/10/23 PHP
利用404错误页面实现UrlRewrite的实现代码
2008/08/20 Javascript
jquery 双色表格实现代码
2009/12/08 Javascript
ExtJs 表单提交登陆实现代码
2010/08/19 Javascript
js实现一个省市区三级联动选择框代码分享
2013/03/06 Javascript
node.js中的fs.read方法使用说明
2014/12/17 Javascript
前端设计师们最常用的JS代码汇总
2016/09/25 Javascript
Javascript中arguments对象的详解与使用方法
2016/10/04 Javascript
vue轮播图插件vue-awesome-swiper
2017/11/27 Javascript
Vue作用域插槽slot-scope实例代码
2018/09/05 Javascript
Node爬取大批量文件的方法示例
2019/06/28 Javascript
jQuery pager.js 插件动态分页功能实例分析
2019/08/02 jQuery
vue 根据选择条件显示指定参数的例子
2019/11/09 Javascript
创建nuxt.js项目流程图解
2020/03/13 Javascript
js最全的数组的降维5种办法(小结)
2020/04/28 Javascript
在js文件中引入(调用)另一个js文件的三种方法
2020/09/11 Javascript
python MySQLdb Windows下安装教程及问题解决方法
2015/05/09 Python
利用python3随机生成中文字符的实现方法
2017/11/24 Python
tensorflow获取变量维度信息
2018/03/10 Python
Python求解任意闭区间的所有素数
2018/06/10 Python
python 通过可变参数计算n个数的乘积方法
2019/06/13 Python
安装好Pycharm后如何配置Python解释器简易教程
2019/06/28 Python
Django模型修改及数据迁移实现解析
2019/08/01 Python
全面总结使用CSS实现水平垂直居中效果的方法
2016/03/10 HTML / CSS
细说CSS3中box属性中的overflow-x属性和overflow-y属性值的效果
2014/07/21 HTML / CSS
日本最大化妆品和美容产品的综合口碑网站:cosme shopping
2019/08/28 全球购物
Java软件工程师综合面试题笔试题
2013/09/08 面试题
构建高效课堂实施方案
2014/03/13 职场文书
警校毕业生自我评价
2014/04/06 职场文书
总经理人事任命书
2014/06/05 职场文书
2015年八一建军节活动总结
2015/03/20 职场文书
MySQL EXPLAIN输出列的详细解释
2021/05/12 MySQL
MySQL实战记录之如何快速定位慢SQL
2022/03/23 MySQL