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中__call__方法示例分析
Oct 11 Python
Python中的True,False条件判断实例分析
Jan 12 Python
Python中下划线的使用方法
Mar 27 Python
分析Python的Django框架的运行方式及处理流程
Apr 08 Python
python生成词云的实现方法(推荐)
Jun 13 Python
用python写个自动SSH登录远程服务器的小工具(实例)
Jun 17 Python
使用Python做定时任务及时了解互联网动态
May 15 Python
django框架防止XSS注入的方法分析
Jun 21 Python
django 通过url实现简单的权限控制的例子
Aug 16 Python
基于TensorFlow常量、序列以及随机值生成实例
Jan 04 Python
tensorflow 报错unitialized value的解决方法
Feb 06 Python
python中sklearn的pipeline模块实例详解
May 21 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
全国FM电台频率大全 - 14 江西省
2020/03/11 无线电
php+mongodb判断坐标是否在指定多边形区域内的实例
2016/10/28 PHP
详解PHP处理字符串类似indexof的方法函数
2017/06/11 PHP
一个简单的js渐显(fadeIn)渐隐(fadeOut)类
2010/06/19 Javascript
firefox下jQuery UI Autocomplete 1.8.*中文输入修正方法
2012/09/19 Javascript
多个checkbox被选中时如何判断是否有自己想要的
2014/09/22 Javascript
Node.js的包详细介绍
2015/01/14 Javascript
AngularJS基础学习笔记之表达式
2015/05/10 Javascript
jQuery插件animateSlide制作多点滑动幻灯片
2015/06/11 Javascript
JavaScript框架是什么?怎样才能叫做框架?
2015/07/01 Javascript
js实现汉字排序的方法
2015/07/23 Javascript
实例解析jQuery插件EasyUI最常用的表单验证规则
2015/11/29 Javascript
移动开发之自适应手机屏幕宽度
2016/11/23 Javascript
jQuery实现删除li节点的方法
2016/12/06 Javascript
网页中右键功能的实现方法之contextMenu的使用
2017/02/20 Javascript
AngularJS Toaster使用详解
2017/02/24 Javascript
详解Node.js项目APM监控之New Relic
2017/05/12 Javascript
Js面试算法详解
2018/04/08 Javascript
微信小程序传值以及获取值方法的详解
2019/04/29 Javascript
实用Javascript调试技巧分享(小结)
2019/06/18 Javascript
Vue 3.x+axios跨域方案的踩坑指南
2019/07/04 Javascript
基于Vue+ElementUI的省市区地址选择通用组件
2019/11/20 Javascript
vue循环中点击选中再点击取消(单选)的实现
2020/09/10 Javascript
[02:23]2014DOTA2国际邀请赛中国战队回顾
2014/08/01 DOTA
python 数据清洗之数据合并、转换、过滤、排序
2017/02/12 Python
Python中的函数式编程:不可变的数据结构
2018/10/08 Python
实时获取Python的print输出流方法
2019/01/07 Python
在Python文件中指定Python解释器的方法
2019/02/18 Python
pyinstaller打包单个exe后无法执行错误的解决方法
2019/06/21 Python
python如何删除文件中重复的字段
2019/07/16 Python
详解vscode实现远程linux服务器上Python开发
2020/11/10 Python
数据库面试要点基本概念
2013/10/31 面试题
读书月活动方案
2014/05/22 职场文书
2014院党委领导班子对照检查材料思想汇报
2014/09/24 职场文书
详解如何修改nginx的默认端口
2021/03/31 Servers
go goroutine 怎样进行错误处理
2021/07/16 Golang