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 相关文章推荐
详谈Python2.6和Python3.0中对除法操作的异同
Apr 28 Python
python 文件转成16进制数组的实例
Jul 09 Python
python实现在遍历列表时,直接对dict元素增加字段的方法
Jan 15 Python
python 将对象设置为可迭代的两种实现方法
Jan 21 Python
python实现扫描ip地址的小程序
Apr 16 Python
用uWSGI和Nginx部署Flask项目的方法示例
May 05 Python
Python实现将字符串的首字母变为大写,其余都变为小写的方法
Jun 11 Python
python3 使用Opencv打开USB摄像头,配置1080P分辨率的操作
Dec 11 Python
Keras搭建自编码器操作
Jul 03 Python
Python如何实现自带HTTP文件传输服务
Jul 08 Python
Python快速优雅的批量修改Word文档样式
May 20 Python
Python办公自动化解决world文件批量转换
Sep 15 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 stripos()函数及注意事项的分析
2013/06/08 PHP
php将文本文件转换csv输出的方法
2014/12/31 PHP
ThinkPHP 3.2.3实现加减乘除图片验证码
2018/12/05 PHP
PHP通过GD库实现验证码功能示例
2019/02/23 PHP
javascript中的对象和数组的应用技巧
2007/01/07 Javascript
Web层改进II-用xmlhttp 无声息提交复杂表单
2007/01/22 Javascript
为原生js Array增加each方法
2012/04/07 Javascript
jquery获取及设置outerhtml的方法
2015/03/09 Javascript
快速掌握Node.js环境的安装与运行方法
2016/02/16 Javascript
Bootstrap 组件之按钮(二)
2016/05/11 Javascript
前端分页功能的实现以及原理(jQuery)
2017/01/22 Javascript
JavaScript如何获取到导航条中HTTP信息
2017/10/10 Javascript
create-react-app修改为多页面支持的方法
2018/05/17 Javascript
vue项目实现表单登录页保存账号和密码到cookie功能
2018/08/31 Javascript
微信小程序学习笔记之表单提交与PHP后台数据交互处理图文详解
2019/03/28 Javascript
使用 Vue cli 3.0 构建自定义组件库的方法
2019/04/30 Javascript
JavaScript实现电灯开关小案例
2020/03/30 Javascript
vue循环中点击选中再点击取消(单选)的实现
2020/09/10 Javascript
nuxt 路由、过渡特效、中间件的实现代码
2020/11/06 Javascript
微信小程序实现音乐播放页面布局
2020/12/11 Javascript
Python简单删除列表中相同元素的方法示例
2017/06/12 Python
Python绑定方法与非绑定方法详解
2017/08/18 Python
Python Flask-web表单使用详解
2017/11/18 Python
python requests 库请求带有文件参数的接口实例
2019/01/03 Python
Python常用特殊方法实例总结
2019/03/22 Python
Pytorch提取模型特征向量保存至csv的例子
2020/01/03 Python
Python如何爬取qq音乐歌词到本地
2020/06/01 Python
pytorch中的weight-initilzation用法
2020/06/24 Python
html5 viewport使用方法示例详解
2013/12/02 HTML / CSS
struct与class的区别
2014/02/03 面试题
利达恒信公司.NET笔试题面试题
2016/03/05 面试题
宿舍违规检讨书
2014/01/12 职场文书
作文评语集锦大全
2014/04/23 职场文书
医院营销工作计划
2015/01/16 职场文书
餐厅保洁员岗位职责
2015/04/10 职场文书
红歌会主持词
2015/07/02 职场文书