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 19 Python
使用Python内置的模块与函数进行不同进制的数的转换
Mar 12 Python
使用Python3制作TCP端口扫描器
Apr 17 Python
Python面向对象编程基础解析(二)
Oct 26 Python
对django中render()与render_to_response()的区别详解
Oct 16 Python
Python实现简单层次聚类算法以及可视化
Mar 18 Python
Python Subprocess模块原理及实例
Aug 26 Python
python可视化实现KNN算法
Oct 16 Python
Python中类似于jquery的pyquery库用法分析
Dec 02 Python
使用pyqt 实现重复打开多个相同界面
Dec 13 Python
Python+MySQL随机试卷及答案生成程序的示例代码
Feb 01 Python
python单向链表实例详解
May 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
造就帕卡马拉的帕卡斯是怎么被发现的
2021/03/03 咖啡文化
php轻松实现中英文混排字符串截取
2014/05/28 PHP
PHP 面向对象程序设计(oop)学习笔记 (五) - PHP 命名空间
2014/06/12 PHP
CI框架Session.php源码分析
2014/11/03 PHP
PHP获取文件相对路径的方法
2015/02/26 PHP
golang与php实现计算两个经纬度之间距离的方法
2016/07/22 PHP
PHP针对多用户实现更换头像功能
2016/09/04 PHP
php readfile下载大文件失败的解决方法
2017/05/22 PHP
PHP反射学习入门示例
2019/06/14 PHP
Laravel-admin之修改操作日志的方法
2019/09/30 PHP
Jquery Ajax的Get方式时需要注意URL地方
2011/04/07 Javascript
JavaScript高级程序设计 阅读笔记(十八) js跨平台的事件
2012/08/14 Javascript
js监听鼠标点击和键盘点击事件并自动跳转页面
2014/09/24 Javascript
实例讲解jquery与json的结合
2016/01/07 Javascript
js实现input密码框提示信息的方法(附html5实现方法)
2016/01/14 Javascript
jquery自定义插件开发之window的实现过程
2016/05/06 Javascript
jQuery基础知识点总结(DOM操作)
2016/06/01 Javascript
jQuery实现模拟flash头像裁切上传功能示例
2016/12/11 Javascript
JS实现HTML页面中动态显示当前时间完整示例
2018/07/30 Javascript
JS实现的对象去重功能示例
2019/06/04 Javascript
node.js中 mysql 增删改查操作及async,await处理实例分析
2020/02/11 Javascript
vue添加自定义右键菜单的完整实例
2020/12/08 Vue.js
vue 使用 v-model 双向绑定父子组件的值遇见的问题及解决方案
2021/03/01 Vue.js
python英语单词测试小程序代码实例
2019/09/09 Python
Python实现Canny及Hough算法代码实例解析
2020/08/06 Python
css3 盒模型以及box-sizing属性全面了解
2016/09/20 HTML / CSS
怎样实现H5+CSS3手指滑动切换图片的示例代码
2019/05/05 HTML / CSS
吃透移动端 Html5 响应式布局
2019/12/16 HTML / CSS
输入一行文字,找出其中大写字母、小写字母、空格、数字、及其他字符各有多少
2016/04/15 面试题
what is the difference between ext2 and ext3
2013/11/03 面试题
代码中finally中的代码会不会执行
2012/02/06 面试题
个性大学生自我评价
2013/12/04 职场文书
端午节演讲稿
2014/05/23 职场文书
2015年行政人事部工作总结
2015/05/13 职场文书
中秋节感想
2015/08/10 职场文书
Java 数组的使用
2022/05/11 Java/Android