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 相关文章推荐
centos下更新Python版本的步骤
Feb 12 Python
python多线程编程方式分析示例详解
Dec 06 Python
python爬虫的工作原理
Mar 05 Python
Python中扩展包的安装方法详解
Jun 14 Python
Python实现图片滑动式验证识别方法
Nov 09 Python
Python爬虫获取整个站点中的所有外部链接代码示例
Dec 26 Python
python使用time、datetime返回工作日列表实例代码
May 09 Python
django foreignkey外键使用的例子 相当于left join
Aug 06 Python
pytorch实现Tensor变量之间的转换
Feb 17 Python
Python列表解析操作实例总结
Feb 26 Python
PyCharm中Matplotlib绘图不能显示UI效果的问题解决
Mar 12 Python
Python通过format函数格式化显示值
Oct 17 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
在IIS上安装PHP4.0正式版
2006/10/09 PHP
php处理斐波那契数列非递归方法
2012/02/04 PHP
php页面消耗内存过大的处理办法
2013/03/18 PHP
双冒号 ::在PHP中的使用情况
2015/11/05 PHP
PHP简单获取随机数的常用方法小结
2017/06/07 PHP
基于jQuery的日期选择控件
2009/10/27 Javascript
jQuery入门第一课 jQuery选择符
2010/03/14 Javascript
浅析jquery数组删除指定元素的方法:grep()
2016/05/19 Javascript
JS 全屏和退出全屏详解及实例代码
2016/11/07 Javascript
JS实现iframe自适应高度的方法示例
2017/01/07 Javascript
jquery做个日期选择适用于手机端示例
2017/01/10 Javascript
教你快速搭建Node.Js服务器的方法教程
2017/03/30 Javascript
Vue实现百度下拉提示搜索功能
2017/06/21 Javascript
移动端触摸滑动插件swiper使用方法详解
2017/08/11 Javascript
Vue使用vue-cli创建项目
2017/09/01 Javascript
JQuery实现ajax请求的示例和注意事项
2018/12/10 jQuery
JavaScript实现美化滑块效果
2019/05/17 Javascript
Nodejs中使用puppeteer控制浏览器中视频播放功能
2019/08/26 NodeJs
vue点击按钮动态创建与删除组件功能
2019/12/29 Javascript
React Native中ScrollView组件轮播图与ListView渲染列表组件用法实例分析
2020/01/06 Javascript
Vue Element校验validate的实例
2020/09/21 Javascript
python通过pil模块将raw图片转换成png图片的方法
2015/03/16 Python
Python实现SVN的目录周期性备份实例
2015/07/17 Python
Python解决抛小球问题 求小球下落经历的距离之和示例
2018/02/01 Python
Python 实现数据结构-堆栈和队列的操作方法
2019/07/17 Python
python 浅谈serial与stm32通信的编码问题
2019/12/18 Python
美国女士内衣在线折扣商店:One Hanes Place
2019/03/24 全球购物
高三毕业生自我鉴定
2013/12/20 职场文书
开学典礼感言
2014/02/16 职场文书
安全宣传标语口号
2014/06/06 职场文书
个人贷款授权委托书样本
2014/10/07 职场文书
同意离婚答辩状
2015/05/22 职场文书
公司环境卫生管理制度
2015/08/05 职场文书
旅行社计调工作总结
2015/08/12 职场文书
中学音乐课教学反思
2016/02/18 职场文书
Javascript 解构赋值详情
2021/11/17 Javascript