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编写一个每天都在系统下新建一个文件夹的脚本
May 04 Python
用Python实现一个简单的能够上传下载的HTTP服务器
May 05 Python
总结Python中逻辑运算符的使用
May 13 Python
Python中字符串的修改及传参详解
Nov 30 Python
关于Python如何避免循环导入问题详解
Sep 14 Python
Python的UTC时间转换讲解
Feb 26 Python
python选取特定列 pandas iloc,loc,icol的使用详解(列切片及行切片)
Aug 06 Python
python字典排序的方法
Oct 12 Python
Pytorch之parameters的使用
Dec 31 Python
基于torch.where和布尔索引的速度比较
Jan 02 Python
TensorFLow 变量命名空间实例
Feb 11 Python
python时间与Unix时间戳相互转换方法详解
Feb 13 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中echo,print_r与var_dump区别分析
2014/09/29 PHP
php等比例缩放图片及剪切图片代码分享
2016/02/13 PHP
PHP array_key_exists检查键名或索引是否存在于数组中的实现方法
2016/06/13 PHP
通过实例解析PHP数据类型转换方法
2020/07/11 PHP
escape、encodeURI、encodeURIComponent等方法的区别比较
2006/12/27 Javascript
IE 下的只读 innerHTML
2009/08/21 Javascript
jQuery.query.js 取参数的两点问题分析
2012/08/06 Javascript
jquery $(this).attr $(this).val方法使用介绍
2013/10/08 Javascript
js 左右悬浮对联广告代码示例
2014/12/12 Javascript
jQuery实现炫酷的鼠标轨迹特效
2015/02/01 Javascript
bootstrap datetimepicker日期插件使用方法
2017/01/13 Javascript
微信小程序实现缓存根据不同的id来进行设置和读取缓存
2017/06/12 Javascript
js实现随机点名系统(实例讲解)
2017/10/18 Javascript
vue在使用ECharts时的异步更新和数据加载详解
2017/11/22 Javascript
解决jQuery使用append添加的元素事件无效的问题
2018/08/30 jQuery
[02:38]DOTA2超级联赛专访Loda 认为IG世界最强
2013/05/27 DOTA
Python发送form-data请求及拼接form-data内容的方法
2016/03/05 Python
python中json格式数据输出的简单实现方法
2016/10/31 Python
python制作小说爬虫实录
2017/08/14 Python
Python3使用PyQt5制作简单的画板/手写板实例
2017/10/19 Python
浅谈Pandas 排序之后索引的问题
2018/06/07 Python
django2.2 和 PyMySQL版本兼容问题
2020/02/17 Python
Django自带的用户验证系统实现
2020/12/18 Python
IE10 Error.stack 让脚本调试更加方便快捷
2013/04/22 HTML / CSS
丝芙兰法国官网:SEPHORA法国
2016/09/01 全球购物
英国最大的电子零件及配件零售商:Partmaster
2017/04/24 全球购物
Champion澳大利亚官网:美国冠军运动服装
2018/05/07 全球购物
总经理助理岗位职责
2013/11/08 职场文书
实习生工作证明范本
2014/09/14 职场文书
2014年银行员工工作总结
2014/11/12 职场文书
五年级学生期末评语
2014/12/26 职场文书
教师聘用意向书
2015/05/11 职场文书
刑事附带民事诉讼答辩状
2015/05/22 职场文书
士兵突击观后感
2015/06/16 职场文书
2016党校学习心得体会
2016/01/07 职场文书
2019年让高校“心动”的自荐信
2019/03/25 职场文书