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 selenium如何设置等待时间
Sep 15 Python
Python对列表中的各项进行关联详解
Aug 15 Python
Python网络编程详解
Oct 31 Python
python如何解析配置文件并应用到项目中
Jun 27 Python
Python 合并多个TXT文件并统计词频的实现
Aug 23 Python
详解Python time库的使用
Oct 10 Python
python+selenium定时爬取丁香园的新型冠状病毒数据并制作出类似的地图(部署到云服务器)
Feb 09 Python
详解django中Template语言
Feb 22 Python
python实现贪吃蛇游戏源码
Mar 21 Python
python报错: 'list' object has no attribute 'shape'的解决
Jul 15 Python
基于PyInstaller各参数的含义说明
Mar 04 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 禁止页面缓存输出
2009/01/07 PHP
php session处理的定制
2009/03/16 PHP
thinkPHP使用post方式查询时分页失效的解决方法
2015/12/09 PHP
浅谈php(codeigniter)安全性注意事项
2017/04/06 PHP
Kibo 用于处理键盘事件的Javascript工具库
2011/10/28 Javascript
jQuery教程 $()包装函数来实现数组元素分页效果
2013/08/13 Javascript
alert和confirm功能介绍
2014/05/21 Javascript
jquery实现可点击伸缩与展开的菜单效果代码
2015/08/31 Javascript
jQuery实现简单滚动动画效果
2016/04/07 Javascript
轻松实现js弹框显示选项
2016/09/13 Javascript
js获取json中key所对应的value值的简单方法
2020/06/17 Javascript
各种选择框jQuery的选中方法(实例讲解)
2017/06/27 jQuery
VSCode 配置React Native开发环境的方法
2017/12/27 Javascript
以v-model与promise两种方式实现vue弹窗组件
2018/05/21 Javascript
jQuery滑动效果实现方法分析
2018/09/05 jQuery
WEEX环境搭建与入门详解
2019/10/16 Javascript
微信小程序顶部导航栏可滑动并选中放大
2019/12/05 Javascript
微信小程序登陆注册功能的实现代码
2019/12/10 Javascript
vue中配置scss全局变量的步骤
2020/12/28 Vue.js
[00:27]DOTA2战队VP、Secret贺新春
2018/02/11 DOTA
利用python代码写的12306订票代码
2015/12/20 Python
python随机数分布random测试
2018/08/27 Python
Pycharm2017版本设置启动时默认自动打开项目的方法
2018/10/29 Python
Python3之外部文件调用Django程序操作model等文件实现方式
2020/04/07 Python
Holiday Inn中国官网:IHG旗下假日酒店预订
2018/04/08 全球购物
新东方旗下远程教育网站:新东方在线
2020/03/19 全球购物
中专药剂专业应届毕的自我评价
2013/12/27 职场文书
优秀教师先进事迹
2014/01/22 职场文书
加拿大探亲邀请信
2014/01/28 职场文书
元旦晚会邀请函
2014/02/01 职场文书
机房搬迁方案
2014/05/01 职场文书
大二学生自我检讨书
2014/10/23 职场文书
2014教师年度思想工作总结
2014/11/10 职场文书
证婚人致辞精选
2015/07/28 职场文书
小学数学新课改心得体会
2016/01/22 职场文书
导游词之湖州-太湖
2019/10/11 职场文书