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 相关文章推荐
Djang中静态文件配置方法
Jul 30 Python
Python自然语言处理之词干,词形与最大匹配算法代码详解
Nov 16 Python
Python中optparser库用法实例详解
Jan 26 Python
python实现Decorator模式实例代码
Feb 09 Python
django 中QuerySet特性功能详解
Jul 25 Python
python实现文件批量编码转换及注意事项
Oct 14 Python
python生成器用法实例详解
Nov 22 Python
浅谈keras中的keras.utils.to_categorical用法
Jul 02 Python
opencv 图像加法与图像融合的实现代码
Jul 08 Python
python3.7调试的实例方法
Jul 21 Python
Python CategoricalDtype自定义排序实现原理解析
Sep 11 Python
Python中time与datetime模块使用方法详解
Mar 31 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实现图片简单上传
2006/10/09 PHP
snoopy 强大的PHP采集类使用实例代码
2010/12/09 PHP
如何设置mysql允许外网访问
2013/06/04 PHP
PHP中__FILE__、dirname与basename用法实例分析
2014/12/01 PHP
PHP的Yii框架使用中的一些错误解决方法与建议
2015/08/21 PHP
thinkphp整合微信支付代码分享
2016/11/24 PHP
PHP5.5基于mysqli连接MySQL数据库和读取数据操作实例详解
2019/02/16 PHP
PHP 实现 JSON 数据的编码和解码操作详解
2020/04/22 PHP
HTTP头隐藏PHP版本号实现过程解析
2020/12/09 PHP
EXT中xtype的含义分析
2010/01/07 Javascript
js加入收藏以及使用Jquery更改透明度
2014/01/26 Javascript
详解JavaScript中void语句的使用
2015/06/04 Javascript
js中获取时间new Date()的全面介绍
2016/06/20 Javascript
vue构建单页面应用实战
2017/04/10 Javascript
jQuery+SpringMVC中的复选框选择与传值实例
2018/01/08 jQuery
angularJS的radio实现单项二选一的使用方法
2018/02/28 Javascript
关于jquery layui弹出层的使用方法
2018/04/21 jQuery
vue 接口请求地址前缀本地开发和线上开发设置方式
2020/08/13 Javascript
Python时间戳与时间字符串互相转换实例代码
2013/11/28 Python
python中json格式数据输出的简单实现方法
2016/10/31 Python
Python实现复杂对象转JSON的方法示例
2017/06/22 Python
Python smtplib实现发送邮件功能
2018/05/22 Python
MxNet预训练模型到Pytorch模型的转换方式
2020/05/25 Python
澳大利亚领先的在线美容商店:Facial Co
2017/10/22 全球购物
C面试题
2015/10/08 面试题
有abstract方法的类一定要用abstract修饰吗
2016/03/14 面试题
Weblogic和WebSphere不同特点
2012/05/09 面试题
车间组长岗位职责
2013/12/20 职场文书
初婚未育未抱养证明
2014/01/12 职场文书
银行办理业务介绍信
2014/01/18 职场文书
物业总经理岗位职责
2014/02/28 职场文书
技术总监管理岗位职责
2014/03/09 职场文书
人民调解员培训方案
2014/06/05 职场文书
预防传染病方案
2014/06/14 职场文书
委托书的写法
2014/09/16 职场文书
学校青年志愿者活动总结
2015/05/06 职场文书