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中用datetime包进行对时间的一些操作
Jun 23 Python
使用pandas对两个dataframe进行join的实例
Jun 08 Python
python使用插值法画出平滑曲线
Dec 15 Python
解决PySide+Python子线程更新UI线程的问题
Jan 11 Python
Python修改文件往指定行插入内容的实例
Jan 30 Python
python binascii 进制转换实例
Jun 12 Python
python多线程+代理池爬取天天基金网、股票数据过程解析
Aug 13 Python
python爬虫数据保存到mongoDB的实例方法
Jul 28 Python
python分布式爬虫中消息队列知识点详解
Nov 26 Python
Python实现迪杰斯特拉算法并生成最短路径的示例代码
Dec 01 Python
python 统计list中各个元素出现的次数的几种方法
Feb 20 Python
Python实现我的世界小游戏源代码
Mar 02 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修正代码
2011/05/09 PHP
ThinkPHP之N方法实例详解
2014/06/20 PHP
PHP伪造来源HTTP_REFERER的方法实例详解
2015/07/06 PHP
PHP中使用array函数新建一个数组
2015/11/19 PHP
php车辆违章查询数据示例
2016/10/14 PHP
Laravel Eloquent ORM 实现查询表中指定的字段
2019/10/17 PHP
laravel Task Scheduling(任务调度)在windows下的使用详解
2019/10/22 PHP
PHP设计模式之外观模式(Facade)入门与应用详解
2019/12/13 PHP
用cssText批量修改样式
2009/08/29 Javascript
关于IE BUG与字符串截取substr的解决办法
2013/04/10 Javascript
JQuery DataTable删除行后的页面更新利用Ajax解决
2013/05/17 Javascript
JS操作JSON要领详细总结
2013/08/25 Javascript
跨域请求的完美解决方法(JSONP, CORS)
2016/06/12 Javascript
理解javascript中的闭包
2017/01/11 Javascript
JS 验证密码 不能为空,必须含有数字、字母、特殊字符,长度在8-12位
2017/06/21 Javascript
微信小程序中setInterval的使用方法
2017/09/29 Javascript
React Native中导航组件react-navigation跨tab路由处理详解
2017/10/31 Javascript
Angular5.0 子组件通过service传递值给父组件的方法
2018/07/13 Javascript
js事件on动态绑定数据,绑定多个事件的方法
2018/09/15 Javascript
微信小程序开发搜索功能实现(前端+后端+数据库)
2020/03/04 Javascript
微信小程序实现时间戳格式转换
2020/07/20 Javascript
解决vue字符串换行问题(绝对管用)
2020/08/06 Javascript
js数组的基本使用总结
2021/01/18 Javascript
[01:43]倾听DOTA2英雄之声 魅惑魔女国服配音鉴赏
2013/06/06 DOTA
[05:20]2018DOTA2亚洲邀请赛主赛事第三日战况回顾 LGD率先挺进胜者组决赛
2018/04/06 DOTA
python+selenium+autoit实现文件上传功能
2017/08/23 Python
python实现五子棋游戏
2019/06/18 Python
python系统指定文件的查找只输出目录下所有文件及文件夹
2020/01/19 Python
全球速卖通法国在线交易平台:AliExpress法国
2017/07/07 全球购物
美国孕妇装品牌:Destination Maternity
2018/02/04 全球购物
优秀学生获奖感言
2014/02/15 职场文书
公司股权转让协议书
2014/04/12 职场文书
教师教学评估方案
2014/05/09 职场文书
媒矿安全生产承诺书
2014/05/23 职场文书
大雁塔导游词
2015/02/04 职场文书
MySQL Threads_running飙升与慢查询的相关问题解决
2021/05/08 MySQL