python如何实时获取tcpdump输出
一、背景
今天有个小需求,要确认客户端有没有往服务端发送udp包,但为了减轻工作量,不想每次到机器上手动执行tcpdump抓包命令。
于是就写了个脚本来释放人力。
二、代码实现
整个脚本我还加了一些其他功能:时间戳、发送端IP提取,数据包分析,数据持久化等。这里都先去掉,仅记录下简单的实时获取tcpdump输出功能。
代码如下:
#-*-coding:utf-8-*- #!/usr/bin/envpython #sudotcpdump-tt-l-nn-c5-ienp4s0udpport514or51414 importsubprocess cmd=['sudo','tcpdump','-tt','-l','-nn','-c','5','-i','enp4s0','udp','port','514','or','51414'] proc=subprocess.Popen(cmd,stdout=subprocess.PIPE) whileTrue: line=proc.stdout.readline() line=line.strip() ifnotline: print('tcpdumpfinished...') break print(line)
输出如下(实时):
wenyuanblog@localhost:/home/test/script#pythontcpdump_udp.py tcpdump:verboseoutputsuppressed,use-vor-vvforfullprotocoldecode listeningonenp4s0,link-typeEN10MB(Ethernet),capturesize262144bytes 1499774951.124178IP192.168.10.210.41974>192.168.10.251.514:UDP,length139 1499774953.125664IP192.168.10.210.54995>192.168.10.251.51414:UDP,length139 1499774956.128498IP192.168.10.210.56748>192.168.10.251.514:UDP,length139 1499774958.129918IP192.168.10.210.53883>192.168.10.251.51414:UDP,length139 1499774961.132921IP192.168.10.210.58803>192.168.10.251.514:UDP,length139 5packetscaptured 6packetsreceivedbyfilter 0packetsdroppedbykernel tcpdumpfinished...
以上代码相当于手动执行了sudotcpdump-tt-l-nn-c5-ienp4s0udpport514or51414这条命令。
注意参数-l很重要(行显)。
三、代码实现(更新)
上面的代码能实现tcpdump的功能,但是有一个问题:没有做超时保护。即当程序执行时间过长时kill该进程(这里使用ctrl+c的方式)。
要实现这个功能有很多种方案,例如定时器+多线程等,这里仅演示一种方案,代码如下:
#-*-coding:utf-8-*- #!/usr/bin/envpython #sudotcpdump-tt-l-nn-c50-ienp4s0udpport514or51414 importsubprocess importsignal importtime importos importre importjson classCmdServer: def__init__(self,cmd,timeout=120): ''' :paramcmd:执行命令(列表形式) :paramtimeout:任务超时时间(seconds,进程运行超过该时间,kill该进程) :paramtaskname:任务名称(根据该任务名称记录命令输出信息) ''' self.cmd=cmd self.timeout=timeout self.base_path=reduce(lambdax,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任务 defrun(self): ifos.path.exists(self.output_path): withopen(self.output_path,'r')asf: self.udp_flow_list=json.load(f) proc=subprocess.Popen(self.cmd,stdout=subprocess.PIPE) stdout='' whileproc.poll()==None: current_time=int(time.time()) ifcurrent_time-self.begin_time>=self.timeout: print('tcpdumptimeout...') proc.send_signal(signal.SIGINT) stdout=proc.stdout.read() ifproc.poll()isnotNoneandnotstdout: print('tcpdumpfinished...') stdout=proc.stdout.read() stdout_list=stdout.split('\n') ifstdout_list: self._merge_data(stdout_list) self._save_data() #数据合并(新增/更新) def_merge_data(self,stdout_list): forlineinstdout_list: line=line.strip() ifnotline: continue timestamp=int(float(line.split('IP')[0].strip()))*1000 #源 src_ip_port_list=re.findall(r'IP(.+?)>',line) ifnotsrc_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) ifnotdst_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(lambdax:src_ip==x['src_ip'],self.udp_flow_list) ifsrc_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): #写入文件 withopen(self.output_path,'w')asf: 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输出的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。