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获取指定网页上所有超链接的方法
Apr 04 Python
Python3.5编程实现修改IIS WEB.CONFIG的方法示例
Aug 18 Python
python中的json总结
Oct 11 Python
python numpy 按行归一化的实例
Jan 21 Python
Pyqt清空某一个QTreeewidgetItem下的所有分支方法
Jun 17 Python
使用OpenCV实现仿射变换—旋转功能
Aug 29 Python
python批量处理文件或文件夹
Jul 28 Python
Python 实现自动导入缺失的库
Oct 29 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
May 15 Python
Python使用Paramiko控制liunx第三方库
May 20 Python
如何基于Django实现上下文章跳转
Sep 16 Python
Python3使用Selenium获取session和token方法详解
Feb 16 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
基于mysql的bbs设计(四)
2006/10/09 PHP
TMDPHP 模板引擎使用教程
2012/03/13 PHP
采集邮箱的php代码(抓取网页中的邮箱地址)
2012/07/17 PHP
PHP循环函数使用介绍之PHP基础入门教程
2013/09/21 PHP
Linux下从零开始安装配置Nginx服务器+PHP开发环境
2015/12/21 PHP
javascript prototype 原型链
2009/03/12 Javascript
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
2011/02/24 Javascript
jQuery查询数据返回object和字符串影响原因是什么
2013/08/09 Javascript
JavaScript var声明变量背后的原理示例解析
2013/10/12 Javascript
JS实现滑动菜单效果代码(包括Tab,选项卡,横向等效果)
2015/09/24 Javascript
js clearInterval()方法的定义和用法
2015/11/11 Javascript
jquery点击切换背景色的简单实例
2016/08/25 Javascript
jsp 网站引入外部css或者js失效问题解决
2016/10/31 Javascript
angular ngClick阻止冒泡使用默认行为的方法
2016/11/03 Javascript
JS正则表达式修饰符中multiline(/m)用法分析
2016/12/27 Javascript
jQuery和CSS仿京东仿淘宝列表导航菜单
2017/01/04 Javascript
微信小程序实战之上拉(分页加载)效果(2)
2017/04/17 Javascript
解决iview打包时UglifyJs报错的问题
2018/03/07 Javascript
微信小程序中使用自定义图标(阿里icon)的方法
2018/08/20 Javascript
微信公众号生成新浪短网址的实现(快速生成)
2019/08/18 Javascript
python解析xml文件实例分析
2015/05/27 Python
Python网络编程使用select实现socket全双工异步通信功能示例
2018/04/09 Python
python学生信息管理系统(完整版)
2020/04/05 Python
Django框架 查询Extra功能实现解析
2019/09/04 Python
html5中使用hotcss.js实现手机端自适配的方法
2020/04/23 HTML / CSS
联想美国官方商城:Lenovo美国
2017/06/19 全球购物
综合测评自我鉴定
2013/10/08 职场文书
竞争上岗实施方案
2014/03/21 职场文书
团日活动总结怎么写
2014/06/25 职场文书
群众路线党员个人剖析材料
2014/10/08 职场文书
公司优秀员工推荐信
2015/03/24 职场文书
2015年班组工作总结
2015/04/20 职场文书
2015年基层党建工作汇报材料
2015/06/25 职场文书
篮球拉拉队口号
2015/12/25 职场文书
《莫泊桑拜师》教学反思
2016/02/22 职场文书
2016年“节能宣传周”活动总结
2016/04/05 职场文书