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学习之面向对象【入门初级篇】
Jan 21 Python
Python2.7环境Flask框架安装简明教程【已测试】
Jul 13 Python
解决pycharm运行时interpreter为空的问题
Oct 29 Python
Django实现一对多表模型的跨表查询方法
Dec 18 Python
详解从Django Rest Framework响应中删除空字段
Jan 11 Python
Python实例方法、类方法、静态方法的区别与作用详解
Mar 25 Python
用python做游戏的细节详解
Jun 25 Python
通过PYTHON来实现图像分割详解
Jun 26 Python
Python3+Requests+Excel完整接口自动化测试框架的实现
Oct 11 Python
python中使用paramiko模块并实现远程连接服务器执行上传下载功能
Feb 29 Python
Python实现一个论文下载器的过程
Jan 18 Python
Django和Ueditor自定义存储上传文件的文件名
Feb 25 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
第六节--访问属性和方法
2006/11/16 PHP
php准确获取文件MIME类型的方法
2015/06/17 PHP
php实现json编码的方法
2015/07/30 PHP
9个比较实用的php代码片段
2016/03/15 PHP
关于 Laravel Redis 多个进程同时取队列问题详解
2017/12/25 PHP
找到了一篇jQuery与Prototype并存的冲突的解决方法
2007/08/29 Javascript
javascript 类定义的4种方法
2009/09/12 Javascript
拖动布局之保存布局页面cookies篇
2010/10/29 Javascript
jquery里的each使用方法详解
2010/12/22 Javascript
Draggable Elements 元素拖拽功能实现代码
2011/03/30 Javascript
JavaScript中的apply()方法和call()方法使用介绍
2012/07/25 Javascript
兼容Firefox的Javascript XSLT 处理XML文件
2014/12/31 Javascript
原生JS仿QQ阅读点击展开、收起效果
2017/03/08 Javascript
浅谈React Native 中组件的生命周期
2017/09/08 Javascript
webpack+vue2构建vue项目骨架的方法
2018/01/09 Javascript
解决vue接口数据赋值给data没有反应的问题
2018/08/27 Javascript
jQuery实现图片下载代码
2019/07/18 jQuery
详解vue中使用axios对同一个接口连续请求导致返回数据混乱的问题
2019/11/06 Javascript
使用npm命令提示: 'npm' 不是内部或外部命令,也不是可运行的程序的处理方法
2020/05/14 Javascript
[00:17]游戏风云独家报道:DD赛后说出数字秘密 吓死你们啊!
2014/07/13 DOTA
Django中模型Model添加JSON类型字段的方法
2015/06/17 Python
Python中的默认参数详解
2015/06/24 Python
详解如何使用Python编写vim插件
2017/11/28 Python
Pandas之drop_duplicates:去除重复项方法
2018/04/18 Python
Python语言快速上手学习方法
2018/12/14 Python
Python动态赋值的陷阱知识点总结
2019/03/17 Python
python将视频转换为全字符视频
2019/04/26 Python
python实现KNN分类算法
2019/10/16 Python
利用PyQt中的QThread类实现多线程
2020/02/18 Python
如何把外网python虚拟环境迁移到内网
2020/05/18 Python
Python filter()及reduce()函数使用方法解析
2020/09/05 Python
class类在python中获取金融数据的实例方法
2020/12/10 Python
怎样有效的进行自我评价
2013/10/06 职场文书
骨干教师个人总结
2015/02/11 职场文书
2015年银行个人工作总结
2015/05/14 职场文书
java Nio使用NioSocket客户端与服务端交互实现方式
2021/06/15 Java/Android